46bbbf21fe046ac1bdae9a8e52ec5b9b9ff95717
[rocksndiamonds.git] / src / game.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  ©1995 Artsoft Development                               *
5 *        Holger Schemel                                    *
6 *        33659 Bielefeld-Senne                             *
7 *        Telefon: (0521) 493245                            *
8 *        eMail: aeglos@valinor.owl.de                      *
9 *               aeglos@uni-paderborn.de                    *
10 *               q99492@pbhrzx.uni-paderborn.de             *
11 *----------------------------------------------------------*
12 *  game.c                                                  *
13 ***********************************************************/
14
15 #include "game.h"
16 #include "misc.h"
17 #include "tools.h"
18 #include "screens.h"
19 #include "sound.h"
20 #include "init.h"
21 #include "buttons.h"
22 #include "files.h"
23
24 void GetPlayerConfig()
25 {
26   int old_joystick_nr = joystick_nr;
27
28   if (sound_status==SOUND_OFF)
29     player.setup &= ~SETUP_SOUND;
30   if (!sound_loops_allowed)
31   {
32     player.setup &= ~SETUP_SOUND_LOOPS;
33     player.setup &= ~SETUP_SOUND_MUSIC;
34   }
35
36   sound_on = SETUP_SOUND_ON(player.setup);
37   sound_loops_on = SETUP_SOUND_LOOPS_ON(player.setup);
38   sound_music_on = SETUP_SOUND_MUSIC_ON(player.setup);
39   toons_on = SETUP_TOONS_ON(player.setup);
40   direct_draw_on = SETUP_DIRECT_DRAW_ON(player.setup);
41   fading_on = SETUP_FADING_ON(player.setup);
42   autorecord_on = SETUP_RECORD_EACH_GAME_ON(player.setup);
43   joystick_nr = SETUP_2ND_JOYSTICK_ON(player.setup);
44   quick_doors = SETUP_QUICK_DOORS_ON(player.setup);
45
46   if (joystick_nr != old_joystick_nr)
47   {
48     if (joystick_device)
49       close(joystick_device);
50     InitJoystick();
51   }
52 }
53
54 void InitGame()
55 {
56   int i,x,y;
57
58   Dynamite = Score = 0;
59   Gems = level.edelsteine;
60   DynaBombCount = DynaBombSize = DynaBombsLeft = 0;
61   Key[0] = Key[1] = Key[2] = Key[3] = FALSE;
62   MampferNr = 0;
63   TimeLeft = level.time;
64   CheckMoving = TRUE;
65   CheckExploding = FALSE;
66   LevelSolved = GameOver = SiebAktiv = FALSE;
67   JX = JY = 0;
68   ZX = ZY = -1;
69
70   if (tape.recording)
71     TapeStartRecording();
72   else if (tape.playing)
73     TapeStartPlaying();
74
75   DigField(0,0,DF_NO_PUSH);
76   SnapField(0,0);
77
78   for(i=0;i<MAX_NUM_AMOEBA;i++)
79     AmoebaCnt[i] = 0;
80
81   for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
82   {
83     Feld[x][y] = Ur[x][y];
84     MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
85     Store[x][y] = Store2[x][y] = Frame[x][y] = AmoebaNr[x][y] = 0;
86     JustHit[x][y] = 0;
87
88     switch(Feld[x][y])
89     {
90       case EL_SPIELFIGUR:
91       case EL_SPIELER1:
92         Feld[x][y] = EL_LEERRAUM;
93         JX = x;
94         JY = y;
95         break;
96       case EL_SPIELER2:
97         Feld[x][y] = EL_LEERRAUM;
98         break;
99       case EL_BADEWANNE:
100         if (x<lev_fieldx-1 && Feld[x+1][y]==EL_SALZSAEURE)
101           Feld[x][y] = EL_BADEWANNE1;
102         else if (x>0 && Feld[x-1][y]==EL_SALZSAEURE)
103           Feld[x][y] = EL_BADEWANNE2;
104         else if (y>0 && Feld[x][y-1]==EL_BADEWANNE1)
105           Feld[x][y] = EL_BADEWANNE3;
106         else if (y>0 && Feld[x][y-1]==EL_SALZSAEURE)
107           Feld[x][y] = EL_BADEWANNE4;
108         else if (y>0 && Feld[x][y-1]==EL_BADEWANNE2)
109           Feld[x][y] = EL_BADEWANNE5;
110         break;
111       case EL_KAEFER_R:
112       case EL_KAEFER_O:
113       case EL_KAEFER_L:
114       case EL_KAEFER_U:
115       case EL_KAEFER:
116       case EL_FLIEGER_R:
117       case EL_FLIEGER_O:
118       case EL_FLIEGER_L:
119       case EL_FLIEGER_U:
120       case EL_FLIEGER:
121       case EL_PACMAN_R:
122       case EL_PACMAN_O:
123       case EL_PACMAN_L:
124       case EL_PACMAN_U:
125       case EL_MAMPFER:
126       case EL_MAMPFER2:
127       case EL_ZOMBIE:
128       case EL_PACMAN:
129         InitMovDir(x,y);
130         break;
131       case EL_AMOEBE_VOLL:
132         InitAmoebaNr(x,y);
133         break;
134       case EL_TROPFEN:
135         if (y==lev_fieldy-1)
136         {
137           Feld[x][y] = EL_AMOEBING;
138           Store[x][y] = EL_AMOEBE_NASS;
139         }
140         break;
141       default:
142         break;
143     }
144   }
145
146   scroll_x = scroll_y = -1;
147   if (JX>=MIDPOSX-1)
148     scroll_x =
149       (JX<=lev_fieldx-MIDPOSX ? JX-MIDPOSX : lev_fieldx-SCR_FIELDX+1);
150   if (JY>=MIDPOSY-1)
151     scroll_y =
152       (JY<=lev_fieldy-MIDPOSY ? JY-MIDPOSY : lev_fieldy-SCR_FIELDY+1);
153
154   DrawLevel();
155   DrawLevelElement(JX,JY,EL_SPIELFIGUR);
156   FadeToFront();
157
158   XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
159             DOOR_GFX_PAGEX5,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
160             DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
161   DrawTextExt(pix[PIX_DB_DOOR],gc,
162               DOOR_GFX_PAGEX1+XX_LEVEL,DOOR_GFX_PAGEY1+YY_LEVEL,
163               int2str(level_nr,2),FS_SMALL,FC_YELLOW);
164   DrawTextExt(pix[PIX_DB_DOOR],gc,
165               DOOR_GFX_PAGEX1+XX_EMERALDS,DOOR_GFX_PAGEY1+YY_EMERALDS,
166               int2str(Gems,3),FS_SMALL,FC_YELLOW);
167   DrawTextExt(pix[PIX_DB_DOOR],gc,
168               DOOR_GFX_PAGEX1+XX_DYNAMITE,DOOR_GFX_PAGEY1+YY_DYNAMITE,
169               int2str(Dynamite,3),FS_SMALL,FC_YELLOW);
170   DrawTextExt(pix[PIX_DB_DOOR],gc,
171               DOOR_GFX_PAGEX1+XX_SCORE,DOOR_GFX_PAGEY1+YY_SCORE,
172               int2str(Score,5),FS_SMALL,FC_YELLOW);
173   DrawTextExt(pix[PIX_DB_DOOR],gc,
174               DOOR_GFX_PAGEX1+XX_TIME,DOOR_GFX_PAGEY1+YY_TIME,
175               int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
176
177   DrawGameButton(BUTTON_GAME_STOP);
178   DrawGameButton(BUTTON_GAME_PAUSE);
179   DrawGameButton(BUTTON_GAME_PLAY);
180   DrawSoundDisplay(BUTTON_SOUND_MUSIC | (BUTTON_ON * sound_music_on));
181   DrawSoundDisplay(BUTTON_SOUND_LOOPS | (BUTTON_ON * sound_loops_on));
182   DrawSoundDisplay(BUTTON_SOUND_SOUND | (BUTTON_ON * sound_on));
183   XCopyArea(display,drawto,pix[PIX_DB_DOOR],gc,
184             DX+GAME_CONTROL_XPOS,DY+GAME_CONTROL_YPOS,
185             GAME_CONTROL_XSIZE,2*GAME_CONTROL_YSIZE,
186             DOOR_GFX_PAGEX1+GAME_CONTROL_XPOS,
187             DOOR_GFX_PAGEY1+GAME_CONTROL_YPOS);
188
189   OpenDoor(DOOR_OPEN_1);
190
191   if (sound_music_on)
192     PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
193
194   XAutoRepeatOff(display);
195 }
196
197 void InitMovDir(int x, int y)
198 {
199   int i, element = Feld[x][y];
200   static int xy[4][2] =
201   {
202     0,+1,
203     +1,0,
204     0,-1,
205     -1,0
206   };
207   static int direction[2][4] =
208   {
209     MV_RIGHT, MV_UP,   MV_LEFT,  MV_DOWN,
210     MV_LEFT,  MV_DOWN, MV_RIGHT, MV_UP
211   };
212
213   switch(element)
214   {
215     case EL_KAEFER_R:
216     case EL_KAEFER_O:
217     case EL_KAEFER_L:
218     case EL_KAEFER_U:
219       Feld[x][y] = EL_KAEFER;
220       MovDir[x][y] = direction[0][element-EL_KAEFER_R];
221       break;
222     case EL_FLIEGER_R:
223     case EL_FLIEGER_O:
224     case EL_FLIEGER_L:
225     case EL_FLIEGER_U:
226       Feld[x][y] = EL_FLIEGER;
227       MovDir[x][y] = direction[0][element-EL_FLIEGER_R];
228       break;
229     case EL_PACMAN_R:
230     case EL_PACMAN_O:
231     case EL_PACMAN_L:
232     case EL_PACMAN_U:
233       Feld[x][y] = EL_PACMAN;
234       MovDir[x][y] = direction[0][element-EL_PACMAN_R];
235       break;
236     default:
237       MovDir[x][y] = 1<<RND(4);
238       if (element!=EL_KAEFER && element!=EL_FLIEGER)
239         break;
240
241       for(i=0;i<4;i++)
242       {
243         int x1,y1;
244
245         x1 = x+xy[i][0];
246         y1 = y+xy[i][1];
247
248         if (!IN_LEV_FIELD(x1,y1) || !IS_FREE(x1,y1))
249         {
250           if (element==EL_KAEFER)
251           {
252             MovDir[x][y] = direction[0][i];
253             break;
254           }
255           else if (element==EL_FLIEGER)
256           {
257             MovDir[x][y] = direction[1][i];
258             break;
259           }
260         }
261       }
262       break;
263   }
264 }
265
266 void InitAmoebaNr(int x, int y)
267 {
268   int i;
269   int group_nr = AmoebeNachbarNr(x,y);
270
271   if (group_nr==0)
272   {
273     for(i=1;i<MAX_NUM_AMOEBA;i++)
274     {
275       if (AmoebaCnt[i]==0)
276       {
277         group_nr = i;
278         break;
279       }
280     }
281   }
282
283   AmoebaNr[x][y] = group_nr;
284   AmoebaCnt[group_nr]++;
285 }
286
287 void GameWon()
288 {
289   int hi_pos;
290   int bumplevel = FALSE;
291
292   if (sound_loops_on)
293     PlaySoundExt(SND_SIRR,PSND_MAX_VOLUME,PSND_MAX_RIGHT,PSND_LOOP);
294
295   if (TimeLeft>0) 
296   {
297     for(;TimeLeft>=0;TimeLeft--)
298     {
299       if (!sound_loops_on)
300         PlaySoundStereo(SND_SIRR,PSND_MAX_RIGHT);
301       if (TimeLeft && !(TimeLeft % 10))
302         RaiseScore(level.score[SC_ZEITBONUS]);
303       DrawText(DX_TIME,DY_TIME,int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
304       BackToFront();
305       Delay(10000);
306     }
307   }
308
309   if (sound_loops_on)
310     StopSound(SND_SIRR);
311   FadeSounds();
312
313   if (tape.playing)
314     return;
315
316   CloseDoor(DOOR_CLOSE_1);
317
318   if (level_nr==player.handicap &&
319       level_nr<leveldir[leveldir_nr].num_ready-1)
320   { 
321     player.handicap++; 
322     bumplevel = TRUE;
323     SavePlayerInfo(PLAYER_LEVEL);
324   }
325
326   if ((hi_pos=NewHiScore())>=0) 
327   {
328     game_status = HALLOFFAME;
329     DrawHallOfFame(hi_pos);
330     if (bumplevel && TAPE_IS_EMPTY(tape))
331       level_nr++;
332   }
333   else
334   {
335     game_status = MAINMENU;
336     if (bumplevel && TAPE_IS_EMPTY(tape))
337       level_nr++;
338     DrawMainMenu();
339   }
340   BackToFront();
341 }
342
343 BOOL NewHiScore()
344 {
345   int k,l;
346   int position = -1;
347
348   LoadScore(level_nr);
349
350   if (!strcmp(player.alias_name,EMPTY_ALIAS) ||
351       Score<highscore[MAX_SCORE_ENTRIES-1].Score) 
352     return(-1);
353
354   for(k=0;k<MAX_SCORE_ENTRIES;k++) 
355   {
356     if (Score>highscore[k].Score)       /* Spieler kommt in Highscore-Liste */
357     {
358       if (k<MAX_SCORE_ENTRIES-1)
359       {
360         int m = MAX_SCORE_ENTRIES-1;
361
362 #ifdef ONE_PER_NAME
363         for(l=k;l<MAX_SCORE_ENTRIES;l++)
364           if (!strcmp(player.alias_name,highscore[l].Name))
365             m = l;
366         if (m==k)       /* Spieler überschreibt seine alte Position */
367           goto put_into_list;
368 #endif
369
370         for(l=m;l>k;l--)
371         {
372           strcpy(highscore[l].Name,highscore[l-1].Name);
373           highscore[l].Score = highscore[l-1].Score;
374         }
375       }
376
377 #ifdef ONE_PER_NAME
378       put_into_list:
379 #endif
380       sprintf(highscore[k].Name,player.alias_name);
381       highscore[k].Score = Score; 
382       position = k;
383       break;
384     }
385
386 #ifdef ONE_PER_NAME
387     else if (!strcmp(player.alias_name,highscore[k].Name))
388       break;    /* Spieler schon mit besserer Punktzahl in der Liste */
389 #endif
390
391   }
392
393   if (position>=0) 
394     SaveScore(level_nr);
395
396   return(position);
397 }
398
399 void InitMovingField(int x, int y, int direction)
400 {
401   int newx = x + (direction==MV_LEFT ? -1 : direction==MV_RIGHT ? +1 : 0);
402   int newy = y + (direction==MV_UP   ? -1 : direction==MV_DOWN  ? +1 : 0);
403
404   CheckMoving = TRUE;
405   MovDir[x][y] = direction;
406   MovDir[newx][newy] = direction;
407   if (Feld[newx][newy]==EL_LEERRAUM)
408     Feld[newx][newy] = EL_BLOCKED;
409 }
410
411 void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y)
412 {
413   int direction = MovDir[x][y];
414   int newx = x + (direction==MV_LEFT ? -1 : direction==MV_RIGHT ? +1 : 0);
415   int newy = y + (direction==MV_UP   ? -1 : direction==MV_DOWN  ? +1 : 0);
416
417   *goes_to_x = newx;
418   *goes_to_y = newy;
419 }
420
421 void Blocked2Moving(int x, int y, int *comes_from_x, int *comes_from_y)
422 {
423   int oldx = x, oldy = y;
424   int direction = MovDir[x][y];
425
426   if (direction==MV_LEFT)
427     oldx++;
428   else if (direction==MV_RIGHT)
429     oldx--;
430   else if (direction==MV_UP)
431     oldy++;
432   else if (direction==MV_DOWN)
433     oldy--;
434
435   *comes_from_x = oldx;
436   *comes_from_y = oldy;
437 }
438
439 int MovingOrBlocked2Element(int x, int y)
440 {
441   int element = Feld[x][y];
442
443   if (element==EL_BLOCKED)
444   {
445     int oldx,oldy;
446
447     Blocked2Moving(x,y,&oldx,&oldy);
448     return(Feld[oldx][oldy]);
449   }
450   else
451     return(element);
452 }
453
454 void RemoveMovingField(int x, int y)
455 {
456   int oldx=x,oldy=y, newx=x,newy=y;
457
458   if (Feld[x][y]!=EL_BLOCKED && !IS_MOVING(x,y))
459     return;
460
461   if (IS_MOVING(x,y))
462   {
463     Moving2Blocked(x,y,&newx,&newy);
464     if (Feld[newx][newy]!=EL_BLOCKED)
465       return;
466   }
467   else if (Feld[x][y]==EL_BLOCKED)
468   {
469     Blocked2Moving(x,y,&oldx,&oldy);
470     if (!IS_MOVING(oldx,oldy))
471       return;
472   }
473
474   Feld[oldx][oldy] = EL_LEERRAUM;
475   Feld[newx][newy] = EL_LEERRAUM;
476   MovPos[oldx][oldy] = MovDir[oldx][oldy] = MovDelay[oldx][oldy] = 0;
477   MovPos[newx][newy] = MovDir[newx][newy] = MovDelay[newx][newy] = 0;
478   DrawLevelField(oldx,oldy);
479   DrawLevelField(newx,newy);
480 }
481
482 void DrawDynamite(int x, int y)
483 {
484   int phase = (48-MovDelay[x][y])/6;
485
486   if (!IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
487     return;
488
489   if (phase>6)
490     phase = 6;
491
492   if (Store[x][y])
493   {
494     DrawGraphic(SCROLLX(x),SCROLLY(y),el2gfx(Store[x][y]));
495     if (PLAYER(x,y))
496       DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR);
497   }
498   else if (PLAYER(x,y))
499     DrawGraphic(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR);
500
501   if (Store[x][y] || PLAYER(x,y))
502     DrawGraphicThruMask(SCROLLX(x),SCROLLY(y),GFX_DYNAMIT+phase);
503   else
504     DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_DYNAMIT+phase);
505 }
506
507 void CheckDynamite(int x, int y)
508 {
509   CheckExploding = TRUE;
510
511   if (MovDelay[x][y])           /* neues Dynamit / in Wartezustand */
512   {
513     MovDelay[x][y]--;
514     if (MovDelay[x][y])
515     {
516       if (!(MovDelay[x][y] % 6))
517       {
518         DrawDynamite(x,y);
519         PlaySoundLevel(x,y,SND_ZISCH);
520       }
521
522       return;
523     }
524   }
525
526   StopSound(SND_ZISCH);
527   Bang(x,y);
528 }
529
530 void Explode(int ex, int ey, int phase, int mode)
531 {
532   int x,y;
533   int num_phase = 9, delay = 1;
534   int last_phase = num_phase*delay;
535   int half_phase = (num_phase/2)*delay;
536
537   if (phase==0)                 /* Feld 'Store' initialisieren */
538   {
539     int center_element = Feld[ex][ey];
540
541     if (center_element==EL_BLOCKED)
542       center_element = MovingOrBlocked2Element(ex,ey);
543
544     for(y=ey-1;y<ey+2;y++) for(x=ex-1;x<ex+2;x++)
545     {
546       int element = Feld[x][y];
547
548       if (!IN_LEV_FIELD(x,y) || IS_MASSIV(element))
549         continue;
550
551       if ((mode!=EX_NORMAL || center_element==EL_AMOEBA2DIAM) &&
552           (x!=ex || y!=ey))
553         continue;
554
555       if (element==EL_EXPLODING)
556         element = Store2[x][y];
557
558       if (PLAYER(ex,ey) || center_element==EL_KAEFER)
559         Store[x][y] = ((x==ex && y==ey) ? EL_DIAMANT : EL_EDELSTEIN);
560       else if (center_element==EL_MAMPFER)
561         Store[x][y] = level.mampfer_inhalt[MampferNr][x-ex+1][y-ey+1];
562       else if (center_element==EL_AMOEBA2DIAM)
563         Store[x][y] = level.amoebe_inhalt;
564       else if (element==EL_ERZ_EDEL)
565         Store[x][y] = EL_EDELSTEIN;
566       else if (element==EL_ERZ_DIAM)
567         Store[x][y] = EL_DIAMANT;
568       else if (element==EL_ERZ_EDEL2)
569         Store[x][y] = EL_EDELSTEIN2;
570       else if (element==EL_ERZ_EDEL3)
571         Store[x][y] = EL_EDELSTEIN3;
572       else if (!IS_PFORTE(Store[x][y]))
573         Store[x][y] = EL_LEERRAUM;
574
575       if (x!=ex || y!=ey || center_element==EL_AMOEBA2DIAM || mode==EX_BORDER)
576         Store2[x][y] = element;
577
578       if (AmoebaNr[x][y] && (element==EL_AMOEBE_VOLL || element==EL_AMOEBING))
579         AmoebaCnt[AmoebaNr[x][y]]--;
580
581       RemoveMovingField(x,y);
582       Feld[x][y] = EL_EXPLODING;
583       MovDir[x][y] = MovPos[x][y] = 0;
584       AmoebaNr[x][y] = 0;
585       Frame[x][y] = 1;
586       Stop[x][y] = TRUE;
587     }
588
589     if (center_element==EL_MAMPFER)
590       MampferNr = (MampferNr+1) % 4;
591
592     return;
593   }
594
595   if (Stop[ex][ey])
596     return;
597
598   x = ex;
599   y = ey;
600
601   Frame[x][y] = (phase<last_phase ? phase+1 : 0);
602
603   if (phase==half_phase)
604   {
605     int element = Store2[x][y];
606
607     if (PLAYER(x,y))
608       KillHero();
609     else if (element==EL_BOMBE ||
610              element==EL_DYNAMIT ||
611              element==EL_DYNAMIT_AUS ||
612              element==EL_DYNABOMB ||
613              element==EL_KAEFER)
614     {
615       Feld[x][y] = Store2[x][y];
616       Store2[x][y] = 0;
617       Bang(x,y);
618     }
619     else if (element==EL_AMOEBA2DIAM)
620       AmoebeUmwandeln(x,y);
621   }
622
623   if (phase==last_phase)
624   {
625     int element;
626
627     element = Feld[x][y] = Store[x][y];
628     Store[x][y] = Store2[x][y] = 0;
629     MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0;
630     if (CAN_MOVE(element) || COULD_MOVE(element))
631       InitMovDir(x,y);
632     DrawLevelField(x,y);
633   }
634   else if (!(phase%delay) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
635   {
636     if (phase==delay)
637       ErdreichAnbroeckeln(SCROLLX(x),SCROLLY(y));
638
639     DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_EXPLOSION+(phase/delay-1));
640   }
641
642   CheckExploding = TRUE;
643 }
644
645 void DynaExplode(int ex, int ey, int size)
646 {
647   int i,j;
648   static int xy[4][2] =
649   {
650     0,-1,
651     -1,0,
652     +1,0,
653     0,+1
654   };
655
656   Explode(ex,ey,0,EX_CENTER);
657
658   for(i=0;i<4;i++)
659   {
660     for(j=1;j<=size;j++)
661     {
662       int x = ex+j*xy[i%4][0];
663       int y = ey+j*xy[i%4][1];
664
665       if (!IN_LEV_FIELD(x,y) || IS_MASSIV(Feld[x][y]))
666         break;
667
668       Explode(x,y,0,EX_BORDER);
669     }
670   }
671
672   DynaBombsLeft++;
673 }
674
675 void Bang(int x, int y)
676 {
677   int element = Feld[x][y];
678
679   CheckExploding = TRUE;
680   PlaySoundLevel(x,y,SND_ROAAAR);
681
682   switch(element)
683   {
684     case EL_KAEFER:
685       RaiseScore(level.score[SC_KAEFER]);
686       break;
687     case EL_FLIEGER:
688       RaiseScore(level.score[SC_FLIEGER]);
689       break;
690     case EL_MAMPFER:
691     case EL_MAMPFER2:
692       RaiseScore(level.score[SC_MAMPFER]);
693       break;
694     case EL_ZOMBIE:
695       RaiseScore(level.score[SC_ZOMBIE]);
696       break;
697     case EL_PACMAN:
698       RaiseScore(level.score[SC_PACMAN]);
699       break;
700     default:
701       break;
702   }
703
704   if (element==EL_DYNABOMB)
705     DynaExplode(x,y,DynaBombSize);
706   else
707     Explode(x,y,0,EX_NORMAL);
708 }
709
710 void Blurb(int x, int y)
711 {
712   int element = Feld[x][y];
713
714   if (element!=EL_BLURB_LEFT && element!=EL_BLURB_RIGHT) /* Anfang */
715   {
716     PlaySoundLevel(x,y,SND_BLURB);
717     if (IN_LEV_FIELD(x-1,y) && IS_FREE(x-1,y) &&
718         (!IN_LEV_FIELD(x-1,y-1) ||
719          !CAN_FALL(MovingOrBlocked2Element(x-1,y-1))))
720     {
721       Feld[x-1][y] = EL_BLURB_LEFT;
722     }
723     if (IN_LEV_FIELD(x+1,y) && IS_FREE(x+1,y) &&
724         (!IN_LEV_FIELD(x+1,y-1) ||
725          !CAN_FALL(MovingOrBlocked2Element(x+1,y-1))))
726     {
727       Feld[x+1][y] = EL_BLURB_RIGHT;
728     }
729   }
730   else                                                   /* Blubbern */
731   {
732     int graphic = (element==EL_BLURB_LEFT ? GFX_BLURB_LEFT : GFX_BLURB_RIGHT);
733
734     CheckExploding = TRUE;
735
736     if (!MovDelay[x][y])        /* neue Phase / noch nicht gewartet */
737       MovDelay[x][y] = 5;
738
739     if (MovDelay[x][y])         /* neue Phase / in Wartezustand */
740     {
741       MovDelay[x][y]--;
742       if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
743         DrawGraphic(SCROLLX(x),SCROLLY(y),graphic+4-MovDelay[x][y]);
744
745       if (!MovDelay[x][y])
746       {
747         Feld[x][y] = EL_LEERRAUM;
748         DrawLevelField(x,y);
749       }
750     }
751   }
752 }
753
754 void Impact(int x, int y)
755 {
756   BOOL lastline = (y==lev_fieldy-1);
757   BOOL object_hit = FALSE;
758   int element = Feld[x][y];
759
760   /* Element darunter berührt? */
761   if (!lastline)
762     object_hit = (!IS_FREE(x,y+1) && (!IS_MOVING(x,y+1) ||
763                                       MovDir[x][y+1]!=MV_DOWN ||
764                                       MovPos[x][y+1]<=TILEY/2));
765
766   /* Auftreffendes Element fällt in Salzsäure */
767   if (!lastline && Feld[x][y+1]==EL_SALZSAEURE)
768   {
769     Blurb(x,y);
770     return;
771   }
772
773   /* Auftreffendes Element ist Bombe */
774   if (element==EL_BOMBE && (lastline || object_hit))
775   {
776     Bang(x,y);
777     return;
778   }
779
780   /* Auftreffendes Element ist Säuretropfen */
781   if (element==EL_TROPFEN && (lastline || object_hit))
782   {
783     if (object_hit && PLAYER(x,y+1))
784       KillHero();
785     else
786     {
787       Feld[x][y] = EL_AMOEBING;
788       Store[x][y] = EL_AMOEBE_NASS;
789     }
790     return;
791   }
792
793   /* Welches Element kriegt was auf die Rübe? */
794   if (!lastline && object_hit)
795   {
796     int smashed = Feld[x][y+1];
797
798     if (PLAYER(x,y+1))
799     {
800       KillHero();
801       return;
802     }
803     else if (element==EL_FELSBROCKEN ||
804              element==EL_EDELSTEIN2 || element==EL_EDELSTEIN3)
805     {
806       if (IS_ENEMY(MovingOrBlocked2Element(x,y+1)))
807       {
808         Bang(x,y+1);
809         return;
810       }
811       else if (!IS_MOVING(x,y+1))
812       {
813         if (smashed==EL_BOMBE)
814         {
815           Bang(x,y+1);
816           return;
817         }
818         else if (smashed==EL_KOKOSNUSS)
819         {
820           Feld[x][y+1] = EL_CRACKINGNUT;
821           PlaySoundLevel(x,y,SND_KNACK);
822           RaiseScore(level.score[SC_KOKOSNUSS]);
823           return;
824         }
825         else if (smashed==EL_DIAMANT)
826         {
827           Feld[x][y+1] = EL_LEERRAUM;
828           PlaySoundLevel(x,y,SND_QUIRK);
829           return;
830         }
831       }
832     }
833   }
834
835   /* Kein Geräusch beim Durchqueren des Siebes */
836   if (!lastline && (Feld[x][y+1]==EL_SIEB_LEER || Feld[x][y+1]==EL_SIEB2_LEER))
837     return;
838
839   /* Geräusch beim Auftreffen */
840   if (lastline || object_hit)
841   {
842     int sound;
843
844     switch(element)
845     {
846       case EL_EDELSTEIN:
847       case EL_EDELSTEIN2:
848       case EL_EDELSTEIN3:
849       case EL_DIAMANT:
850         sound = SND_PLING;
851         break;
852       case EL_KOKOSNUSS:
853         sound = SND_KLUMPF;
854         break;
855       case EL_FELSBROCKEN:
856         sound = SND_KLOPF;
857         break;
858       case EL_SCHLUESSEL:
859       case EL_SCHLUESSEL1:
860       case EL_SCHLUESSEL2:
861       case EL_SCHLUESSEL3:
862       case EL_SCHLUESSEL4:
863         sound = SND_KINK;
864         break;
865       case EL_ZEIT_VOLL:
866       case EL_ZEIT_LEER:
867         sound = SND_DENG;
868         break;
869       default:
870         sound = -1;
871         break;
872     }
873
874     if (sound>=0)
875       PlaySoundLevel(x,y,sound);
876   }
877 }
878
879 void TurnRound(int x, int y)
880 {
881   int element = Feld[x][y];
882   int direction = MovDir[x][y];
883
884   if (element==EL_KAEFER)
885   {
886     TestIfBadThingHitsOtherBadThing(x,y);
887
888     if (MovDir[x][y]==MV_LEFT)
889     {
890       if (IN_LEV_FIELD(x,y-1) && IS_FREE(x,y-1))
891         MovDir[x][y]=MV_UP;
892       else if (!IN_LEV_FIELD(x-1,y) || !IS_FREE(x-1,y))
893         MovDir[x][y]=MV_DOWN;
894     }
895     else if (MovDir[x][y]==MV_RIGHT)
896     {
897       if (IN_LEV_FIELD(x,y+1) && IS_FREE(x,y+1))
898         MovDir[x][y]=MV_DOWN;
899       else if (!IN_LEV_FIELD(x+1,y) || !IS_FREE(x+1,y))
900         MovDir[x][y]=MV_UP;
901     }
902     else if (MovDir[x][y]==MV_UP)
903     {
904       if (IN_LEV_FIELD(x+1,y) && IS_FREE(x+1,y))
905         MovDir[x][y]=MV_RIGHT;
906       else if (!IN_LEV_FIELD(x,y-1) || !IS_FREE(x,y-1))
907         MovDir[x][y]=MV_LEFT;
908     }
909     else if (MovDir[x][y]==MV_DOWN)
910     {
911       if (IN_LEV_FIELD(x-1,y) && IS_FREE(x-1,y))
912         MovDir[x][y]=MV_LEFT;
913       else if (!IN_LEV_FIELD(x,y+1) || !IS_FREE(x,y+1))
914         MovDir[x][y]=MV_RIGHT;
915     }
916
917     if (direction!=MovDir[x][y])
918       MovDelay[x][y]=5;
919   }
920   else if (element==EL_FLIEGER)
921   {
922     TestIfBadThingHitsOtherBadThing(x,y);
923
924     if (MovDir[x][y]==MV_LEFT)
925     {
926       if (IN_LEV_FIELD(x,y+1) && IS_FREE(x,y+1))
927         MovDir[x][y]=MV_DOWN;
928       else if (!IN_LEV_FIELD(x-1,y) || !IS_FREE(x-1,y))
929         MovDir[x][y]=MV_UP;
930     }
931     else if (MovDir[x][y]==MV_RIGHT)
932     {
933       if (IN_LEV_FIELD(x,y-1) && IS_FREE(x,y-1))
934         MovDir[x][y]=MV_UP;
935       else if (!IN_LEV_FIELD(x+1,y) || !IS_FREE(x+1,y))
936         MovDir[x][y]=MV_DOWN;
937     }
938     else if (MovDir[x][y]==MV_UP)
939     {
940       if (IN_LEV_FIELD(x-1,y) && IS_FREE(x-1,y))
941         MovDir[x][y]=MV_LEFT;
942       else if (!IN_LEV_FIELD(x,y-1) || !IS_FREE(x,y-1))
943         MovDir[x][y]=MV_RIGHT;
944     }
945     else if (MovDir[x][y]==MV_DOWN)
946     {
947       if (IN_LEV_FIELD(x+1,y) && IS_FREE(x+1,y))
948         MovDir[x][y]=MV_RIGHT;
949       else if (!IN_LEV_FIELD(x,y+1) || !IS_FREE(x,y+1))
950         MovDir[x][y]=MV_LEFT;
951     }
952
953     if (direction!=MovDir[x][y])
954       MovDelay[x][y]=5;
955   }
956   else if (element==EL_MAMPFER)
957   {
958     if (MovDir[x][y]==MV_LEFT || MovDir[x][y]==MV_RIGHT)
959     {
960       MovDir[x][y]=(MovDir[x][y]==MV_LEFT ? MV_RIGHT : MV_LEFT);
961       if (IN_LEV_FIELD(x,y-1) &&
962           (IS_FREE(x,y-1) || Feld[x][y-1]==EL_DIAMANT) &&
963           RND(2))
964         MovDir[x][y]=MV_UP;
965       if (IN_LEV_FIELD(x,y+1) &&
966           (IS_FREE(x,y+1) || Feld[x][y+1]==EL_DIAMANT) &&
967           RND(2))
968         MovDir[x][y]=MV_DOWN;
969     }
970     else if (MovDir[x][y]==MV_UP || MovDir[x][y]==MV_DOWN)
971     {
972       MovDir[x][y]=(MovDir[x][y]==MV_UP ? MV_DOWN : MV_UP);
973       if (IN_LEV_FIELD(x-1,y) &&
974           (IS_FREE(x-1,y) || Feld[x-1][y]==EL_DIAMANT) &&
975           RND(2))
976         MovDir[x][y]=MV_LEFT;
977       if (IN_LEV_FIELD(x+1,y) &&
978           (IS_FREE(x+1,y) || Feld[x+1][y]==EL_DIAMANT) &&
979           RND(2))
980         MovDir[x][y]=MV_RIGHT;
981     }
982
983     MovDelay[x][y]=8+8*RND(3);
984   }
985   else if (element==EL_MAMPFER2)
986   {
987     if (MovDir[x][y]==MV_LEFT || MovDir[x][y]==MV_RIGHT)
988     {
989       MovDir[x][y]=(MovDir[x][y]==MV_LEFT ? MV_RIGHT : MV_LEFT);
990       if (IN_LEV_FIELD(x,y-1) &&
991           (IS_FREE(x,y-1) || IS_MAMPF2(Feld[x][y-1])) && RND(2))
992         MovDir[x][y]=MV_UP;
993       if (IN_LEV_FIELD(x,y+1) &&
994           (IS_FREE(x,y+1) || IS_MAMPF2(Feld[x][y+1])) && RND(2))
995         MovDir[x][y]=MV_DOWN;
996     }
997     else if (MovDir[x][y]==MV_UP || MovDir[x][y]==MV_DOWN)
998     {
999       MovDir[x][y]=(MovDir[x][y]==MV_UP ? MV_DOWN : MV_UP);
1000       if (IN_LEV_FIELD(x-1,y) &&
1001           (IS_FREE(x-1,y) || IS_MAMPF2(Feld[x-1][y])) && RND(2))
1002         MovDir[x][y]=MV_LEFT;
1003       if (IN_LEV_FIELD(x+1,y) &&
1004           (IS_FREE(x+1,y) || IS_MAMPF2(Feld[x+1][y])) && RND(2))
1005         MovDir[x][y]=MV_RIGHT;
1006     }
1007
1008     MovDelay[x][y]=8+8*RND(3);
1009   }
1010   else if (element==EL_PACMAN)
1011   {
1012     if (MovDir[x][y]==MV_LEFT || MovDir[x][y]==MV_RIGHT)
1013     {
1014       MovDir[x][y]=(MovDir[x][y]==MV_LEFT ? MV_RIGHT : MV_LEFT);
1015       if (IN_LEV_FIELD(x,y-1) &&
1016           (IS_FREE(x,y-1) || IS_AMOEBOID(Feld[x][y-1])) &&
1017           RND(2))
1018         MovDir[x][y]=MV_UP;
1019       if (IN_LEV_FIELD(x,y+1) &&
1020           (IS_FREE(x,y+1) || IS_AMOEBOID(Feld[x][y+1])) &&
1021           RND(2))
1022         MovDir[x][y]=MV_DOWN;
1023     }
1024     else if (MovDir[x][y]==MV_UP || MovDir[x][y]==MV_DOWN)
1025     {
1026       MovDir[x][y]=(MovDir[x][y]==MV_UP ? MV_DOWN : MV_UP);
1027       if (IN_LEV_FIELD(x-1,y) &&
1028           (IS_FREE(x-1,y) || IS_AMOEBOID(Feld[x-1][y])) &&
1029           RND(2))
1030         MovDir[x][y]=MV_LEFT;
1031       if (IN_LEV_FIELD(x+1,y) &&
1032           (IS_FREE(x+1,y) || IS_AMOEBOID(Feld[x+1][y])) &&
1033           RND(2))
1034         MovDir[x][y]=MV_RIGHT;
1035     }
1036
1037     MovDelay[x][y]=3+RND(20);
1038   }
1039   else if (element==EL_ZOMBIE)
1040   {
1041     int attr_x = JX, attr_y = JY;
1042
1043     if (ZX>=0 && ZY>=0)
1044     {
1045       attr_x = ZX;
1046       attr_y = ZY;
1047     }
1048
1049     MovDir[x][y]=MV_NO_MOVING;
1050     if (attr_x<x)
1051       MovDir[x][y]|=MV_LEFT;
1052     else if (attr_x>x)
1053       MovDir[x][y]|=MV_RIGHT;
1054     if (attr_y<y)
1055       MovDir[x][y]|=MV_UP;
1056     else if (attr_y>y)
1057       MovDir[x][y]|=MV_DOWN;
1058     if ((MovDir[x][y]&(MV_LEFT|MV_RIGHT)) && (MovDir[x][y]&(MV_UP|MV_DOWN)))
1059       MovDir[x][y] &= (RND(2) ? (MV_LEFT|MV_RIGHT) : (MV_UP|MV_DOWN));
1060
1061     MovDelay[x][y] = 8+8*RND(2);
1062   }
1063 }
1064
1065 void StartMoving(int x, int y)
1066 {
1067   int element = Feld[x][y];
1068
1069   if (Stop[x][y])
1070     return;
1071
1072   if (CAN_FALL(element) && y<lev_fieldy-1)
1073   {
1074     if (element==EL_MORAST_VOLL)
1075     {
1076       if (IS_FREE(x,y+1))
1077       {
1078         InitMovingField(x,y,MV_DOWN);
1079         Feld[x][y] = EL_FELSBROCKEN;
1080         Store[x][y] = EL_MORAST_LEER;
1081       }
1082       else if (Feld[x][y+1]==EL_MORAST_LEER)
1083       {
1084         CheckMoving = TRUE;
1085
1086         if (!MovDelay[x][y])
1087           MovDelay[x][y] = 16;
1088
1089         if (MovDelay[x][y])
1090         {
1091           MovDelay[x][y]--;
1092           if (MovDelay[x][y])
1093             return;
1094         }
1095
1096         Feld[x][y] = EL_MORAST_LEER;
1097         Feld[x][y+1] = EL_MORAST_VOLL;
1098       }
1099     }
1100     else if (element==EL_FELSBROCKEN && Feld[x][y+1]==EL_MORAST_LEER)
1101     {
1102       InitMovingField(x,y,MV_DOWN);
1103       Store[x][y] = EL_MORAST_VOLL;
1104     }
1105     else if (element==EL_SIEB_VOLL)
1106     {
1107       if (IS_FREE(x,y+1))
1108       {
1109         InitMovingField(x,y,MV_DOWN);
1110         Feld[x][y] = EL_CHANGED(Store2[x][y]);
1111         Store[x][y] = EL_SIEB_LEER;
1112       }
1113     }
1114     else if (element==EL_SIEB2_VOLL)
1115     {
1116       if (IS_FREE(x,y+1))
1117       {
1118         InitMovingField(x,y,MV_DOWN);
1119         Feld[x][y] = EL_CHANGED2(Store2[x][y]);
1120         Store[x][y] = EL_SIEB2_LEER;
1121       }
1122     }
1123     else if (CAN_CHANGE(element) &&
1124              (Feld[x][y+1]==EL_SIEB_LEER || Feld[x][y+1]==EL_SIEB2_LEER))
1125     {
1126       InitMovingField(x,y,MV_DOWN);
1127       Store[x][y] =
1128         (Feld[x][y+1]==EL_SIEB_LEER ? EL_SIEB_VOLL : EL_SIEB2_VOLL);
1129       Store2[x][y+1] = element;
1130       SiebAktiv = 330;
1131     }
1132     else if (CAN_SMASH(element) && Feld[x][y+1]==EL_SALZSAEURE)
1133     {
1134       Blurb(x,y);
1135       InitMovingField(x,y,MV_DOWN);
1136       Store[x][y] = EL_SALZSAEURE;
1137     }
1138     else if (CAN_SMASH(element) && Feld[x][y+1]==EL_BLOCKED && JustHit[x][y])
1139     {
1140       Impact(x,y);
1141     }
1142     else if (IS_FREE(x,y+1))
1143     {
1144       InitMovingField(x,y,MV_DOWN);
1145     }
1146     else if (element==EL_TROPFEN)
1147     {
1148       Feld[x][y] = EL_AMOEBING;
1149       Store[x][y] = EL_AMOEBE_NASS;
1150     }
1151     else if (IS_SLIPPERY(Feld[x][y+1]) && !Store[x][y+1])
1152     {
1153       int left  = (x>0 && IS_FREE(x-1,y) &&
1154                    (IS_FREE(x-1,y+1) || Feld[x-1][y+1]==EL_SALZSAEURE));
1155       int right = (x<lev_fieldx-1 && IS_FREE(x+1,y) &&
1156                    (IS_FREE(x+1,y+1) || Feld[x+1][y+1]==EL_SALZSAEURE));
1157
1158       if (left || right)
1159       {
1160         if (left && right)
1161           left = !(right=RND(2));
1162         InitMovingField(x,y,left ? MV_LEFT : MV_RIGHT);
1163       }
1164     }
1165   }
1166   else if (CAN_MOVE(element))
1167   {
1168     int newx,newy;
1169
1170     CheckMoving = TRUE;
1171
1172     if (!MovDelay[x][y])        /* neuer Schritt / noch nicht gewartet */
1173     {
1174       if (element==EL_ZOMBIE || element==EL_KAEFER || element==EL_FLIEGER)
1175       {
1176         TurnRound(x,y);
1177         if (MovDelay[x][y] && (element==EL_KAEFER || element==EL_FLIEGER))
1178           DrawLevelField(x,y);
1179       }
1180     }
1181
1182     if (MovDelay[x][y])         /* neuer Schritt / in Wartezustand */
1183     {
1184       MovDelay[x][y]--;
1185
1186       if (element==EL_ZOMBIE || element==EL_MAMPFER || element==EL_MAMPFER2)
1187       {
1188         int phase = MovDelay[x][y] % 8;
1189
1190         if (phase>3)
1191           phase = 7-phase;
1192
1193         if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1194           DrawGraphic(SCROLLX(x),SCROLLY(y),
1195                       el2gfx(element)+phase);
1196
1197         if ((element==EL_MAMPFER || element==EL_MAMPFER2)
1198             && MovDelay[x][y]%4==3)
1199           PlaySoundLevel(x,y,SND_NJAM);
1200       }
1201
1202       if (MovDelay[x][y])
1203         return;
1204     }
1205
1206     if (element==EL_KAEFER)
1207     {
1208       PlaySoundLevel(x,y,SND_KLAPPER);
1209     }
1210     else if (element==EL_FLIEGER)
1211     {
1212       PlaySoundLevel(x,y,SND_ROEHR);
1213     }
1214
1215     /* neuer Schritt / Wartezustand beendet */
1216
1217     Moving2Blocked(x,y,&newx,&newy);    /* wohin soll's gehen? */
1218
1219     if (PLAYER(newx,newy))              /* Spieler erwischt */
1220     {
1221       MovDir[x][y] = 0;
1222       KillHero();
1223       return;
1224     }
1225     else if (element==EL_MAMPFER && IN_LEV_FIELD(newx,newy) &&
1226              Feld[newx][newy]==EL_DIAMANT)
1227     {
1228       if (IS_MOVING(newx,newy))
1229         RemoveMovingField(newx,newy);
1230       else
1231       {
1232         Feld[newx][newy] = EL_LEERRAUM;
1233         DrawLevelField(newx,newy);
1234       }
1235     }
1236     else if (element==EL_MAMPFER2 && IN_LEV_FIELD(newx,newy) &&
1237              IS_MAMPF2(Feld[newx][newy]))
1238     {
1239       if (AmoebaNr[newx][newy] && Feld[newx][newy]==EL_AMOEBE_VOLL)
1240         AmoebaCnt[AmoebaNr[newx][newy]]--;
1241
1242       if (IS_MOVING(newx,newy))
1243         RemoveMovingField(newx,newy);
1244       else
1245       {
1246         Feld[newx][newy] = EL_LEERRAUM;
1247         DrawLevelField(newx,newy);
1248       }
1249     }
1250     else if (element==EL_PACMAN && IN_LEV_FIELD(newx,newy) &&
1251              IS_AMOEBOID(Feld[newx][newy]))
1252     {
1253       if (AmoebaNr[newx][newy] && Feld[newx][newy]==EL_AMOEBE_VOLL)
1254         AmoebaCnt[AmoebaNr[newx][newy]]--;
1255
1256       Feld[newx][newy] = EL_LEERRAUM;
1257       DrawLevelField(newx,newy);
1258     }
1259     else if (element==EL_ZOMBIE && IN_LEV_FIELD(newx,newy) &&
1260              MovDir[x][y]==MV_DOWN && Feld[newx][newy]==EL_SALZSAEURE)
1261     {
1262       Blurb(x,y);
1263       Store[x][y] = EL_SALZSAEURE;
1264     }
1265     else if (!IN_LEV_FIELD(newx,newy) || !IS_FREE(newx,newy))
1266     {                                   /* gegen Wand gelaufen */
1267       TurnRound(x,y);
1268       DrawLevelField(x,y);
1269       return;
1270     }
1271
1272     InitMovingField(x,y,MovDir[x][y]);
1273   }
1274
1275   if (MovDir[x][y])
1276     ContinueMoving(x,y);
1277 }
1278
1279 void ContinueMoving(int x, int y)
1280 {
1281   int element = Feld[x][y];
1282   int direction = MovDir[x][y];
1283   int dx = (direction==MV_LEFT ? -1 : direction==MV_RIGHT ? +1 : 0);
1284   int dy = (direction==MV_UP   ? -1 : direction==MV_DOWN  ? +1 : 0);
1285   int horiz_move = (dx!=0);
1286   int newx = x + dx, newy = y + dy;
1287   int step = (horiz_move ? dx : dy)*TILEX/4;
1288
1289   if (CAN_FALL(element) && horiz_move)
1290     step*=2;
1291   else if (element==EL_TROPFEN)
1292     step/=2;
1293   else if (Store[x][y]==EL_MORAST_VOLL || Store[x][y]==EL_MORAST_LEER)
1294     step/=4;
1295
1296   MovPos[x][y] += step;
1297
1298   if (ABS(MovPos[x][y])>=TILEX)         /* Zielfeld erreicht */
1299   {
1300     Feld[x][y] = EL_LEERRAUM;
1301     Feld[newx][newy] = element;
1302
1303     if (Store[x][y]==EL_MORAST_VOLL)
1304     {
1305       Store[x][y] = 0;
1306       Feld[newx][newy] = EL_MORAST_VOLL;
1307       element = EL_MORAST_VOLL;
1308     }
1309     else if (Store[x][y]==EL_MORAST_LEER)
1310     {
1311       Store[x][y] = 0;
1312       Feld[x][y] = EL_MORAST_LEER;
1313     }
1314     else if (Store[x][y]==EL_SIEB_VOLL)
1315     {
1316       Store[x][y] = 0;
1317       Feld[newx][newy] = EL_SIEB_VOLL;
1318       element = EL_SIEB_VOLL;
1319     }
1320     else if (Store[x][y]==EL_SIEB_LEER)
1321     {
1322       Store[x][y] = Store2[x][y] = 0;
1323       Feld[x][y] = EL_SIEB_LEER;
1324     }
1325     else if (Store[x][y]==EL_SIEB2_VOLL)
1326     {
1327       Store[x][y] = 0;
1328       Feld[newx][newy] = EL_SIEB2_VOLL;
1329       element = EL_SIEB2_VOLL;
1330     }
1331     else if (Store[x][y]==EL_SIEB2_LEER)
1332     {
1333       Store[x][y] = Store2[x][y] = 0;
1334       Feld[x][y] = EL_SIEB2_LEER;
1335     }
1336     else if (Store[x][y]==EL_SALZSAEURE)
1337     {
1338       Store[x][y] = 0;
1339       Feld[newx][newy] = EL_SALZSAEURE;
1340       element = EL_SALZSAEURE;
1341     }
1342     else if (Store[x][y]==EL_AMOEBE_NASS)
1343     {
1344       Store[x][y] = 0;
1345       Feld[x][y] = EL_AMOEBE_NASS;
1346     }
1347
1348     MovPos[x][y] = MovDir[x][y] = 0;
1349
1350     if (!CAN_MOVE(element))
1351       MovDir[newx][newy] = 0;
1352
1353     DrawLevelField(x,y);
1354     DrawLevelField(newx,newy);
1355
1356     Stop[newx][newy] = TRUE;
1357     JustHit[x][newy] = 3;
1358     CheckMoving = TRUE;
1359
1360     if (DONT_TOUCH(element))    /* Käfer oder Flieger */
1361     {
1362       TestIfBadThingHitsHero();
1363       TestIfBadThingHitsOtherBadThing(newx,newy);
1364     }
1365
1366     if (CAN_SMASH(element) && direction==MV_DOWN &&
1367         (newy==lev_fieldy-1 || !IS_FREE(x,newy+1)))
1368       Impact(x,newy);
1369   }
1370   else                          /* noch in Bewegung */
1371   {
1372     DrawLevelField(x,y);
1373     CheckMoving = TRUE;
1374   }
1375 }
1376
1377 int AmoebeNachbarNr(int ax, int ay)
1378 {
1379   int i;
1380   int element = Feld[ax][ay];
1381   int group_nr = 0;
1382   static int xy[4][2] =
1383   {
1384     0,-1,
1385     -1,0,
1386     +1,0,
1387     0,+1
1388   };
1389
1390   for(i=0;i<4;i++)
1391   {
1392     int x = ax+xy[i%4][0];
1393     int y = ay+xy[i%4][1];
1394
1395     if (!IN_LEV_FIELD(x,y))
1396       continue;
1397
1398     if (Feld[x][y]==element && AmoebaNr[x][y]>0)
1399       group_nr = AmoebaNr[x][y];
1400   }
1401
1402   return(group_nr);
1403 }
1404
1405 void AmoebenVereinigen(int ax, int ay)
1406 {
1407   int i,x,y,xx,yy;
1408   int new_group_nr = AmoebaNr[ax][ay];
1409   static int xy[4][2] =
1410   {
1411     0,-1,
1412     -1,0,
1413     +1,0,
1414     0,+1
1415   };
1416
1417   if (!new_group_nr)
1418     return;
1419
1420   for(i=0;i<4;i++)
1421   {
1422     x = ax+xy[i%4][0];
1423     y = ay+xy[i%4][1];
1424
1425     if (!IN_LEV_FIELD(x,y))
1426       continue;
1427
1428     if ((Feld[x][y]==EL_AMOEBE_VOLL || Feld[x][y]==EL_AMOEBE_TOT) &&
1429         AmoebaNr[x][y] != new_group_nr)
1430     {
1431       int old_group_nr = AmoebaNr[x][y];
1432
1433       AmoebaCnt[new_group_nr] += AmoebaCnt[old_group_nr];
1434       AmoebaCnt[old_group_nr] = 0;
1435
1436       for(yy=0;yy<lev_fieldy;yy++) for(xx=0;xx<lev_fieldx;xx++)
1437         if (AmoebaNr[xx][yy]==old_group_nr)
1438           AmoebaNr[xx][yy] = new_group_nr;
1439     }
1440   }
1441 }
1442
1443 void AmoebeUmwandeln(int ax, int ay)
1444 {
1445   int i,x,y;
1446   int group_nr = AmoebaNr[ax][ay];
1447   static int xy[4][2] =
1448   {
1449     0,-1,
1450     -1,0,
1451     +1,0,
1452     0,+1
1453   };
1454
1455   if (Feld[ax][ay]==EL_AMOEBE_TOT)
1456   {
1457     for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
1458     {
1459       if (Feld[x][y]==EL_AMOEBE_TOT && AmoebaNr[x][y]==group_nr)
1460       {
1461         AmoebaNr[x][y] = 0;
1462         Feld[x][y] = EL_AMOEBA2DIAM;
1463       }
1464     }
1465     Bang(ax,ay);
1466   }
1467   else
1468   {
1469     for(i=0;i<4;i++)
1470     {
1471       x = ax+xy[i%4][0];
1472       y = ay+xy[i%4][1];
1473
1474       if (!IN_LEV_FIELD(x,y))
1475         continue;
1476
1477       if (Feld[x][y]==EL_AMOEBA2DIAM)
1478         Bang(x,y);
1479     }
1480   }
1481 }
1482
1483 void AmoebeWaechst(int x, int y)
1484 {
1485   static long sound_delay = 0;
1486   static int sound_delay_value = 0;
1487
1488   CheckExploding = TRUE;
1489
1490   if (!MovDelay[x][y])          /* neue Phase / noch nicht gewartet */
1491   {
1492     MovDelay[x][y] = 4;
1493
1494     if (DelayReached(&sound_delay,sound_delay_value))
1495     {
1496       PlaySoundLevel(x,y,SND_AMOEBE);
1497       sound_delay_value = 30;
1498     }
1499   }
1500
1501   if (MovDelay[x][y])           /* neue Phase / in Wartezustand */
1502   {
1503     MovDelay[x][y]--;
1504     if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1505       DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_AMOEBING+3-MovDelay[x][y]);
1506
1507     if (!MovDelay[x][y])
1508     {
1509       Feld[x][y] = Store[x][y];
1510       Store[x][y] = 0;
1511       DrawLevelField(x,y);
1512     }
1513   }
1514 }
1515
1516 void AmoebeAbleger(int ax, int ay)
1517 {
1518   int i;
1519   int element = Feld[ax][ay];
1520   int newax = ax, neway = ay;
1521   static int xy[4][2] =
1522   {
1523     0,-1,
1524     -1,0,
1525     +1,0,
1526     0,+1
1527   };
1528
1529   CheckExploding = TRUE;
1530
1531   if (!level.tempo_amoebe)
1532   {
1533     Feld[ax][ay] = EL_AMOEBE_TOT;
1534     DrawLevelField(ax,ay);
1535     return;
1536   }
1537
1538   if (!MovDelay[ax][ay])        /* neue Amoebe / noch nicht gewartet */
1539     MovDelay[ax][ay] = RND(33*20/(1+level.tempo_amoebe));
1540
1541   if (MovDelay[ax][ay])         /* neue Amoebe / in Wartezustand */
1542   {
1543     MovDelay[ax][ay]--;
1544     if (MovDelay[ax][ay])
1545       return;
1546   }
1547
1548   if (element==EL_AMOEBE_NASS)  /* tropfende Amöbe */
1549   {
1550     int start = RND(4);
1551     int x = ax+xy[start][0];
1552     int y = ay+xy[start][1];
1553
1554     if (!IN_LEV_FIELD(x,y))
1555       return;
1556
1557     if (IS_FREE(x,y) ||
1558         Feld[x][y]==EL_ERDREICH || Feld[x][y]==EL_MORAST_LEER)
1559     {
1560       newax = x;
1561       neway = y;
1562     }
1563
1564     if (newax==ax && neway==ay)
1565       return;
1566   }
1567   else                          /* normale oder "gefüllte" Amöbe */
1568   {
1569     int start = RND(4);
1570     BOOL waiting_for_player = FALSE;
1571
1572     for(i=0;i<4;i++)
1573     {
1574       int j = (start+i)%4;
1575       int x = ax+xy[j][0];
1576       int y = ay+xy[j][1];
1577
1578       if (!IN_LEV_FIELD(x,y))
1579         continue;
1580
1581       if (IS_FREE(x,y) ||
1582           Feld[x][y]==EL_ERDREICH || Feld[x][y]==EL_MORAST_LEER)
1583       {
1584         newax = x;
1585         neway = y;
1586         break;
1587       }
1588       else if (PLAYER(x,y))
1589         waiting_for_player = TRUE;
1590     }
1591
1592     if (newax==ax && neway==ay)
1593     {
1594       if (i==4 && !waiting_for_player)
1595       {
1596         Feld[ax][ay] = EL_AMOEBE_TOT;
1597         DrawLevelField(ax,ay);
1598
1599         if (element==EL_AMOEBE_VOLL && --AmoebaCnt[AmoebaNr[ax][ay]]<=0)
1600           AmoebeUmwandeln(ax,ay);
1601       }
1602       return;
1603     }
1604     else if (element==EL_AMOEBE_VOLL)
1605     {
1606       int new_group_nr = AmoebaNr[ax][ay];
1607
1608       AmoebaNr[newax][neway] = new_group_nr;
1609       AmoebaCnt[new_group_nr]++;
1610       AmoebenVereinigen(newax,neway);
1611     }
1612   }
1613
1614   if (element!=EL_AMOEBE_NASS || neway<ay || !IS_FREE(newax,neway) ||
1615       (neway==lev_fieldy-1 && newax!=ax))
1616   {
1617     Feld[newax][neway] = EL_AMOEBING;
1618     Store[newax][neway] = element;
1619   }
1620   else if (neway==ay)
1621     Feld[newax][neway] = EL_TROPFEN;
1622   else
1623   {
1624     InitMovingField(ax,ay,MV_DOWN);
1625     Feld[ax][ay] = EL_TROPFEN;
1626     Store[ax][ay] = EL_AMOEBE_NASS;
1627     ContinueMoving(ax,ay);
1628     return;
1629   }
1630
1631   DrawLevelField(newax,neway);
1632 }
1633
1634 void Life(int ax, int ay)
1635 {
1636   int x1,y1,x2,y2;
1637   static int life[4] = { 2,3,3,3 };     /* "Life"-Parameter */
1638   int life_time = 20;
1639   int element = Feld[ax][ay];
1640
1641   CheckExploding = TRUE;
1642
1643   if (Stop[ax][ay])
1644     return;
1645
1646   if (!MovDelay[ax][ay])        /* neue Phase / noch nicht gewartet */
1647     MovDelay[ax][ay] = life_time;
1648
1649   if (MovDelay[ax][ay])         /* neue Phase / in Wartezustand */
1650   {
1651     MovDelay[ax][ay]--;
1652     if (MovDelay[ax][ay])
1653       return;
1654   }
1655
1656   for(y1=-1;y1<2;y1++) for(x1=-1;x1<2;x1++)
1657   {
1658     int xx = ax+x1, yy = ay+y1;
1659     int nachbarn = 0;
1660
1661     if (!IN_LEV_FIELD(xx,yy))
1662       continue;
1663
1664     for(y2=-1;y2<2;y2++) for(x2=-1;x2<2;x2++)
1665     {
1666       int x = xx+x2, y = yy+y2;
1667
1668       if (!IN_LEV_FIELD(x,y) || (x==xx && y==yy))
1669         continue;
1670
1671       if (((Feld[x][y]==element || (element==EL_LIFE && PLAYER(x,y))) &&
1672            !Stop[x][y]) ||
1673           (IS_FREE(x,y) && Stop[x][y]))
1674         nachbarn++;
1675     }
1676
1677     if (xx==ax && yy==ay)               /* mittleres Feld mit Amoebe */
1678     {
1679       if (nachbarn<life[0] || nachbarn>life[1])
1680       {
1681         Feld[xx][yy] = EL_LEERRAUM;
1682         if (!Stop[xx][yy])
1683           DrawLevelField(xx,yy);
1684         Stop[xx][yy] = TRUE;
1685       }
1686     }
1687     else if (IS_FREE(xx,yy) || Feld[xx][yy]==EL_ERDREICH)
1688     {                                   /* Randfeld ohne Amoebe */
1689       if (nachbarn>=life[2] && nachbarn<=life[3])
1690       {
1691         Feld[xx][yy] = element;
1692         MovDelay[xx][yy] = (element==EL_LIFE ? 0 : life_time-1);
1693         if (!Stop[xx][yy])
1694           DrawLevelField(xx,yy);
1695         Stop[xx][yy] = TRUE;
1696       }
1697     }
1698   }
1699 }
1700
1701 void Ablenk(int x, int y)
1702 {
1703   CheckExploding = TRUE;
1704
1705   if (!MovDelay[x][y])          /* neue Phase / noch nicht gewartet */
1706     MovDelay[x][y] = 33*(level.dauer_ablenk/10);
1707   if (MovDelay[x][y])           /* neue Phase / in Wartezustand */
1708   {
1709     MovDelay[x][y]--;
1710     if (MovDelay[x][y])
1711     {
1712       if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1713         DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_ABLENK+MovDelay[x][y]%4);
1714       if (!(MovDelay[x][y]%4))
1715         PlaySoundLevel(x,y,SND_MIEP);
1716       return;
1717     }
1718   }
1719
1720   Feld[x][y]=EL_ABLENK_AUS;
1721   DrawLevelField(x,y);
1722   if (ZX==x && ZY==y)
1723     ZX=ZY=-1;
1724 }
1725
1726 void Birne(int x, int y)
1727 {
1728   CheckExploding = TRUE;
1729
1730   if (!MovDelay[x][y])          /* neue Phase / noch nicht gewartet */
1731     MovDelay[x][y] = 400;
1732
1733   if (MovDelay[x][y])           /* neue Phase / in Wartezustand */
1734   {
1735     MovDelay[x][y]--;
1736     if (MovDelay[x][y])
1737     {
1738       if (!(MovDelay[x][y]%5))
1739       {
1740         if (!(MovDelay[x][y]%10))
1741           Feld[x][y]=EL_ABLENK_EIN;
1742         else
1743           Feld[x][y]=EL_ABLENK_AUS;
1744         DrawLevelField(x,y);
1745         Feld[x][y]=EL_ABLENK_EIN;
1746       }
1747       return;
1748     }
1749   }
1750
1751   Feld[x][y]=EL_ABLENK_AUS;
1752   DrawLevelField(x,y);
1753   if (ZX==x && ZY==y)
1754     ZX=ZY=-1;
1755 }
1756
1757 void Blubber(int x, int y)
1758 {
1759   CheckExploding = TRUE;
1760
1761   if (!MovDelay[x][y])          /* neue Phase / noch nicht gewartet */
1762     MovDelay[x][y] = 20;
1763
1764   if (MovDelay[x][y])           /* neue Phase / in Wartezustand */
1765   {
1766     int blubber;
1767
1768     MovDelay[x][y]--;
1769     blubber = MovDelay[x][y]/5;
1770     if (!(MovDelay[x][y]%5) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1771       DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_GEBLUBBER+3-blubber);
1772   }
1773 }
1774
1775 void NussKnacken(int x, int y)
1776 {
1777   CheckExploding = TRUE;
1778
1779   if (!MovDelay[x][y])          /* neue Phase / noch nicht gewartet */
1780     MovDelay[x][y] = 4;
1781
1782   if (MovDelay[x][y])           /* neue Phase / in Wartezustand */
1783   {
1784     MovDelay[x][y]--;
1785     if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1786       DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_CRACKINGNUT+3-MovDelay[x][y]);
1787
1788     if (!MovDelay[x][y])
1789     {
1790       Feld[x][y] = EL_EDELSTEIN;
1791       DrawLevelField(x,y);
1792     }
1793   }
1794 }
1795
1796 void SiebAktivieren(int x, int y, int typ)
1797 {
1798   CheckExploding = TRUE;
1799
1800   if (SiebAktiv>1)
1801   {
1802     if (SiebAktiv%2 && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1803       DrawGraphic(SCROLLX(x),SCROLLY(y),
1804                   (typ==1 ? GFX_SIEB_VOLL : GFX_SIEB2_VOLL)+3-(SiebAktiv%8)/2);
1805
1806 /*
1807     if (!(SiebAktiv%4))
1808       PlaySoundLevel(x,y,SND_MIEP);
1809 */
1810
1811   }
1812   else
1813   {
1814     Feld[x][y] = (typ==1 ? EL_SIEB_TOT : EL_SIEB2_TOT);
1815     DrawLevelField(x,y);
1816   }
1817 }
1818
1819 void AusgangstuerPruefen(int x, int y)
1820 {
1821   CheckExploding = TRUE;
1822
1823   if (!Gems)
1824   {
1825     Feld[x][y] = EL_AUSGANG_ACT;
1826     PlaySoundLevel(x,y,SND_OEFFNEN);
1827   }
1828 }
1829
1830 void AusgangstuerOeffnen(int x, int y)
1831 {
1832   int speed = 3;
1833
1834   CheckExploding = TRUE;
1835
1836   if (!MovDelay[x][y])          /* neue Phase / noch nicht gewartet */
1837     MovDelay[x][y] = 5*speed;
1838
1839   if (MovDelay[x][y])           /* neue Phase / in Wartezustand */
1840   {
1841     int tuer;
1842
1843     MovDelay[x][y]--;
1844     tuer = MovDelay[x][y]/speed;
1845     if (!(MovDelay[x][y]%speed) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1846       DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_AUSGANG_AUF-tuer);
1847
1848     if (!MovDelay[x][y])
1849     {
1850       Feld[x][y] = EL_AUSGANG_AUF;
1851       DrawLevelField(x,y);
1852     }
1853   }
1854 }
1855
1856 void AusgangstuerBlinken(int x, int y)
1857 {
1858   CheckExploding = TRUE;
1859
1860   if (!MovDelay[x][y])          /* neue Phase / noch nicht gewartet */
1861     MovDelay[x][y] = 16;
1862
1863   if (MovDelay[x][y])           /* neue Phase / in Wartezustand */
1864   {
1865     int phase;
1866
1867     MovDelay[x][y]--;
1868     phase = (MovDelay[x][y] % 16)/2;
1869     if (phase>3)
1870       phase = 7-phase;
1871     if (!(MovDelay[x][y]%2) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1872       DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_AUSGANG_AUF+phase);
1873   }
1874 }
1875
1876 void EdelsteinFunkeln(int x, int y)
1877 {
1878   int speed = 2;
1879
1880   CheckExploding = TRUE;
1881
1882   if (IS_MOVING(x,y))
1883     return;
1884
1885   if (!MovDelay[x][y])          /* neue Phase / noch nicht gewartet */
1886     MovDelay[x][y] = 4*speed;
1887
1888   if (MovDelay[x][y])           /* neue Phase / in Wartezustand */
1889   {
1890     int phase;
1891
1892     MovDelay[x][y]--;
1893     phase = MovDelay[x][y]/speed;
1894     if (!(MovDelay[x][y]%speed) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1895       DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_EDELSTEIN2-phase);
1896   }
1897 }
1898
1899 void MauerWaechst(int x, int y)
1900 {
1901   int speed = 3;
1902
1903   CheckExploding = TRUE;
1904
1905   if (!MovDelay[x][y])          /* neue Phase / noch nicht gewartet */
1906     MovDelay[x][y] = 3*speed;
1907
1908   if (MovDelay[x][y])           /* neue Phase / in Wartezustand */
1909   {
1910     int phase;
1911
1912     MovDelay[x][y]--;
1913     phase = 2-MovDelay[x][y]/speed;
1914     if (!(MovDelay[x][y]%speed) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1915       DrawGraphic(SCROLLX(x),SCROLLY(y),
1916                   (Store[x][y]==MV_LEFT ? GFX_MAUER_L1 : GFX_MAUER_R1)+phase);
1917
1918     if (!MovDelay[x][y])
1919     {
1920       if (Store[x][y]==MV_LEFT)
1921       {
1922         if (IN_LEV_FIELD(x-1,y) && IS_MAUER(Feld[x-1][y]))
1923           DrawLevelField(x-1,y);
1924       }
1925       else
1926       {
1927         if (IN_LEV_FIELD(x+1,y) && IS_MAUER(Feld[x+1][y]))
1928           DrawLevelField(x+1,y);
1929       }
1930
1931       Feld[x][y] = EL_MAUER_LEBT;
1932       Store[x][y] = 0;
1933       DrawLevelField(x,y);
1934     }
1935   }
1936 }
1937
1938 void MauerAbleger(int ax, int ay)
1939 {
1940   BOOL links_frei = FALSE, rechts_frei = FALSE;
1941   BOOL links_massiv = FALSE, rechts_massiv = FALSE;
1942
1943   CheckExploding = TRUE;
1944
1945   if (!MovDelay[ax][ay])        /* neue Mauer / noch nicht gewartet */
1946     MovDelay[ax][ay] = 3;
1947
1948   if (MovDelay[ax][ay])         /* neue Mauer / in Wartezustand */
1949   {
1950     MovDelay[ax][ay]--;
1951     if (MovDelay[ax][ay])
1952       return;
1953   }
1954
1955   if (IN_LEV_FIELD(ax-1,ay) && IS_FREE(ax-1,ay))
1956     links_frei = TRUE;
1957   if (IN_LEV_FIELD(ax+1,ay) && IS_FREE(ax+1,ay))
1958     rechts_frei = TRUE;
1959
1960   if (links_frei)
1961   {
1962     Feld[ax-1][ay] = EL_MAUERND;
1963     Store[ax-1][ay] = MV_LEFT;
1964     if (IN_SCR_FIELD(SCROLLX(ax-1),SCROLLY(ay)))
1965       DrawGraphic(SCROLLX(ax-1),SCROLLY(ay),GFX_MAUER_L1);
1966   }
1967   if (rechts_frei)
1968   {
1969     Feld[ax+1][ay] = EL_MAUERND;
1970     Store[ax+1][ay] = MV_RIGHT;
1971     if (IN_SCR_FIELD(SCROLLX(ax+1),SCROLLY(ay)))
1972       DrawGraphic(SCROLLX(ax+1),SCROLLY(ay),GFX_MAUER_R1);
1973   }
1974
1975   if (links_frei || rechts_frei)
1976     DrawLevelField(ax,ay);
1977
1978   if (!IN_LEV_FIELD(ax-1,ay) || IS_MAUER(Feld[ax-1][ay]))
1979     links_massiv = TRUE;
1980   if (!IN_LEV_FIELD(ax+1,ay) || IS_MAUER(Feld[ax+1][ay]))
1981     rechts_massiv = TRUE;
1982
1983   if (links_massiv && rechts_massiv)
1984     Feld[ax][ay] = EL_MAUERWERK;
1985 }
1986
1987 int GameActions(int mx, int my, int button)
1988 {
1989   static long time_delay=0, action_delay=0;
1990   int Action;
1991
1992   if (TimeLeft>0 && DelayReached(&time_delay,100) && !tape.pausing)
1993   {
1994     TimeLeft--;
1995
1996     if (tape.recording || tape.playing)
1997       DrawVideoDisplay(VIDEO_STATE_TIME_ON,level.time-TimeLeft);
1998
1999     if (TimeLeft<=10)
2000       PlaySoundStereo(SND_GONG,PSND_MAX_RIGHT);
2001
2002     DrawText(DX_TIME,DY_TIME,int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
2003     BackToFront();
2004   }
2005
2006   if (!TimeLeft)
2007     KillHero();
2008
2009   Action = (CheckMoving || CheckExploding || SiebAktiv);
2010
2011 /*
2012   if (Action && DelayReached(&action_delay,3))
2013 */
2014
2015   if (DelayReached(&action_delay,3))
2016   {
2017     int x,y,element;
2018
2019     if (tape.pausing || (tape.playing && !TapePlayDelay()))
2020       return(ACT_GO_ON);
2021     else if (tape.recording)
2022       TapeRecordDelay();
2023
2024     CheckMoving = CheckExploding = FALSE;
2025     for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
2026     {
2027       Stop[x][y] = FALSE;
2028       if (JustHit[x][y]>0)
2029         JustHit[x][y]--;
2030     }
2031
2032     for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
2033     {
2034       element = Feld[x][y];
2035
2036       if (element==EL_LEERRAUM || element==EL_ERDREICH)
2037         continue;
2038
2039       if (!IS_MOVING(x,y) && (CAN_FALL(element) || CAN_MOVE(element)))
2040       {
2041         StartMoving(x,y);
2042         if (Feld[x][y]==EL_EDELSTEIN2)
2043           EdelsteinFunkeln(x,y);
2044       }
2045       else if (IS_MOVING(x,y))
2046         ContinueMoving(x,y);
2047       else if (element==EL_DYNAMIT || element==EL_DYNABOMB)
2048         CheckDynamite(x,y);
2049       else if (element==EL_EXPLODING)
2050         Explode(x,y,Frame[x][y],EX_NORMAL);
2051       else if (element==EL_AMOEBING)
2052         AmoebeWaechst(x,y);
2053       else if (IS_AMOEBALIVE(element))
2054         AmoebeAbleger(x,y);
2055       else if (element==EL_LIFE || element==EL_LIFE_ASYNC)
2056         Life(x,y);
2057       else if (element==EL_ABLENK_EIN)
2058         Ablenk(x,y);
2059       else if (element==EL_SALZSAEURE)
2060         Blubber(x,y);
2061       else if (element==EL_BLURB_LEFT || element==EL_BLURB_RIGHT)
2062         Blurb(x,y);
2063       else if (element==EL_CRACKINGNUT)
2064         NussKnacken(x,y);
2065       else if (element==EL_AUSGANG_ZU)
2066         AusgangstuerPruefen(x,y);
2067       else if (element==EL_AUSGANG_ACT)
2068         AusgangstuerOeffnen(x,y);
2069       else if (element==EL_AUSGANG_AUF)
2070         AusgangstuerBlinken(x,y);
2071       else if (element==EL_MAUERND)
2072         MauerWaechst(x,y);
2073       else if (element==EL_MAUER_LEBT)
2074         MauerAbleger(x,y);
2075
2076       if (SiebAktiv)
2077       {
2078         if (element==EL_SIEB_LEER || element==EL_SIEB_VOLL ||
2079             Store[x][y]==EL_SIEB_LEER)
2080           SiebAktivieren(x,y,1);
2081         else if (element==EL_SIEB2_LEER || element==EL_SIEB2_VOLL ||
2082                  Store[x][y]==EL_SIEB2_LEER)
2083           SiebAktivieren(x,y,2);
2084       }
2085     }
2086
2087     if (SiebAktiv)
2088       SiebAktiv--;
2089
2090     if (CheckMoving || CheckExploding)
2091       BackToFront();
2092   }
2093
2094   return(ACT_GO_ON);
2095 }
2096
2097 void ScrollLevel(int dx, int dy)
2098 {
2099   int x,y;
2100
2101   XCopyArea(display,drawto_field,drawto_field,gc,
2102             SX+TILEX*(dx==-1),SY+TILEY*(dy==-1),
2103             SXSIZE-TILEX*(dx!=0),SYSIZE-TILEY*(dy!=0),
2104             SX+TILEX*(dx==1),SY+TILEY*(dy==1));
2105
2106   if (dx)
2107   {
2108     x = dx==1 ? 0 : SCR_FIELDX-1;
2109     for(y=0;y<SCR_FIELDY;y++)
2110       DrawScreenField(x,y);
2111   }
2112   if (dy)
2113   {
2114     y = dy==1 ? 0 : SCR_FIELDY-1;
2115     for(x=0;x<SCR_FIELDY;x++)
2116       DrawScreenField(x,y);
2117   }
2118
2119   redraw_mask|=REDRAW_FIELD;
2120 }
2121
2122 BOOL MoveFigureOneStep(int dx, int dy)
2123 {
2124   int oldJX,oldJY, newJX = JX+dx,newJY = JY+dy;
2125   int element;
2126   int can_move;
2127
2128   if (!dx && !dy)
2129     return(MF_NO_ACTION);
2130   if (!IN_LEV_FIELD(newJX,newJY))
2131     return(MF_NO_ACTION);
2132
2133   element = MovingOrBlocked2Element(newJX,newJY);
2134
2135   if (DONT_GO_TO(element))
2136   {
2137     if (element==EL_SALZSAEURE && dx==0 && dy==1)
2138     {
2139       Blurb(JX,JY);
2140       Feld[JX][JY] = EL_SPIELFIGUR;
2141       InitMovingField(JX,JY,MV_DOWN);
2142       Store[JX][JY] = EL_SALZSAEURE;
2143       ContinueMoving(JX,JY);
2144
2145       PlaySoundLevel(JX,JY,SND_AUTSCH);
2146       PlaySoundLevel(JX,JY,SND_LACHEN);
2147       GameOver = TRUE;
2148       JX = JY = -1;
2149     }
2150     else
2151       KillHero();
2152
2153     return(MF_MOVING);
2154   }
2155
2156   can_move = DigField(newJX,newJY,DF_DIG);
2157   if (can_move != MF_MOVING)
2158     return(can_move);
2159
2160   oldJX = JX;
2161   oldJY = JY;
2162   JX = newJX;
2163   JY = newJY;
2164
2165   if (Store[oldJX][oldJY])
2166   {
2167     DrawGraphic(SCROLLX(oldJX),SCROLLY(oldJY),el2gfx(Store[oldJX][oldJY]));
2168     DrawGraphicThruMask(SCROLLX(oldJX),SCROLLY(oldJY),
2169                         el2gfx(Feld[oldJX][oldJY]));
2170   }
2171   else if (Feld[oldJX][oldJY]==EL_DYNAMIT)
2172     DrawDynamite(oldJX,oldJY);
2173   else
2174     DrawLevelField(oldJX,oldJY);
2175
2176   return(MF_MOVING);
2177 }
2178
2179 BOOL MoveFigure(int dx, int dy)
2180 {
2181   static long move_delay = 0;
2182   int moved = MF_NO_ACTION;
2183
2184   if (GameOver || (!dx && !dy))
2185     return(FALSE);
2186
2187   if (!DelayReached(&move_delay,10) && !tape.playing)
2188     return(FALSE);
2189
2190   if (moved |= MoveFigureOneStep(dx,0))
2191     moved |= MoveFigureOneStep(0,dy);
2192   else
2193   {
2194     moved |= MoveFigureOneStep(0,dy);
2195     moved |= MoveFigureOneStep(dx,0);
2196   }
2197
2198   if (moved & MF_MOVING)
2199   {
2200     int old_scroll_x=scroll_x, old_scroll_y=scroll_y;
2201
2202     if (scroll_x!=JX-MIDPOSX && JX>=MIDPOSX-1 && JX<=lev_fieldx-MIDPOSX)
2203       scroll_x = JX-MIDPOSX;
2204     if (scroll_y!=JY-MIDPOSY && JY>=MIDPOSY-1 && JY<=lev_fieldy-MIDPOSY)
2205       scroll_y = JY-MIDPOSY;
2206
2207     if (scroll_x!=old_scroll_x || scroll_y!=old_scroll_y)
2208       ScrollLevel(old_scroll_x-scroll_x,old_scroll_y-scroll_y);
2209
2210     if (Feld[JX][JY]==EL_LEERRAUM)
2211       DrawLevelElement(JX,JY,EL_SPIELFIGUR);
2212     else
2213       DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR);
2214   }
2215
2216   TestIfHeroHitsBadThing();
2217
2218   BackToFront();
2219
2220   if (LevelSolved)
2221     GameWon();
2222
2223   return(moved);
2224 }
2225
2226 void TestIfHeroHitsBadThing()
2227 {
2228   int i, killx = JX,killy = JY;
2229   static int xy[4][2] =
2230   {
2231     0,-1,
2232     -1,0,
2233     +1,0,
2234     0,+1
2235   };
2236   static int harmless[4] =
2237   {
2238     MV_UP,
2239     MV_LEFT,
2240     MV_RIGHT,
2241     MV_DOWN
2242   };
2243
2244   for(i=0;i<4;i++)
2245   {
2246     int x,y,element;
2247
2248     x = JX+xy[i][0];
2249     y = JY+xy[i][1];
2250     if (!IN_LEV_FIELD(x,y))
2251       continue;
2252
2253     element = Feld[x][y];
2254
2255     if (DONT_TOUCH(element))
2256     {
2257       if (MovDir[x][y]==harmless[i])
2258         continue;
2259
2260       killx = x;
2261       killy = y;
2262       break;
2263     }
2264   }
2265
2266   if (killx!=JX || killy!=JY)
2267     KillHero();
2268 }
2269
2270 void TestIfBadThingHitsHero()
2271 {
2272   TestIfHeroHitsBadThing();
2273 }
2274
2275 void TestIfBadThingHitsOtherBadThing(int badx, int bady)
2276 {
2277   int i, killx=badx, killy=bady;
2278   static int xy[4][2] =
2279   {
2280     0,-1,
2281     -1,0,
2282     +1,0,
2283     0,+1
2284   };
2285
2286   for(i=0;i<4;i++)
2287   {
2288     int x,y,element;
2289
2290     x=badx+xy[i][0];
2291     y=bady+xy[i][1];
2292     if (!IN_LEV_FIELD(x,y))
2293       continue;
2294
2295     element=Feld[x][y];
2296     if (IS_AMOEBOID(element) || element==EL_LIFE ||
2297         element==EL_AMOEBING || element==EL_TROPFEN)
2298     {
2299       killx=x;
2300       killy=y;
2301       break;
2302     }
2303   }
2304
2305   if (killx!=badx || killy!=bady)
2306     Bang(badx,bady);
2307 }
2308
2309 void KillHero()
2310 {
2311   if (PLAYER(-1,-1))
2312     return;
2313
2314   if (IS_PFORTE(Feld[JX][JY]))
2315     Feld[JX][JY] = EL_LEERRAUM;
2316
2317   PlaySoundLevel(JX,JY,SND_AUTSCH);
2318   PlaySoundLevel(JX,JY,SND_LACHEN);
2319   Bang(JX,JY);
2320   GameOver = TRUE;
2321   JX = JY = -1;
2322 }
2323
2324 int DigField(int x, int y, int mode)
2325 {
2326   int dx = x-JX, dy = y-JY;
2327   int element;
2328   static long push_delay = 0;
2329   static int push_delay_value = 20;
2330
2331   if (mode==DF_NO_PUSH)
2332   {
2333     push_delay = 0;
2334     return(MF_NO_ACTION);
2335   }
2336
2337   if (IS_MOVING(x,y))
2338     return(MF_NO_ACTION);
2339
2340   element = Feld[x][y];
2341
2342   switch(element)
2343   {
2344     case EL_LEERRAUM:
2345       CheckMoving = TRUE;
2346       break;
2347     case EL_ERDREICH:
2348       Feld[x][y] = EL_LEERRAUM;
2349       CheckMoving = TRUE;
2350       break;
2351     case EL_EDELSTEIN:
2352     case EL_EDELSTEIN2:
2353     case EL_EDELSTEIN3:
2354       Feld[x][y] = EL_LEERRAUM;
2355       CheckMoving = TRUE;
2356       if (Gems>0)
2357         Gems--;
2358       RaiseScore(level.score[SC_EDELSTEIN]);
2359       DrawText(DX_EMERALDS,DY_EMERALDS,int2str(Gems,3),FS_SMALL,FC_YELLOW);
2360       PlaySoundLevel(x,y,SND_PONG);
2361       break;
2362     case EL_DIAMANT:
2363       Feld[x][y] = EL_LEERRAUM;
2364       CheckMoving = TRUE;
2365       Gems -= 3;
2366       if (Gems<0)
2367         Gems=0;
2368       RaiseScore(level.score[SC_DIAMANT]);
2369       DrawText(DX_EMERALDS,DY_EMERALDS,int2str(Gems,3),FS_SMALL,FC_YELLOW);
2370       PlaySoundLevel(x,y,SND_PONG);
2371       break;
2372     case EL_DYNAMIT_AUS:
2373       Feld[x][y] = EL_LEERRAUM;
2374       CheckMoving = TRUE;
2375       Dynamite++;
2376       RaiseScore(level.score[SC_DYNAMIT]);
2377       DrawText(DX_DYNAMITE,DY_DYNAMITE,int2str(Dynamite,3),FS_SMALL,FC_YELLOW);
2378       PlaySoundLevel(x,y,SND_PONG);
2379       break;
2380     case EL_DYNABOMB_NR:
2381       Feld[x][y] = EL_LEERRAUM;
2382       CheckMoving = TRUE;
2383       DynaBombCount++;
2384       DynaBombsLeft++;
2385       RaiseScore(level.score[SC_DYNAMIT]);
2386       PlaySoundLevel(x,y,SND_PONG);
2387       break;
2388     case EL_DYNABOMB_SZ:
2389       Feld[x][y] = EL_LEERRAUM;
2390       CheckMoving = TRUE;
2391       DynaBombSize++;
2392       RaiseScore(level.score[SC_DYNAMIT]);
2393       PlaySoundLevel(x,y,SND_PONG);
2394       break;
2395     case EL_SCHLUESSEL1:
2396     case EL_SCHLUESSEL2:
2397     case EL_SCHLUESSEL3:
2398     case EL_SCHLUESSEL4:
2399     {
2400       int key_nr = element-EL_SCHLUESSEL1;
2401
2402       Feld[x][y] = EL_LEERRAUM;
2403       CheckMoving = TRUE;
2404       Key[key_nr] = TRUE;
2405       RaiseScore(level.score[SC_SCHLUESSEL]);
2406       DrawMiniGraphicExtHiRes(drawto,gc,
2407                               DX_KEYS+key_nr*MINI_TILEX,DY_KEYS,
2408                               GFX_SCHLUESSEL1+key_nr);
2409       DrawMiniGraphicExtHiRes(window,gc,
2410                               DX_KEYS+key_nr*MINI_TILEX,DY_KEYS,
2411                               GFX_SCHLUESSEL1+key_nr);
2412       PlaySoundLevel(x,y,SND_PONG);
2413       break;
2414     }
2415     case EL_ABLENK_AUS:
2416       Feld[x][y] = EL_ABLENK_EIN;
2417       CheckExploding = TRUE;
2418       ZX=x;
2419       ZY=y;
2420       DrawLevelField(x,y);
2421       return(MF_ACTION);
2422       break;
2423     case EL_FELSBROCKEN:
2424     case EL_BOMBE:
2425     case EL_KOKOSNUSS:
2426     case EL_ZEIT_LEER:
2427       if (mode==DF_SNAP)
2428         return(MF_NO_ACTION);
2429       if (dy || !IN_LEV_FIELD(x+dx,y+dy) || Feld[x+dx][y+dy]!=EL_LEERRAUM)
2430         return(MF_NO_ACTION);
2431
2432       if (Counter() > push_delay+4*push_delay_value)
2433         push_delay = Counter();
2434       if (!DelayReached(&push_delay,push_delay_value) && !tape.playing)
2435         return(MF_NO_ACTION);
2436
2437       Feld[x][y] = EL_LEERRAUM;
2438       Feld[x+dx][y+dy] = element;
2439       push_delay_value = 10+RND(30);
2440       CheckMoving = TRUE;
2441       DrawLevelField(x+dx,y+dy);
2442       if (element==EL_FELSBROCKEN)
2443         PlaySoundLevel(x+dx,y+dy,SND_PUSCH);
2444       else if (element==EL_KOKOSNUSS)
2445         PlaySoundLevel(x+dx,y+dy,SND_KNURK);
2446       else
2447         PlaySoundLevel(x+dx,y+dy,SND_KLOPF);
2448       break;
2449     case EL_PFORTE1:
2450     case EL_PFORTE2:
2451     case EL_PFORTE3:
2452     case EL_PFORTE4:
2453       if (!Key[element-EL_PFORTE1])
2454         return(MF_NO_ACTION);
2455       break;
2456     case EL_PFORTE1X:
2457     case EL_PFORTE2X:
2458     case EL_PFORTE3X:
2459     case EL_PFORTE4X:
2460       if (!Key[element-EL_PFORTE1X])
2461         return(MF_NO_ACTION);
2462       break;
2463     case EL_AUSGANG_ZU:
2464     case EL_AUSGANG_ACT:
2465       /* Tür ist (noch) nicht offen! */
2466       return(MF_NO_ACTION);
2467       break;
2468     case EL_AUSGANG_AUF:
2469 /*
2470       if (mode==DF_SNAP || Gems>0)
2471         return(MF_NO_ACTION);
2472 */
2473       if (mode==DF_SNAP)
2474         return(MF_NO_ACTION);
2475       LevelSolved = GameOver = TRUE;
2476       PlaySoundLevel(x,y,SND_BUING);
2477       break;
2478     case EL_BIRNE_AUS:
2479       Feld[x][y] = EL_BIRNE_EIN;
2480       DrawLevelField(x,y);
2481       PlaySoundLevel(x,y,SND_DENG);
2482       return(MF_ACTION);
2483       break;
2484     case EL_ZEIT_VOLL:
2485       Feld[x][y] = EL_ZEIT_LEER;
2486       DrawLevelField(x,y);
2487       PlaySoundStereo(SND_GONG,PSND_MAX_RIGHT);
2488       return(MF_ACTION);
2489       break;
2490     default:
2491       return(MF_NO_ACTION);
2492       break;
2493   }
2494   push_delay=0;
2495   return(MF_MOVING);
2496 }
2497
2498 BOOL SnapField(int dx, int dy)
2499 {
2500   int x = JX+dx, y = JY+dy;
2501   static int snapped = FALSE;
2502
2503   if (GameOver || !IN_LEV_FIELD(x,y))
2504     return(FALSE);
2505   if (dx && dy)
2506     return(FALSE);
2507   if (!dx && !dy)
2508   {
2509     snapped = FALSE;
2510     return(FALSE);
2511   }
2512   if (snapped)
2513     return(FALSE);
2514
2515   if (!DigField(x,y,DF_SNAP))
2516     return(FALSE);
2517
2518   snapped = TRUE;
2519   DrawLevelField(x,y);
2520   BackToFront();
2521
2522   return(TRUE);
2523 }
2524
2525 BOOL PlaceBomb(void)
2526 {
2527   if ((Dynamite==0 && DynaBombsLeft==0) ||
2528       Feld[JX][JY]==EL_DYNAMIT || Feld[JX][JY]==EL_DYNABOMB)
2529     return(FALSE);
2530
2531   if (Feld[JX][JY]!=EL_LEERRAUM)
2532     Store[JX][JY] = Feld[JX][JY];
2533
2534   if (Dynamite)
2535   {
2536     Feld[JX][JY] = EL_DYNAMIT;
2537     MovDelay[JX][JY] = 48;
2538     Dynamite--;
2539     DrawText(DX_DYNAMITE,DY_DYNAMITE,int2str(Dynamite,3),FS_SMALL,FC_YELLOW);
2540     DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_DYNAMIT);
2541   }
2542   else
2543   {
2544     Feld[JX][JY] = EL_DYNABOMB;
2545     MovDelay[JX][JY] = 48;
2546     DynaBombsLeft--;
2547
2548     /* ändern, wenn Maske für DYNABOMB vorliegt! */
2549
2550     DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_DYNAMIT);
2551   }
2552
2553   CheckExploding = TRUE;
2554   return(TRUE);
2555 }
2556
2557 void PlaySoundLevel(int x, int y, int sound_nr)
2558 {
2559   int sx = SCROLLX(x), sy = SCROLLY(y);
2560   int volume, stereo;
2561
2562   if (!sound_loops_on && IS_LOOP_SOUND(sound_nr))
2563     return;
2564
2565   if (!IN_LEV_FIELD(x,y))
2566     return;
2567
2568   volume = PSND_MAX_VOLUME;
2569   stereo = (sx-SCR_FIELDX/2)*12;
2570
2571   if (!IN_SCR_FIELD(sx,sy))
2572   {
2573     if (sx<0 || sx>=SCR_FIELDX)
2574       volume = PSND_MAX_VOLUME - 2*ABS(sx-SCR_FIELDX/2);
2575     else
2576       volume = PSND_MAX_VOLUME - 2*ABS(sy-SCR_FIELDY/2);
2577   }
2578
2579   PlaySoundExt(sound_nr, volume, stereo, PSND_NO_LOOP);
2580 }
2581
2582 void RaiseScore(int value)
2583 {
2584   Score += value;
2585   DrawText(DX_SCORE,DY_SCORE,int2str(Score,5),FS_SMALL,FC_YELLOW);
2586   BackToFront();
2587 }
2588
2589 void TapeInitRecording()
2590 {
2591   time_t zeit1 = time(NULL);
2592   struct tm *zeit2 = localtime(&zeit1);
2593
2594   if (tape.recording || tape.playing)
2595     return;
2596
2597   tape.level_nr = level_nr;
2598   tape.recording = TRUE;
2599   tape.pausing = TRUE;
2600   tape.date =
2601     10000*(zeit2->tm_year%100) + 100*zeit2->tm_mon + zeit2->tm_mday;
2602
2603   DrawVideoDisplay(VIDEO_STATE_REC_ON | VIDEO_STATE_PAUSE_ON,0);
2604   DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
2605   DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
2606 }
2607
2608 void TapeStartRecording()
2609 {
2610   tape.length = 0;
2611   tape.counter = 0;
2612   tape.pos[tape.counter].delay = 0;
2613   tape.recording = TRUE;
2614   tape.playing = FALSE;
2615   tape.pausing = FALSE;
2616   tape.random_seed = InitRND(NEW_RANDOMIZE);
2617   DrawVideoDisplay(VIDEO_STATE_REC_ON | VIDEO_STATE_PAUSE_OFF,0);
2618 }
2619
2620 void TapeStopRecording()
2621 {
2622   if (!tape.recording)
2623     return;
2624
2625   tape.length = tape.counter;
2626   tape.recording = FALSE;
2627   tape.pausing = FALSE;
2628   DrawVideoDisplay(VIDEO_STATE_REC_OFF,0);
2629
2630   master_tape = tape;
2631 }
2632
2633 void TapeRecordAction(int joy)
2634 {
2635   if (!tape.recording || tape.pausing)
2636     return;
2637
2638   if (tape.counter>=MAX_TAPELEN-1)
2639   {
2640     TapeStopRecording();
2641     return;
2642   }
2643
2644   if (joy)
2645   {
2646     tape.pos[tape.counter].joystickdata = joy;
2647     tape.counter++;
2648     tape.pos[tape.counter].delay = 0;
2649   }
2650 }
2651
2652 void TapeRecordDelay()
2653 {
2654   if (!tape.recording || tape.pausing)
2655     return;
2656
2657   if (tape.counter>=MAX_TAPELEN)
2658   {
2659     TapeStopRecording();
2660     return;
2661   }
2662
2663   tape.pos[tape.counter].delay++;
2664
2665   if (tape.pos[tape.counter].delay>=255)
2666   {
2667     tape.pos[tape.counter].joystickdata = 0;
2668     tape.counter++;
2669     tape.pos[tape.counter].delay = 0;
2670   }
2671 }
2672
2673 void TapeTogglePause()
2674 {
2675   if (!tape.recording && !tape.playing)
2676     return;
2677
2678   if (tape.pausing)
2679   {
2680     tape.pausing = FALSE;
2681     DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
2682     if (game_status==MAINMENU)
2683       HandleMainMenu(SX+16,SY+7*32+16,0,0,MB_MENU_CHOICE);
2684   }
2685   else
2686   {
2687     tape.pausing = TRUE;
2688     DrawVideoDisplay(VIDEO_STATE_PAUSE_ON,0);
2689   }
2690 }
2691
2692 void TapeInitPlaying()
2693 {
2694   if (tape.recording || tape.playing || TAPE_IS_EMPTY(tape))
2695     return;
2696
2697   tape.playing = TRUE;
2698   tape.pausing = TRUE;
2699   DrawVideoDisplay(VIDEO_STATE_PLAY_ON | VIDEO_STATE_PAUSE_ON,0);
2700   DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
2701   DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
2702 }
2703
2704 void TapeStartPlaying()
2705 {
2706   tape = master_tape;
2707
2708   tape.counter = 0;
2709   tape.recording = FALSE;
2710   tape.playing = TRUE;
2711   tape.pausing = FALSE;
2712   InitRND(tape.random_seed);
2713   DrawVideoDisplay(VIDEO_STATE_PLAY_ON | VIDEO_STATE_PAUSE_OFF,0);
2714 }
2715
2716 void TapeStopPlaying()
2717 {
2718   if (!tape.playing)
2719     return;
2720
2721   tape.playing = FALSE;
2722   tape.pausing = FALSE;
2723   DrawVideoDisplay(VIDEO_STATE_PLAY_OFF,0);
2724 }
2725
2726 int TapePlayAction()
2727 {
2728   if (!tape.playing || tape.pausing)
2729     return(0);
2730
2731   if (tape.counter>=tape.length)
2732   {
2733     TapeStopPlaying();
2734     return(0);
2735   }
2736
2737   if (!tape.pos[tape.counter].delay)
2738   {
2739     tape.counter++;
2740     return(tape.pos[tape.counter-1].joystickdata);
2741   }
2742   else
2743     return(0);
2744 }
2745
2746 BOOL TapePlayDelay()
2747 {
2748   if (!tape.playing || tape.pausing)
2749     return(0);
2750
2751   if (tape.counter>=tape.length)
2752   {
2753     TapeStopPlaying();
2754     return(TRUE);
2755   }
2756
2757   if (tape.pos[tape.counter].delay)
2758   {
2759     tape.pos[tape.counter].delay--;
2760     return(TRUE);
2761   }
2762   else
2763     return(FALSE);
2764 }
2765
2766 void TapeStop()
2767 {
2768   TapeStopRecording();
2769   TapeStopPlaying();
2770   DrawVideoDisplay(VIDEO_ALL_OFF,0);
2771   if (tape.date && tape.length)
2772   {
2773     DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
2774     DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
2775   }
2776 }
2777
2778 void TapeErase()
2779 {
2780   tape.length = 0;
2781 }