1 /* XDigger  Copyright (C) 1988-99 Alexander Lang.
2 
3 XDigger is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7 
8 XDigger is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License
14 along with this program; see the file COPYING.  If not, write to
15 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
16 
17 #include <stdio.h>
18 #include <string.h>
19 #include <sys/time.h>
20 #include <unistd.h>
21 
22 #include <X11/keysym.h>
23 #include <X11/Xatom.h>
24 #include <X11/Xlib.h>
25 #include <X11/Xutil.h>
26 
27 #include "configure.h"
28 #include "defines.h"
29 #include "drawpixmaps.h"
30 #include "drawtext.h"
31 #include "icon.h"
32 #include "runlevels.h"
33 #include "sound.h"
34 #include "typedef.h"
35 #include "xdigger.h"
36 
37 FieldEntry field[20][14];
38 GhostEntry ghosts[16];
39 int akt_level_number, new_level_number, lives, wait_count;
40 Bool last_level = False;
41 int number_diamonds, collected_diamonds, collected_grounds, number_ghosts;
42 int lefttime, score;
43 int diggerposx, diggerposy;
44 int ldiggerposx = -1, ldiggerposy = -1;
45 Bool levelready, alllevelsready, digger_death, digger_candie = True;
46 Bool intakt = False;
47 Bool inpause = False, step = False;
48 int lastdiggerarrow;
49 Bool in_runlevels = False;
50 Bool in_LevelEditor = False;
51 Bool indiggeridlesequence;
52 Bool cheat = False, ones_cheated = False;
53 Bool ton_schritt, ton_steine, ton_diamant;
54 Bool replay = False;
55 
ChangePS()56 void ChangePS()
57 {
58   char slevel[3], scmdln[7];
59 
60   sprintf(slevel, "%d", akt_level_number);
61   if (cheat)
62     strcat(strcat(strcpy(scmdln, " (C"), slevel), ")");
63   else
64     strcat(strcat(strcpy(scmdln, " (L"), slevel), ")");
65   strcpy(LastArgv, scmdln);
66 } /* ChangePS() */
67 
id2pixmap_id(int id,int flags)68 unsigned char id2pixmap_id(int id, int flags)
69 {
70   switch (id)
71   {
72     case ID_NOTHING : return(PXID_NOTHING);
73     case ID_STONE : return(PXID_STONE);
74     case ID_GROUND : return(PXID_GROUND);
75     case ID_GHOST :
76       {
77         switch (flags & F_GHOST_TYPEMASK)
78         {
79         case F_GHOST_NOTYPE:
80           switch (flags & F_GHOST_MOVEMASK)
81           {
82           case F_GHOST_DOWN:  return(PXID_GHOST);
83           case F_GHOST_UP:    return(PXID_GHOST_UP);
84           case F_GHOST_LEFT:  return(PXID_GHOST_LEFT);
85           case F_GHOST_RIGHT: return(PXID_GHOST_RIGHT);
86           }
87         case F_GHOST_TYPE180:
88           switch (flags & F_GHOST_MOVEMASK)
89           {
90           case F_GHOST_DOWN:  return(PXID_GHOST_DOWN_180);
91           case F_GHOST_UP:    return(PXID_GHOST_UP_180);
92           case F_GHOST_LEFT:  return(PXID_GHOST_LEFT_180);
93           case F_GHOST_RIGHT: return(PXID_GHOST_RIGHT_180);
94           }
95         case F_GHOST_TYPEL:
96           switch (flags & F_GHOST_MOVEMASK)
97           {
98           case F_GHOST_DOWN:  return(PXID_GHOST_DOWN_L);
99           case F_GHOST_UP:    return(PXID_GHOST_UP_L);
100           case F_GHOST_LEFT:  return(PXID_GHOST_LEFT_L);
101           case F_GHOST_RIGHT: return(PXID_GHOST_RIGHT_L);
102           }
103         case F_GHOST_TYPER:
104           switch (flags & F_GHOST_MOVEMASK)
105           {
106           case F_GHOST_DOWN:  return(PXID_GHOST_DOWN_R);
107           case F_GHOST_UP:    return(PXID_GHOST_UP_R);
108           case F_GHOST_LEFT:  return(PXID_GHOST_LEFT_R);
109           case F_GHOST_RIGHT: return(PXID_GHOST_RIGHT_R);
110           }
111         case F_GHOST_TYPELR:
112           switch (flags & F_GHOST_MOVEMASK)
113           {
114           case F_GHOST_DOWN:  return(PXID_GHOST_DOWN_LR);
115           case F_GHOST_UP:    return(PXID_GHOST_UP_LR);
116           case F_GHOST_LEFT:  return(PXID_GHOST_LEFT_LR);
117           case F_GHOST_RIGHT: return(PXID_GHOST_RIGHT_LR);
118           }
119         }
120       }
121     case ID_DIAMOND : /*return(PXID_DIAMOND);*/
122       {
123         switch (flags & F_DIAMOND_BLINKMASK)
124         {
125           case F_DIAMOND_NOBLINK:  return(PXID_DIAMOND);
126           case F_DIAMOND_BLINK0:   return(PXID_DIAMOND_BLINK0);
127           case F_DIAMOND_BLINK1:   return(PXID_DIAMOND_BLINK1);
128           case F_DIAMOND_BLINK2:   return(PXID_DIAMOND_BLINK2);
129           case F_DIAMOND_BLINK3:   return(PXID_DIAMOND_BLINK3);
130           case F_DIAMOND_BLINK4:   return(PXID_DIAMOND_BLINK4);
131           case F_DIAMOND_BLINK5:   return(PXID_DIAMOND_BLINK5);
132         }
133       }
134     case ID_WALL : return(PXID_WALL);
135     case ID_DIGGER :
136       {
137 	if ((flags & F_DIGGER_DEATH) == 0)
138 	  switch (flags & F_DIGGER_MOVEMASK)
139 	    {
140 	    case F_DIGGER_LEFT0:  return(PXID_DIGGER_LEFT0);
141 	    case F_DIGGER_LEFT1:  return(PXID_DIGGER_LEFT1);
142 	    case F_DIGGER_LEFT2:  return(PXID_DIGGER_LEFT2);
143 	    case F_DIGGER_LEFT3:  return(PXID_DIGGER_LEFT3);
144 	    case F_DIGGER_RIGHT0: return(PXID_DIGGER_RIGHT0);
145 	    case F_DIGGER_RIGHT1: return(PXID_DIGGER_RIGHT1);
146 	    case F_DIGGER_RIGHT2: return(PXID_DIGGER_RIGHT2);
147 	    case F_DIGGER_RIGHT3: return(PXID_DIGGER_RIGHT3);
148 	    case F_DIGGER_UP1:    return(PXID_DIGGER_UP1);
149 	    case F_DIGGER_UP2:    return(PXID_DIGGER_UP2);
150 	    case F_DIGGER_DOWN0:  return(PXID_DIGGER);
151 	    case F_DIGGER_DOWN1:  return(PXID_DIGGER_DOWN1);
152 	    case F_DIGGER_DOWN2:  return(PXID_DIGGER_DOWN2);
153 	    case F_DIGGER_FOOT:   return(PXID_DIGGER_FOOT);
154 	    case F_DIGGER_EYE1:   return(PXID_DIGGER_EYE1);
155 	    case F_DIGGER_EYE2:   return(PXID_DIGGER_EYE2);
156 	    }
157 	else return(PXID_DIGGER_DEATH);
158       }
159     case ID_EXIT : return(PXID_EXIT);
160     case ID_CHANGER : return(PXID_CHANGER);
161     }
162   return(PXID_NOTHING);
163 } /* unsigned char id2pixmap_id(int id, int flags) */
164 
CopyField(FieldEntry * dest,FieldEntry * source)165 void CopyField(FieldEntry *dest, FieldEntry *source)
166 {
167   dest->id        = source->id;
168   dest->flags     = source->flags;
169   dest->pixmap_id = source->pixmap_id;
170   /*dest->todraw    = True; ???*/
171 } /* CopyField(FieldEntry *dest, FieldEntry *source) */
172 
FillField(FieldEntry * fieldentry,unsigned char id,unsigned char flags)173 void FillField(FieldEntry *fieldentry, unsigned char id, unsigned char flags)
174 {
175   fieldentry->id = id;
176   fieldentry->flags = flags;
177   fieldentry->pixmap_id = id2pixmap_id(id, flags);
178   fieldentry->todraw = True;
179 } /* FillField(FieldEntry *fieldentry, unsigned char id, unsigned char flags)*/
180 
FillFieldNothing(FieldEntry * fieldentry)181 void FillFieldNothing(FieldEntry *fieldentry)
182 {
183   fieldentry->id        = ID_NOTHING;
184   fieldentry->flags     = 0;
185   fieldentry->pixmap_id = id2pixmap_id(ID_NOTHING, 0);
186 } /* FillFieldNothing(FieldEntry *fieldentry) */
187 
Test_ReadWrite(char * filename)188 Bool Test_ReadWrite(char *filename)
189 {
190   FILE *filehandle;
191 
192   if ((filehandle = fopen(filename, "r+")) != NULL)
193   {
194     fclose(filehandle);
195     return(True);
196   }
197   else return(False);
198 } /* Bool Test_ReadWrite(char *filename) */
199 
LoadLevel(int level_number,Bool edit)200 Bool LoadLevel(int level_number, Bool edit)
201 {
202 /*   char filename[256]; */
203   unsigned char file_daten[0x9c], *c, ginfo, b;
204   int x, y, id, flags;
205   FILE *filehandle;
206 
207 /*   XDefineCursor(display, mainwindow, cursor_watch); */
208 
209   akt_level_number = level_number;
210   new_level_number = 0;
211   number_ghosts = 0;
212 
213   if ((filehandle = fopen(level_filename, "r")) == NULL) return(False);
214 
215   if ((edit) && !(Test_ReadWrite(level_filename)))
216   {
217     fclose(filehandle);
218     fprintf(stderr, "%s: can't open %s for rw\n", progname, level_filename);
219     return(False);
220   }
221 
222   fseek(filehandle, (level_number -1 ) * 0x9c, SEEK_SET);
223   fread(file_daten, 0x9c, 1, filehandle);
224   fclose(filehandle);
225 
226   c = file_daten;
227   for (y=0; y<14; y++) for (x=0; x<20; x++)
228     {
229       if (!(x & 1))
230         id = *c >> 4;
231       else
232       {
233         id = *c & 0xf;
234         c++;
235       }
236 
237       flags = 0;
238 
239       if ((id == 3) || (id == 7) || (id == 11) || (id == 15))
240 	{
241 	  ginfo = file_daten[0x94 + number_ghosts/2];
242 	  if (number_ghosts & 1) ginfo = ginfo & 0xf; else ginfo = ginfo >> 4;
243 	  ghosts[number_ghosts].x = x;
244 	  ghosts[number_ghosts].y = y;
245 	  ghosts[number_ghosts].type = id >> 2;
246 	  ghosts[number_ghosts].arrow = ginfo;
247 	  ghosts[number_ghosts].lastturn = LGHOSTL;
248 	  ghosts[number_ghosts].dead = False;
249           if (edit)
250           {
251             switch (id)
252             {
253             case 3:
254               flags = F_GHOST_TYPE180;
255               break;
256             case 7:
257               flags = F_GHOST_TYPEL;
258               break;
259             case 11:
260               flags = F_GHOST_TYPELR;
261               break;
262             case 15:
263               flags = F_GHOST_TYPER;
264               break;
265             }
266             switch (ginfo)
267             {
268             case AGHOSTL:
269               flags |= F_GHOST_LEFT;
270               break;
271             case AGHOSTR:
272               flags |= F_GHOST_RIGHT;
273               break;
274             case AGHOSTU:
275               flags |= F_GHOST_UP;
276               break;
277             case AGHOSTD:
278               flags |= F_GHOST_DOWN;
279               break;
280             }
281           }
282           id = 3;
283 	  number_ghosts++;
284 	}
285 
286       field[x][y].id         = id;
287       field[x][y].flags      = flags;
288       field[x][y].pixmap_id  =
289 	id2pixmap_id(field[x][y].id, field[x][y].flags);
290       field[x][y].todraw     = True;
291     }
292   c += 3;
293   last_level = ((*c == 0) && (*(c+1) == 0));
294   c += 2;
295   diggerposx = *(c++);
296   diggerposy = *(c++)-2;
297   b = *(c++);
298   number_diamonds = (b/0x10)*10 + (b%0x10);
299   ldiggerposx = -1; ldiggerposy = -1;
300   levelready = False;
301   digger_death = False;
302   lastdiggerarrow = ADIGGERN;
303   indiggeridlesequence = False;
304   collected_diamonds = 0;
305   collected_grounds = 0;
306   lefttime = 5000;
307   if (!replay) wait_count = 256;
308 /*   XDefineCursor(display, mainwindow, cursor_digger); */
309   return(True);
310 } /* loadlevel(int level_number, Bool edit) */
311 
DrawField()312 void DrawField()
313 {
314   int x, y;
315 
316   for (y=0; y<14; y++) for (x=0; x<20; x++)
317     if (field[x][y].todraw)
318       {
319 	DrawOnePixmap(field[x][y].pixmap_id, x, y);
320 	field[x][y].todraw = False;
321       }
322 } /* DrawField() */
323 
Restore_LeftTime()324 void Restore_LeftTime()
325 {
326   char slefttime[7];
327 
328   sprintf(slefttime, "%.6d", lefttime);
329   if ((lefttime < 1000) && ((lefttime % 4) <= 1) && (lefttime != 0))
330     strcpy(slefttime, "      ");
331   WriteTextStr(slefttime, 18, vertvar, kcf_weiss, kcb_rot);
332 } /* Restore_LeftTime() */
333 
Restore_Diamonds()334 void Restore_Diamonds()
335 {
336   char snumber_diamonds[3];
337 
338   sprintf(snumber_diamonds, "%.2d", number_diamonds);
339   WriteTextStr(snumber_diamonds, 36, vertvar, kcf_weiss, kcb_rot);
340 } /* Restore_Diamonds() */
341 
Restore_Score()342 void Restore_Score()
343 {
344   char sscore[7];
345 
346   sprintf(sscore, "%.6d", score);
347   WriteTextStr(sscore, 18, 1+vertvar, kcf_weiss, kcb_rot);
348 } /* Restore_Score() */
349 
Restore_Collected_Diamonds()350 void Restore_Collected_Diamonds()
351 {
352   char scollected_diamonds[3];
353 
354   sprintf(scollected_diamonds, "%.2d", collected_diamonds);
355   WriteTextStr(scollected_diamonds, 36, 1+vertvar, kcf_weiss, kcb_rot);
356 } /* Restore_Collected_Diamonds() */
357 
Init_First_Line()358 void Init_First_Line()
359 {
360   char croom[41], clives[41], slevel_number[3], slives[20];
361 
362   sprintf(slevel_number, "%.2d", akt_level_number);
363   sprintf(slives, "%.2d", lives);
364   strcat(strcpy(croom, " ROOM:  "), slevel_number);
365   strcat(strcpy(clives, " LIVES: "), slives);
366 
367   if (!vert240)
368     WriteTextStr("\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135", 0, 0, kcf_tuerkis, kcb_blau);
369 
370   WriteTextStr(croom, 0, vertvar, kcf_weiss, kcb_rot);
371   WriteTextStr(" TIME:  ", 10, vertvar, kcf_weiss, kcb_rot);
372   Restore_LeftTime();
373   WriteTextStr(" DIAMONDS:  ", 24, vertvar, kcf_weiss, kcb_rot);
374   Restore_Diamonds();
375   WriteTextStr("  ", 38, vertvar, kcf_weiss, kcb_rot);
376 
377   WriteTextStr(clives, 0, 1+vertvar, kcf_weiss, kcb_rot);
378   Restore_Collected_Diamonds();
379   WriteTextStr(" SCORE: ", 10, 1+vertvar, kcf_weiss, kcb_rot);
380   WriteTextStr(" COLLECTED: ", 24, 1+vertvar, kcf_weiss, kcb_rot);
381   Restore_Score();
382   WriteTextStr("  ", 38, 1+vertvar, kcf_weiss, kcb_rot);
383   if (!vert240)
384     WriteTextStr("\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135\135", 0, 3, kcf_tuerkis, kcb_blau);
385 
386 } /* Init_First_Line() */
387 
Handle_ExposeEvent(XExposeEvent * xexpose)388 void Handle_ExposeEvent(XExposeEvent *xexpose)
389 {
390   int x, xa, xe, y, ya, ye;
391   XWindowAttributes windowattributes;
392 
393   /* Resize ? */
394   XGetWindowAttributes(display, mainwindow, &windowattributes);
395   if (xpmmag != windowattributes.width / 320)
396     ResizeXPixmaps(windowattributes.width / 320);
397 
398   if (xexpose->y < (vertvar+1)*16 * xpmmag)
399     /*restore_first_line = True;*/
400     Mark_CharField(xexpose, 1+2*vertvar);
401 
402   xa = (xexpose->x / (16*xpmmag));
403   xe = ((xexpose->x + xexpose->width - 1) / (16*xpmmag));
404   if (xa > 19) return;
405   if (xe > 19) xe = 19;
406   ya = (xexpose->y / (16*xpmmag)) - (1+vertvar); if (ya < 0) ya = 0;
407   ye = ((xexpose->y + xexpose->height - 1) / (16*xpmmag)) - (1+vertvar);
408   if (ya > 13) return;
409   if (ye > 13) ye = 13;
410   if (ye < 0) ye = 0;
411   for (y=ya; y<=ye; y++) for (x=xa; x<=xe; x++)
412     field[x][y].todraw = True;
413   if (xexpose->count == 0)
414     {
415       DrawTextField();
416       DrawField();
417     }
418 } /* Handle_ExposeEvent(XExposeEvent *xexpose) */
419 
DieDigger()420 void DieDigger()
421 {
422   if ((digger_candie) && (!digger_death))
423     {
424       digger_death = True;
425       field[diggerposx][diggerposy].flags = F_DIGGER_DEATH;
426       field[diggerposx][diggerposy].pixmap_id =
427 	id2pixmap_id(ID_DIGGER, F_DIGGER_DEATH);
428       field[diggerposx][diggerposy].todraw = True;
429     }
430 } /* DieDigger() */
431 
NoGroundsLeft()432 Bool NoGroundsLeft()
433 {
434   int x, y;
435 
436   for (y=0; y<14; y++) for (x=0; x<20; x++)
437     if (field[x][y].id == ID_GROUND) return(False);
438   return(True);
439 } /* NoGroundsLeft() */
440 
441 Bool kb_left, kb_right, kb_up, kb_down;
442 Bool stone_r = False, stone_l = False;
443 
444 int fdiggerleftsequence[6] =
445 {F_DIGGER_LEFT1, F_DIGGER_LEFT2, F_DIGGER_LEFT3, F_DIGGER_LEFT2,
446  F_DIGGER_LEFT1, F_DIGGER_LEFT0};
447 int fdiggerrightsequence[6] =
448 {F_DIGGER_RIGHT1, F_DIGGER_RIGHT2, F_DIGGER_RIGHT3, F_DIGGER_RIGHT2,
449  F_DIGGER_RIGHT1, F_DIGGER_RIGHT0};
450 int fdiggerupsequence[2] = {F_DIGGER_UP1, F_DIGGER_UP2};
451 int fdiggerdownsequence[2] = {F_DIGGER_DOWN1, F_DIGGER_DOWN2};
452 int fdiggeridlesequence[2][13] =
453 {{10, F_DIGGER_FOOT, F_DIGGER_FOOT, F_DIGGER_DOWN0, F_DIGGER_DOWN0,
454   F_DIGGER_FOOT, F_DIGGER_FOOT, F_DIGGER_DOWN0, F_DIGGER_DOWN0,
455   F_DIGGER_FOOT, F_DIGGER_FOOT, F_DIGGER_DOWN0, F_DIGGER_DOWN0},
456  {8, F_DIGGER_EYE1, F_DIGGER_EYE2, F_DIGGER_EYE1, F_DIGGER_DOWN0,
457   F_DIGGER_EYE1, F_DIGGER_EYE2, F_DIGGER_EYE1, F_DIGGER_DOWN0, 0, 0}};
458 
459 int fdiggersequenceidx, fdiggeridleidx;
460 
DiggerStep()461 void DiggerStep()
462 {
463   int dx, dy, zx, zy;
464   int arrow, pixid;
465 
466   /* Loesche alte Schattenposition */
467   if ((ldiggerposx >= 0) && (ldiggerposy >= 0))
468     {
469       field[ldiggerposx][ldiggerposy].id = ID_NOTHING;
470       ldiggerposx = -1;
471       ldiggerposy = -1;
472     }
473 
474   if (digger_death) return;
475   dx = diggerposx; dy = diggerposy; zx = dx; zy = dy;
476   if (kb_left) {zx--; arrow = ADIGGERL;}
477   else if (kb_right) {zx++; arrow = ADIGGERR;}
478   else if (kb_up) {zy--; arrow = ADIGGERU;}
479   else if (kb_down) {zy++; arrow = ADIGGERD;}
480   else arrow = ADIGGERN;
481 
482   if (stone_r && !kb_right) stone_r = False;
483   if (stone_l && !kb_left)  stone_l = False;
484 
485   if ((zx != dx) || (zy != dy))
486       {
487 	if (field[zx][zy].id == ID_DIAMOND)
488 	  {
489 	    collected_diamonds++;
490 	    Restore_Collected_Diamonds();
491 	    score = score + 3;
492 	    Restore_Score();
493 	    ton_diamant = True;
494 	  }
495 	if ((field[zx][zy].id == ID_GROUND) && laszlo)
496 	  {
497 	    collected_grounds++;
498 	    if (collected_grounds == 10)
499 	      {
500 		collected_grounds = 0;
501 		score++;
502 		Restore_Score();
503 	      }
504 	  }
505 	if (field[zx][zy].id == ID_STONE)
506 	  {
507 	    if ((zx>dx) && (field[zx+1][zy].id == ID_NOTHING))
508 		{
509 		  if (stone_r)
510 		    {
511 		      CopyField(&field[dx+2][dy], &field[dx+1][dy]);
512 		      field[dx+2][dy].todraw = True;
513 
514 		      field[dx+1][dy].id = ID_NOTHING;
515 		      field[dx+1][dy].flags = 0;
516 		      field[dx+1][dy].pixmap_id = id2pixmap_id(ID_NOTHING, 0);
517 		      field[dx+1][dy].todraw = True;
518 
519 		      stone_r = False;
520 		    }
521 		  else stone_r = True;
522 		}
523 	    if ((zx<dx) && (field[zx-1][zy].id == ID_NOTHING))
524 		{
525 		  if (stone_l)
526 		    {
527 		      CopyField(&field[dx-2][dy], &field[dx-1][dy]);
528 		      field[dx-2][dy].todraw = True;
529 
530 		      field[dx-1][dy].id = ID_NOTHING;
531 		      field[dx-1][dy].flags = 0;
532 		      field[dx-1][dy].pixmap_id = id2pixmap_id(ID_NOTHING, 0);
533 		      field[dx-1][dy].todraw = True;
534 
535 		      stone_l = False;
536 		    }
537 		  else stone_l = True;
538 		}
539 	  }
540 	if ((field[zx][zy].id == ID_NOTHING) ||
541 	    (field[zx][zy].id == ID_GROUND) ||
542 	    (field[zx][zy].id == ID_DIAMOND))
543 	  {
544 	    CopyField(&field[zx][zy], &field[dx][dy]);
545 	    field[zx][zy].todraw    = True;
546 
547 	    field[dx][dy].id        = ID_LDIGGER;
548 	    field[dx][dy].flags     = 0;
549 	    field[dx][dy].pixmap_id = id2pixmap_id(ID_NOTHING, 0);
550 	    field[dx][dy].todraw    = True;
551 
552 	    diggerposx  = zx;
553 	    diggerposy  = zy;
554 	    ldiggerposx = dx;
555 	    ldiggerposy = dy;
556 
557 	    ton_schritt = True;
558 	  }
559 	if ((field[zx][zy].id == ID_EXIT) &&
560 	    (collected_diamonds >= number_diamonds))
561 	  {
562 	    if ((laszlo) && NoGroundsLeft())
563 	      {
564 		score = score + 100;
565 		Restore_Score();
566 	      }
567 	    levelready = True;
568 	  }
569 	if (field[zx][zy].id == ID_GHOST) DieDigger();
570       }
571 
572   if (!digger_death)
573     {
574       dx = diggerposx;
575       dy = diggerposy;
576       pixid = field[dx][dy].pixmap_id;
577       switch (arrow)
578 	{
579 	case ADIGGERL:
580 	  if (lastdiggerarrow == ADIGGERL)
581 	    {if (++fdiggersequenceidx == 6) fdiggersequenceidx = 0;}
582 	  else fdiggersequenceidx = 0;
583 	  field[dx][dy].flags = (field[dx][dy].flags & !F_DIGGER_MOVEMASK) |
584 	    fdiggerleftsequence[fdiggersequenceidx];
585 	  break;
586 	case ADIGGERR:
587 	  if (lastdiggerarrow == ADIGGERR)
588 	    {if (++fdiggersequenceidx == 6) fdiggersequenceidx = 0;}
589 	  else fdiggersequenceidx = 0;
590 	  field[dx][dy].flags = (field[dx][dy].flags & !F_DIGGER_MOVEMASK) |
591 	    fdiggerrightsequence[fdiggersequenceidx];
592 	  break;
593 	case ADIGGERU:
594 	  if (lastdiggerarrow == ADIGGERU)
595 	    {if (++fdiggersequenceidx == 2) fdiggersequenceidx = 0;}
596 	  else fdiggersequenceidx = 0;
597 	  field[dx][dy].flags = (field[dx][dy].flags & !F_DIGGER_MOVEMASK) |
598 	    fdiggerupsequence[fdiggersequenceidx];
599 	  break;
600 	case ADIGGERD:
601 	  if (lastdiggerarrow == ADIGGERD)
602 	    {if (++fdiggersequenceidx == 2) fdiggersequenceidx = 0;}
603 	  else fdiggersequenceidx = 0;
604 	  field[dx][dy].flags = (field[dx][dy].flags & !F_DIGGER_MOVEMASK) |
605 	    fdiggerdownsequence[fdiggersequenceidx];
606 	  break;
607 	case ADIGGERN:
608 	  if (lastdiggerarrow == ADIGGERN)
609 	    {
610 	      if ((!indiggeridlesequence) && (MyRand(10) == 1))
611 		{
612 		  fdiggeridleidx = MyRand(2);
613 		  fdiggersequenceidx = 0;
614 		  indiggeridlesequence = True;
615 		}
616 	      if (indiggeridlesequence)
617 		{
618 		  if (++fdiggersequenceidx >
619 		      fdiggeridlesequence[fdiggeridleidx][0])
620 		    indiggeridlesequence = False;
621 		}
622 	    }
623 	  else indiggeridlesequence = False;
624 	  if (indiggeridlesequence)
625 	    field[dx][dy].flags =
626 	      (field[dx][dy].flags & !F_DIGGER_MOVEMASK) |
627 	      fdiggeridlesequence[fdiggeridleidx][fdiggersequenceidx];
628 	  else
629 	    field[dx][dy].flags =
630 	      (field[dx][dy].flags & !F_DIGGER_MOVEMASK) | F_DIGGER_DOWN0;
631 	  break;
632 	}
633       field[dx][dy].pixmap_id =
634 	id2pixmap_id(field[dx][dy].id, field[dx][dy].flags);
635       if (field[dx][dy].pixmap_id != pixid) field[dx][dy].todraw = True;
636       lastdiggerarrow = arrow;
637     }
638 } /* DiggerStep() */
639 
DiggerHalfStep()640 void DiggerHalfStep()
641 {
642   int dx, dy;
643   int arrow, pixid;
644 
645   if (!digger_death)
646     {
647       dx = diggerposx;
648       dy = diggerposy;
649       pixid = field[dx][dy].pixmap_id;
650       arrow = lastdiggerarrow;
651       switch (arrow)
652 	{
653 	case ADIGGERL:
654 	  if (lastdiggerarrow == ADIGGERL)
655 	    {if (++fdiggersequenceidx == 6) fdiggersequenceidx = 0;}
656 	  else fdiggersequenceidx = 0;
657 	  field[dx][dy].flags = (field[dx][dy].flags & !F_DIGGER_MOVEMASK) |
658 	    fdiggerleftsequence[fdiggersequenceidx];
659 	  break;
660 	case ADIGGERR:
661 	  if (lastdiggerarrow == ADIGGERR)
662 	    {if (++fdiggersequenceidx == 6) fdiggersequenceidx = 0;}
663 	  else fdiggersequenceidx = 0;
664 	  field[dx][dy].flags = (field[dx][dy].flags & !F_DIGGER_MOVEMASK) |
665 	    fdiggerrightsequence[fdiggersequenceidx];
666 	  break;
667 	}
668       field[dx][dy].pixmap_id =
669 	id2pixmap_id(field[dx][dy].id, field[dx][dy].flags);
670       if (field[dx][dy].pixmap_id != pixid) field[dx][dy].todraw = True;
671       lastdiggerarrow = arrow;
672     }
673 } /* DiggerHalfStep() */
674 
675 typedef struct
676 {
677   unsigned char x, y, id, type;
678 } TMerk;
679 
Merke(unsigned char type,int x,int y,int * merkidx,TMerk * merk)680 void Merke(unsigned char type, int x, int y, int *merkidx, TMerk *merk)
681 {
682   merk[*merkidx].x = x;
683   merk[*merkidx].y = y;
684   merk[*merkidx].id = field[x][y].id & 7;
685   merk[*merkidx].type = type;
686   *merkidx++;
687 }
688 
StoneDiamondStep()689 void StoneDiamondStep()
690 {
691 
692 #define SF_DOWN      0
693 #define SF_RIGHTDOWN 1
694 #define SF_LEFTDOWN  2
695 #define SF_CHANGER   3
696 
697   TMerk merk[140], ghosts_todie[17];
698   int i, x, y, dx, dy, merkidx, ghosts_todie_idx;
699   Bool digger_todie = False;
700 
701   /* Schritt 1  (nur markieren) : */
702   merkidx = 0; ghosts_todie_idx = 0;
703 
704   for (y=0; y<14; y++) for (x=0; x<20; x++)
705     if ((field[x][y].id == ID_STONE) ||
706 	(field[x][y].id == ID_DIAMOND) ||
707 	(field[x][y].id == ID_IVSTONE) ||
708         (field[x][y].id == ID_IVDIAMOND))
709     {
710       if (field[x][y+1].id == ID_NOTHING)
711         Merke(SF_DOWN, x, y, &merkidx, merk);
712       else
713         if ((field[x][y+1].id == ID_STONE) ||
714             (field[x][y+1].id == ID_DIAMOND))
715         {
716           if ((field[x-1][y].id == ID_NOTHING) &&
717               (field[x-1][y+1].id == ID_NOTHING))
718             Merke(SF_LEFTDOWN, x, y, &merkidx, merk);
719           else
720             if ((field[x+1][y].id == ID_NOTHING) &&
721                 (field[x+1][y+1].id == ID_NOTHING))
722             {
723               Merke(SF_RIGHTDOWN, x, y, &merkidx, &merk);
724               field[x+1][y+1].id = ID_FSTODMD;
725             }
726         }
727         else
728           if (((field[x][y].id == ID_STONE) ||
729                (field[x][y].id == ID_IVSTONE)) &&
730               (field[x][y+1].id == ID_CHANGER) &&
731               (field[x][y+2].id == ID_NOTHING))
732             Merke(SF_CHANGER, x, y, &merkidx, &merk);
733     }
734   merk[merkidx].x = 0;
735   merk[merkidx].y = 0;
736 
737   /* Schritt 2  (wirklich bewegen) : */
738   merkidx = 0;
739   while ((merk[merkidx].x != 0) || (merk[merkidx].y != 0))
740   {
741     x = merk[merkidx].x;
742     y = merk[merkidx].y;
743     switch (merk[merkidx].type)
744     {
745     case SF_DOWN:
746       dx = x;
747       dy = y+1;
748       break;
749     case SF_LEFTDOWN:
750       dx = x-1;
751       dy = y+1;
752       break;
753     case SF_RIGHTDOWN:
754       dx = x+1;
755       dy = y+1;
756       break;
757     case SF_CHANGER:
758       dx = x;
759       dy = y+2;
760       break;
761     }
762     if ((dy - y) == 2) /* Umwandler*/
763       FillField(&field[dx][dy], ID_DIAMOND, 0);
764     else
765       if ((field[x][y].id == ID_STONE) ||
766           (field[x][y].id == ID_IVSTONE))
767         FillField(&field[dx][dy], ID_STONE, 0);
768       else
769         if ((field[x][y].id == ID_DIAMOND) ||
770             (field[x][y].id == ID_IVDIAMOND))
771           FillField(&field[dx][dy], ID_DIAMOND, 0);
772     FillField(&field[x][y], ID_NOTHING, 0);
773     if (field[dx][dy+1].id == ID_DIGGER) digger_todie = True;
774     if (field[dx][dy+1].id == ID_GHOST)
775     {
776       /* Geist von Stein/Diamant getroffen --> Sprengen */
777       ghosts_todie[ghosts_todie_idx].x = dx;
778       ghosts_todie[ghosts_todie_idx].y = dy+1;
779       ghosts_todie_idx++;
780     }
781 
782     if ((field[dx][dy+1].id == ID_STONE) ||
783         (field[dx][dy+1].id == ID_DIAMOND) ||
784         (field[dx][dy+1].id == ID_WALL) ||
785         (field[dx][dy+1].id == ID_GHOST))
786       ton_steine = True;
787     merkidx++;
788   }
789 
790   ghosts_todie[ghosts_todie_idx].x = 0;
791   ghosts_todie[ghosts_todie_idx].y = 0;
792 
793   /* Digger vom Stein/Diamant getroffen --> TOT! */
794   if (digger_todie) DieDigger();
795 
796   /* Geister toeten */
797   ghosts_todie_idx = 0;
798   while ((ghosts_todie[ghosts_todie_idx].x != 0) ||
799          (ghosts_todie[ghosts_todie_idx].y != 0))
800   {
801     for (y=ghosts_todie[ghosts_todie_idx].y-1;
802          y<=ghosts_todie[ghosts_todie_idx].y+1; y++)
803       for (x=ghosts_todie[ghosts_todie_idx].x-1;
804            x<=ghosts_todie[ghosts_todie_idx].x+1; x++)
805         if ((x>0) && (x<19) && (y>0) && (y<13))
806         {
807           if (field[x][y].id == ID_DIGGER) DieDigger();
808           else
809           {
810             if (field[x][y].id == ID_GHOST)
811               for (i=0; i<number_ghosts; i++)
812                 if ((ghosts[i].x == x) && (ghosts[i].y == y))
813                 {
814                   ghosts[i].dead = True;
815                   ghosts[i].x = 100;
816                   ghosts[i].y = 100;
817                   score = score + 99;
818                   Restore_Score();
819                   break;
820                 }
821             FillField(&field[x][y], ID_NOTHING, 0);
822           }
823         }
824     ghosts_todie_idx++;
825   }
826 } /* StoneDiamondStep() */
827 
828 int fdiamondblinksequence[6] =
829 /*{F_DIAMOND_BLINK0, F_DIAMOND_BLINK1, F_DIAMOND_BLINK2, F_DIAMOND_BLINK3,
830  F_DIAMOND_BLINK4, F_DIAMOND_BLINK5, F_DIAMOND_BLINK6, F_DIAMOND_BLINK7};*/
831 {F_DIAMOND_BLINK5, F_DIAMOND_BLINK4, F_DIAMOND_BLINK3, F_DIAMOND_BLINK2,
832  F_DIAMOND_BLINK1, F_DIAMOND_BLINK0};
833 
834 int fdiamondblinksequenceidx;
835 
DiamondBlinkStep()836 void DiamondBlinkStep()
837 {
838   int x, y;
839 
840   if (++fdiamondblinksequenceidx == 6) fdiamondblinksequenceidx = 0;
841   for (y=0; y<=13; y++) for (x=0; x<=19; x++)
842   {
843     if (field[x][y].id == ID_DIAMOND)
844     {
845       field[x][y].flags = (field[x][y].flags & !F_DIAMOND_BLINKMASK) |
846         fdiamondblinksequence[(fdiamondblinksequenceidx+4*y)%6];
847       field[x][y].pixmap_id =
848 	id2pixmap_id(field[x][y].id, field[x][y].flags);
849       field[x][y].todraw = True;
850     }
851   }
852 
853 } /* DiamondBlinkStep() */
854 
GhostStep()855 void GhostStep()
856 {
857   int g, i, x, y, wx[4], wy[4], dx, dy, arrow, larrow, lastturn;
858 
859   for (g=0; g < number_ghosts; g++) if (!ghosts[g].dead)
860     {
861       x = ghosts[g].x; wx[3] = wx[2] = wx[1] = wx[0] = x;
862       y = ghosts[g].y; wy[3] = wy[2] = wy[1] = wy[0] = y;
863       arrow = ghosts[g].arrow;
864       switch (ghosts[g].type)
865 	{
866 	case TGHOST180:
867 	  if (arrow == AGHOSTL) {wx[0]--; wx[1]++;} else
868 	    if (arrow == AGHOSTR) {wx[0]++; wx[1]--;} else
869 	      if (arrow == AGHOSTU) {wy[0]--; wy[1]++;} else
870 		if (arrow == AGHOSTD) {wy[0]++; wy[1]--;}
871 	  break;
872 	case TGHOST90L:
873 	  if (arrow == AGHOSTL)
874 	    {wx[0]--; wy[1]++; wy[2]--; wx[3]++;} else
875 	      if (arrow == AGHOSTR)
876 		{wx[0]++; wy[1]--; wy[2]++; wx[3]--;} else
877 		  if (arrow == AGHOSTU)
878 		    {wy[0]--; wx[1]--; wx[2]++; wy[3]++;} else
879 		      if (arrow == AGHOSTD)
880 			{wy[0]++; wx[1]++; wx[2]--; wy[3]--;}
881 	  break;
882 	case TGHOST90R:
883 	  if (arrow == AGHOSTL)
884 	    {wx[0]--; wy[1]--; wy[2]++; wx[3]++;} else
885 	      if (arrow == AGHOSTR)
886 		{wx[0]++; wy[1]++; wy[2]--; wx[3]--;} else
887 		  if (arrow == AGHOSTU)
888 		    {wy[0]--; wx[1]++; wx[2]--; wy[3]++;} else
889 		      if (arrow == AGHOSTD)
890 			{wy[0]++; wx[1]--; wx[2]++; wy[3]--;}
891 	  break;
892 
893 	case TGHOST90LR:
894 	  lastturn = ghosts[g].lastturn;
895 	  if (arrow == AGHOSTL)
896 	    {
897 	      wx[0]--;
898 	      if (lastturn == LGHOSTL) {wy[1]--; wy[2]++;}
899 	      else {wy[1]++; wy[2]--;}
900 	      wx[3]++;
901 	    }
902 	  else
903 	    if (arrow == AGHOSTR)
904 	      {
905 		wx[0]++;
906 		if (lastturn == LGHOSTL) {wy[1]++; wy[2]--;}
907 		else {wy[1]--; wy[2]++;}
908 		wx[3]--;
909 	      }
910 	    else
911 	      if (arrow == AGHOSTU)
912 		{
913 		  wy[0]--;
914 		  if (lastturn == LGHOSTL) {wx[1]++; wx[2]--;}
915 		  else {wx[1]--; wx[2]++;}
916 		  wy[3]++;
917 		}
918 	      else
919 	      if (arrow == AGHOSTD)
920 		{
921 		  wy[0]++;
922 		  if (lastturn == LGHOSTL) {wx[1]--; wx[2]++;}
923 		  else {wx[1]++; wx[2]--;}
924 		  wy[3]--;
925 		}
926 	  break;
927 	}
928       /* ------------------------------------------------------------------ */
929       for (i=0; i<4; i++)
930 	if ((wx[i] != x) || (wy[i] != y))
931 	  {
932 	    dx = wx[i]; dy = wy[i];
933 	    if (field[dx][dy].id == ID_DIGGER)
934 	      {
935 		if (!digger_death) DieDigger();
936 		break;
937 	      }
938 	    else
939 	      if (field[dx][dy].id == ID_NOTHING)
940 		{
941 		  larrow = ghosts[g].arrow;
942 		  ghosts[g].x = dx;
943 		  ghosts[g].y = dy;
944 		  if (dx < x) ghosts[g].arrow = AGHOSTL; else
945 		    if (dx > x) ghosts[g].arrow = AGHOSTR; else
946 		      if (dy < y) ghosts[g].arrow = AGHOSTU; else
947 			if (dy > y) ghosts[g].arrow = AGHOSTD;
948 		  arrow = ghosts[g].arrow;
949 		  if (ghosts[g].type == TGHOST90LR)
950 		    switch (larrow)
951 		      {
952 		      case AGHOSTL:
953 			if (arrow == AGHOSTD) ghosts[g].lastturn = LGHOSTL;
954 			else
955 			  if (arrow == AGHOSTU) ghosts[g].lastturn = LGHOSTR;
956 			break;
957 		      case AGHOSTR:
958 			if (arrow == AGHOSTD) ghosts[g].lastturn = LGHOSTR;
959 			else
960 			  if (arrow == AGHOSTU) ghosts[g].lastturn = LGHOSTL;
961 			break;
962 		      case AGHOSTU:
963 			if (arrow == AGHOSTL) ghosts[g].lastturn = LGHOSTL;
964 			else
965 			  if (arrow == AGHOSTR) ghosts[g].lastturn = LGHOSTR;
966 			break;
967 		      case AGHOSTD:
968 			if (arrow == AGHOSTL) ghosts[g].lastturn = LGHOSTR;
969 			else
970 			  if (arrow == AGHOSTR) ghosts[g].lastturn = LGHOSTL;
971 			break;
972 		      }
973 		  CopyField(&field[dx][dy], &field[x][y]);
974 		  switch (arrow)
975 		    {
976 		    case AGHOSTL:
977 		      field[dx][dy].flags =
978 			(field[dx][dy].flags & !F_GHOST_MOVEMASK) |
979 			F_GHOST_LEFT;
980 		      break;
981 		    case AGHOSTR:
982 		      field[dx][dy].flags =
983 			(field[dx][dy].flags & !F_GHOST_MOVEMASK) |
984 			F_GHOST_RIGHT;
985 		      break;
986 		    case AGHOSTU:
987 		      field[dx][dy].flags =
988 			(field[dx][dy].flags & !F_GHOST_MOVEMASK) |
989 			F_GHOST_UP;
990 		      break;
991 		    case AGHOSTD:
992 		      field[dx][dy].flags =
993 			(field[dx][dy].flags & !F_GHOST_MOVEMASK) |
994 			F_GHOST_DOWN;
995 		      break;
996 		    }
997 		  field[dx][dy].pixmap_id =
998 		    id2pixmap_id(field[dx][dy].id, field[dx][dy].flags);
999 		  field[dx][dy].todraw = True;
1000 		  FillFieldNothing(&field[x][y]);
1001 		  field[x][y].todraw = True;
1002 		  break;
1003 		}
1004 	  }
1005     }
1006 } /* GhostStep() */
1007 
TimeStep()1008 void TimeStep()
1009 {
1010   if (lefttime != 0)
1011     {
1012       lefttime--;
1013       Restore_LeftTime();
1014     }
1015   if ((lefttime == 0) && (!digger_death)) DieDigger();
1016 } /* TimeStep() */
1017 
1018 char rec_data[2500];
1019 int rec_data_pointer;
1020 
RecordStep()1021 void RecordStep()
1022 {
1023   char arrow;
1024 
1025   if (lefttime == 0) return;
1026 
1027   if (kb_left) arrow = ADIGGERL;
1028   else if (kb_right) arrow = ADIGGERR;
1029   else if (kb_up) arrow = ADIGGERU;
1030   else if (kb_down) arrow = ADIGGERD;
1031   else arrow = ADIGGERN;
1032 
1033   rec_data[rec_data_pointer] = arrow;
1034   /*printf("%d ", rec_data_pointer);*/
1035   rec_data_pointer++;
1036 }
1037 
ReplayStep()1038 void ReplayStep()
1039 {
1040   char s[2];
1041 
1042   if (lefttime == 0) return;
1043 
1044   if (rec_data_pointer % 8 >= 4) strcpy(s, "R"); else strcpy(s, " ");
1045   WriteTextStr(s, 39, vertvar, kcf_weiss, kcb_rot);
1046 
1047   kb_left = False; kb_right = False; kb_up = False; kb_down = False;
1048 
1049   switch (rec_data[rec_data_pointer])
1050     {
1051     case ADIGGERL:
1052       kb_left = True;
1053       break;
1054     case ADIGGERR:
1055       kb_right = True;
1056       break;
1057     case ADIGGERU:
1058       kb_up = True;
1059       break;
1060     case ADIGGERD:
1061       kb_down = True;
1062       break;
1063     }
1064   rec_data_pointer++;
1065 }
1066 
Ton_Bearbeitung_1()1067 void Ton_Bearbeitung_1()
1068 {
1069   ton_schritt = False;
1070   ton_steine = False;
1071   ton_diamant = False;
1072 } /* Ton_Bearbeitung_1() */
1073 
Ton_Bearbeitung_2()1074 void Ton_Bearbeitung_2()
1075 {
1076   if (ton_diamant) sound(TON_DIAMANT);
1077   else if (ton_steine) sound(TON_STEINE);
1078   else if (ton_schritt) sound(TON_SCHRITT);
1079 
1080   ton_schritt = False;
1081   ton_steine = False;
1082   ton_diamant = False;
1083 } /* Ton_Bearbeitung_2() */
1084 
NextStep()1085 void NextStep()
1086 {
1087   Ton_Bearbeitung_1();
1088 
1089   if (replay) ReplayStep(); else RecordStep();
1090   DiggerStep();
1091   StoneDiamondStep();
1092   GhostStep();
1093   TimeStep();
1094 
1095   Ton_Bearbeitung_2();
1096 } /* NextStep() */
1097 
1098 Bool rl_left, rl_right, rl_up, rl_down;
1099 Bool rd_left, rd_right, rd_up, rd_down;
1100 
ClearKeys()1101 void ClearKeys()
1102 {
1103   kb_left = False; kb_right = False; kb_up = False; kb_down = False;
1104   rl_left = False; rl_right = False; rl_up = False; rl_down = False;
1105   rd_left = False; rd_right = False; rd_up = False; rd_down = False;
1106 }
1107 
1108 int takt_zaehler_one_step, takt_zaehler_diamond_blink;
1109 
ResetZaehler()1110 void ResetZaehler()
1111 {
1112   takt_zaehler_one_step = -1; takt_zaehler_diamond_blink = -1;
1113   if (!replay) bzero(rec_data, sizeof(rec_data));
1114   rec_data_pointer = 0;
1115 }
1116 
DoTakt()1117 Bool DoTakt()
1118 {
1119   takt = False;
1120   intakt = True;
1121   setitimer(ITIMER_REAL, &timervalue, 0);
1122   if (++takt_zaehler_one_step >= STEP_MAX) takt_zaehler_one_step = 0;
1123   if (++takt_zaehler_diamond_blink >= BLINK_MAX)
1124     takt_zaehler_diamond_blink = 0;
1125 
1126   if (takt_zaehler_one_step == 0)
1127   {
1128     if (new_level_number)
1129     {
1130       if (LoadLevel(new_level_number, False))
1131       {
1132         ChangePS();
1133         Init_First_Line();
1134         DrawTextField();
1135         DrawField();
1136         ClearKeys();
1137         ResetZaehler();
1138         XFlush(display);
1139         intakt = False;
1140         return(True);
1141       }
1142       else
1143       {
1144         intakt = False;
1145         return(False);
1146       }
1147     }
1148     else
1149     {
1150       if (wait_count) wait_count--;
1151       if (!wait_count)
1152       {
1153         if ((!inpause) || (step)) {NextStep(); step = False;}
1154       }
1155       if (levelready)
1156       {
1157         if (!last_level)
1158           new_level_number = akt_level_number + 1;
1159         else
1160           alllevelsready = True;
1161       }
1162     }
1163     if (rl_left)  {kb_left  = False; rl_left  = False;}
1164     if (rl_right) {kb_right = False; rl_right = False;}
1165     if (rl_up)    {kb_up    = False; rl_up    = False;}
1166     if (rl_down)  {kb_down  = False; rl_down  = False;}
1167     rd_left  = True;
1168     rd_right = True;
1169     rd_up    = True;
1170     rd_down  = True;
1171   }
1172 
1173   if (takt_zaehler_one_step == STEP_HALF)
1174   {
1175     if ((!wait_count) && (!inpause))
1176     {
1177       if (STEP_HALF > 0) DiggerHalfStep();
1178       TimeStep();
1179     }
1180   }
1181 
1182   if ((takt_zaehler_diamond_blink == 0) && (blink))
1183   {
1184     DiamondBlinkStep();
1185   }
1186 
1187   if ((takt_zaehler_one_step == 0) || (takt_zaehler_one_step == STEP_HALF) ||
1188       (takt_zaehler_diamond_blink == 0))
1189   {
1190     DrawTextField();
1191     DrawField();
1192     XFlush(display);
1193   }
1194 
1195   intakt = False;
1196   return(True);
1197 } /* Bool DoTakt() */
1198 
RunLevels(int von_level,int bis_level)1199 void RunLevels(int von_level, int bis_level)
1200 {
1201   XSetWindowAttributes windowattributes;
1202   unsigned long valuemask;
1203   Bool done;
1204   XEvent event;
1205   KeySym keysym;
1206   char scheat[4] = "";
1207 
1208   in_runlevels = True;
1209   windowattributes.background_pixel = BlackPixel(display, screen);
1210   valuemask = CWBackPixel;
1211   XChangeWindowAttributes(display, mainwindow, valuemask, &windowattributes);
1212 
1213   ClearCharField(BlackPixel(display, screen), False);
1214   ResetZaehler();
1215   alllevelsready = False;
1216   lives = 20;
1217   score = 0;
1218   new_level_number = von_level;
1219   replay = False;
1220   takt = True;
1221 
1222   done = False;
1223   back = False;
1224   while (!done)
1225     {
1226       if (!XEventsQueued(display, QueuedAfterReading))
1227  	{
1228           if (takt)
1229           {
1230             if (DoTakt())
1231             {
1232               if ((new_level_number) && (bis_level != -1) &&
1233                   (new_level_number > bis_level)) done = True;
1234               if (alllevelsready) done = True;
1235             }
1236             else
1237             {
1238               quit = True;
1239               done = True;
1240             }
1241           }
1242           XDigger_Idle();
1243 	} /* if (!XEventsQueued()) */
1244       else
1245 	{
1246 	  XNextEvent(display, &event);
1247           if (event.xany.window == iconwindow)
1248             Handle_IconWindow_Event(&event); else
1249 	  switch(event.type)
1250 	    {
1251 	    case ButtonPress:
1252 	      if (event.xbutton.button == Button3)
1253 		{
1254 		  if (lives > 1)
1255 		    {
1256 		      if (!cheat) lives--;
1257 		      new_level_number = akt_level_number;
1258 		    }
1259 		  else done = True;
1260 		}
1261 	      if ((event.xbutton.button == Button2) && cheat)
1262 		{
1263 		  if (!last_level)
1264 		    new_level_number = akt_level_number + 1;
1265 		  else
1266 		    done = True;
1267 		}
1268 	      break;
1269 	    case Expose:
1270 	      Handle_ExposeEvent(&event.xexpose);
1271 	      break;
1272 	    case MappingNotify:
1273 	      XRefreshKeyboardMapping(&event.xmapping);
1274 	      break;
1275 	    case KeyPress:
1276 	      keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);
1277 	      switch (keysym)
1278               {
1279 		case XK_Return:
1280 		  wait_count = 0;
1281 		  break;
1282 		case XK_Left:
1283 		  kb_left = True; rd_left = False;
1284 		  if (cheat && inpause) step = True;
1285 		  break;
1286 	        case XK_Right:
1287 		  kb_right = True; rd_right = False;
1288 		  if (cheat && inpause) step = True;
1289 		  break;
1290 		case XK_Up:
1291 		  kb_up = True; rd_up = False;
1292 		  if (cheat && inpause) step = True;
1293 		  break;
1294 		case XK_Down:
1295 		  kb_down = True; rd_down = False;
1296 		  if (cheat && inpause) step = True;
1297 		  break;
1298 		case XK_b:
1299 		  if (event.xkey.state & ControlMask)
1300                   {
1301                     if (lives > 1)
1302                     {
1303                       if (!cheat) lives--;
1304                       new_level_number = akt_level_number;
1305                     }
1306                     else done = True;
1307                   }
1308 		  break;
1309 		case XK_Escape:
1310 		  replay = False;
1311                   if (lives > 1)
1312                   {
1313                     if (!cheat) lives--;
1314                     new_level_number = akt_level_number;
1315                   } else done = True;
1316 		  break;
1317 		case XK_Insert:
1318 		  if (cheat) digger_candie = False;
1319 		  break;
1320 		case XK_Delete:
1321 		  if (cheat) digger_candie = True;
1322 		  break;
1323 		  case XK_Home:
1324 		    if (cheat)
1325 		      {
1326 			if (event.xkey.state & ShiftMask)
1327 			  {if (akt_level_number > 1)
1328 			    new_level_number = akt_level_number - 1;}
1329 			else
1330 			  {if (!last_level)
1331 			    new_level_number = akt_level_number + 1;}
1332 		      }
1333 		    break;
1334 		case XK_p:
1335 		  if (cheat) inpause = !inpause;
1336 		  break;
1337 		case XK_q:
1338 		  quit = True;
1339 		  done = True;
1340 		  break;
1341 		case XK_r:
1342 		  new_level_number = akt_level_number;
1343 		  replay = True;
1344 		  break;
1345 		case XK_x:
1346                 case XK_m:
1347                   back = True;
1348 		  done = True;
1349 		  break;
1350 		case XK_space:
1351 		  if (cheat) step = True;
1352 		  break;
1353                 case XK_plus:
1354                 case XK_KP_Add:
1355                   XResizeWindow(display, mainwindow, 320*(xpmmag+1),
1356                                 (240 + vertvar*16)*(xpmmag+1));
1357                   break;
1358                 case XK_minus:
1359                 case XK_KP_Subtract:
1360                   if (xpmmag > 1)
1361                     XResizeWindow(display, mainwindow, 320*(xpmmag-1),
1362                                   (240 + vertvar*16)*(xpmmag-1));
1363                   break;
1364 		}
1365 	      if ((keysym == XK_9) || (keysym == XK_d))
1366 		{
1367 		  if (keysym == XK_9) strcat(scheat, "9");
1368 		  if (keysym == XK_d) strcat(scheat, "d");
1369 		  if (strcmp(scheat, "99d") == 0)
1370 		    {
1371 		      XBell(display, 0);
1372 		      cheat = (!cheat);
1373 		      ones_cheated = True;
1374 		      ChangePS();
1375 		    }
1376 		  if (strlen(scheat) == 3) strcpy(scheat, "");
1377 		}
1378 	      else
1379 		strcpy(scheat, "");
1380 	      break;
1381 	    case KeyRelease:
1382 	      keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);
1383 
1384 	      if (keysym == XK_Left) {
1385 		if (rd_left) kb_left = False;
1386 		else rl_left = True;
1387               }
1388 	      if (keysym == XK_Right) {
1389 		if (rd_right) kb_right = False;
1390 		else rl_right = True;
1391               }
1392 	      if (keysym == XK_Up) {
1393 		if (rd_up) kb_up = False;
1394 		else rl_up = True;
1395               }
1396 	      if (keysym == XK_Down) {
1397 		if (rd_down) kb_down = False;
1398 		else rl_down  = True;
1399               }
1400 	      break;
1401 	    case ClientMessage:
1402 	      if (event.xclient.data.l[0] == protocol[0])
1403 		{
1404 		  quit = True;
1405 		  done = True;
1406 		  break;
1407 		}
1408 	      break ;
1409 	    } /* switch(event.type) */
1410 
1411 	} /* if (!XEventsQueued()) else */
1412     } /* while (!done) */
1413   in_runlevels = False;
1414   if (takt) setitimer(ITIMER_REAL, &timervalue, 0);
1415   strcpy(LastArgv, "");
1416 } /* RunLevels() */
1417 
1418 /*---------------------------------------------------------------------------*/
1419 
ALookAtTheRoomsTakt()1420 void ALookAtTheRoomsTakt()
1421 {
1422   takt = False;
1423   intakt = True;
1424   setitimer(ITIMER_REAL, &timervalue, 0);
1425   if (++takt_zaehler_diamond_blink == 3) takt_zaehler_diamond_blink = 0;
1426 
1427   if ((takt_zaehler_diamond_blink == 1) && (blink))
1428   {
1429     DiamondBlinkStep();
1430   }
1431 
1432   if (takt_zaehler_diamond_blink == 1)
1433   {
1434     DrawTextField();
1435     DrawField();
1436     XFlush(display);
1437   }
1438 
1439   intakt = False;
1440 } /* DoTakt() */
1441 
ALookAtTheRooms()1442 void ALookAtTheRooms()
1443 {
1444   XSetWindowAttributes windowattributes;
1445   unsigned long valuemask;
1446   XEvent event;
1447   KeySym keysym;
1448   Bool done = False;
1449 
1450   in_runlevels = True;
1451   strcpy(LastArgv, " (Look)");
1452   windowattributes.background_pixel = BlackPixel(display, screen);
1453   valuemask = CWBackPixel;
1454   XChangeWindowAttributes(display, mainwindow, valuemask, &windowattributes);
1455 
1456   ClearCharField(BlackPixel(display, screen), False);
1457   lives = 20;
1458   score = 0;
1459   new_level_number = 1;
1460 
1461   while (!done)
1462     {
1463       if (new_level_number)
1464 	{
1465 	  if (LoadLevel(new_level_number, False))
1466           {
1467             Init_First_Line();
1468             DrawTextField();
1469             DrawField();
1470             ClearKeys();
1471           }
1472           else
1473           {
1474             quit = True;
1475             done = True;
1476           }
1477 	}
1478       if (!XEventsQueued(display, QueuedAfterReading))
1479 	{
1480 	  if (takt)
1481 	    {
1482 	      ALookAtTheRoomsTakt();
1483 	    }
1484 	  XDigger_Idle();
1485 	  XFlush(display);
1486 	} /* if (!XEventsQueued()) */
1487       else
1488 	{
1489 	  XNextEvent(display, &event);
1490           if (event.xany.window == iconwindow)
1491             Handle_IconWindow_Event(&event); else
1492 	  switch(event.type)
1493 	    {
1494 	    case Expose:
1495 	      Handle_ExposeEvent(&event.xexpose);
1496 	      break;
1497 	    case MappingNotify:
1498 	      XRefreshKeyboardMapping(&event.xmapping);
1499 	      break;
1500 	    case ButtonPress:
1501 	      if (event.xbutton.button == Button1)
1502 		{
1503 		  if (!last_level)
1504 		    new_level_number = akt_level_number + 1;
1505 		  else
1506 		    done = True;
1507 		}
1508 	      if (event.xbutton.button == Button3)
1509 		{
1510 		  if (akt_level_number > 1)
1511 		    new_level_number = akt_level_number - 1;
1512 		  else
1513 		    done = True;
1514 		}
1515 	      break;
1516 	    case KeyPress:
1517 	      keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);
1518 	      switch (keysym)
1519               {
1520                 case XK_Left:
1521                 case XK_Down:
1522 		  if (akt_level_number > 1)
1523 		    new_level_number = akt_level_number - 1;
1524                   break;
1525                 case XK_Right:
1526                 case XK_Up:
1527 		  if (!last_level)
1528 		    new_level_number = akt_level_number + 1;
1529                   break;
1530                 case XK_Return:
1531 		  if (!last_level)
1532 		    new_level_number = akt_level_number + 1;
1533 		  else
1534 		    done = True;
1535 		  break;
1536 		case XK_q:
1537 		  quit = True;
1538 		  done = True;
1539 		  break;
1540 		case XK_x:
1541                 case XK_m:
1542                 case XK_Escape:
1543                   done = True;
1544 		  break;
1545                 case XK_plus:
1546                 case XK_KP_Add:
1547                   XResizeWindow(display, mainwindow, 320*(xpmmag+1),
1548                                 (240 + vertvar*16)*(xpmmag+1));
1549                   break;
1550                 case XK_minus:
1551                 case XK_KP_Subtract:
1552                   if (xpmmag > 1)
1553                     XResizeWindow(display, mainwindow, 320*(xpmmag-1),
1554                                   (240 + vertvar*16)*(xpmmag-1));
1555                   break;
1556               }
1557 	      break;
1558 	    case ClientMessage:
1559 	      if (event.xclient.data.l[0] == protocol[0])
1560 		{
1561 		  /*exit(0);*/
1562 		  quit = True;
1563 		  done = True;
1564 		  break;
1565 		}
1566 	    } /* switch(event.type) */
1567 	} /* if (!XEventsQueued()) else */
1568     } /* while (!done) */
1569   strcpy(LastArgv, "");
1570   in_runlevels = False;
1571   if (takt) setitimer(ITIMER_REAL, &timervalue, 0);
1572 } /* ALookAtTheRooms() */
1573 
1574 /*---------------------------------------------------------------------------*/
1575 
Save_Ghost(int flags,int * id,int * d,unsigned char * file_daten)1576 void Save_Ghost(int flags, int *id, int *d, unsigned char *file_daten)
1577 {
1578   switch (flags & F_GHOST_TYPEMASK)
1579   {
1580   case F_GHOST_TYPE180:
1581     *id = 3;
1582     break;
1583   case F_GHOST_TYPEL:
1584     *id = 7;
1585     break;
1586   case F_GHOST_TYPER:
1587     *id = 15;
1588     break;
1589   case F_GHOST_TYPELR:
1590     *id = 11;
1591     break;
1592   }
1593   switch (flags & F_GHOST_MOVEMASK)
1594   {
1595   case F_GHOST_DOWN:
1596     *d = 0;
1597     break;
1598   case F_GHOST_UP:
1599     *d = 1;
1600     break;
1601   case F_GHOST_RIGHT:
1602     *d = 2;
1603     break;
1604   case F_GHOST_LEFT:
1605     *d = 3;
1606     break;
1607   }
1608   if (number_ghosts < MAX_GHOSTS)
1609   {
1610     if (number_ghosts & 1)
1611       file_daten[0x94 + number_ghosts/2] =
1612         (file_daten[0x94 + number_ghosts/2] & 0xf0) | (*d);
1613     else
1614       file_daten[0x94 + number_ghosts/2] =
1615         (file_daten[0x94 + number_ghosts/2] & 0x0f) | (*d << 4);
1616     number_ghosts++;
1617   }
1618 }
1619 
Edit_SaveLevel(int level_number)1620 void Edit_SaveLevel(int level_number)
1621 {
1622 /*   char filename[256]; */
1623   unsigned char file_daten[0x9c], *c, b;
1624   int x, y, id, flags, i, d;
1625   FILE *filehandle;
1626 
1627   bzero(file_daten, sizeof(file_daten));
1628   number_ghosts = 0;
1629   c = file_daten;
1630   for (y=0; y<14; y++) for (x=0; x<10; x++, c++)
1631     {
1632         id = field[x*2][y].id;
1633         flags = field[x*2][y].flags;
1634         if (id == ID_DIGGER)
1635         {
1636             diggerposx = x*2;
1637             diggerposy = y;
1638         }
1639         if (id == ID_GHOST)
1640           Save_Ghost(flags, &id, &d, file_daten);
1641         *c = (*c & 0x0f) | (id << 4);
1642 
1643   /* ------------------------------------------------------------------ */
1644 
1645         id = field[x*2+1][y].id;
1646         flags = field[x*2+1][y].flags;
1647         if (id == ID_DIGGER)
1648         {
1649             diggerposx = x*2+1;
1650             diggerposy = y;
1651         }
1652         if (id == ID_GHOST)
1653           Save_Ghost(flags, &id, &d, file_daten);
1654         *c = (*c & 0xf0) | id;
1655     }
1656   c += 3;
1657   if (!last_level) *c = 1;
1658   c += 2;
1659   *(c++) = diggerposx;
1660   *(c++) = diggerposy + 2;
1661   b = number_diamonds / 10 * 0x10 + number_diamonds % 10;
1662   *(c++) = b;
1663 
1664   if ((filehandle = fopen(level_filename, "r+")) == NULL)
1665   {
1666     XBell(display, -50);
1667     fprintf(stderr, "%s: can't open %s for rw\n", progname, level_filename);
1668     return;
1669   }
1670   i = fseek(filehandle, (level_number - 1) * 0x9c, SEEK_SET);
1671   i = fwrite(file_daten, 0x9c, 1, filehandle);
1672   fclose(filehandle);
1673   if (i==1)
1674     printf("%s: Level saved.\n", progname);
1675 } /* edit_savelevel(int level_number) */
1676 
1677 struct ttools {unsigned char id, flags;}
1678 tools[] = {
1679   {ID_NOTHING, 0}, {ID_GROUND, 0}, {ID_WALL, 0}, {ID_STONE, 0},
1680   {ID_DIAMOND, 0}, {ID_CHANGER, 0}, {ID_EXIT, 0}, {ID_DIGGER, F_DIGGER_DOWN0},
1681   {ID_GHOST, F_GHOST_DOWN + F_GHOST_TYPE180},
1682   {ID_GHOST, F_GHOST_UP + F_GHOST_TYPE180},
1683   {ID_GHOST, F_GHOST_RIGHT + F_GHOST_TYPE180},
1684   {ID_GHOST, F_GHOST_LEFT + F_GHOST_TYPE180},
1685   {ID_GHOST, F_GHOST_DOWN + F_GHOST_TYPEL},
1686   {ID_GHOST, F_GHOST_UP + F_GHOST_TYPEL},
1687   {ID_GHOST, F_GHOST_RIGHT + F_GHOST_TYPEL},
1688   {ID_GHOST, F_GHOST_LEFT + F_GHOST_TYPEL},
1689   {ID_GHOST, F_GHOST_DOWN + F_GHOST_TYPER},
1690   {ID_GHOST, F_GHOST_UP + F_GHOST_TYPER},
1691   {ID_GHOST, F_GHOST_RIGHT + F_GHOST_TYPER},
1692   {ID_GHOST, F_GHOST_LEFT + F_GHOST_TYPER},
1693   {ID_GHOST, F_GHOST_DOWN + F_GHOST_TYPELR},
1694   {ID_GHOST, F_GHOST_UP + F_GHOST_TYPELR},
1695   {ID_GHOST, F_GHOST_RIGHT + F_GHOST_TYPELR},
1696   {ID_GHOST, F_GHOST_LEFT + F_GHOST_TYPELR}
1697 };
1698 
1699 int auswahl_pos[3] = {1, 2, 0},
1700   auswahl_id[3] = {ID_GROUND, ID_WALL, ID_NOTHING},
1701   auswahl_flags[3] = {0,0,0},
1702     last_pressed_button = 0;
1703 
Handle_Tools_ExposeEvent(XExposeEvent * xexpose)1704 void Handle_Tools_ExposeEvent(XExposeEvent *xexpose)
1705 {
1706   int i;
1707 
1708   for (i=0; i<24; i++)
1709   {
1710     CopyOnePixmap_Window(toolswindow,
1711                          id2pixmap_id(tools[i].id, tools[i].flags), i%4, i/4);
1712   }
1713 
1714   for (i=0; i<3; i++)
1715   {
1716     XDrawRectangle(display, toolswindow, gc,
1717                    (auswahl_pos[i]%4)*16*xpmmag, (auswahl_pos[i]/4)*16*xpmmag,
1718                    16*xpmmag-1, 16*xpmmag-1);
1719     XFillRectangle(display, toolswindow, gc,
1720                    (auswahl_pos[i]%4)*16*xpmmag + (i*5+1)*xpmmag,
1721                    (auswahl_pos[i]/4)*16*xpmmag,
1722                    4*xpmmag, 4*xpmmag);
1723   }
1724   XFlush(display);
1725 }
1726 
Anzahl_Ghosts()1727 int Anzahl_Ghosts()
1728 {
1729   int erg = 0, x, y;
1730 
1731   for (y=0; y<14; y++) for (x=0; x<20; x++)
1732     if (field[x][y].id == ID_GHOST) erg++;
1733   return erg;
1734 }
1735 
Handle_ButtonPressEvent_mainwindow(XButtonEvent * xbutton)1736 void Handle_ButtonPressEvent_mainwindow(XButtonEvent *xbutton)
1737 {
1738   int i=0, x, y;
1739 
1740   if (xbutton->button == Button1) i=0;
1741   if (xbutton->button == Button2) i=1;
1742   if (xbutton->button == Button3) i=2;
1743   last_pressed_button = i;
1744 
1745   x = xbutton->x / (16*xpmmag);
1746   y = xbutton->y / (16*xpmmag) - (vertvar+1);
1747 
1748   if (y < 0)
1749   {
1750     if (xbutton->button == Button1)
1751       {
1752         if (number_diamonds > 0) number_diamonds--;
1753       } else
1754       {
1755         if (number_diamonds < 99) number_diamonds++;
1756       }
1757     Restore_Diamonds();
1758     DrawTextField();
1759   }
1760   else
1761   {
1762     if ((auswahl_id[i] == ID_GHOST) && (Anzahl_Ghosts() >= MAX_GHOSTS))
1763     {
1764       fprintf(stderr, "%s: You can�t have more than 16 ghosts.\n", progname);
1765     }
1766     else
1767     {
1768       FillFieldNothing(&field[x][y]);
1769       field[x][y].id = auswahl_id[i];
1770       field[x][y].flags = auswahl_flags[i];
1771       field[x][y].pixmap_id = id2pixmap_id(field[x][y].id, field[x][y].flags);
1772       field[x][y].todraw = True;
1773       DrawField();
1774     }
1775   }
1776   XFlush(display);
1777 }
1778 
Handle_MotionEvent_mainwindow(XMotionEvent * xmotion)1779 void Handle_MotionEvent_mainwindow(XMotionEvent *xmotion)
1780 {
1781   int x, y;
1782 
1783   if (xmotion->state == 0) return;
1784 
1785   x = xmotion->x / (16*xpmmag);
1786   y = xmotion->y / (16*xpmmag) - (vertvar+1);
1787 
1788   if (y < 0)
1789   {
1790   }
1791   else
1792   {
1793     if ((auswahl_id[last_pressed_button] == ID_GHOST) &&
1794         (Anzahl_Ghosts() >= MAX_GHOSTS))
1795     {
1796       fprintf(stderr, "%s: You can�t have more than 16 ghosts.\n", progname);
1797     }
1798     else
1799     {
1800       FillFieldNothing(&field[x][y]);
1801       field[x][y].id = auswahl_id[last_pressed_button];
1802       field[x][y].flags = auswahl_flags[last_pressed_button];
1803       field[x][y].pixmap_id = id2pixmap_id(field[x][y].id, field[x][y].flags);
1804       field[x][y].todraw = True;
1805       DrawField();
1806     }
1807   }
1808   XFlush(display);
1809 }
1810 
Handle_ButtonPressEvent_toolswindow(XButtonEvent * xbutton)1811 void Handle_ButtonPressEvent_toolswindow(XButtonEvent *xbutton)
1812 {
1813   int i=0, x, y;
1814 
1815   if (xbutton->button == Button1) i=0;
1816   if (xbutton->button == Button2) i=1;
1817   if (xbutton->button == Button3) i=2;
1818 
1819   x = xbutton->x / (16*xpmmag);
1820   y = xbutton->y / (16*xpmmag);
1821   auswahl_pos[i] = y * 4 + x;
1822   auswahl_id[i] = tools[auswahl_pos[i]].id;
1823   auswahl_flags[i] = tools[auswahl_pos[i]].flags;
1824 
1825   Handle_Tools_ExposeEvent(NULL);
1826 }
1827 
LevelEditor()1828 void LevelEditor()
1829 {
1830   int win_width, win_height;
1831   XSizeHints sizehints;
1832   XSetWindowAttributes windowattributes;
1833   unsigned long valuemask;
1834   XEvent event;
1835   KeySym keysym;
1836   Bool done = False;
1837 
1838   in_runlevels = True;
1839   in_LevelEditor = True;
1840   strcpy(LastArgv, " (Edit)");
1841   windowattributes.background_pixel = BlackPixel(display, screen);
1842   valuemask = CWBackPixel;
1843   XChangeWindowAttributes(display, mainwindow, valuemask, &windowattributes);
1844 
1845   ClearCharField(BlackPixel(display, screen), False);
1846   if (pixmaps[PXID_GHOST_DOWN_180] == 0) Make16x16Pixmaps_Editor();
1847   lives = 20;
1848   score = 0;
1849   new_level_number = 1;
1850 
1851   win_width = 4*16 * xpmmag;
1852   win_height = 6*16 * xpmmag;
1853   toolswindow = XCreateSimpleWindow(display, rootwindow, 0, 0,
1854                                      win_width, win_height, border_width,
1855                                      WhitePixel(display, screen),
1856                                      BlackPixel(display, screen));
1857   sizehints.width = win_width;
1858   sizehints.height = win_height;
1859   sizehints.min_width = win_width;
1860   sizehints.min_height = win_height;
1861   sizehints.max_width = win_width;
1862   sizehints.max_height = win_height;
1863   sizehints.flags = PSize | PMinSize | PMaxSize;
1864   XSetStandardProperties(display, toolswindow, "Tools", "Tools",
1865 			 None, NULL, 0, &sizehints);
1866   XSelectInput(display, toolswindow, ButtonPressMask | ButtonMotionMask |
1867                KeyPressMask | KeyReleaseMask | ExposureMask);
1868   XMapRaised(display, toolswindow);
1869 /*   XMapSubwindows(display, mainwindow); */
1870 
1871   while (!done)
1872   {
1873     if (new_level_number)
1874     {
1875       if (LoadLevel(new_level_number, True))
1876       {
1877         Init_First_Line();
1878         DrawTextField();
1879         DrawField();
1880         XFlush(display);
1881         ClearKeys();
1882       }
1883       else
1884       {
1885         done = True;
1886       }
1887     }
1888     if (!XEventsQueued(display, QueuedAfterReading))
1889     {
1890       XDigger_Idle();
1891       XFlush(display);
1892     }
1893     else
1894     {
1895       XNextEvent(display, &event);
1896       if (event.xany.window == iconwindow)
1897         Handle_IconWindow_Event(&event); else
1898       if (event.xany.window == mainwindow)
1899         {
1900           switch(event.type)
1901           {
1902             case Expose:
1903 	      Handle_ExposeEvent(&event.xexpose);
1904               XFlush(display);
1905               break;
1906             case MappingNotify:
1907               XRefreshKeyboardMapping(&event.xmapping);
1908               break;
1909             case ButtonPress:
1910               Handle_ButtonPressEvent_mainwindow(&event.xbutton);
1911               break;
1912             case MotionNotify:
1913               Handle_MotionEvent_mainwindow(&event.xmotion);
1914               break;
1915             case KeyPress:
1916               keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);
1917               switch (keysym)
1918               {
1919                 case XK_p:
1920                   Edit_SaveLevel(akt_level_number);
1921                   in_LevelEditor = False;
1922                   RunLevels(akt_level_number, akt_level_number);
1923                   new_level_number = akt_level_number;
1924                   in_runlevels = True;
1925                   in_LevelEditor = True;
1926                   strcpy(LastArgv, " (Edit)");
1927                   done = quit;
1928                   break;
1929                 case XK_q:
1930                   quit = True;
1931                   done = True;
1932                   break;
1933                 case XK_s:
1934                   Edit_SaveLevel(akt_level_number);
1935                   break;
1936 		case XK_x:
1937                 case XK_m:
1938 		  done = True;
1939 		  break;
1940                 case XK_Home:
1941                   if (event.xkey.state & ShiftMask)
1942                   {if (akt_level_number > 1)
1943                      new_level_number = akt_level_number - 1;}
1944                   else
1945                   {if (!last_level)
1946                      new_level_number = akt_level_number + 1;}
1947                   break;
1948                 case XK_KP_Add:
1949                   XResizeWindow(display, mainwindow, 320*(xpmmag+1),
1950                                 (240 + vertvar*16)*(xpmmag+1));
1951                   break;
1952                 case XK_minus:
1953                 case XK_KP_Subtract:
1954                   if (xpmmag > 1)
1955                     XResizeWindow(display, mainwindow, 320*(xpmmag-1),
1956                                   (240 + vertvar*16)*(xpmmag-1));
1957                   break;
1958               }
1959               break;
1960             case ClientMessage:
1961               if (event.xclient.data.l[0] == protocol[0])
1962               {
1963                 /*exit(0);*/
1964 		quit = True;
1965 		done = True;
1966 		break;
1967               }
1968           } /* switch(event.type) */
1969         }
1970         else
1971         {
1972           switch(event.type)
1973           {
1974             case Expose:
1975 	      Handle_Tools_ExposeEvent(&event.xexpose);
1976               XFlush(display);
1977               break;
1978             case MappingNotify:
1979               XRefreshKeyboardMapping(&event.xmapping);
1980               break;
1981             case ButtonPress:
1982               Handle_ButtonPressEvent_toolswindow(&event.xbutton);
1983               break;
1984             case KeyPress:
1985               keysym = XKeycodeToKeysym(display, event.xkey.keycode, 0);
1986               switch (keysym)
1987               {
1988                 case XK_q:
1989                   quit = True;
1990                   done = True;
1991                   break;
1992               }
1993               break;
1994             case ClientMessage:
1995               if (event.xclient.data.l[0] == protocol[0])
1996               {
1997                 /*exit(0);*/
1998 		quit = True;
1999 		done = True;
2000 		break;
2001               }
2002           } /* switch(event.type) */
2003         }
2004     } /* if (!XEventsQueued()) else */
2005   } /* while (!done) */
2006 
2007   XDestroyWindow(display, toolswindow);
2008   strcpy(LastArgv, "");
2009   in_runlevels = False;
2010   in_LevelEditor = False;
2011 }
2012