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