home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume5 / tron / part01 / tron_server.c < prev   
Encoding:
C/C++ Source or Header  |  1989-11-21  |  18.9 KB  |  749 lines

  1. /*     This program was written by Helmut Hoenig    */
  2. /*        in May of 1988 at the Unitversity of        */
  3. /*   Kaiserslautern, Germany. It may be copied freely.    */
  4.  
  5. #define    moremessages    0
  6.  
  7. #include <X11/Xlib.h>
  8. #include <stdio.h>
  9. #include <strings.h>
  10. #include <sys/types.h>
  11. #include <sys/socket.h>
  12. #include <sys/uio.h>
  13. #include <sys/time.h>
  14. #include <netinet/in.h>
  15. #include <netdb.h>
  16.  
  17. #include "header.h"
  18. #include "messages.h"
  19.  
  20. short    readshort();
  21.  
  22. #define    HMAX        8
  23. int    max;    /* when starting the system, this is the actual number of players */
  24.  
  25. int    messflag;
  26. #define    MAXPLAYERS    10
  27.  
  28. /* fields for result-messages */
  29. static    int    points[MAXPLAYERS];
  30. static    int    place[MAXPLAYERS];
  31. static    int    count[MAXPLAYERS];
  32. static    int    sorted[MAXPLAYERS];
  33. static    char    tscreen[20][80];
  34. static    int    lines;
  35. static    int    players;
  36.  
  37. struct hostent    *hostaddr[HMAX];
  38. int        active[HMAX]={ 0,0,0,0,0,0,0,0 };
  39. int        auto_only[HMAX]={ 0,0,0,0,0,0,0,0 };
  40.  
  41. char        host_name[HMAX][20];
  42. char        disp_name[HMAX][20];
  43.  
  44. int        sockets[HMAX],ports[HMAX];
  45. long        play_time[HMAX];
  46. struct    sockaddr_in    rsin[HMAX];
  47. int            rsinlen[HMAX];
  48. int            socks[HMAX];
  49.  
  50.  
  51. char    *my_host;        /* eigener hostname */
  52.  
  53. struct    servent    *sp;
  54.  
  55. struct    sockaddr_in sin;
  56. int    mastersocket;
  57.  
  58. char    *getenv();
  59.  
  60. long    packet_count = 0;
  61. int    data_error=0;
  62. int    g_count=0;
  63. int    match;
  64.  
  65. Display    *display;
  66. Screen    *screen;
  67. char    dispname[20];
  68. extern    XFontStruct    *(finfo[]);
  69. extern    Window        aw;
  70. int    waiting;
  71. XEvent    event;
  72. #define    FID    0
  73.  
  74. usage()
  75. {
  76.     printf("\n\nusage:\ttron_server [ option ] <player_list>\n");
  77.     printf("\n\t-v      - prints some additional messages in starting sequence.\n");
  78.     printf("\t-h      - prints this.\n");
  79.     printf("\t-s<sec> - to sleep <sec> seconds after the start of each players.\n");
  80.     printf("\n<player_list>: List with the display_names and/or host_names of the players.\n");
  81.     printf("  If only one name per player is given, the display is the display of the host.\n");
  82.     printf("  Otherwise you can write <display_name>'^'<host_name> to get a special display.\n");
  83.     printf("  An empty display-name stands for an automatic player. (e.g. ^host)\n");
  84.     printf("\n");
  85. }
  86.  
  87. main(argc,argv)
  88.     int    argc;
  89.     char    *argv[];
  90. {    int    i,j;
  91.     char    command[200];
  92.     int    test;
  93.     int    waitflag=0;
  94.     char    *ptr;
  95.     char    *disp_arg=NULL;
  96. XSetWindowAttributes    attrib;
  97.  
  98. /*********************************************************************
  99.  * At first, the host-names of the command-line are tested.         *
  100.  * If there is a display for the player (no auto-player), the server *
  101.  * tests the possibility of opening XWindows on the display. If that *
  102.  * fails or a display is used twice, the player is ignored.         *
  103.  * ==> In the end, there should be at least 2 correct names.         *
  104.  *********************************************************************/
  105.  
  106.     max=0;
  107.     messflag=0;
  108.     printf("\nTRON - programmed by Helmut Hoenig. (MAY-1988)\n");
  109.     printf("startup-sequence at the following displays:\n");
  110.  
  111.     if (argc==1)
  112.     {    usage();
  113.         exit();
  114.     };
  115.  
  116.     for (i=1;i<argc;i++)
  117.     {   if (strcmp("-v",argv[i])==0)        messflag=1;
  118.         else if (strncmp("-s",argv[i],2)==0)    waitflag=atoi(&argv[i][2]);
  119.         else if ((strcmp("-",argv[i])==0)||(strcmp("-h",argv[i])==0))
  120.         {        usage();
  121.                 exit();
  122.         }
  123.         else if (strcmp("-display",argv[i])==0)    disp_arg = argv[++i];
  124.         else if (max<HMAX)
  125.         {    ptr = index(argv[i],'^');
  126.         if (ptr==NULL)
  127.         {    if ((ptr=index(argv[i],':'))==NULL)
  128.             {
  129.     /* a single host-name is extended by ":0.0" to the display-name */
  130.             strcpy(host_name[max],argv[i]);
  131.                 strcpy(disp_name[max],argv[i]);
  132.                 strcat(disp_name[max],":0.0");
  133.             }
  134.             else
  135.             {
  136.     /* in display-names the host-names are the string up to the ':' */
  137.                 strncpy(host_name[max],argv[i],ptr-argv[i]);
  138.                 host_name[max][ptr-argv[i]+1]='\0';
  139.                 strcpy(disp_name[max],argv[i]);
  140.                 if ((ptr=index(argv[i],'.'))==NULL)
  141.                 {    strcat(disp_name[max],".0");
  142.                 }
  143.             }
  144.         }
  145.         else
  146.         {
  147.     /* if host- and display is given the display-name, the display-name
  148.        might be extended to a '*:*.0'-form. */
  149.             strcpy(host_name[max],ptr+1);
  150.             if (ptr==argv[i])
  151.             {
  152.         /* A missing display-name indicates an auto-player. */
  153.                 strcpy(disp_name[max],host_name[max]);
  154.                 strcat(disp_name[max],"-0");
  155.             }
  156.             else
  157.             {   *ptr ='\0';
  158.                 strcpy(disp_name[max],argv[i]);
  159.                 if ((ptr=index(argv[i],':'))==NULL)
  160.                 {    strcat(disp_name[max],":0.0");
  161.                 }
  162.                 else
  163.                 {    if ((ptr=index(argv[i],'.'))==NULL)
  164.                 {    strcat(disp_name[max],".0");
  165.                 }
  166.                 }
  167.             }
  168.         }
  169.  
  170.     /* after extending names: check, if the argument is a host-name. */
  171.         hostaddr[max]=gethostbyname(host_name[max]);
  172.         if (hostaddr[max]==NULL)
  173.         {    printf("*** %s is not a host.\n",host_name[max]);
  174.         }
  175.         else
  176.         {
  177.     /* check the display-name */
  178.         do
  179.         {    for (j=0;j<max;j++)
  180.             {    if (strcmp(disp_name[j],disp_name[max])==NULL)    break;
  181.             }
  182.  
  183.             if (j==max)
  184.             {   if (index(disp_name[max],'-')!=NULL)
  185.                 {
  186.         /* Name of Auto-Player is O.K. */
  187.                     printf("%2d: auto-player %s\n",max+1,disp_name[max]);
  188.                     auto_only[max++]=1;
  189.                 }
  190.                 else
  191.                 {
  192.                     if ((display=XOpenDisplay(disp_name[max]))==NULL)
  193.                 {    printf("XWindows ??? ");
  194.                 }
  195.                 else
  196.         /* Display is O.K. */
  197.                 {   XCloseDisplay(display);
  198.                 }
  199.                 if (strncmp(disp_name[max],host_name[max],strlen(host_name[max]))==NULL)
  200.                         printf("%2d: %s\n",max+1,disp_name[max]);
  201.                 else
  202.                         printf("%2d: %s (%s)\n",max+1,disp_name[max],host_name[max]);
  203.                 auto_only[max++]=0;
  204.                 }
  205.                 break;
  206.             }
  207.             else
  208.             {
  209.         /* disp_name[max] already used. is it for an auto-player ? */
  210.                 if (index(disp_name[max],'-')!=NULL)
  211.                 {    disp_name[max][strlen(disp_name[max])-1]++;
  212.                 }
  213.                 else
  214.                 {    printf("display %s used twice.\n",disp_name[max]);
  215.                     break;
  216.                 }
  217.             }
  218.         }
  219.         while(j<max);
  220.         };
  221.         }
  222.     }
  223.  
  224.     if (max<2)
  225.     {    fprintf(stderr,"*** But there should be at least 2 players. ***\n");
  226.         usage();
  227.         exit(0);
  228.     };
  229.  
  230. /***************************************************************
  231.  * After name-checking is done, a streamsocket is created      *
  232.  * where the player-programs can connect to. A socket_name is  *
  233.  * *NOT* nescessary as the server tells the clients his        *
  234.  * socket-number as a parameter.                   *
  235.  ***************************************************************/
  236.  
  237.     my_host=getenv("HOST");
  238.  
  239. /* Erzeugung eines Streamsockets in der Domain AF_INET */
  240.     mastersocket=streamsocket();
  241.  
  242. /* Information ueber den Service mit Namen "service" */
  243.     if ((sp=getservbyname(SOCKET_NAME,0))==0)
  244.     {    fprintf(stderr,"#%s: socket not found by name.\n",my_host);
  245.         init_addr(&sin,my_host,htons((short)22222));
  246.     }
  247.     else
  248. /* Initialisieren der Struktur sockaddr_in */
  249.     {    bzero(&sin,sizeof sin);
  250.         sin.sin_family=AF_INET;
  251.         sin.sin_port= sp->s_port;
  252.         sin.sin_addr.s_addr= INADDR_ANY;
  253.     };
  254.  
  255. /* Namensbindung an den Socket */
  256.     if (bind ( mastersocket,&sin,sizeof sin)<0)
  257.     {    fprintf(stderr,"### #%s: error in bind.\n",my_host);
  258.         do
  259.         {    sin.sin_port++;
  260.         }
  261.         while (bind (mastersocket,&sin,sizeof sin)<0);
  262.         fprintf(stderr,"### #%s: port %d selected as an alternative.\n",my_host,ntohs(sin.sin_port));
  263.     };
  264.     if (messflag)    printf("*** master-socket is %s@%d. ***\n",my_host,(int)ntohs(sin.sin_port));
  265.  
  266. /* Einrichten einer Warteschlange */
  267.     listen(mastersocket,max);
  268.  
  269. /******************************************************************
  270.  * The 'tron_run'-Program will now be started on each player-host.*
  271.  * A Bell-Signal is given on each display.              *
  272.  ******************************************************************/
  273.  
  274.     for (i=0;i<max;i++)
  275.     {    play_time[i]=0;
  276.         if (!auto_only[i])
  277.         {    if ((display=XOpenDisplay(disp_name[i]))!=NULL)
  278.             {    XBell(display,60);
  279.                 XCloseDisplay(display);
  280.             }
  281.         }
  282.  
  283. /***********************************************************************************
  284.  the following command is now prepared to be executed by system():
  285. '<foreign_host> <file_name> <my_host> <mastersocket> <count> <message_flag> &'
  286. with    <foreign_host>    - host for a player
  287.     <file_name>    - name of the 'tron_run'-binary-file on that host
  288.               the macro TRON_RUN_FILE from the top off that source-file is used.
  289.     <my_host>    - my host   (for the stream-connection)
  290.     <mastersocket>    - my socket (for the stream-connection)
  291.     <display>    - the display, usually <foreign_host>:0.0
  292.     <count>        - to get the players in an order
  293.     <messageflag>    - to produce additional messages by the players
  294. ***********************************************************************************/
  295.         sprintf(command,"%s '%s %s %d %s %d %d' &",
  296.             host_name[i],
  297.             TRON_RUN_FILE,
  298.             my_host,
  299.             (int)ntohs(sin.sin_port),
  300.             disp_name[i],
  301.             i,
  302.             messflag);
  303.  
  304.         if (messflag)    printf("#%s: starting up %s on %s.\n",my_host,disp_name[i],host_name[i]);
  305. #if (moremessages)
  306.         printf("%s\n",command);
  307. #endif
  308.         system(command);
  309.         if (waitflag)
  310.         {    printf("sleeping %d seconds.\n",waitflag);
  311.             fflush(stdout);
  312.             sleep(waitflag);
  313.         }
  314.     }
  315.  
  316.     printf("#%s: %d clients started.\n",my_host,max);
  317.  
  318. /********************************************************************************
  319.  * The server waits, until all players are started and connected to the server. *
  320.  * Each Player-Program returns a port-number, which it uses in the game.    *
  321.  ********************************************************************************/
  322.  
  323.     for (i=0;i<max;i++)
  324.     {    int    j,count,auto_player;
  325.  
  326.         rsinlen[i]=sizeof rsin[i];
  327.         socks[i]=accept(mastersocket,&rsin[i],&rsinlen[i]);
  328.         count=readint(socks[i]);    /*** that's the <count>-argument
  329.                              of the player's command-line. ***/
  330.         sockets[count]=socks[i];
  331.         ports[count]=(int)readshort(sockets[count]);
  332.         auto_player = readint(sockets[count]);
  333.         if (auto_player!=auto_only[count])
  334.         {    fprintf(stderr,"*** no XWindows on %s -> auto-player-mode only\n",disp_name[count]);
  335.             auto_only[count]=auto_player;
  336.         };
  337.         if (messflag)    printf("#%s: connection %s@%d established.\n",my_host,disp_name[count],ports[count]);
  338.     };
  339.     printf("#%s: all clients connected.\n",my_host);
  340.  
  341.     close(mastersocket);
  342.  
  343. /**********************************************************
  344.  * After all players are running, a window can be openend *
  345.  * to select who is really playing.              *
  346.  **********************************************************/
  347.  
  348.     if ((display=XOpenDisplay(disp_arg))==NULL)
  349.     {    fprintf(stderr,"*** %s: Can't open display.\n",my_host);
  350.         exit(0);
  351.     };
  352.     screen=XScreenOfDisplay(display,DefaultScreen(display));
  353.     init_texter();
  354.  
  355.     aw=XCreateSimpleWindow(display,RootWindowOfScreen(screen),
  356.             20,50,26 * CharWidth(FID),(max+3+7) * CharHeight(FID),
  357.             4,XBlackPixelOfScreen(screen),XWhitePixelOfScreen(screen));
  358.     attrib.override_redirect = 1;
  359.     XChangeWindowAttributes(display,aw,CWOverrideRedirect,&attrib);
  360.     XSelectInput(display,aw,ExposureMask | ButtonPressMask);
  361.  
  362. /*************************************************************************
  363.  * The next loop is executed, until QUIT is selected in the main menu.   *
  364.  * You have to wait until a match is ended to get back to the main menu. *
  365.  *************************************************************************/
  366.     for(;;)
  367.     {    long    tp1,tp2;
  368.  
  369.         if (data_error)
  370.             prepare_message();
  371.         else
  372.             prepare_scores();
  373.         send_scores();
  374.  
  375.         if (match)
  376.         {    int    root_x,root_y,x,y;
  377.             Window    root,child;
  378.             int    mask;
  379.  
  380.             sleep(2);
  381.     /***********************************************************
  382.      * you CAN STOP a match by holding down the left AND right *
  383.      * button on your mouse, befor the next game starts.       *
  384.      ***********************************************************/
  385.  
  386.             XQueryPointer(display,ROOT,&root,&child,&root_x,&root_y,&x,&y,&mask);
  387.             if ((mask & Button3Mask) && (mask & Button1Mask))
  388.             {    match=0;
  389.                 sprintf(tscreen[0],"Match ended.");
  390.                 send_scores();
  391.             };    
  392.         };
  393.  
  394.         if (!match)
  395.         {
  396.             XMapRaised(display,aw);
  397.             waiting=1;
  398.             do
  399.             {
  400.                 XWindowEvent(display,aw,ExposureMask | ButtonPressMask,&event);
  401.                 aw_event(event.type);
  402.             }
  403.             while(waiting);
  404.             XUnmapWindow(display,aw);
  405.         };
  406.         tp1=time((long)0);
  407.         send_game_start();
  408.         wait_players_ready();
  409.         wait_game_over();
  410.         tp2=time((long)0);
  411.  
  412.         for(i=0;i<max;i++)
  413.             if (active[i]==1)    play_time[i]+=(tp2 - tp1);
  414.     };
  415. }
  416.  
  417. int check_points(a,b)
  418.     int    *a,*b;
  419. {
  420.     if (points[*a]<points[*b])    return(1);
  421.     if (points[*a]>points[*b])    return(-1);
  422.     return(0);
  423. }
  424.  
  425. /************************************************
  426.  * preparation of a text-field with the        *
  427.  * sorted list of players with their scores.    *
  428.  ************************************************/
  429. prepare_scores()
  430. {    int    i;
  431.  
  432. /* Spieler nach Punkten sortieren */
  433.     players=0;
  434.     for (i=0;i<max;i++)
  435.         if (active[i])        sorted[players++]=i;
  436.  
  437.     qsort(sorted,players,sizeof(int),check_points);
  438.  
  439. /* pruefen, ob Spielende erreicht */
  440.     if (match)
  441.     {    int    mp=5*players;
  442.         
  443.         if ((points[sorted[0]]>=mp) && (points[sorted[0]]>points[sorted[1]]+1))
  444.         {    match=0;
  445.             sprintf(tscreen[0],"-- Final Result --");
  446.         }
  447.         else
  448.             sprintf(tscreen[0],"Points:       (%d)",mp);
  449.     }
  450.     else
  451.     {
  452.         sprintf(tscreen[0],"Points:");
  453.     };
  454.  
  455.     sprintf(tscreen[1],"");
  456.  
  457.     lines=2;
  458.     for (i=0;i<players;i++)
  459.         sprintf(tscreen[lines++],"%-13s%2d%3d",disp_name[sorted[i]],place[sorted[i]],points[sorted[i]]);
  460. }
  461.  
  462. show_keys()
  463. {
  464.     sprintf(tscreen[0],"****  TRON  - by Helmut Hoenig ****");
  465.     sprintf(tscreen[1],"");
  466.     sprintf(tscreen[2],"             Keyboard         Mouse");
  467.     sprintf(tscreen[3],"");
  468.     sprintf(tscreen[4],"left turn:   'z' 'x' 'm' ','  left");
  469.     sprintf(tscreen[5],"right turn:  'c' 'v' '.' '/'  right");
  470.     sprintf(tscreen[6],"jump:        SPACE            middle");
  471.     sprintf(tscreen[7],"speed:       SHIFT");
  472.     sprintf(tscreen[8],"booster:     SHIFT & CTRL");
  473.     sprintf(tscreen[9],"");
  474.     sprintf(tscreen[10]," >> no turns while booster's on. <<");
  475.     lines=11;
  476.     send_scores();
  477. };
  478.     
  479. prepare_message()
  480. {
  481.     sprintf(tscreen[0],"- Timeout -");
  482.     lines=1;
  483. }
  484.  
  485. /*********************************************
  486.  * sends the textfield to all active players *
  487.  *********************************************/
  488. send_scores()
  489. {    int    i,l;
  490.  
  491.     for (i=0;i<max;i++)
  492.         if (active[i] & 1)
  493.         {    writeint(sockets[i],SCORE);
  494.             writeint(sockets[i],lines);
  495.                 for (l=0;l<lines;l++)
  496.             {        writestring(sockets[i],tscreen[l]);
  497.             };
  498.         };
  499. }
  500.  
  501. /**************************************************************
  502.  * sends the game_start-message to all players.              *
  503.  * containing the port-number and host of the next player and *
  504.  * a flag, if the player should create the first datagram.    *
  505.  **************************************************************/        
  506. send_game_start()
  507. {    int    i,ind=0,starter=0;
  508.     
  509.     int    perm[MAXPLAYERS];
  510.  
  511.     g_count++;
  512.  
  513.     for (i=0;i<max;i++)
  514.         if (active[i])    perm[ind++]=i;
  515.  
  516.     for (i=0;i<ind;i++)
  517.     {    writeint(sockets[perm[i]],GAMESTART);
  518.         writeint(sockets[perm[i]],players);
  519.         writeint(sockets[perm[i]],active[perm[i]]);
  520.         writeint(sockets[perm[i]],g_count);
  521.         if (i == 0)
  522.             writeint(sockets[perm[i]],1);
  523.         else
  524.             writeint(sockets[perm[i]],0);
  525.  
  526.         writestring(sockets[perm[i]],host_name[perm[((i+1) % ind)]]);
  527.         writeshort(sockets[perm[i]],ports[perm[((i+1) % ind)]]);
  528.     };
  529. }
  530.  
  531. send_exit()
  532. {    int    i;
  533.  
  534.     for (i=0;i<max;i++)
  535.         writeint(sockets[i],EXIT);
  536. }
  537.  
  538. /***********************************************
  539.  * waits, until all players are ready to start *
  540.  ***********************************************/
  541. wait_players_ready()
  542. {
  543. int    readfds,writefds,execptfds;
  544. struct    timeval    timeout;
  545.  
  546. int    ready_count=0,i,nfound;
  547.  
  548.     do
  549.     {    readfds=0;
  550.     writefds=0;
  551.     execptfds=0;
  552. /*    timeout.tv_sec=0;
  553.     timeout.tv_usec=0;
  554. */
  555.     for (i=0;i<max;i++)
  556.         if (active[i])    readfds |= (1<<sockets[i]);
  557.  
  558.     nfound=select(32,&readfds,&writefds,&execptfds,0);
  559.     if (nfound<0)
  560.     {    fprintf(stderr,"#%s: error occured in select.\n",my_host);
  561.         exit(0);
  562.     };
  563.     for (i=0;i<max;i++)
  564.         if (readfds & (1<<sockets[i]))
  565.         {    int    v;
  566.             if ((v=readint(sockets[i]))!=PLAYER_READY)
  567.             {    fprintf(stderr,"#%s: illegal message (%d) received from %s.\n",my_host,v,disp_name[i]);
  568.             send_exit();
  569.                 exit(0);
  570.             };
  571.             ready_count++;
  572.         };
  573.     }
  574.     while(ready_count<players);
  575. }
  576.  
  577. int check_count(a,b)
  578.     int    *a,*b;
  579. {
  580.     if (count[*a]<count[*b])    return(1);
  581.     if (count[*a]>count[*b])    return(-1);
  582.     return(0);
  583. }
  584.  
  585. /***************************************************
  586.  * waits, until the game is over.           *
  587.  * the server receives a counter from each player, *
  588.  * which says, when it was destroyed.           *
  589.  ***************************************************/
  590. wait_game_over()
  591. {
  592. int    readfds,writefds,execptfds;
  593. struct    timeval    timeout;
  594.  
  595. int    ready_count=0,i,nfound;
  596.  
  597.     data_error=0;
  598.     while(ready_count<players)
  599.     {    readfds=0;
  600.     writefds=0;
  601.     execptfds=0;
  602. /*    timeout.tv_sec=0;
  603.     timeout.tv_usec=0;
  604. */
  605.     for (i=0;i<max;i++)
  606.         if (active[i])        readfds |= (1<<sockets[i]);
  607.  
  608.     nfound=select(32,&readfds,&writefds,&execptfds,0);
  609.     if (nfound<0)
  610.     {    fprintf(stderr,"#%s: error occured in select.\n",my_host);
  611.         exit(0);
  612.     };
  613.     for (i=0;i<max;i++)
  614.         if (readfds & (1<<sockets[i]))
  615.         {    int    v;
  616.             if ((v=readint(sockets[i]))!=DESTROYED)
  617.         {    data_error=1;
  618.             printf("#%s: error-message by %s.\n",my_host,disp_name[i]);
  619.             fflush(stdout);
  620.         }
  621.             else
  622.             {
  623. /*            printf("#%s: %s destroyed.\n",my_host,disp_name[i]); */
  624.                 count[i]=readint(sockets[i]);
  625.             };
  626.             ready_count++;
  627.         };
  628.     };
  629.  
  630. /*  printf("#%s: all players destroyed.\n",my_host); */
  631.  
  632. /* Punkte verteilen */
  633. if (!data_error)
  634. {   players=0;
  635.     for (i=0;i<max;i++)
  636.         if (active[i])    sorted[players++]=i;
  637.  
  638.     qsort(sorted,players,sizeof(int),check_count);
  639.  
  640.     for (i=0;i<players;i++)
  641.     {    points[sorted[i]] +=(place[sorted[i]] = players-i-1);
  642.  
  643.     };
  644.     packet_count += (long)count[sorted[0]];
  645. };
  646. }
  647.  
  648.  
  649. /*******************************************************
  650.  * XWindow-Functions for redrawing and event-executing *
  651.  *******************************************************/
  652. redraw_disps()
  653. {    int    i;
  654.  
  655.     XRaiseWindow(display,aw);
  656.     printat(1,1,"TRON",FID);
  657.     for (i=0;i<max;i++)
  658.     {    printat(1,i+3,disp_name[i],FID);
  659.         if (active[i]==2)
  660.             printcleared(20,i+3,"AUTO",FID);
  661.         else if (active[i]==1)
  662.             printcleared(20,i+3," YES",FID);
  663.         else
  664.             printcleared(20,i+3,"  NO",FID);
  665.     };
  666.     printat(1,3+max+1,"Start Match",FID);
  667.     printat(1,3+max+2,"Start Game",FID);
  668.     printat(1,3+max+3,"Show Keys",FID);
  669.     printat(1,3+max+4,"Clear Scores",FID);
  670.     printat(1,3+max+5,"Quit",FID);
  671.     XFlush(display);
  672. }
  673.  
  674. aw_event(type)
  675.     unsigned    type;
  676. {    int        i,y;
  677.  
  678.     switch(type)
  679.     {
  680.     case Expose:
  681.         redraw_disps();
  682.         break;
  683.     case ButtonPress:
  684.         y=((event.xbutton.y)/CharHeight(FID))-3;
  685.         if (y<0)    break;
  686.  
  687.         if (y<max)
  688.         {
  689.             active[y]=(active[y]+1)%3;    /* switching:    NO->YES->AUTO->NO */
  690.             if (auto_only[y])
  691.             {    if (active[y]==1)    active[y]++;
  692.             }
  693.             if (active[y] & 2)    writeint(sockets[y],UNMAP);
  694.         }
  695.         else
  696.         {    y-=max+1;
  697.             if (y<2)            /* START GAME OR MATCH */
  698.             {    int    i1,i2,j;
  699.  
  700.                 i1=i2=0;
  701.                 for (j=0;j<max;j++)
  702.                 {    if (active[j])
  703.                     {    i1++;
  704.                         if (active[j]==1)    i2++;
  705.                     }
  706.                 }
  707.                 if ((i1>1)&&(i2>0))
  708.                 {    waiting=0;
  709.                     match=(y==0);
  710.                 }
  711.                 else
  712.                 {    XBell(display,50);
  713.                     XFlush(display);
  714.                 }
  715.             };
  716.             if (y==2)            /* SHOW KEYS */
  717.             {    int    t;
  718.                 for (t=0;t<max;t++)
  719.                     if (active[t]==1)    break;
  720.                 if (t==max)
  721.                     XBell(display,10);
  722.                 else
  723.                     show_keys();
  724.                 return;
  725.             };
  726.  
  727.             if ((y==3) || (match))        /* CLEAR SCORES */
  728.                 for (i=0;i<max;i++)
  729.                 {    sorted[i]=i;
  730.                     points[i]=0;
  731.                     place[i]=0;
  732.                 };
  733.             if (y==4)            /* QUIT */
  734.             {    send_exit();
  735.  
  736.                 printf("#%s: program ends.\n",my_host);
  737.                 printf("#total number of datagrams: %ld\n",packet_count);
  738.                 fflush(stdout);
  739.                 exit(0);
  740.             };
  741.         };
  742.         if (waiting)
  743.         {    redraw_disps();
  744.             prepare_scores();
  745.             send_scores();
  746.         };
  747.     };
  748. }
  749.