home *** CD-ROM | disk | FTP | other *** search
- /* This program was written by Helmut Hoenig */
- /* in May of 1988 at the Unitversity of */
- /* Kaiserslautern, Germany. It may be copied freely. */
-
- #define NONE 255
- #define P_TYPE unsigned char
-
- #define DX 128 /* Groesse des Feldes */
- #define DY 108
- #define DYSHIFT 1
-
- #define times 0
- #define moremess 0
- #define datagramm 1
-
- int messflag;
- short readshort();
-
- #define CHECK(n) printf("%s: check %d%c",my_host,n,(char)10); fflush(stdout)
-
- #include <X11/Xlib.h>
- #include <stdio.h>
- #include <strings.h>
- #include <sys/types.h>
- #include <sys/time.h>
- #include <netinet/in.h>
- #include <netdb.h>
-
- #define XK_MISCELLANY
- #define XK_LATIN1
- #include <X11/keysymdef.h>
-
- #include "grey_maps.h"
-
- #include "header.h"
- #include "messages.h"
-
- #define MAXPLAYERS 8
- #define DIMENSION 4
-
- char *my_host,
- *mast_host; /* host of the server, received at the start */
- int my_count; /* count to use, when sending messages to the server */
- short mast_port; /* port-number of the servers master_socket */
-
- int master, /* my own stream-socket */
- next; /* datagram socket to send pakets to the next player */
-
- struct sockaddr_in mast_sin,next_sin,my_sin;
- int lastlen;
-
- char next_host[20]; /* address of the next player, received befor a game starts */
- short next_port;
-
- #if (datagramm==0)
- int last_acc,last;
- struct sockaddr_in last_sin;
- #endif
-
- /* XWindowstrukturen und -Variablen */
-
- #define FID 0
- #define MAPS 8
-
- extern XFontStruct *(finfo[]);
- extern Window aw;
- extern GC gc_set,gc_clear,gc_filler,gc_copy,gc_orInverted,gc_or;
-
- Display *display;
- Screen *screen;
- char *dispname; /* received by the server */
- XEvent event;
- Window backw, /* just a black background window, if the display-size doesn't fit */
- mw, /* main-window, where the action takes place
- **** no eposure-events executed here (too much effort) ***/
- scorew; /* window in the middle of the screen for text-outputs */
-
- XColor colors[MAPS];
- Pixmap grey[MAPS];
- long pixels[256];
- XColor cols[DY];
- long planes[1];
- int colored;
-
- /* Spielstrukturen und -Variablen */
-
- #define x_size ((DWidth / DX))
- #define y_size ((DHeight / DY))
- #define MWWidth (DX*x_size)
- #define MWHeight (DY*y_size)
-
- int field[DX][DY];
-
- P_TYPE xmove[DX * DY];
- P_TYPE ymove[DX * DY];
- int lastmove,actmove;
-
- typedef struct _Pack { /* Spielpaket */
- short mode; /* mode: SETUP / PLAY */
- short game_count; /* laufende Nummer der Paketuebertragung */
- short game_number; /* Nummer des Spiels */
- short players; /* aktuelle Zahl der Spieler */
- short ready;
-
- P_TYPE x[MAXPLAYERS][DIMENSION];
- P_TYPE y[MAXPLAYERS][DIMENSION];
- } Pack;
-
- #define SETUP 1
- #define PLAY 2
- #define GAME_OVER 4
- #define AUTO_START 8
-
- Pack p; /* Buffer for the datagram-paket */
-
- int start_flag,players;
- int ready,wait,winner;
- int active;
- int game_num;
-
- P_TYPE posx,posy;
- int dx,dy;
- int fast,boost,jmp_count;
-
- #if (times==1)
-
- #define MAXMESS 100
-
- int t_count;
- struct timeval tfield[MAXMESS+1];
- struct timezone zone;
-
- #endif
-
- /* Ausgabefenster */
- static int lines,max_col;
- static char tscreen[20][80];
-
- /* */
- char *getenv();
-
- int max_time;
- int auto_only=0;
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- struct hostent *hp;
- struct servent *sp;
- int buffer;
- int help;
-
- long timefield;
-
- time(&timefield);
- srandom((int)timefield);
-
- if (argc!=6)
- { fprintf(stderr,"*** you must not start this directly. ***\n");
- exit(0);
- };
-
- my_host=getenv("HOST");
- mast_host=argv[1];
- sscanf(argv[2],"%d",&help);
- mast_port = htons((short)help);
- dispname = argv[3];
- sscanf(argv[4],"%d",&my_count);
- sscanf(argv[5],"%d",&messflag);
-
- #if (moremess==1)
- printf("%s: count: %d\n",my_host,my_count);
- fflush(stdout);
- #endif
-
- /* Display oeffnen */
- if (index(dispname,'-')==NULL)
- { if ((display=XOpenDisplay(dispname))==NULL)
- { fprintf(stderr,"*** %s: Can't open display.\n",my_host);
- auto_only=1;
- }
- else
- { screen=XScreenOfDisplay(display,DefaultScreen(display));
- auto_only=0;
- };
- }
- else auto_only=1;
-
- /* 2 bis 3 Sockets aufmachen */
- master=streamsocket();
-
- next=dgramsocket();
-
- /* Socketnamen fuer eigenen Socket holen */
-
- init_addr(&my_sin,my_host,htons((short)14253));
-
- while (bind(next,&my_sin,sizeof my_sin)) my_sin.sin_port++;
-
- #if (moremess==1)
- printf("%s: my port is %d.\n",my_host,(int)ntohs(my_sin.sin_port));
- fflush(stdout);
- #endif
- if (messflag)
- { printf("%s: master: %s@%d, my-port: %s@%d\n",my_host,mast_host,(int)ntohs(mast_port),my_host,(int)ntohs(my_sin.sin_port));
- fflush(stdout);
- }
- /* Verbindung zum Master aufbauen */
- connect_to(master,mast_host,mast_port);
- writeint(master,my_count);
- writeshort(master,(short)ntohs(my_sin.sin_port));
- writeint(master,auto_only);
-
- game();
-
- /* Sockets schliessen */
- close(master);
- close(next);
- }
-
- /*****************************************************
- * Initialisation *
- * + Loop, executing command-messages of the master. *
- *****************************************************/
-
- game()
- {
- XSetWindowAttributes attrib;
- int i,j,t;
- int mess;
-
- if(!auto_only)
- { init_texter();
- XBell(display,40);
- /* XSynchronize(display,1); */ /* Hilfe fuer Testzwecke */
-
- XFlush(display);
-
- /******************************************************
- * tries to allocate a special amount of color cells. *
- * if it fails, it continues in monochrom. *
- ******************************************************/
- if (XAllocColorCells(display,XDefaultColormapOfScreen(screen),False,planes,0,pixels,10+(DY>>DYSHIFT)))
- { int r1,g1,b1,r2,g2,b2;
- colored = True;
-
- XSetFillStyle(display,gc_filler,FillSolid);
-
- XStoreNamedColor(display,XDefaultColormapOfScreen(screen),
- "red",pixels[0],DoRed | DoGreen | DoBlue);
- XStoreNamedColor(display,XDefaultColormapOfScreen(screen),
- "blue",pixels[1],DoRed | DoGreen | DoBlue);
- XStoreNamedColor(display,XDefaultColormapOfScreen(screen),
- "violet",pixels[2],DoRed | DoGreen | DoBlue);
- XStoreNamedColor(display,XDefaultColormapOfScreen(screen),
- "green",pixels[3],DoRed | DoGreen | DoBlue);
- XStoreNamedColor(display,XDefaultColormapOfScreen(screen),
- "yellow",pixels[4],DoRed | DoGreen | DoBlue);
- XStoreNamedColor(display,XDefaultColormapOfScreen(screen),
- "cyan",pixels[5],DoRed | DoGreen | DoBlue);
- XStoreNamedColor(display,XDefaultColormapOfScreen(screen),
- "navy",pixels[6],DoRed | DoGreen | DoBlue);
- XStoreNamedColor(display,XDefaultColormapOfScreen(screen),
- "orange",pixels[7],DoRed | DoGreen | DoBlue);
-
- XStoreNamedColor(display,XDefaultColormapOfScreen(screen),
- "wheat",pixels[8],DoRed | DoGreen | DoBlue);
- XStoreNamedColor(display,XDefaultColormapOfScreen(screen),
- "dark green",pixels[9],DoRed | DoGreen | DoBlue);
- XSetState(display,gc_or,pixels[9],pixels[9],GXcopy,AllPlanes);
-
- r1 = 192 * 256; g1 = 224 * 256; b1 = 255 * 256;
- r2 = 255 * 256; g2 = 192 * 256; b2 = 192 * 256;
-
- for (i=0;i<(DY>>DYSHIFT);i++)
- { cols[i].pixel = pixels[10+i];
- cols[i].red = (unsigned short)(r1+((r2-r1)*i)/(DY>>DYSHIFT));
- cols[i].green = (unsigned short)(g1+((g2-g1)*i)/(DY>>DYSHIFT));
- cols[i].blue = (unsigned short)(b1+((b2-b1)*i)/(DY>>DYSHIFT));
- cols[i].flags = DoRed | DoGreen | DoBlue;
- }
- XStoreColors(display,XDefaultColormapOfScreen(screen),cols,(DY>>DYSHIFT));
- }
- else
- { colored = False; }
-
-
- grey[0]=XCreatePixmapFromBitmapData(display,ROOT,grey0_bits,grey0_width,grey0_height,
- 1,0,DefaultDepthOfScreen(screen));
- grey[1]=XCreatePixmapFromBitmapData(display,ROOT,grey1_bits,grey1_width,grey1_height,
- 1,0,DefaultDepthOfScreen(screen));
- grey[2]=XCreatePixmapFromBitmapData(display,ROOT,grey2_bits,grey2_width,grey2_height,
- 1,0,DefaultDepthOfScreen(screen));
- grey[3]=XCreatePixmapFromBitmapData(display,ROOT,grey3_bits,grey3_width,grey3_height,
- 1,0,DefaultDepthOfScreen(screen));
- grey[4]=XCreatePixmapFromBitmapData(display,ROOT,grey4_bits,grey4_width,grey4_height,
- 1,0,DefaultDepthOfScreen(screen));
- grey[5]=XCreatePixmapFromBitmapData(display,ROOT,grey5_bits,grey5_width,grey5_height,
- 1,0,DefaultDepthOfScreen(screen));
- grey[6]=XCreatePixmapFromBitmapData(display,ROOT,grey6_bits,grey6_width,grey6_height,
- 1,0,DefaultDepthOfScreen(screen));
- grey[7]=XCreatePixmapFromBitmapData(display,ROOT,grey7_bits,grey7_width,grey7_height,
- 1,0,DefaultDepthOfScreen(screen));
-
- backw=XCreateSimpleWindow(display,ROOT,0,0,DWidth,DHeight,
- 0,WhitePixelOfScreen(screen),BlackPixelOfScreen(screen));
- attrib.override_redirect = 1;
- XChangeWindowAttributes(display,backw,CWOverrideRedirect,&attrib);
-
- if (colored)
- { mw=XCreateSimpleWindow(display,backw,
- (DWidth-MWWidth)>>1,(DHeight-MWHeight)>>1,MWWidth,MWHeight,
- 0,WhitePixelOfScreen(screen),cols[DY>>(DYSHIFT+1)].pixel);
- }
- else
- { mw=XCreateSimpleWindow(display,backw,
- (DWidth-MWWidth)>>1,(DHeight-MWHeight)>>1,MWWidth,MWHeight,
- 0,WhitePixelOfScreen(screen),BlackPixelOfScreen(screen));
- }
-
- XSelectInput(display,mw,ExposureMask | ButtonPressMask | KeyPressMask | KeyReleaseMask );
- attrib.override_redirect = 1;
- XChangeWindowAttributes(display,mw,CWOverrideRedirect,&attrib);
- XMapRaised(display,mw);
-
- if (colored)
- { scorew=XCreateSimpleWindow(display,ROOT,0,0,DWidth,DHeight,8,pixels[9],cols[DY>>(DYSHIFT+1)].pixel);
- }
- else
- { scorew=XCreateSimpleWindow(display,ROOT,0,0,DWidth,DHeight,8,BlackPixelOfScreen(screen),WhitePixelOfScreen(screen));
- XSetWindowBorderPixmap(display,scorew,grey[5]);
- }
- XSelectInput(display,scorew,ExposureMask);
- XChangeWindowAttributes(display,scorew,CWOverrideRedirect,&attrib);
- }
-
- /*************
- * MAIN-LOOP *
- *************/
- for(;;)
- switch(mess=readint(master))
- { int len,signs;
-
- case GAMESTART:
- /* weitere Informationen zum aktuellen Spiel holen */
- players=readint(master); /* Anzahl der Spieler */
- active=readint(master); /* Flag, ob eigener Spieler rechnergesteuert */
- game_num=readint(master); /* Spielezaehler */
-
- start_flag=readint(master); /* Flag, ob man fuer das erste Datagramm im Ring sorgen soll */
-
- /* Socket-Adresse des naechsten Spielers im Ring empfangen */
- readstring(master,next_host,19);
- next_port=htons(readshort(master));
- init_addr(&next_sin,next_host,next_port);
- if (messflag)
- { printf("%s: start of game %d with %d players (start_flag=%d)\n",my_host,game_num,players,start_flag);
- printf("%s: next port is %s@%d\n",my_host,next_host,(int)ntohs(next_port));
- fflush(stdout);
- }
- prepare_to_start();
-
- #if (moremess==1)
- printf("%s: received players: %d active: %d start: %d.\n",my_host,players,active,start_flag);
- fflush(stdout);
- #endif
-
- /* ausgewaehlter Spieler initialisiert Packet-Struktur und sendet sie in den Ring */
- p.mode=(short)SETUP;
- if (start_flag)
- { p.game_count=(short)0;
- p.players=(short)players;
- p.ready=(short)0;
- p.game_number=(short)game_num;
- for (i=0;i<MAXPLAYERS;i++)
- for (j=0;j<DIMENSION;j++)
- { p.x[i][j]=posx= (P_TYPE)NONE;
- p.y[i][j]=posy= (P_TYPE)NONE;
- };
- write_p();
- }
-
- /* Schleife fuer Ausfuehrung eines Zuges */
- #if (times==0)
- while(make_move());
- #else
- /*************************************************************************
- * Testprogramm zur Messung der Umlaufzeit des Datagramms durch den Ring *
- *************************************************************************/
-
- for (t_count=0;t_count<=MAXMESS;t_count++)
- { gettimeofday(&tfield[t_count],&zone);
- while (read_p());
- write_p();
- };
- if (start_flag)
- { FILE *fopen(),*fp;
- fp=fopen("sockets/time_file","w");
- for (t_count=1;t_count<=MAXMESS;t_count++)
- { long t;
-
- t=((tfield[t_count].tv_sec & 0xffff)*1000000 + tfield[t_count].tv_usec)
- -((tfield[t_count-1].tv_sec & 0xffff)*1000000 + tfield[t_count-1].tv_usec);
- fprintf(fp,"%3d: %8ld usec\n",t_count,t);
- };
- fclose(fp);
- printf("%s: Timefile written.\n",my_host);
- fflush(stdout);
- };
- #endif
- if (!auto_only) XUngrabServer(display);
- break;
- case SCORE:
- read_scores(); /* Stringfeld lesen und ausgeben */
- if (!auto_only) redraw_scores();
- break;
- case EXIT:
- printf("%s: program ends.\n",my_host); /* Programm beenden */
- exit(0);
- break;
- case UNMAP:
- if (auto_only) break;
- XUnmapWindow(display,scorew); /* Punktefenster vom Bildschirm entfernen */
- XUnmapWindow(display,backw);
- XFlush(display);
- break;
- default:
- fprintf(stderr,"%s: received unknown instruction (%d) from master.\n",my_host,mess);
- break;
- };
- }
-
- /********************
- * Stringfeld lesen *
- ********************/
-
- read_scores()
- { int l;
-
- max_col=0;
- lines=readint(master);
-
- for (l=0;l<lines;l++)
- { readstring(master,&tscreen[l][0],80);
- if (strlen(tscreen[l])>max_col)
- max_col=strlen(tscreen[l]);
- };
- }
-
- /***********************
- * Stringfeld ausgeben *
- ***********************/
-
- redraw_scores()
- { int x_wsize,y_wsize;
- int l;
- XEvent event;
-
- if (auto_only) return;
-
- XUnmapWindow(display,scorew);
- x_wsize=CharWidth(FID) * (2+max_col);
- y_wsize=CharHeight(FID) * (2+lines);
- XMoveResizeWindow(display,scorew,(DWidth-x_wsize)>>1,(DHeight-y_wsize)>>1,x_wsize,y_wsize);
- XMapRaised(display,scorew);
- /* XWindowEvent(display,scorew,ExposureMask,&event); */
- if (colored)
- { int xw=1,i;
- int sdx=(x_wsize>>5);
- int y0,y1;
-
- y0=0;
- for (i=0;i<32;i++)
- { y1 = y_wsize*(i+1)/32;
- XSetForeground(display,gc_filler,cols[(DY>>DYSHIFT)*(31-i)/32].pixel);
- XFillRectangle(display,scorew,gc_filler,0,y0,xw*sdx,y1-y0);
- y0=y1;
- }
- do
- { XCopyArea(display,scorew,scorew,gc_filler,
- 0,0,xw*sdx,y_wsize,xw*sdx,0);
- xw<<=1;
- }
- while (xw<=32);
- }
- else
- { XClearWindow(display,scorew);
- }
- aw=scorew;
-
- for (l=0;l<lines;l++)
- { printat(1,l+1,tscreen[l],FID);
- };
- XFlush(display);
- }
-
- /**********************
- * Spielfeld loeschen *
- **********************/
-
- empty_all()
- { int x,y;
-
- for (x=0;x<DX;x++)
- for (y=0;y<DY;y++)
- field[x][y]=0;
- for (x=0;x<DX;x++)
- { field[x][0]= -1;
- field[x][DY-1]= -1;
- };
- for (y=0;y<DY;y++)
- { field[0][y]= -1;
- field[DX-1][y]= -1;
- };
- }
-
- /*****************************************
- * Vorbereitungen zum Spielstart treffen *
- *****************************************/
-
- prepare_to_start()
- { int i;
- XEvent event;
-
- empty_all();
- if (active==1)
- { XGrabServer(display);
- XMapRaised(display,backw);
- /* XWindowEvent(display,mw,ExposureMask,&event); */
- XClearWindow(display,mw);
-
- if (colored)
- { int xw = 1;
-
- for (i=0;i<(DY>>DYSHIFT);i++)
- { XSetForeground(display,gc_filler,cols[i].pixel);
- XFillRectangle(display,mw,gc_filler,0,y_size+i*(y_size<<DYSHIFT),xw*x_size,(y_size<<DYSHIFT));
- }
- do
- { XCopyArea(display,mw,mw,gc_filler,
- 0,0,xw*x_size,MWHeight,xw*x_size,0);
- xw<<=1;
- }
- while (xw<DX);
-
- XSetForeground(display,gc_filler,pixels[9]);
- XFillRectangle(display,mw,gc_filler,0,0,MWWidth,y_size-1);
- XFillRectangle(display,mw,gc_filler,0,MWHeight-y_size,MWWidth,y_size);
- XFillRectangle(display,mw,gc_filler,0,0,x_size-1,MWHeight);
- XFillRectangle(display,mw,gc_filler,MWWidth-x_size,0,x_size,MWHeight);
- }
- else
- { XFillRectangle(display,mw,gc_clear,0,0,MWWidth-1,y_size-1);
- XFillRectangle(display,mw,gc_clear,0,MWHeight-y_size,MWWidth-1,y_size-1);
- XFillRectangle(display,mw,gc_clear,0,0,x_size-1,MWHeight-1);
- XFillRectangle(display,mw,gc_clear,MWWidth-x_size,0,x_size-1,MWHeight-1);
- }
- XFlush(display);
- };
-
- writeint(master,PLAYER_READY);
- dx = 0;
- dy = 0;
- fast = 0;
- boost = 0;
- ready = 0;
- wait = 0;
- winner = 0;
-
- jmp_count = 10;
-
- lastmove=0;
- actmove=0;
-
-
- if (!auto_only)
- { XSync(display,1);
- while(XPending(display)) XNextEvent(display,&event);
- }
-
- }
-
- /*** Datagramm schreiben ***/
-
- write_p()
- {
- p.mode = htons(p.mode);
- p.game_count = htons(p.game_count);
- p.game_number = htons(p.game_number);
- p.players = htons(p.players);
- p.ready = htons(p.ready);
- sendto(next,&p,sizeof (Pack),0,&next_sin,sizeof next_sin);
- p.mode = ntohs(p.mode);
- p.game_count = ntohs(p.game_count);
- p.game_number = ntohs(p.game_number);
- p.players = ntohs(p.players);
- p.ready = ntohs(p.ready);
- }
-
- /*** Datagramm lesen (Fehler bei Wartezeit>5 Sekunden) ***/
-
- read_p()
- {
- int nfound,readfds,writefds,execptfds;
- struct timeval timeout;
- int fromlen=0;
-
- readfds=(1<<next);
- writefds=execptfds=0;
- /* bei angefangenem Spiel Timeout nach 5 Sekunden */
- timeout.tv_sec=(p.mode!=(short)PLAY)?(long)60:(long)5;
- timeout.tv_usec=(long)0;
-
- nfound=select(32,&readfds,&writefds,&execptfds,&timeout);
-
- if (nfound<=0) return(1);
- else
- { recvfrom(next,&p,sizeof (Pack),0,NULL,&fromlen);
- p.mode = ntohs(p.mode);
- p.game_count = ntohs(p.game_count);
- p.game_number = ntohs(p.game_number);
- p.players = ntohs(p.players);
- p.ready = ntohs(p.ready);
- return(0);
- };
- }
-
- /*****************************************
- * einen kompletten Spielzug ausfuehren: *
- * - Datagramm empfangen *
- * - Spielfeld aktualisieren *
- * - Eingabeevents auswerten *
- * - eigenen Zug ausfuehren *
- * - Datagramm senden *
- * - Bildschirm aktualisieren *
- *****************************************/
-
- make_move()
- {
- int i,j;
- int root_x,root_y,mx,my;
- Window root,child;
- int mask;
-
- /* Packet holen */
- do
- {
- if (read_p())
- { missing_datagram();
- return(0);
- };
- }
- while (game_num != (int)p.game_number);
-
- p.game_count++;
-
- if (p.mode & (short)GAME_OVER)
- { if (!(winner)) write_p(); /* Alle ausser dem Sieger leiten das Packet noch einmal weiter */
- return(0);
- };
-
- if (p.mode & (short)(SETUP | AUTO_START))
- { if ((p.players==(short)0) && (active==1))
- { XBell(display,0);
- XFlush(display);
- };
-
- if (start_flag)
- { if (p.game_count>(short)400) p.mode=(short)AUTO_START;
- };
-
- if (wait)
- { sleep(2);
- wait=0;
- p.mode=(short)PLAY;
- p.players=(short)players;
- };
-
- };
-
- if (active==0)
- { write_p();
- return(1);
- };
-
- /* Zug ausfuehren */
-
- /* a.) neue Positionen ins Spielfeld eintragen */
- for (i=0;i<MAXPLAYERS;i++)
- if (p.ready & (short)(1<<i))
- { if (p.x[i][0]!=(P_TYPE)NONE)
- { field[p.x[i][0]][p.y[i][0]]=i+1;
- if (p.x[i][1]!=(P_TYPE)NONE)
- { field[p.x[i][1]][p.y[i][1]]=i+1;
- if (p.x[i][2]!=(P_TYPE)NONE)
- { field[p.x[i][2]][p.y[i][2]]=i+1;
- if (p.x[i][3]!=(P_TYPE)NONE)
- field[p.x[i][3]][p.y[i][3]]=i+1;
- };
- };
- };
- }
- else
- { if (p.x[i][0]!=(P_TYPE)NONE)
- { field[p.x[i][0]][p.y[i][0]]=0;
- if (p.x[i][1]!=(P_TYPE)NONE)
- { field[p.x[i][1]][p.y[i][1]]=0;
- if (p.x[i][2]!=(P_TYPE)NONE)
- { field[p.x[i][2]][p.y[i][2]]=0;
- if (p.x[i][3]!=(P_TYPE)NONE)
- field[p.x[i][3]][p.y[i][3]]=0;
- };
- };
- };
- };
-
- /* Computerspiel ? */
- if (active==2)
- { comp_move();
- write_p();
- return(1);
- };
-
- /* b.) MausEvent auswerten */
- if (XPending(display)!=0) execute_event();
-
- /* Spieler automatisch setzen, wenn er es nicht selbst tut. */
- if ((p.mode & (short)AUTO_START) && (ready==0))
- { XQueryPointer(display,mw,&root,&child,&root_x,&root_y,&mx,&my,&mask);
- setplayer((P_TYPE)(mx / x_size),(P_TYPE)(my / y_size),1);
- };
-
- /* c.) eigenen Zug ausfuehren */
- if (p.mode & (short)PLAY)
- { if (ready)
- { move(0);
-
- /* bei gedrueckter mittlerer Taste schnellere Fahrt */
- if (fast)
- { if (XPending(display)!=0) execute_event();
- move(1);
-
- if (boost)
- { if (XPending(display)!=0) execute_event();
- move(2);
- if (XPending(display)!=0) execute_event();
- move(3);
- }
- else
- { p.x[my_count][2]= (P_TYPE)NONE;
- p.y[my_count][2]= (P_TYPE)NONE;
- p.x[my_count][3]= (P_TYPE)NONE;
- p.y[my_count][3]= (P_TYPE)NONE;
- };
- }
- else
- { p.x[my_count][1]= (P_TYPE)NONE;
- p.y[my_count][1]= (P_TYPE)NONE;
- };
- }
- else if (actmove!=lastmove) deleter();
- else p.x[my_count][0]=(P_TYPE)NONE;
-
-
- };
-
- /* Packet senden */
- write_p();
-
- /* Bildschirm bearbeiten */
- for (i=0;i<MAXPLAYERS;i++)
- if (p.ready & (short)(1<<i))
- { if (p.x[i][0]!=(P_TYPE)NONE)
- { if (colored) XSetForeground(display,gc_filler,pixels[i]);
- else XSetTile(display,gc_filler,grey[i]);
- XFillRectangle(display,mw,gc_filler,p.x[i][0]*x_size,p.y[i][0]*y_size,x_size-1,y_size-1);
- if (p.x[i][1]!=(P_TYPE)NONE)
- { XFillRectangle(display,mw,gc_filler,p.x[i][1]*x_size,p.y[i][1]*y_size,x_size-1,y_size-1);
- if (p.x[i][2]!=(P_TYPE)NONE)
- { XFillRectangle(display,mw,gc_filler,p.x[i][2]*x_size,p.y[i][2]*y_size,x_size-1,y_size-1);
- if (p.x[i][3]!=(P_TYPE)NONE)
- { XFillRectangle(display,mw,gc_filler,p.x[i][3]*x_size,p.y[i][3]*y_size,x_size-1,y_size-1);
- };
- };
- };
- };
- }
- else
- { if (colored)
- { if (p.x[i][0]!=(P_TYPE)NONE)
- { XSetForeground(display,gc_filler,cols[p.y[i][0]>>DYSHIFT].pixel);
- XFillRectangle(display,mw,gc_filler,p.x[i][0]*x_size,p.y[i][0]*y_size,x_size-1,y_size-1);
- if (p.x[i][1]!=(P_TYPE)NONE)
- { XSetForeground(display,gc_filler,cols[p.y[i][1]>>DYSHIFT].pixel);
- XFillRectangle(display,mw,gc_filler,p.x[i][1]*x_size,p.y[i][1]*y_size,x_size-1,y_size-1);
- if (p.x[i][2]!=(P_TYPE)NONE)
- { XSetForeground(display,gc_filler,cols[p.y[i][2]>>DYSHIFT].pixel);
- XFillRectangle(display,mw,gc_filler,p.x[i][2]*x_size,p.y[i][2]*y_size,x_size-1,y_size-1);
- if (p.x[i][3]!=(P_TYPE)NONE)
- { XSetForeground(display,gc_filler,cols[p.y[i][3]>>DYSHIFT].pixel);
- XFillRectangle(display,mw,gc_filler,p.x[i][3]*x_size,p.y[i][3]*y_size,x_size-1,y_size-1);
- }
- };
- };
- }
- }
- else
- { if (p.x[i][0]!=(P_TYPE)NONE)
- { XFillRectangle(display,mw,gc_set,p.x[i][0]*x_size,p.y[i][0]*y_size,x_size-1,y_size-1);
- if (p.x[i][1]!=(P_TYPE)NONE)
- { XFillRectangle(display,mw,gc_set,p.x[i][1]*x_size,p.y[i][1]*y_size,x_size-1,y_size-1);
- if (p.x[i][2]!=(P_TYPE)NONE)
- { XFillRectangle(display,mw,gc_set,p.x[i][2]*x_size,p.y[i][2]*y_size,x_size-1,y_size-1);
- if (p.x[i][3]!=(P_TYPE)NONE)
- XFillRectangle(display,mw,gc_set,p.x[i][3]*x_size,p.y[i][3]*y_size,x_size-1,y_size-1);
- };
- };
- }
- }
- };
-
- XSync(display,0);
- return(1);
- }
-
- /********************************************************************
- * Automatisches Setzen des Spielers, wenn Wartezeit ueberschritten *
- ********************************************************************/
-
- setplayer(mx,my,again)
- P_TYPE mx,my;
- int again;
- {
- do
- { if ((mx>0) && (mx<DX-1) && (my>0) && (my<DY-1) && (field[mx][my]==0))
- { xmove[lastmove ]= posx = p.x[my_count][0] = mx;
- ymove[lastmove++]= posy = p.y[my_count][0] = my;
- field[mx][my]=my_count+1;
- if ((--p.players) == 0) wait=1;
- else wait=0;
- ready = 1;
- p.ready |= (short)(1<<my_count);
- again = 0;
- };
- if (again)
- { if ((mx<(DX>>1)) || (again>10)) mx++;
- else mx--;
- if (my<(DY>>1)) my++;
- else my--;
- again++;
- };
- }
- while(again);
- }
-
- /********************
- * Event bearbeiten *
- ********************/
-
- execute_event()
- { int help;
-
- XEvent event;
-
- int fct=0;
-
- do
- {
- XNextEvent(display,&event);
-
- switch (event.type)
- {
- case ButtonPress:
- switch((int)event.xbutton.button)
- {
- case Button3:
- if (!(boost)) fct=2;
- break;
- case Button2:
- if ((ready == 0) && (p.mode & (short)SETUP))
- { P_TYPE mx,my;
- setplayer((P_TYPE)(event.xbutton.x / x_size),(P_TYPE)(event.xbutton.y / y_size),0);
- }
- else
- fct=3;
- break;
- case Button1:
- if (!(boost)) fct=1;
- break;
- }; /* end switch(button) */
- break; /* end ButtonPress */
-
- case KeyPress:
- { char sign;
- KeySym keysym;
-
- static Time last_time;
-
- XLookupString(&event,&sign,1,&keysym,NULL);
-
- if ((event.xkey.time==last_time) || (event.xkey.time==last_time + 1)) break;
-
- switch(keysym)
- {
- /*** KEYS to turn left ***/
- case XK_Z:
- case XK_z:
- case XK_X:
- case XK_x:
- case XK_M:
- case XK_m:
- case XK_less:
- case XK_comma:
- fct=1;
- last_time=event.xkey.time;
- break;
-
- /*** KEYS to turn right ***/
- case XK_C:
- case XK_c:
- case XK_V:
- case XK_v:
- case XK_greater:
- case XK_period:
- case XK_question:
- case XK_slash:
- fct=2;
- last_time=event.xkey.time;
- break;
-
- /*** jump ***/
- case XK_space:
- fct=3;
- break;
- /*** double speed ***/
- case XK_Shift_L:
- fast=1; boost=0; break;
- break;
-
- /*** double double speed ***/
- case XK_Control_L:
- fast=boost=((event.xkey.state & ShiftMask)?1:0);
- break;
- };
- };
- break;
-
- case KeyRelease:
- { char sign;
- KeySym keysym;
-
- XLookupString(&event,&sign,1,&keysym,NULL);
- switch(keysym)
- {
- case XK_Shift_L: fast=0; boost=0; break;
- case XK_Control_L: fast=((event.xkey.state & ShiftMask)?1:0); boost=0; break;
- };
- };
- };
- }
- while ((XPending(display)) && (event.type==KeyRelease));
-
- switch(fct)
- {
- case 1:
- help= dx ;
- dx = dy ;
- dy = -help;
- break;
- case 2:
- help=dy ;
- dy =dx ;
- dx = -help;
- break;
- case 3:
- if (jmp_count == 0)
- { XBell(display,80);
- }
- else
- {
- posx += (P_TYPE)(3*dx) ;
- posy += (P_TYPE)(3*dy) ;
- jmp_count--;
- }
- break;
- }; /* end switch(fct) */
- }
-
- /********************************
- * bust - Spieler ist zerstoert *
- ********************************/
-
- bust()
- { if (active==1)
- { XBell(display,40);
- XFlush(display);
- };
- ready = 0;
- p.ready &= (short)~(1<<my_count);
- p.x[my_count][0]= (P_TYPE)NONE;
-
- if (--p.players==0)
- { p.mode=(short)GAME_OVER; /* falls letzter Spieler => Spiel ist aus */
- winner=1;
- };
- writeint(master,DESTROYED);
- writeint(master,(int)p.game_count);
- }
-
- missing_datagram()
- {
- writeint(master,ERROR);
- }
-
- /*********************************************************************************
- * Zug ausfuehren (ind = Index bei gleichzeitigen Zuegen (maxmal 4 bei boost=1)) *
- *********************************************************************************/
-
- move(ind)
- int ind;
- { int root_x,root_y,mx,my;
- Window root,child;
- int mask;
-
- if ((dx == 0) && (dy == 0))
- { XQueryPointer(display,mw,&root,&child,&root_x,&root_y,&mx,&my,&mask);
- mx= (mx/x_size-posx );
- my= -(my/y_size-posy );
- if (mx>my)
- { if (mx> -my)
- { dx =1; dy =0; }
- else
- { dx =0; dy =1; }
- }
- else
- { if (mx> -my)
- { dx =0; dy = -1; }
- else
- { dx = -1; dy =0; };
- };
- fast = (mask & ShiftMask)?1:0;
- boost = ((mask & ControlMask)&&(fast))?1:0;
- };
- posx += (P_TYPE)dx ;
- posy += (P_TYPE)dy ;
-
- if ((posx!=(P_TYPE)0) && (posy!=(P_TYPE)0) && (posx<(P_TYPE)DX-1) && (posy<(P_TYPE)DY-1) && (field[posx][posy]==0) && ((p.players>(short)1) || (players==1)))
- { field[posx][posy]=my_count+1;
- xmove[lastmove] =p.x[my_count][ind]=posx;
- ymove[lastmove++]=p.y[my_count][ind]=posy;
- }
- else if (ind==0) bust();
- else
- { posx -= (P_TYPE)dx ;
- posy -= (P_TYPE)dy ;
- };
- }
-
- /************************************
- * zu loeschende Felder vorbereiten *
- ************************************/
-
- deleter()
- { int i;
-
- for (i=0;i<DIMENSION;i++)
- { if (actmove<lastmove)
- { p.x[my_count][i]=xmove[actmove];
- p.y[my_count][i]=ymove[actmove++];
- }
- else
- { p.x[my_count][i]=(P_TYPE)NONE;
- p.y[my_count][i]=(P_TYPE)NONE;
- };
- }
- }
-
- /***************************
- * Computerzug-Algorithmus *
- ***************************/
-
- changedir()
- { int dir[4],dir2[4],r1,r2,ok;
-
- dir2[0]=(dir[0]=(field[posx+1][posy ]==0)) & (field[posx+2][posy ]==0);
- dir2[1]=(dir[1]=(field[posx ][posy+1]==0)) & (field[posx ][posy+2]==0);
- dir2[2]=(dir[2]=(field[posx-1][posy ]==0)) & (field[posx-2][posy ]==0);
- dir2[3]=(dir[3]=(field[posx ][posy-1]==0)) & (field[posx ][posy-2]==0);
-
- r1=r2=(random() & 3);
- ok=0;
- do
- { if (dir2[r1])
- { ok=1;
- break;
- };
- }
- while ((r1= ((r1+1)&3))!=r2);
-
- if (ok==0)
- do
- { if (dir[r1]) break;
- }
- while ((r1= ((r1+1)&3))!=r2);
-
- switch(r1)
- {
- case 0: dx= 1; dy= 0; break;
- case 1: dx= 0; dy= 1; break;
- case 2: dx= -1; dy= 0; break;
- case 3:
- default: dx= 0; dy= -1; break;
- };
-
- posx+=(P_TYPE)dx;
- posy+=(P_TYPE)dy;
- }
-
- comp_move()
- {
- if (p.mode==(short)PLAY)
- { if (ready)
- {
- if ((dx==0) && (dy==0))
- { switch(random() & 3)
- {
- case 0: dx= 1; dy= 0; break;
- case 1: dx= 0; dy= 1; break;
- case 2: dx= -1; dy= 0; break;
- case 3:
- default: dx= 0; dy= -1; break;
- };
- };
- if ((random()%30)>0)
- { int helpx,helpy;
-
- if (field[helpx=((int)posx+dx)][helpy=((int)posy+dy)]==0)
- { if (field[helpx+dx][helpy+dy]==0)
- { posx=(P_TYPE)helpx;
- posy=(P_TYPE)helpy;
- }
- else
- changedir();
- }
- else
- changedir();
- }
- else
- changedir();
-
- if ((field[posx][posy]==0) && ((p.players>(short)1) || (players==1)))
- { field[posx][posy]=my_count+1;
- xmove[lastmove] =p.x[my_count][0]=posx;
- ymove[lastmove++]=p.y[my_count][0]=posy;
- }
- else bust();
- }
- else if (actmove!=lastmove) deleter();
- else p.x[my_count][0]=(P_TYPE)NONE;
- }
- else if ((p.mode==(short)SETUP) && (ready==0))
- {
- setplayer(1+(random()%(DX-2)),1+(random()%(DY-2)),1);
- };
- }
-