#include <stdio.h>
#include <time.h>
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/Xos.h>
#include <X11/Xresource.h>
/*** Sockets include *****/
#include <errno.h>      /* obligatory includes */
#include <signal.h> 
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h> 
#include <sys/socket.h>
#include <sys/time.h> 
#include <sys/wait.h> 
#include <netinet/in.h>
#include <netdb.h>



#define X_MAX    31        /* wert+1 = maximale anzahl steine in x            */ 
#define Y_MAX    17        /* dto. nur fuer y                                 */
#define BOMB_MAX 80        /* wieviele Steine maximal auf dem Spielfeld sind */

#define LEER      0            
#define SHOW      18
#define LOCK      20
#define HIDE      17
#define NIX       21
#define BOMB      19
#define EXBOMB    22

#define max_msg   4 
#define SWIDTH    20
#define SHEIGHT   20
#define bigx      20
#define bigy      20
#define BWIDTH    14
#define XOFFSET   10
#define YOFFSET   60
#define BHEIGHT   14

struct verbindungen {                                        /* struktur der verbindungsliste     */
                          int    kanal_nummer;                 /* Kanal-nummer                      */
                          struct verbindungen *nextptr;          /* zeiger auf naechstes element      */
                           char Was;                    /* ='W' write to server    ='R' read to server */
                       };

short int Feld_Intern[X_MAX+X_MAX*Y_MAX+10];
short int Feld_Visible[X_MAX+X_MAX*Y_MAX+10];
short int Feld_Backup[X_MAX+X_MAX*Y_MAX+10];

struct AnfragePaket
 {
     short int Feld_Visible[X_MAX+X_MAX*Y_MAX+10];
     short int Feld_Intern[X_MAX+X_MAX*Y_MAX+10];
     char UserName[100];
     char Was;                    /* ='W' write to server    ='R' read to server */
 };

int t,i,z,u,v,w,x,y,xx,yy,weiter_msg;
int spiel_laeuft,err;
Display *display;
Window  window;
struct verbindungen *next;
char fontname[80] = "8x13bold";
char *Display_name = NULL; 
unsigned long bg; 
int sock_server,sock_client,screen;
int s1,s2,max,HighScore;
Window  hswindow = 0;
XEvent event;
XSizeHints hint;
GC gc,hsgc;
GC highlightgc;
XFontStruct *xfontinfo;
int height;
int highest_kanal_number ;
int width;
int Server,Client;
char msg[max_msg+5][120];
char ServerName[200],User[200],Port[200],text[100],winner[100];
KeySym  key;
Colormap cmap;
XColor exact_def;
unsigned long foreground, background,patbg,patfg,b1,b2,b3,b4,b5,b6,b7,b8,gray,white,black;
int depth;
Pixmap graypix;
Pixmap minepix;
Pixmap minepix_a;   
Pixmap coveredpix;
Pixmap smileypix;
Pixmap copyrightpix;
Pixmap netpix;
Pixmap newpix;
Pixmap lockpix;

char lock_bits[] = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0xe0, 0x3f, 0x00,
  0xe0, 0x3f, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x00,
  0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00,
  0x00, 0x02, 0x00, 0x00, 0x07, 0x00, 0xc0, 0x1f, 0x00, 0xe0, 0x3f, 0x00,
  0xe0, 0x3f, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };


char new_bits[] = {
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f,
  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xcf, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xcf, 0x0f, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x0f,
  0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x0f, 0xcf, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xcf, 0x0f, 0xcf, 0x03, 0x00, 0x00, 0x00, 0x80, 0xcf, 0x0f,
  0xcf, 0x03, 0x00, 0x00, 0x00, 0x80, 0xcf, 0x0f, 0xcf, 0x03, 0x00, 0x00,
  0x00, 0x80, 0xcf, 0x0f, 0xcf, 0x03, 0x00, 0x00, 0x00, 0x80, 0xcf, 0x0f,
  0xcf, 0xc3, 0xf0, 0xbf, 0x3b, 0x87, 0xcf, 0x0f, 0xcf, 0x83, 0x21, 0x21,
  0x11, 0x82, 0xcf, 0x0f, 0xcf, 0x83, 0x21, 0x01, 0x33, 0x82, 0xcf, 0x0f,
  0xcf, 0x83, 0x22, 0x11, 0x22, 0x81, 0xcf, 0x0f, 0xcf, 0x83, 0x24, 0x1f,
  0x76, 0x81, 0xcf, 0x0f, 0xcf, 0x83, 0x24, 0x11, 0x54, 0x81, 0xcf, 0x0f,
  0xcf, 0x83, 0x28, 0x01, 0xcc, 0x80, 0xcf, 0x0f, 0xcf, 0x83, 0x30, 0x21,
  0x88, 0x80, 0xcf, 0x0f, 0xcf, 0xc3, 0xa1, 0x3f, 0x88, 0x80, 0xcf, 0x0f,
  0xcf, 0x03, 0x00, 0x00, 0x00, 0x80, 0xcf, 0x0f, 0xcf, 0x03, 0x00, 0x00,
  0x00, 0x80, 0xcf, 0x0f, 0xcf, 0x03, 0x00, 0x00, 0x00, 0x80, 0xcf, 0x0f,
  0xcf, 0x03, 0x00, 0x00, 0x00, 0x80, 0xcf, 0x0f, 0xcf, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xcf, 0x0f, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x0f,
  0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x0f, 0xcf, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xcf, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f,
  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, };

static unsigned char net_bits[] = {
 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x01, 0x22, 0x22, 0x22, 0x22,
  0x22, 0x22, 0x22, 0x02, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x04,
  0x88, 0x88, 0x88, 0x08, 0x88, 0x88, 0x88, 0x08, 0x44, 0x44, 0x44, 0x44,
  0x44, 0x44, 0x44, 0x04, 0x22, 0x22, 0x22, 0x22, 0x02, 0x22, 0x22, 0x02,
  0x11, 0x11, 0x01, 0x11, 0x11, 0x10, 0x11, 0x01, 0x22, 0x02, 0x22, 0x22,
  0x22, 0x02, 0x22, 0x02, 0x44, 0x04, 0x40, 0x40, 0x40, 0x44, 0x44, 0x04,
  0x80, 0x00, 0x80, 0x00, 0x08, 0x80, 0x88, 0x08, 0x44, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x44, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x02,
  0x11, 0x01, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x22, 0x02, 0x1e, 0xe7,
  0xf7, 0x07, 0x22, 0x02, 0x44, 0x00, 0x33, 0x42, 0x92, 0x04, 0x44, 0x04,
  0x88, 0x00, 0x21, 0x42, 0x82, 0x00, 0x88, 0x08, 0x44, 0x80, 0x40, 0x42,
  0x82, 0x00, 0x44, 0x04, 0x22, 0x80, 0x40, 0x42, 0x82, 0x00, 0x22, 0x02,
  0x11, 0x80, 0x40, 0x42, 0x82, 0x00, 0x11, 0x01, 0x00, 0x02, 0x21, 0x42,
  0x82, 0x00, 0x20, 0x02, 0x44, 0x00, 0x33, 0x66, 0x82, 0x00, 0x44, 0x04,
  0x88, 0x00, 0x1e, 0x3c, 0xc7, 0x01, 0x88, 0x08, 0x44, 0x04, 0x18, 0x00,
  0x00, 0x00, 0x44, 0x04, 0x22, 0x00, 0x60, 0x00, 0x00, 0x00, 0x22, 0x02,
  0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x22, 0x02, 0x00, 0x00,
  0x00, 0x20, 0x02, 0x02, 0x44, 0x04, 0x00, 0x00, 0x00, 0x40, 0x44, 0x04,
  0x88, 0x00, 0x00, 0x00, 0x00, 0x80, 0x88, 0x08, 0x44, 0x44, 0x00, 0x40,
  0x00, 0x40, 0x44, 0x04, 0x22, 0x22, 0x20, 0x20, 0x22, 0x22, 0x22, 0x02,
  0x11, 0x01, 0x01, 0x11, 0x11, 0x10, 0x11, 0x01, 0x22, 0x22, 0x22, 0x22,
  0x22, 0x22, 0x22, 0x02, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x04,
  0x88, 0x08, 0x88, 0x88, 0x80, 0x88, 0x88, 0x08, 0x44, 0x44, 0x44, 0x44,
  0x44, 0x44, 0x44, 0x04, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x02,
  0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x01, 0x22, 0x22, 0x22, 0x22,
  0x22, 0x22, 0x22, 0x02, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x00,
  0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x08, };


char copyright_bits[] = {
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x10, 0x10, 0x10, 0x10,
  0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,
  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0xff, 0xff, 0x7f, 0xfb,
  0xf8, 0xff, 0xff, 0x0f, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
  0x01, 0x01, 0x01, 0x01, 0xff, 0xff, 0x7e, 0x62, 0x40, 0xff, 0xff, 0x0f,
  0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00,
  0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00,
  0xff, 0xff, 0x1a, 0x01, 0x00, 0xfa, 0xff, 0x0f, 0x01, 0x01, 0x01, 0xe0,
  0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0xb0, 0x03, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x00, 0x18, 0x02, 0x00, 0x01, 0x01, 0xff, 0xff, 0x03, 0x08,
  0x00, 0xf8, 0xff, 0x0f, 0x10, 0x10, 0x00, 0x08, 0x00, 0x10, 0x10, 0x00,
  0x10, 0x10, 0x10, 0x08, 0x02, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x18,
  0x02, 0x10, 0x10, 0x00, 0xff, 0xff, 0x05, 0x30, 0x03, 0xff, 0xff, 0x0f,
  0x01, 0x01, 0x01, 0xe0, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
  0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01,
  0xff, 0xff, 0x35, 0x01, 0x00, 0xf9, 0xff, 0x0f, 0x10, 0x10, 0x10, 0x00,
  0x00, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00,
  0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0x0f, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10,
  0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, };

char covered_bits[] = {
   0x00, 0x00, 0x08, 0x00, 0x00, 0x0c, 0x54, 0x55, 0x0d, 0xa8, 0xaa, 0x0e,
   0x54, 0x55, 0x0d, 0xa8, 0xaa, 0x0e, 0x54, 0x55, 0x0d, 0xa8, 0xaa, 0x0e,
   0x54, 0x55, 0x0d, 0xa8, 0xaa, 0x0e, 0x54, 0x55, 0x0d, 0xa8, 0xaa, 0x0e,
   0x54, 0x55, 0x0d, 0xa8, 0xaa, 0x0e, 0x54, 0x55, 0x0d, 0xa8, 0xaa, 0x0e,
   0x54, 0x55, 0x0d, 0xa8, 0xaa, 0x0e, 0xfe, 0xff, 0x0f, 0xff, 0xff, 0x0f};

char gray_bits[] = {
   0x55, 0x55, 0x05, 0xaa, 0xaa, 0x0a, 0x55, 0x55, 0x05, 0xaa, 0xaa, 0x0a,
   0x55, 0x55, 0x05, 0xaa, 0xaa, 0x0a, 0x55, 0x55, 0x05, 0xaa, 0xaa, 0x0a,
   0x55, 0x55, 0x05, 0xaa, 0xaa, 0x0a, 0x55, 0x55, 0x05, 0xaa, 0xaa, 0x0a,
   0x55, 0x55, 0x05, 0xaa, 0xaa, 0x0a, 0x55, 0x55, 0x05, 0xaa, 0xaa, 0x0a,
   0x55, 0x55, 0x05, 0xaa, 0xaa, 0x0a, 0x55, 0x55, 0x05, 0xaa, 0xaa, 0x0a};

char mine_bits[] = {
   0xff, 0xff, 0x0f, 0x01, 0x00, 0x08, 0x01, 0x02, 0x08, 0x01, 0x02, 0x08,
   0x91, 0x4f, 0x08, 0xe1, 0x3f, 0x08, 0xe1, 0x3f, 0x08, 0x71, 0x7e, 0x08,
   0x71, 0x7e, 0x08, 0xfd, 0xff, 0x09, 0xf1, 0x7f, 0x08, 0xf1, 0x7f, 0x08,
   0xe1, 0x3f, 0x08, 0xe1, 0x3f, 0x08, 0x91, 0x4f, 0x08, 0x01, 0x02, 0x08,
   0x01, 0x02, 0x08, 0x01, 0x00, 0x08, 0x01, 0x00, 0x08, 0xff, 0xff, 0x0f};

char smiley_bits[] = {
   0xff, 0xff, 0x0f, 0x01, 0x00, 0x0c, 0x81, 0x0f, 0x0c, 0x61, 0x30, 0x0c,
   0x11, 0x40, 0x0c, 0x09, 0x80, 0x0c, 0x09, 0x80, 0x0c, 0x45, 0x10, 0x0d,
   0x05, 0x00, 0x0d, 0x05, 0x00, 0x0d, 0x05, 0x00, 0x0d, 0x25, 0x20, 0x0d,
   0xc9, 0x98, 0x0c, 0x09, 0x87, 0x0c, 0x11, 0x40, 0x0c, 0x61, 0x30, 0x0c,
   0x81, 0x0f, 0x0c, 0x01, 0x00, 0x0c, 0xff, 0xff, 0x0f, 0xff, 0xff, 0x0f};

void draw_screen();
void male_gitter();
void draw_item();
unsigned long getcolor();

/***********************************/

int reads(socket,ptr,size)
int socket;
char *ptr;
int size;
{ int s,t,r;
  r=0; t=0; s=0;
 for (;1==1;)
 {
  t++;
  if (t>(size+3)) return(r);
  s=read(socket,ptr,size-r); 
  ptr=ptr+s;
  r=r+s;
  if (r==-1) { return(0); }
  if (r==size) return(size);
 }
}


 int call_socket(hostname, portnum)

  char *hostname;
  long portnum;
  { struct sockaddr_in sa;
    struct hostent     *hp;
    int a, s;

    if ((hp= gethostbyname(hostname)) == NULL) { /* do we know the host's */
      errno= ECONNREFUSED;                       /* address? */
      return(-1);                                /* no */
    }

    bzero(&sa,sizeof(sa));
    bcopy(hp->h_addr,(char *)&sa.sin_addr,hp->h_length); /* set address */
    sa.sin_family= hp->h_addrtype;
    sa.sin_port= htons((u_short)portnum);
    if ((s= socket(hp->h_addrtype,SOCK_STREAM,0)) < 0)   /* get socket */
      return(-1);
    if (connect(s,(struct sockaddr *)&sa,sizeof sa) < 0)                    /* connect */
      return(-1);
    return(s);
  }

int establish(portnum)                                         /* funktion stellt einen socket zur */
  u_short portnum;                                             /* zur verfuegung                   */

 {  char   myname[100];                                        /* diverse variablen                */
    int    s;
    struct sockaddr_in sa;
    struct hostent *hp;

    bzero(&sa,sizeof(struct sockaddr_in));                     /* strukutr saubermachen           */
    gethostname(myname,99);                                    /* unserer eigener hostname        */
    hp= gethostbyname(myname);                                 /* ... infos ueber uns bekommen    */
    if (hp == NULL)                                            /* gib es uns wirklich ?           */
       {perror("Keine Hostadresse gefunden"); exit(-1); };     /* nein, scream and die ....       */
    sa.sin_family= hp->h_addrtype;                             /* unsere host addresse            */
    sa.sin_port= htons(portnum);                               /* unsere port nummer              */
    if ((s= socket(AF_INET,SOCK_STREAM,0)) < 0)                /* und einen socket machen         */
       {perror("Socket not installed"); exit(-1);};      /* kein socket => scream and die   */
    if (bind(s,(struct sockaddr *) &sa,sizeof sa) < 0)         /* adresse dem socket mitteilen    */
     { printf("\n XNetBomb-Server is already running !\n"); exit(-1);};   /* binde addresse zum socket       */
    listen(s, 5 );                                             /* warteschlagne = 5 plaetze       */
    return(s);                                                 /* und unseren socket zurueckgeben */
 }


alte_verbindung_loeschen(verbindung_next) /* loescht einen Kanal aus der Verbindungs-liste */
struct verbindungen *verbindung_next;
{

verbindung_next->Was=9;
return;
fflush(stdout);
  if (verbindung_next==next)                                   /* sind wir erstes element ?       */
     {                                                         /* ja,wir sind erstes element      */
       next=verbindung_next->nextptr;
       free(verbindung_next);
     }
   else                                                        /* nein, wir sind nicht erstes element */
     { struct verbindungen *Ptr;
       for (Ptr=next;Ptr!=NULL;) 
       { if (Ptr->nextptr==verbindung_next)
         {
           Ptr->nextptr=verbindung_next->nextptr;
           free(verbindung_next);
          return;
         }
           Ptr=Ptr->nextptr;
       }
     }
}



void Sende_to_Client()
{          long res,max,t,err,size;
           struct verbindungen *verbindung_next;
           struct timeval timeout;
           fd_set writefds;
           struct AnfragePaket Anfrage;
           Anfrage.Was=0;
           strcpy( Anfrage.UserName,"SERVER");
           max=X_MAX*Y_MAX+6; 
           timeout.tv_sec=0;
           timeout.tv_usec=900;
           for (t=0;t<=max;t++)
           {
             Anfrage.Feld_Visible[t]=Feld_Visible[t];
             Anfrage.Feld_Intern[t]=Feld_Intern[t];
             if (Anfrage.Feld_Intern[t]==EXBOMB) Anfrage.Feld_Intern[t]=BOMB;
           }
           verbindung_next=next;                                            /* listenstart setzen                       */
           for (;(verbindung_next!=NULL)&&(next!=NULL);)                    /* und bis zum letzten element machen ...   */
            {
              if (verbindung_next->Was=='R')
              {
                size=sizeof(struct AnfragePaket);
                FD_ZERO(&writefds);
                FD_SET(verbindung_next->kanal_nummer,&writefds);
                err=0;
                res = select(verbindung_next->kanal_nummer+10,0,&writefds,0,&timeout);          
                if (res==1) { err=write(verbindung_next->kanal_nummer,&Anfrage,size); } 
                if (err!=size) {KillKanal(verbindung_next); }
                verbindung_next=verbindung_next->nextptr; 

              } else { verbindung_next=verbindung_next->nextptr; }
            }   
}

void neue_verbindung_einfuegen(wert,kanal_nummer)                  /* fuegt ein Kanal in die Verbindungsliste ein */
char wert;
int kanal_nummer;
{
  struct verbindungen *Ptr;
  Ptr=(struct verbindungen *)malloc(sizeof(struct verbindungen));
  if (Ptr==NULL) { printf("\n Error, no memory "); exit(-1); }
  Ptr->kanal_nummer=kanal_nummer;
   Ptr->nextptr=next;
  Ptr->Was=wert;

  next=Ptr;
}


KillKanal(Ptr)
 struct verbindungen *Ptr;
{ 
 close ((int) Ptr->kanal_nummer);
 
 alte_verbindung_loeschen(Ptr);
}

void Play_Server_Game()
{
  if (XPending(display))      
  {
   getXevent();    /* bearbeite event */
  }
}

void other_player_win(a)
int a;
{
if (a==0)
{ /* client zeigt an */
  spiel_laeuft=0;
  strcpy(text,"Another Player win the game. Serverplayer will restart the game now.");
  XSetForeground(display, gc, getcolor("gray",foreground));
  XFillRectangle(display,window,gc,4,385,625,400);
  strcpy(winner,text);
  XSetForeground(display, gc, getcolor("blue",foreground));
  XDrawString(display,window,gc,10,395 ,text,strlen(text));
} else
{ /* Server zeigt an */
  spiel_laeuft=0;
  strcpy(text,"Another Player win the game. Please RESTART NOW the game.");
  strcpy(winner,text);
  XSetForeground(display, gc, getcolor("gray",foreground));
  XFillRectangle(display,window,gc,4,385,625,400);
  XSetForeground(display, gc, getcolor("blue",foreground));
  XDrawString(display,window,gc,10,395 ,text,strlen(text));
  Feld_Visible[X_MAX*Y_MAX+3]=77;
  if (Server==1) Sende_to_Client();                     
}
}

int get_connection(s)                                       /* warte auf eine verbindungsversuch und verwalte die */
int s;                                                      /* restlichen Lese/schreibaufforderungen ....         */
 {
    struct verbindungen *verbindung_next;
    struct verbindungen *verbindung_neu;
    struct sockaddr_in isa;                                   /* addresse des sockets                               */
    char *buffer[10];
    int size,i,err,change;                                    /* i=groesse der adresse                              */
    int res,t,new_socket;                                     /* new_socket = socket of connection                  */
    fd_set readfds;
    fd_set writefds;
    int nfds,okk;
    struct timeval timeout;
    FD_ZERO(&readfds);
    change=1;
    i = sizeof(isa);                                                     /* socket addresse finden                            */
    getsockname(s,(struct sockaddr *) &isa,&i);                          /*                                                   */
    while (1==1)              /* endlos machen */
     {
      Play_Server_Game();
      timeout.tv_sec=0;
      timeout.tv_usec=500;
      FD_SET(s ,&readfds );
      res=select(highest_kanal_number+10,&readfds,0,0,&timeout);               /* warte auf connect bzw. 100usec                    */
      if ((FD_ISSET(s ,&readfds)) && (res>0))                                             /* war da ein connect ?                              */
       {                                                                  /* ok, hier haben wir einen neuen requester          */
        i = sizeof(isa);                                                     /* socket addresse finden                            */
        getsockname(s,(struct sockaddr *) &isa,&i);                      
        new_socket =accept(s ,(struct sockaddr *) &isa ,&i );           /* neuer socket in die liste aufnehmen               */
        if (new_socket>=highest_kanal_number) {highest_kanal_number=new_socket+10;};  /* gleiche obergrenze fuer fd-files an     */
        if (new_socket==-1) { exit(-1); }  
        if (new_socket != -1) 
         {  
          struct AnfragePaket Anfrage;
          size=sizeof(struct AnfragePaket);
          FD_ZERO(&readfds);
          FD_SET(new_socket ,&readfds );
          timeout.tv_sec=10;
          err=0;
          timeout.tv_usec=900;
          res = select(new_socket+3, &readfds, 0, 0, &timeout);
          if (res==1) { err=reads(new_socket,&Anfrage,size); }
          if (err==size) 
           {
            if (Anfrage.Was=='W') neue_verbindung_einfuegen('W',new_socket);
            if (Anfrage.Was=='R') neue_verbindung_einfuegen('R',new_socket);  
            Sende_to_Client();
           }
         }   
       } 
      verbindung_next=next;
      FD_ZERO(&readfds);                                                              
      timeout.tv_sec=0;                                                               
      timeout.tv_usec=500;                                                            
      okk=0; 
      while (verbindung_next!=NULL)                                                    
       {
        if (verbindung_next->Was=='W') { okk=1; FD_SET(verbindung_next->kanal_nummer,&readfds); }  
        verbindung_next=verbindung_next->nextptr;                                 
       }
      res=-1;
      if (okk==1) 
       {
         res = select(highest_kanal_number, &readfds, 0, 0, &timeout);
        }                 
      if (res)                                                                 
       {
       verbindung_next=next;                                        
        while ((verbindung_next!=NULL)&&(next!=NULL))                   
         {
          if (FD_ISSET(verbindung_next->kanal_nummer,&readfds))                  
           { 
            struct AnfragePaket Anfrage;
            size=sizeof(struct AnfragePaket);
            err=reads(verbindung_next->kanal_nummer,&Anfrage,size);
            if (err!=size) { KillKanal(verbindung_next); }
            if (err==size)
             {
               long max,t;
                max=X_MAX*Y_MAX; 
     
              if (Anfrage.Feld_Visible[max+3]==77)
                {
                 spiel_laeuft=0;
                 other_player_win(1);                        
                } 
       
              for (t=0;t<=max;t++)
                {
                 if ((Anfrage.Feld_Visible[t]==SHOW) && (Feld_Visible[t]==HIDE))
                  { 
                   Feld_Visible[t]=SHOW; 
                   change=1;
                  }
                } 
              
             } 
           } 
          if (verbindung_next!=NULL) verbindung_next=verbindung_next->nextptr;
         } 
       } 
       if (change==1) 
        { 
         Sende_to_Client();
         for (y=1;(y<Y_MAX);y++)
          {                    
           for (x=1;x<X_MAX;x++)   
            {
             if (Feld_Visible[x+y*X_MAX]!=Feld_Backup[x+y*X_MAX])
              {
               draw_item(x,y);
              }
            } 
          }                   
         male_gitter();  
        }  
       change=0;
     } 
} 



unsigned long getcolor(s,monocolor)
    char *s;
    unsigned long monocolor;
{
    if(depth != 1)
    {
        XParseColor(display,cmap,s,&exact_def);
        XAllocColor(display,cmap,&exact_def);
        return exact_def.pixel;
    }
    else
    {
        return monocolor;
    }
}

void spielfeld_init()
{

short int zufall_x,zufall_y; 
int x,y,xx,yy;
spiel_laeuft=1;
 
/* Init des Spielfeldes */

for (y=0;y<=Y_MAX;y++)
{
 for (x=0;x<=X_MAX;x++)
 {
  Feld_Intern [x+y*X_MAX]=0;
  Feld_Visible[x+y*X_MAX]=HIDE;
  Feld_Backup[x+y*X_MAX]=NIX;
 }
}
 
  Feld_Intern [Y_MAX*X_MAX+3]=0;
  Feld_Visible[Y_MAX*X_MAX+3]=HIDE;
  Feld_Backup [Y_MAX*X_MAX+3]=NIX;
  Feld_Intern [Y_MAX*X_MAX+4]=0;
  Feld_Visible[Y_MAX*X_MAX+4]=HIDE;
  Feld_Backup [Y_MAX*X_MAX+4]=NIX;

for  (y=0;y<=Y_MAX;y++)
{
 Feld_Visible[y*X_MAX]=SHOW;
 Feld_Visible[y*X_MAX+X_MAX]=SHOW;
}
for  (x=0;x<=X_MAX;x++)
{ 
 Feld_Visible[x]=SHOW;
 Feld_Visible[Y_MAX*X_MAX+x]=SHOW;
}


/* Verteilung der Bomben */
srand(time(NULL));           /* init der Random-zahlen */

for (t=1;t!=BOMB_MAX;t++)
{
 zufall_x=1+(rand() % (X_MAX-1));
 zufall_y=1+(rand() % (Y_MAX-1));
 Feld_Intern[zufall_x+zufall_y*X_MAX]=BOMB;  
}


/* Durchzaehlung , wo die Bomben liegen */

for (y=1;y<Y_MAX;y++)    
{                         
 for (x=1;x<=X_MAX;x++)   
 {                        
  if (BOMB!=Feld_Intern[x+y*X_MAX])
  {
   t=0;
   if (BOMB==Feld_Intern[x-1+(y-1)*X_MAX]) t++;      /* element oben links   */
   if (BOMB==Feld_Intern[x-1+(y  )*X_MAX]) t++;      /* element links        */
   if (BOMB==Feld_Intern[x-1+(y+1)*X_MAX]) t++;      /* element unten links  */
   if (BOMB==Feld_Intern[x+1+(y-1)*X_MAX]) t++;      /* element oben rechts  */ 
   if (BOMB==Feld_Intern[x+1+(y  )*X_MAX]) t++;      /* element rechts       */
   if (BOMB==Feld_Intern[x+1+(y+1)*X_MAX]) t++;      /* element rechts unten */
   if (BOMB==Feld_Intern[x  +(y+1)*X_MAX]) t++;      /* element unten        */
   if (BOMB==Feld_Intern[x  +(y-1)*X_MAX]) t++;      /* element oben         */
   Feld_Intern[x+y*X_MAX]=t;  
  }                        
 }          
}

}

void E()
{
printf("\n Parameters are: -Server -Client -Name.... -PortNumber.... -ServerName.... -NoNet\n");
printf("\n (1) if you are the server :  -Server -PortNumber..... -Name..... ");
printf("\n (2) if you are the client :  -Client -PortNumber..... -ServerName..... -Name..... ");
printf("\n     Server-Programm MUST be running !");
printf("\n (3) for a single user game:  -NoNet -Name.... \n");
printf("\n .... stands for a string\n\n\n"); 
printf("\n(C) by Martin Bauer\nif you want to contact me write a email to:");
printf("\nInternet-Adress: Martin_Bauer@S2.MAUS.DE\n\n");
fflush(stdout); exit(-1);
}


void check_command(argc,argv)
int argc;
char *argv[];
{
Server=1;
Client=1;
strcpy(Port,"");
strcpy(ServerName,"");
strcpy(User,"");
if (argc>1)
{
 for (t=0;t<(argc-1);t++)
 {
  if (strcmp("-Server",argv[t+1])==0) 
  {
    Server=1;
    Client=0;
  }
   if (strcmp("-Client",argv[t+1])==0)
  {
   Server=0;
   Client=1;
  }
  if (strcmp("-NoNet",argv[t+1])==0)
  {
   Server=0;
   Client=0; 
  }
  if (strncmp("-PortNumber",argv[t+1],11)==0)
  { char text[500];
    strcpy(text,argv[t+1]);
    strcpy(Port,&text[11]);
  }
  if (strncmp("-Name",argv[t+1],5)==0)
  {
    char text[500];
    strcpy(text,argv[t+1]);
    strcpy(User,&text[5]);
}
  if (strncmp("-ServerName",argv[t+1],11)==0)
  {
    char text[500];
    strcpy(text,argv[t+1]);
    strcpy(ServerName,&text[11]);
  }
 }
} else { printf("\n ERROR - not enough paramters\n\n"); fflush(stdout); E(); }
if ((Client==1) && (Server==1)) { printf("\n ERROR   -Client or -Server flag is missing ! \n\n"); E(); }
if ((Client==0) && (Server==0)) { if (strcmp(User,"")==0) {printf("\n ERROR - UserName is missing ! \n\n"); E(); } }
printf("\n Server:%d  Client:%d  PortNum:%s \n",Server,Client,Port);
printf(" Name:\"%s\"  ServerName:\"%s\"\n",User,ServerName);fflush(stdout);
}

void CheckForClientEvent();

main(argc,argv)
int argc;
char *argv[];
{   char into[600];
    next=NULL;
    strcpy(winner,"it's not a sony, it's freeware  :=)");
    weiter_msg=0;  
    strcpy(msg[0],"May your children and mine live in peace");
    strcpy(msg[1],"This is not a fault, this is a feature !");
    strcpy(msg[2],"If you are female... write me ... soon !");
    strcpy(msg[3],"Dont hit any mines !");
    strcpy(msg[4],"Please write me if you enjoy this game");

 
   highest_kanal_number=20;

    check_command(argc,argv);
    spielfeld_init();
 
    if(!(display = XOpenDisplay(Display_name)))
    {
        printf("Error: can't open display\n");
        exit(1);
    }


    screen = DefaultScreen(display);
    depth  = DefaultDepth(display,screen) ; 
    cmap = DefaultColormap(display,screen); 
    background = WhitePixel(display,screen);
    foreground = BlackPixel(display,screen);
    bg = getcolor("gray",background); 

    hint.x = 0; hint.y = 0;
    hint.width = 622;
    hint.height = 400;
    hint.flags = PPosition | PSize;
    window = XCreateSimpleWindow (display,
                DefaultRootWindow(display),
                hint.x, hint.y, hint.width, hint.height,
                5, foreground, background);
    sprintf(into,"XNetMines  [%s]",User);  
    XSetStandardProperties(display, window,into, into,
        None, argv, argc, &hint);
  
    gc = XCreateGC(display, window, 0, 0);
    XSetBackground(display, gc, background);
    XSetForeground(display, gc, foreground);
    highlightgc = XCreateGC(display, window, 0, 0);

     XSelectInput(display, window,
        Button1MotionMask | Button2MotionMask | Button3MotionMask |
         ButtonPressMask | ButtonReleaseMask |
        KeyPressMask | ExposureMask);



    if((xfontinfo = XLoadQueryFont(display,fontname)) == NULL)
    {
        fprintf(stderr,"Can't find font '%s'\n",fontname);
        xfontinfo = XQueryFont(display,XGContextFromGC(gc));
    }
    XSetFont(display,gc,xfontinfo->fid);
 
    b1=getcolor("blue",foreground);
    b2=getcolor("green",foreground);
    b3=getcolor("red",foreground);
    b4=getcolor("orange",foreground);
    b5=getcolor("violett",foreground);
    b6=getcolor("cyan",foreground);
    b7=getcolor("white",foreground);
    b8=getcolor("magenta",foreground);
    black=getcolor("black",foreground);
    gray =getcolor("gray",foreground);
    white=getcolor("white",foreground);


    smileypix = XCreatePixmapFromBitmapData(display,window,
                     smiley_bits,SWIDTH,SHEIGHT,foreground,
                     background, depth);

    graypix = XCreatePixmapFromBitmapData(display,window,
                    gray_bits,SWIDTH,SHEIGHT,foreground,
                    background, depth);

    coveredpix = XCreatePixmapFromBitmapData(display,window,
                    covered_bits,SWIDTH,SHEIGHT,foreground,
                    background, depth);     

   lockpix = XCreatePixmapFromBitmapData(display,window,
                    lock_bits,SWIDTH,SHEIGHT,foreground,
                    background, depth);

  
    minepix = XCreatePixmapFromBitmapData(display,window,
                mine_bits,SWIDTH,SHEIGHT,foreground,
                background, depth);

   netpix = XCreatePixmapFromBitmapData(display,window,
                net_bits,60,40,b1,
                background, depth);

   copyrightpix = XCreatePixmapFromBitmapData(display,window,
                copyright_bits,60,40,b1,
                background, depth);

   newpix = XCreatePixmapFromBitmapData(display,window,
                new_bits,60,40,b1,
                background, depth);
    HighScore=0;
    if(depth == 1)    
    {
        XSetWindowBackgroundPixmap(display,window,graypix);
    }
     
    minepix_a = XCreatePixmapFromBitmapData(display,window,
                mine_bits,SWIDTH,SHEIGHT,foreground,
                b3, depth);


    XMapRaised(display, window);
    XFlush(display);
    draw_screen();

    if ((Server==0) && (Client==0)) { CheckforEvent(); }

if (Server==1)
{ long PortNumber;
 if (strcmp(Port,"")==0)       {printf("\n ERROR - PortNumber is missing ! \n\n"); E(); }
 if (strcmp(User,"")==0)       {printf("\n ERROR - UserName   is missing ! \n\n"); E(); }
 if (0==sscanf(Port,"%ld",&PortNumber)) { printf("\n ERROR - PortNumber is wrong ! \n\n"); E(); } 
 sock_server=establish(PortNumber);
 get_connection(sock_server);     /* und endlosschleife */
 }

if (Client==1)
{ long PortNumber;
	fd_set readfds;
	struct timeval timeout;
 if (strcmp(ServerName,"")==0) {printf("\n ERROR - ServerName is missing ! \n\n"); E(); }
 if (strcmp(Port,"")==0)       {printf("\n ERROR - PortNumber is missing ! \n\n"); E(); }
 if (strcmp(User,"")==0)       {printf("\n ERROR - UserName   is missing ! \n\n"); E(); }
 if (0==sscanf(Port,"%ld",&PortNumber)) { printf("\n ERROR - PortNumber is wrong ! \n\n"); E(); }
 s1=call_socket(ServerName,PortNumber);
 if (s1==-1)
 {
   printf("\nError: Socketerror\n"); E();  
 }

 {
  long max,t;
  struct AnfragePaket Anfrage;
  strcpy( Anfrage.UserName,User);
  max=X_MAX*Y_MAX;
  for (t=0;t<=max;t++)
    {
      Anfrage.Feld_Visible[t]=Feld_Visible[t];
      Anfrage.Feld_Intern[t] =Feld_Intern[t];
    }
  Anfrage.Was='W';                     /* s1 ist der kanal ZUM SCHREIBEN */
timeout.tv_sec=10;
timeout.tv_usec=0;
FD_ZERO(&readfds);
FD_SET(s1,&readfds);
if (1==select(s1+1,0,&readfds,0,&timeout))
	{ 
	write(s1,&Anfrage,sizeof(struct AnfragePaket));
	}
	else
	{
	printf("Error: Server-Timeout V1.0\n");
	exit(-1);
	}

  Anfrage.Was='R';                     /* s2 ist der kanal zum LESEN */
  s2=call_socket(ServerName,PortNumber);
timeout.tv_sec=10;
timeout.tv_usec=0;
FD_ZERO(&readfds);
 if (s2==-1) {printf("\nError: Socketerror\n"); E(); }
FD_SET(s2,&readfds);
if (1==select(s2+1,0,&readfds,0,&timeout))
	{
  write(s2,&Anfrage,sizeof(struct AnfragePaket));
	 } 
	else
	{
	printf("Error: Server-Timeout V2.0\n");
	exit(-1);
	}
 CheckForClientEvent();  
 }
}
}

void show_end()
{
  int xx,yy,nr,x,y;

  for (y=1;(y<Y_MAX-1);y++)
  {                    
   for (x=1;x<X_MAX;x++)   
   {

  xx=x*bigx;
  yy=y*bigy;
  nr=x+y*X_MAX;

  if ((Feld_Intern[nr]==BOMB))
   {
     XCopyArea(display,minepix,window,gc,0,0,SWIDTH,SHEIGHT,xx-10,40+yy);
   }

   if ((Feld_Visible[nr]==SHOW) && (Feld_Intern[nr]==EXBOMB))
   {
     XCopyArea(display,minepix_a,window,gc,0,0,SWIDTH,SHEIGHT,xx-10,40+yy);
   }

  if ((Feld_Visible[nr]==LOCK) && (Feld_Intern[nr]!=BOMB))
   { 
     XSetForeground(display, gc, b3);
     XDrawLine(display,window,gc,xx-10+bigx-3,40+yy,xx-10-3,40+yy+bigy);
     XDrawLine(display,window,gc,xx-10,40+yy,xx-10+bigx,40+yy+bigy);
   }
}
}
  male_gitter();
}

void CheckForClientEvent()
{ int max,res,x,y,xx,yy,size,i,err,change;    
  fd_set readfds;
  struct timeval timeout;
  struct AnfragePaket Anfrage;

  for (;1==1;)
  {
   FD_ZERO(&readfds);
   FD_SET(s2,&readfds );
   timeout.tv_sec=0; 
   timeout.tv_usec=800;
   res = select(s2+1, &readfds, 0, 0, &timeout);
   if ((res!=-1) && (FD_ISSET(s2,&readfds))) 
   { /* aha, server schickt uns daten */
     err=reads(s2,&Anfrage,sizeof(struct AnfragePaket));
     if (err!=sizeof(struct AnfragePaket)) {  printf("\n Socket-Datenfehler \n"); exit(-1);}
     max=X_MAX*Y_MAX;
     if ((Anfrage.Feld_Visible[Y_MAX*X_MAX+3]==77) && (Feld_Visible[Y_MAX*X_MAX+3]!=77))
     {  spiel_laeuft=0;
         /* anderer Player hat gewonnen */
        other_player_win(0);
     }
     
     if (Anfrage.Feld_Intern[Y_MAX*X_MAX+4]==99) 
     {
      weiter_msg++;
      if (weiter_msg>max_msg) weiter_msg=0;  
      strcpy(winner,msg[weiter_msg]);
  
      spiel_laeuft=1;HighScore=0;
      for (t=0;t<=(max+4);t++)
      { 
        Feld_Visible[t]=HIDE;
        Feld_Intern[t]=0;
       }
       draw_screen(); 
     }
    for (t=0;t<=max;t++)
     {
     if (spiel_laeuft==1)
     {
      if ((SHOW==Anfrage.Feld_Visible[t])&&(Feld_Intern[t]!=BOMB)) Feld_Visible[t]=SHOW;
      if (Feld_Intern[t]!=EXBOMB) Feld_Intern[t]=Anfrage.Feld_Intern[t];
     }
       }
          for (y=1;(y<Y_MAX);y++)
          {
            for (x=1;x<X_MAX;x++)
            {
            
             if (Feld_Visible[x+y*X_MAX]!=Feld_Backup[x+y*X_MAX])
              {
               draw_item(x,y);
              }
            }
          }
          male_gitter();
       }
  if (XPending(display))      
  {
   getXevent();    /* bearbeite event */
  }
 }
}

CheckforEvent()
{   
 for (;1==1;)
 {    
 /*  if (XPending(display))          => nur wenn wir noch was machen wollen */
  {                                       
   getXevent();                      
  }
 }
}

void draw_item(x,y)
int x,y;
{
  char a;
  int xx,yy,nr;
  a='.';
  xx=x*bigx;
  yy=y*bigy;
  nr=x+y*X_MAX;
  XSetForeground(display, gc, gray);
  XFillRectangle(display,window,gc,xx-10,40+yy,20,20); 
  Feld_Backup[nr]=Feld_Visible[nr];
  if (Feld_Visible[nr]==SHOW)
  {
   if (Feld_Intern[nr]==0)    { a='.'; }
   if (Feld_Intern[nr]==1)    { a='1'; XSetForeground(display, gc, b1); }
   if (Feld_Intern[nr]==2)    { a='2'; XSetForeground(display, gc, b2); }
   if (Feld_Intern[nr]==3)    { a='3'; XSetForeground(display, gc, b3); }
   if (Feld_Intern[nr]==4)    { a='4'; XSetForeground(display, gc, b4); }
   if (Feld_Intern[nr]==5)    { a='5'; XSetForeground(display, gc, b5); }
   if (Feld_Intern[nr]==6)    { a='6'; XSetForeground(display, gc, b6); }
   if (Feld_Intern[nr]==7)    { a='7'; XSetForeground(display, gc, b7); }
   if (Feld_Intern[nr]==8)    { a='8'; XSetForeground(display, gc, b8); }
   if (Feld_Intern[nr]==EXBOMB) 
   { a='.';  
    XCopyArea(display,minepix_a,window,gc,0,0,SWIDTH,SHEIGHT,xx-10,40+yy);
   }

  if (Feld_Intern[nr]==BOMB)
   {
       XCopyArea(display,minepix,window,gc,0,0,SWIDTH,SHEIGHT,xx-10,40+yy);
       a='.';  
   }
   if (a!='.')
   { char text[4];
     text[0]=a; text[1]=0;
     XDrawString(display,window,gc,xx-4,54+yy,text,1);
   }
  }
  if (Feld_Visible[nr]==HIDE)
  { 
     xx=x*bigx-8;
     yy=y*bigy+42;
     XSetForeground(display, gc, white);
     XFillRectangle(display,window,gc,xx-2,yy-2,20,20);
     XSetForeground(display, gc, gray);
     XFillRectangle(display,window,gc,xx,yy,18,18);
  }

 if (Feld_Visible[nr]==LOCK)
  { 
   XCopyArea(display,lockpix,window,gc,0,0,SWIDTH,SHEIGHT,x*bigx-10,39+y*bigy);
  }
}

void male_gitter()
{
   int i,x,y,xx,yy;
   XSetForeground(display, gc, black);
   for (i=0;i<2;i++)
   {
    for (y=0;y<(Y_MAX);y++)     
    {
     yy=y*bigy;
     XDrawLine(display,window,gc,bigx-12,yy+58+i,X_MAX*bigx-bigx+9,58+yy+i);
    }
    for (x=0;x<(X_MAX);x++)
    {
     xx=x*bigx;
     XDrawLine(display,window,gc,i+xx+8,60,i+xx+8,38+Y_MAX*bigy);
    }
   }
}


void draw_screen()
{ 
  long dir,xx,yy,x,y,a,b,c,d;
  GC highlightgc,shadowgc;
 
  XSetForeground(display, gc, white);
  XFillRectangle(display,window,gc,9,60,bigx*X_MAX-bigx,bigy*Y_MAX);
  XSetBackground(display, gc, gray);
  XSetForeground(display, gc, gray);
  XFillRectangle(display,window,gc,0,0,1280,59);
  XFillRectangle(display,window,gc,0,0,9,1000);
  XFillRectangle(display,window,gc,8+(X_MAX-1)*bigx,0,800,1000);
  XFillRectangle(display,window,gc,0,60+(Y_MAX-1)*bigy,800,1000);
  XSetForeground(display, gc, gray);
  for (y=1;y<Y_MAX;y++)
  {
   for (x=1;x<X_MAX;x++)
   {
     xx=x*bigx-8;
     yy=y*bigy+42;
     XFillRectangle(display,window,gc,xx,yy,18,18);
  }
  }
  for (y=1;(y<Y_MAX);y++)
  {                    
   for (x=1;x<X_MAX;x++)   
   {
    if (Feld_Visible[x+y*X_MAX]!=HIDE)
    {
     draw_item(x,y);
    }
   }
  }
  XSetForeground(display, gc, black);
  XCopyArea(display,copyrightpix,window,gc,0,0,60,40,10,10);
  XCopyArea(display,netpix,window,gc,0,0,60,40,550,10);
  if (Client!=1) XCopyArea(display,newpix,window,gc,0,0,60,40,270,10);
  male_gitter();
  if (spiel_laeuft==0) show_end();
    sprintf(text,"Score: %d",HighScore);
                       XSetForeground(display, gc, getcolor("gray",foreground));
                       XFillRectangle(display,window,gc,75,0,60,50);
                       XSetForeground(display, gc, getcolor("blue",foreground));
                       XDrawString(display,window,gc,75,30 ,text,strlen(text));
                  

                XSetForeground(display, gc, getcolor("gray",foreground));
                       XFillRectangle(display,window,gc,4,383,625,400);
                       XSetForeground(display, gc, getcolor("red",foreground));
                    XDrawString(display,window,gc,10,395,winner,strlen(winner));
       

}


void Fuelle(x,y)
int x,y;
{
xx=x+y*X_MAX;
Feld_Visible[xx]=SHOW;
draw_item(x,y);
if (Feld_Intern[xx]==0)
 { 
   if (Feld_Visible[x+y*X_MAX+1    ]==HIDE) Fuelle(x+1,y);
   if (Feld_Visible[x+y*X_MAX-1    ]==HIDE) Fuelle(x-1,y);
   if (Feld_Visible[x+y*X_MAX+X_MAX]==HIDE) Fuelle(x,y+1);
   if (Feld_Visible[x+y*X_MAX-X_MAX]==HIDE) Fuelle(x,y-1);
 }
}

Client_to_Server()
{   struct AnfragePaket Anfrage;
                       Anfrage.Was='W'; 
                       strcpy( Anfrage.UserName,User);
                       max=X_MAX*Y_MAX+4;
                       for (t=0;t<=max;t++)
                       {
                         Anfrage.Feld_Visible[t]=Feld_Visible[t];
                         Anfrage.Feld_Intern[t]=Feld_Intern[t];
                       }
    err=write(s1,&Anfrage,sizeof(struct AnfragePaket));
    if (err!=sizeof(struct AnfragePaket)) { printf("\n socket-write fehler \n"); exit(-1); }
}                    

getXevent()                                 
{
    XNextEvent(display, &event);
    switch(event.type)
    {
        case Expose:
            if(event.xexpose.window == window)
            {
                if(event.xexpose.count == 0)
                {
                    /* window wurde gemoved , also neu aufbauen */
                    draw_screen();
                }
            }
            break;                          
        case ButtonPress:                      
            if(event.xkey.window == window)
            {
                x = (event.xbutton.x-XOFFSET)/SWIDTH;
                y = (event.xbutton.y-YOFFSET)/SHEIGHT;
                xx=event.xbutton.x;
                yy=event.xbutton.y;
                if ((yy>=10) && (yy<=40))
                {
                  if ((xx>10) && (xx<70))
                  { /* Copyright angeklickt */
                       char text[120];
                       XSetForeground(display, gc, getcolor("gray",foreground));
                       XFillRectangle(display,window,gc,4,383,625,400);
                       XSetForeground(display, gc, getcolor("red",foreground));
                       strcpy(text,"(c) 1994 by Martin Bauer    to contact me: Martin_Bauer@S2.MAUS.DE");
                       strcpy(winner,text);   
                    XDrawString(display,window,gc,10,395,text,strlen(text));
                  }
                 
                  if ((xx>270) && (xx<330) && (Client!=1))
                  { /* new angeklickt */

                    spielfeld_init();
                    weiter_msg++;
                     if (weiter_msg>max_msg) weiter_msg=0;  
  
                    strcpy(winner,msg[weiter_msg]);

                    HighScore=0;
                    draw_screen(); 
                    Feld_Intern[Y_MAX*X_MAX+4]=99;
                    Sende_to_Client();           
                    Feld_Intern[Y_MAX*X_MAX+4]=0;
                 }

                  if ((xx>550) && (xx<610))
                  { /* net-config angeklickt */
                    if (Server==1) close(sock_server);
                    if (Client==1) close(s1);
                    if (Client==1) close(s2);
                    exit(-1);
                  }
                } 
               if ((x>=0) && (x<(X_MAX-1)) && (y>=0) && (y<(Y_MAX-1)) && (spiel_laeuft==1))
                {    /* spieler hat im Spielfeld geklickt ! */
                  x++; y++;
             if (event.xbutton.button==Button1)
             {    /* taste 1 im spielfeld geklickt ! */
                  xx=x+y*X_MAX; 
                  if (Feld_Visible[xx]==HIDE)
                  {  /* hat auf verstecktes feld getippt */
                     Feld_Visible[xx]=SHOW;
                     if (Feld_Intern[xx]==0)    { Fuelle(x,y); }

                     if ((Feld_Intern[xx]!=BOMB) && (Client==1))
                     {  /* ok, jetzt dem server mitteilen */
                       long max,t,err,size;
                       struct AnfragePaket Anfrage;
                       Anfrage.Was='W'; 
                       strcpy( Anfrage.UserName,User);
                       max=X_MAX*Y_MAX;
                       for (t=0;t<=max;t++)
                       {
                         Anfrage.Feld_Visible[t]=Feld_Visible[t];
                         Anfrage.Feld_Intern[t]=Feld_Intern[t];
                       }
                     err=write(s1,&Anfrage,sizeof(struct AnfragePaket));
                     if (err!=sizeof(struct AnfragePaket)) { printf("\n socket-write fehler \n"); exit(-1); }
                     }
                     if ((Feld_Intern[xx]!=BOMB) && (Server==1))
                     {  /* ok, jetzt den clients mitteilen */
                      Sende_to_Client();                       
                     }
                     if (Feld_Intern[xx]==BOMB) 
                     { char text[80];
                       spiel_laeuft=0;
                       Feld_Intern[xx]=EXBOMB;
                       strcpy(text,"Booooooommmmmm , you lost the game. Please restart the game now.");
                       if (Client==1) strcpy(text,"You lost the game. This game will be restart after one Player is left");
                       if (Server==1) strcpy(text,"You lost the game. Please DO NOT restart the Game NOW. ");
                       if ((Server==1) && (next==NULL))  strcpy(text,"You lost the game. Please RESTART the Game NOW. ");

                       strcpy(winner,text); 
                      XSetForeground(display, gc, getcolor("gray",foreground));
                       XFillRectangle(display,window,gc,4,385,625,400);
                       XSetForeground(display, gc, getcolor("blue",foreground));
                       XDrawString(display,window,gc,10,395 ,text,strlen(text));
                       show_end(); 
                      }
                     if ((Feld_Intern[xx]!=BOMB))
                     {  /* user hat ein zahlenfeld/space aufgedeckt ! */
                       int k;
                       k=0;
                       if (Feld_Intern[xx]<=8) HighScore=HighScore+Feld_Intern[xx];
                       sprintf(text,"Score: %d",HighScore);
                       XSetForeground(display, gc, getcolor("gray",foreground));
                       XFillRectangle(display,window,gc,75,0,80,55);
                       XSetForeground(display, gc, getcolor("blue",foreground));
                       XDrawString(display,window,gc,75,30 ,text,strlen(text));
                       max=X_MAX*Y_MAX;
                       for (t=0;t<=max;t++)
                       {
                         if ((Feld_Visible[t]==HIDE)) k=1;
                         if ((Feld_Intern[t]!=BOMB) && (Feld_Visible[t]==LOCK)) k=1;
                       }
                       if (k==0) 
                       {/* spiel beendet und gewonnen ! */ 
                        spiel_laeuft=0;
                       strcpy(text,"You win the game. Please RESTART NOW the game ");
                       if (Client==1) strcpy(text,"You win the game. This game will be restart by the Serverplayer now");
                       if (Server==1) strcpy(text,"You win the game. Please RESTART NOW the game ");
                        strcpy(winner,text);
                       Feld_Visible[X_MAX*Y_MAX+3]=77;
                       XSetForeground(display, gc, getcolor("gray",foreground));
                       XFillRectangle(display,window,gc,4,385,625,400);
                       XSetForeground(display, gc, getcolor("blue",foreground));
                       XDrawString(display,window,gc,10,395 ,text,strlen(text));
                       if (Server==1) Sende_to_Client();
                       if (Client==1) 
                         {
                           Client_to_Server();                    
                         }    

                    }

                   }


                     draw_item(x,y);
                     male_gitter();
                  }
              } else
              { /* taste 2/3 im spielfeld geklickt ! */
                  xx=x+y*X_MAX;
                  
                  if (Feld_Visible[xx]==HIDE)
                  {
                   /* hat auf verstecktes feld getippt */
                   Feld_Visible[xx]=LOCK;
                   draw_item(x,y);
                   male_gitter();
                  } else
                  { 
                  if (Feld_Visible[xx]==LOCK)
                    {
                     /* hat auf gelocktes feld getippt */
                    Feld_Visible[xx]=HIDE;               
                    draw_item(x,y);
                    male_gitter();
                    } 
                  }
                     {  /* user hat ein zahlenfeld/space aufgedeckt ! */
                       int k;
                       k=0;
                       sprintf(text,"Score: %d",HighScore);
                       XSetForeground(display, gc, getcolor("gray",foreground));
                       XFillRectangle(display,window,gc,75,0,80,55);
                       XSetForeground(display, gc, getcolor("blue",foreground));
                       XDrawString(display,window,gc,75,30 ,text,strlen(text));
                       max=X_MAX*Y_MAX;
                      for (t=0;t<=max;t++)
                       {
                         if ((Feld_Visible[t]==HIDE)) k=1;
                         if ((Feld_Intern[t]!=BOMB) && (Feld_Visible[t]==LOCK)) k=1;
                       }
                       if (k==0) 
                       {/* spiel beendet und gewonnen ! */ 
                       spiel_laeuft=0;
                       strcpy(text,"You win the game.");
                       strcpy(text,"You win the game. Please RESTART NOW the game ");
                       if (Client==1) strcpy(text,"You win the game. This game will be restart by the Serverplayer now");
                       if (Server==1) strcpy(text,"You win the game. Please RESTART NOW the game ");
                       strcpy(winner,text);
                       Feld_Visible[X_MAX*Y_MAX+3]=77;
                       XSetForeground(display, gc, getcolor("gray",foreground));
                       XFillRectangle(display,window,gc,4,385,625,400);
                       XSetForeground(display, gc, getcolor("blue",foreground));
                       XDrawString(display,window,gc,10,395 ,text,strlen(text));
                       if (Server==1) Sende_to_Client();
                       if (Client==1) 
                         {
                          Client_to_Server();
                         }    

                        }

                   }

              }
                }
            }
            break;

    }


}

