1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * ©1995 Artsoft Development *
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 *----------------------------------------------------------*
13 ***********************************************************/
24 void GetPlayerConfig()
26 int old_joystick_nr = joystick_nr;
28 if (sound_status==SOUND_OFF)
29 player.setup &= ~SETUP_SOUND;
30 if (!sound_loops_allowed)
32 player.setup &= ~SETUP_SOUND_LOOPS;
33 player.setup &= ~SETUP_SOUND_MUSIC;
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);
46 if (joystick_nr != old_joystick_nr)
49 close(joystick_device);
59 Gems = level.edelsteine;
60 Key[0] = Key[1] = Key[2] = Key[3] = FALSE;
62 TimeLeft = level.time;
64 CheckExploding = FALSE;
65 LevelSolved = GameOver = SiebAktiv = FALSE;
71 else if (tape.playing)
74 DigField(0,0,DF_NO_PUSH);
77 for(i=0;i<MAX_NUM_AMOEBA;i++)
80 for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
82 Feld[x][y] = Ur[x][y];
83 MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
84 Store[x][y] = Store2[x][y] = Frame[x][y] = AmoebaNr[x][y] = 0;
90 Feld[x][y] = EL_LEERRAUM;
95 Feld[x][y] = EL_LEERRAUM;
98 if (x<lev_fieldx-1 && Feld[x+1][y]==EL_SALZSAEURE)
99 Feld[x][y] = EL_BADEWANNE1;
100 else if (x>0 && Feld[x-1][y]==EL_SALZSAEURE)
101 Feld[x][y] = EL_BADEWANNE2;
102 else if (y>0 && Feld[x][y-1]==EL_BADEWANNE1)
103 Feld[x][y] = EL_BADEWANNE3;
104 else if (y>0 && Feld[x][y-1]==EL_SALZSAEURE)
105 Feld[x][y] = EL_BADEWANNE4;
106 else if (y>0 && Feld[x][y-1]==EL_BADEWANNE2)
107 Feld[x][y] = EL_BADEWANNE5;
134 Feld[x][y] = EL_AMOEBING;
135 Store[x][y] = EL_AMOEBE_NASS;
143 scroll_x = scroll_y = -1;
146 (JX<=lev_fieldx-MIDPOSX ? JX-MIDPOSX : lev_fieldx-SCR_FIELDX+1);
149 (JY<=lev_fieldy-MIDPOSY ? JY-MIDPOSY : lev_fieldy-SCR_FIELDY+1);
152 DrawLevelElement(JX,JY,EL_SPIELFIGUR);
155 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
156 DOOR_GFX_PAGEX5,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
157 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
158 DrawTextExt(pix[PIX_DB_DOOR],gc,
159 DOOR_GFX_PAGEX1+XX_LEVEL,DOOR_GFX_PAGEY1+YY_LEVEL,
160 int2str(level_nr,2),FS_SMALL,FC_YELLOW);
161 DrawTextExt(pix[PIX_DB_DOOR],gc,
162 DOOR_GFX_PAGEX1+XX_EMERALDS,DOOR_GFX_PAGEY1+YY_EMERALDS,
163 int2str(Gems,3),FS_SMALL,FC_YELLOW);
164 DrawTextExt(pix[PIX_DB_DOOR],gc,
165 DOOR_GFX_PAGEX1+XX_DYNAMITE,DOOR_GFX_PAGEY1+YY_DYNAMITE,
166 int2str(Dynamite,3),FS_SMALL,FC_YELLOW);
167 DrawTextExt(pix[PIX_DB_DOOR],gc,
168 DOOR_GFX_PAGEX1+XX_SCORE,DOOR_GFX_PAGEY1+YY_SCORE,
169 int2str(Score,5),FS_SMALL,FC_YELLOW);
170 DrawTextExt(pix[PIX_DB_DOOR],gc,
171 DOOR_GFX_PAGEX1+XX_TIME,DOOR_GFX_PAGEY1+YY_TIME,
172 int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
174 DrawGameButton(BUTTON_GAME_STOP);
175 DrawGameButton(BUTTON_GAME_PAUSE);
176 DrawGameButton(BUTTON_GAME_PLAY);
177 DrawSoundDisplay(BUTTON_SOUND_MUSIC | (BUTTON_ON * sound_music_on));
178 DrawSoundDisplay(BUTTON_SOUND_LOOPS | (BUTTON_ON * sound_loops_on));
179 DrawSoundDisplay(BUTTON_SOUND_SOUND | (BUTTON_ON * sound_on));
180 XCopyArea(display,drawto,pix[PIX_DB_DOOR],gc,
181 DX+GAME_CONTROL_XPOS,DY+GAME_CONTROL_YPOS,
182 GAME_CONTROL_XSIZE,2*GAME_CONTROL_YSIZE,
183 DOOR_GFX_PAGEX1+GAME_CONTROL_XPOS,
184 DOOR_GFX_PAGEY1+GAME_CONTROL_YPOS);
186 OpenDoor(DOOR_OPEN_1);
189 PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
191 XAutoRepeatOff(display);
194 void InitMovDir(int x, int y)
196 int i, element = Feld[x][y];
197 static int xy[4][2] =
204 static int direction[2][4] =
206 MV_RIGHT, MV_UP, MV_LEFT, MV_DOWN,
207 MV_LEFT, MV_DOWN, MV_RIGHT, MV_UP
216 Feld[x][y] = EL_KAEFER;
217 MovDir[x][y] = direction[0][element-EL_KAEFER_R];
223 Feld[x][y] = EL_FLIEGER;
224 MovDir[x][y] = direction[0][element-EL_FLIEGER_R];
230 Feld[x][y] = EL_PACMAN;
231 MovDir[x][y] = direction[0][element-EL_PACMAN_R];
234 MovDir[x][y] = 1<<RND(4);
235 if (element!=EL_KAEFER && element!=EL_FLIEGER)
245 if (!IN_LEV_FIELD(x1,y1) || !IS_FREE(x1,y1))
247 if (element==EL_KAEFER)
249 MovDir[x][y] = direction[0][i];
252 else if (element==EL_FLIEGER)
254 MovDir[x][y] = direction[1][i];
263 void InitAmoebaNr(int x, int y)
266 int group_nr = AmoebeNachbarNr(x,y);
270 for(i=1;i<MAX_NUM_AMOEBA;i++)
280 AmoebaNr[x][y] = group_nr;
281 AmoebaCnt[group_nr]++;
287 int bumplevel = FALSE;
290 PlaySoundExt(SND_SIRR,PSND_MAX_VOLUME,PSND_MAX_RIGHT,PSND_LOOP);
294 for(;TimeLeft>=0;TimeLeft--)
297 PlaySoundStereo(SND_SIRR,PSND_MAX_RIGHT);
298 if (TimeLeft && !(TimeLeft % 10))
299 RaiseScore(level.score[SC_ZEITBONUS]);
300 DrawText(DX_TIME,DY_TIME,int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
313 CloseDoor(DOOR_CLOSE_1);
315 if (level_nr==player.handicap &&
316 level_nr<leveldir[leveldir_nr].num_ready)
320 SavePlayerInfo(PLAYER_LEVEL);
323 if ((hi_pos=NewHiScore())>=0)
325 game_status = HALLOFFAME;
326 DrawHallOfFame(hi_pos);
327 if (bumplevel && TAPE_IS_EMPTY(tape))
332 game_status = MAINMENU;
333 if (bumplevel && TAPE_IS_EMPTY(tape))
347 if (!strcmp(player.alias_name,EMPTY_ALIAS) ||
348 Score<highscore[MAX_SCORE_ENTRIES-1].Score)
351 for(k=0;k<MAX_SCORE_ENTRIES;k++)
353 if (Score>highscore[k].Score) /* Spieler kommt in Highscore-Liste */
355 if (k<MAX_SCORE_ENTRIES-1)
357 int m = MAX_SCORE_ENTRIES-1;
360 for(l=k;l<MAX_SCORE_ENTRIES;l++)
361 if (!strcmp(player.alias_name,highscore[l].Name))
363 if (m==k) /* Spieler überschreibt seine alte Position */
369 strcpy(highscore[l].Name,highscore[l-1].Name);
370 highscore[l].Score = highscore[l-1].Score;
377 sprintf(highscore[k].Name,player.alias_name);
378 highscore[k].Score = Score;
384 else if (!strcmp(player.alias_name,highscore[k].Name))
385 break; /* Spieler schon mit besserer Punktzahl in der Liste */
396 void InitMovingField(int x, int y, int direction)
398 int newx = x + (direction==MV_LEFT ? -1 : direction==MV_RIGHT ? +1 : 0);
399 int newy = y + (direction==MV_UP ? -1 : direction==MV_DOWN ? +1 : 0);
402 MovDir[x][y] = direction;
403 MovDir[newx][newy] = direction;
404 if (Feld[newx][newy]==EL_LEERRAUM)
405 Feld[newx][newy] = EL_BLOCKED;
408 void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y)
410 int direction = MovDir[x][y];
411 int newx = x + (direction==MV_LEFT ? -1 : direction==MV_RIGHT ? +1 : 0);
412 int newy = y + (direction==MV_UP ? -1 : direction==MV_DOWN ? +1 : 0);
418 void Blocked2Moving(int x, int y, int *comes_from_x, int *comes_from_y)
420 int oldx = x, oldy = y;
421 int direction = MovDir[x][y];
423 if (direction==MV_LEFT)
425 else if (direction==MV_RIGHT)
427 else if (direction==MV_UP)
429 else if (direction==MV_DOWN)
432 *comes_from_x = oldx;
433 *comes_from_y = oldy;
436 int MovingOrBlocked2Element(int x, int y)
438 int element = Feld[x][y];
440 if (element==EL_BLOCKED)
444 Blocked2Moving(x,y,&oldx,&oldy);
445 return(Feld[oldx][oldy]);
451 void RemoveMovingField(int x, int y)
453 int oldx=x,oldy=y, newx=x,newy=y;
455 if (Feld[x][y]!=EL_BLOCKED && !IS_MOVING(x,y))
460 Moving2Blocked(x,y,&newx,&newy);
461 if (Feld[newx][newy]!=EL_BLOCKED)
464 else if (Feld[x][y]==EL_BLOCKED)
466 Blocked2Moving(x,y,&oldx,&oldy);
467 if (!IS_MOVING(oldx,oldy))
471 Feld[oldx][oldy] = EL_LEERRAUM;
472 Feld[newx][newy] = EL_LEERRAUM;
473 MovPos[oldx][oldy] = MovDir[oldx][oldy] = MovDelay[oldx][oldy] = 0;
474 MovPos[newx][newy] = MovDir[newx][newy] = MovDelay[newx][newy] = 0;
475 DrawLevelField(oldx,oldy);
476 DrawLevelField(newx,newy);
479 void DrawDynamite(int x, int y)
481 int phase = (48-MovDelay[x][y])/6;
483 if (!IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
491 DrawGraphic(SCROLLX(x),SCROLLY(y),el2gfx(Store[x][y]));
493 DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR);
495 else if (PLAYER(x,y))
496 DrawGraphic(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR);
498 if (Store[x][y] || PLAYER(x,y))
499 DrawGraphicThruMask(SCROLLX(x),SCROLLY(y),GFX_DYNAMIT+phase);
501 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_DYNAMIT+phase);
504 void CheckDynamite(int x, int y)
508 if (MovDelay[x][y]) /* neues Dynamit / in Wartezustand */
513 if (!(MovDelay[x][y] % 6))
516 PlaySoundLevel(x,y,SND_ZISCH);
523 StopSound(SND_ZISCH);
527 void Explode(int ex, int ey, int phase)
530 int num_phase = 9, delay = 1;
531 int last_phase = num_phase*delay;
532 int half_phase = (num_phase/2)*delay;
534 if (phase==0) /* Feld 'Store' initialisieren */
536 int center_element = Feld[ex][ey];
538 if (center_element==EL_BLOCKED)
539 center_element = MovingOrBlocked2Element(ex,ey);
541 for(y=ey-1;y<ey+2;y++) for(x=ex-1;x<ex+2;x++)
543 int element = Feld[x][y];
545 if (!IN_LEV_FIELD(x,y) || IS_MASSIV(element))
548 if (center_element==EL_AMOEBA2DIAM && (x!=ex || y!=ey))
551 if (element==EL_EXPLODING)
552 element = Store2[x][y];
554 if (PLAYER(ex,ey) || center_element==EL_KAEFER)
555 Store[x][y] = ((x==ex && y==ey) ? EL_DIAMANT : EL_EDELSTEIN);
556 else if (center_element==EL_MAMPFER)
557 Store[x][y] = level.mampfer_inhalt[MampferNr][x-ex+1][y-ey+1];
558 else if (center_element==EL_AMOEBA2DIAM)
559 Store[x][y] = level.amoebe_inhalt;
560 else if (element==EL_ERZ_EDEL)
561 Store[x][y] = EL_EDELSTEIN;
562 else if (element==EL_ERZ_DIAM)
563 Store[x][y] = EL_DIAMANT;
564 else if (!IS_PFORTE(Store[x][y]))
565 Store[x][y] = EL_LEERRAUM;
567 if (x!=ex || y!=ey || center_element==EL_AMOEBA2DIAM)
568 Store2[x][y] = element;
570 if (AmoebaNr[x][y] && (element==EL_AMOEBE_VOLL || element==EL_AMOEBING))
571 AmoebaCnt[AmoebaNr[x][y]]--;
573 RemoveMovingField(x,y);
574 Feld[x][y] = EL_EXPLODING;
575 MovDir[x][y] = MovPos[x][y] = 0;
581 if (center_element==EL_MAMPFER)
582 MampferNr = (MampferNr+1) % 4;
593 Frame[x][y] = (phase<last_phase ? phase+1 : 0);
595 if (phase==half_phase)
597 int element = Store2[x][y];
601 else if (element==EL_BOMBE ||
602 element==EL_DYNAMIT ||
603 element==EL_DYNAMIT_AUS ||
606 Feld[x][y] = Store2[x][y];
610 else if (element==EL_AMOEBA2DIAM)
611 AmoebeUmwandeln(x,y);
614 if (phase==last_phase)
618 element = Feld[x][y] = Store[x][y];
619 Store[x][y] = Store2[x][y] = 0;
620 MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0;
621 if (CAN_MOVE(element) || COULD_MOVE(element))
625 else if (!(phase%delay) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
628 ErdreichAnbroeckeln(SCROLLX(x),SCROLLY(y));
630 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_EXPLOSION+(phase/delay-1));
636 void Bang(int x, int y)
638 int element = Feld[x][y];
641 PlaySoundLevel(x,y,SND_ROAAAR);
646 RaiseScore(level.score[SC_KAEFER]);
649 RaiseScore(level.score[SC_FLIEGER]);
652 RaiseScore(level.score[SC_MAMPFER]);
655 RaiseScore(level.score[SC_ZOMBIE]);
658 RaiseScore(level.score[SC_PACMAN]);
667 void Blurb(int x, int y)
669 int element = Feld[x][y];
671 if (element!=EL_BLURB_LEFT && element!=EL_BLURB_RIGHT) /* Anfang */
673 PlaySoundLevel(x,y,SND_BLURB);
674 if (IN_LEV_FIELD(x-1,y) && IS_FREE(x-1,y) &&
675 (!IN_LEV_FIELD(x-1,y-1) ||
676 !CAN_FALL(MovingOrBlocked2Element(x-1,y-1))))
678 Feld[x-1][y] = EL_BLURB_LEFT;
680 if (IN_LEV_FIELD(x+1,y) && IS_FREE(x+1,y) &&
681 (!IN_LEV_FIELD(x+1,y-1) ||
682 !CAN_FALL(MovingOrBlocked2Element(x+1,y-1))))
684 Feld[x+1][y] = EL_BLURB_RIGHT;
689 int graphic = (element==EL_BLURB_LEFT ? GFX_BLURB_LEFT : GFX_BLURB_RIGHT);
693 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
696 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
699 if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
700 DrawGraphic(SCROLLX(x),SCROLLY(y),graphic+4-MovDelay[x][y]);
704 Feld[x][y] = EL_LEERRAUM;
711 void Impact(int x, int y)
713 BOOL lastline = (y==lev_fieldy-1);
714 BOOL object_hit = FALSE;
715 int element = Feld[x][y];
717 /* Element darunter berührt? */
719 object_hit = (!IS_FREE(x,y+1) && (!IS_MOVING(x,y+1) ||
720 MovDir[x][y+1]!=MV_DOWN ||
721 MovPos[x][y+1]<=TILEY/2));
723 /* Auftreffendes Element fällt in Salzsäure */
724 if (!lastline && Feld[x][y+1]==EL_SALZSAEURE)
730 /* Auftreffendes Element ist Bombe */
731 if (element==EL_BOMBE && (lastline || object_hit))
737 /* Auftreffendes Element ist Säuretropfen */
738 if (element==EL_TROPFEN && (lastline || object_hit))
740 if (object_hit && PLAYER(x,y+1))
744 Feld[x][y] = EL_AMOEBING;
745 Store[x][y] = EL_AMOEBE_NASS;
750 /* Welches Element kriegt was auf die Rübe? */
751 if (!lastline && object_hit)
753 int smashed = Feld[x][y+1];
760 else if (element==EL_FELSBROCKEN)
762 if (IS_ENEMY(MovingOrBlocked2Element(x,y+1)))
767 else if (!IS_MOVING(x,y+1))
769 if (smashed==EL_BOMBE)
774 else if (smashed==EL_KOKOSNUSS)
776 Feld[x][y+1] = EL_CRACKINGNUT;
777 PlaySoundLevel(x,y,SND_KNACK);
778 RaiseScore(level.score[SC_KOKOSNUSS]);
781 else if (smashed==EL_DIAMANT)
783 Feld[x][y+1] = EL_LEERRAUM;
784 PlaySoundLevel(x,y,SND_QUIRK);
791 /* Kein Geräusch beim Durchqueren des Siebes */
792 if (!lastline && Feld[x][y+1]==EL_SIEB_LEER)
795 /* Geräusch beim Auftreffen */
796 if (lastline || object_hit)
829 PlaySoundLevel(x,y,sound);
833 void TurnRound(int x, int y)
835 int element = Feld[x][y];
836 int direction = MovDir[x][y];
838 if (element==EL_KAEFER)
840 TestIfBadThingHitsOtherBadThing(x,y);
842 if (MovDir[x][y]==MV_LEFT)
844 if (IN_LEV_FIELD(x,y-1) && IS_FREE(x,y-1))
846 else if (!IN_LEV_FIELD(x-1,y) || !IS_FREE(x-1,y))
847 MovDir[x][y]=MV_DOWN;
849 else if (MovDir[x][y]==MV_RIGHT)
851 if (IN_LEV_FIELD(x,y+1) && IS_FREE(x,y+1))
852 MovDir[x][y]=MV_DOWN;
853 else if (!IN_LEV_FIELD(x+1,y) || !IS_FREE(x+1,y))
856 else if (MovDir[x][y]==MV_UP)
858 if (IN_LEV_FIELD(x+1,y) && IS_FREE(x+1,y))
859 MovDir[x][y]=MV_RIGHT;
860 else if (!IN_LEV_FIELD(x,y-1) || !IS_FREE(x,y-1))
861 MovDir[x][y]=MV_LEFT;
863 else if (MovDir[x][y]==MV_DOWN)
865 if (IN_LEV_FIELD(x-1,y) && IS_FREE(x-1,y))
866 MovDir[x][y]=MV_LEFT;
867 else if (!IN_LEV_FIELD(x,y+1) || !IS_FREE(x,y+1))
868 MovDir[x][y]=MV_RIGHT;
871 if (direction!=MovDir[x][y])
874 else if (element==EL_FLIEGER)
876 TestIfBadThingHitsOtherBadThing(x,y);
878 if (MovDir[x][y]==MV_LEFT)
880 if (IN_LEV_FIELD(x,y+1) && IS_FREE(x,y+1))
881 MovDir[x][y]=MV_DOWN;
882 else if (!IN_LEV_FIELD(x-1,y) || !IS_FREE(x-1,y))
885 else if (MovDir[x][y]==MV_RIGHT)
887 if (IN_LEV_FIELD(x,y-1) && IS_FREE(x,y-1))
889 else if (!IN_LEV_FIELD(x+1,y) || !IS_FREE(x+1,y))
890 MovDir[x][y]=MV_DOWN;
892 else if (MovDir[x][y]==MV_UP)
894 if (IN_LEV_FIELD(x-1,y) && IS_FREE(x-1,y))
895 MovDir[x][y]=MV_LEFT;
896 else if (!IN_LEV_FIELD(x,y-1) || !IS_FREE(x,y-1))
897 MovDir[x][y]=MV_RIGHT;
899 else if (MovDir[x][y]==MV_DOWN)
901 if (IN_LEV_FIELD(x+1,y) && IS_FREE(x+1,y))
902 MovDir[x][y]=MV_RIGHT;
903 else if (!IN_LEV_FIELD(x,y+1) || !IS_FREE(x,y+1))
904 MovDir[x][y]=MV_LEFT;
907 if (direction!=MovDir[x][y])
910 else if (element==EL_MAMPFER)
912 if (MovDir[x][y]==MV_LEFT || MovDir[x][y]==MV_RIGHT)
914 MovDir[x][y]=(MovDir[x][y]==MV_LEFT ? MV_RIGHT : MV_LEFT);
915 if (IN_LEV_FIELD(x,y-1) &&
916 (IS_FREE(x,y-1) || Feld[x][y-1]==EL_DIAMANT) &&
919 if (IN_LEV_FIELD(x,y+1) &&
920 (IS_FREE(x,y+1) || Feld[x][y+1]==EL_DIAMANT) &&
922 MovDir[x][y]=MV_DOWN;
924 else if (MovDir[x][y]==MV_UP || MovDir[x][y]==MV_DOWN)
926 MovDir[x][y]=(MovDir[x][y]==MV_UP ? MV_DOWN : MV_UP);
927 if (IN_LEV_FIELD(x-1,y) &&
928 (IS_FREE(x-1,y) || Feld[x-1][y]==EL_DIAMANT) &&
930 MovDir[x][y]=MV_LEFT;
931 if (IN_LEV_FIELD(x+1,y) &&
932 (IS_FREE(x+1,y) || Feld[x+1][y]==EL_DIAMANT) &&
934 MovDir[x][y]=MV_RIGHT;
937 MovDelay[x][y]=8+8*RND(3);
939 else if (element==EL_PACMAN)
941 if (MovDir[x][y]==MV_LEFT || MovDir[x][y]==MV_RIGHT)
943 MovDir[x][y]=(MovDir[x][y]==MV_LEFT ? MV_RIGHT : MV_LEFT);
944 if (IN_LEV_FIELD(x,y-1) &&
945 (IS_FREE(x,y-1) || IS_AMOEBOID(Feld[x][y-1])) &&
948 if (IN_LEV_FIELD(x,y+1) &&
949 (IS_FREE(x,y+1) || IS_AMOEBOID(Feld[x][y+1])) &&
951 MovDir[x][y]=MV_DOWN;
953 else if (MovDir[x][y]==MV_UP || MovDir[x][y]==MV_DOWN)
955 MovDir[x][y]=(MovDir[x][y]==MV_UP ? MV_DOWN : MV_UP);
956 if (IN_LEV_FIELD(x-1,y) &&
957 (IS_FREE(x-1,y) || IS_AMOEBOID(Feld[x-1][y])) &&
959 MovDir[x][y]=MV_LEFT;
960 if (IN_LEV_FIELD(x+1,y) &&
961 (IS_FREE(x+1,y) || IS_AMOEBOID(Feld[x+1][y])) &&
963 MovDir[x][y]=MV_RIGHT;
966 MovDelay[x][y]=3+RND(20);
968 else if (element==EL_ZOMBIE)
970 int attr_x = JX, attr_y = JY;
978 MovDir[x][y]=MV_NO_MOVING;
980 MovDir[x][y]|=MV_LEFT;
982 MovDir[x][y]|=MV_RIGHT;
986 MovDir[x][y]|=MV_DOWN;
987 if ((MovDir[x][y]&(MV_LEFT|MV_RIGHT)) && (MovDir[x][y]&(MV_UP|MV_DOWN)))
988 MovDir[x][y] &= (RND(2) ? (MV_LEFT|MV_RIGHT) : (MV_UP|MV_DOWN));
990 MovDelay[x][y] = 8+8*RND(2);
994 void StartMoving(int x, int y)
996 int element = Feld[x][y];
1001 if (CAN_FALL(element) && y<lev_fieldy-1)
1003 if (element==EL_MORAST_VOLL)
1007 InitMovingField(x,y,MV_DOWN);
1008 Feld[x][y] = EL_FELSBROCKEN;
1009 Store[x][y] = EL_MORAST_LEER;
1011 else if (Feld[x][y+1]==EL_MORAST_LEER)
1015 if (!MovDelay[x][y])
1016 MovDelay[x][y] = 16;
1025 Feld[x][y] = EL_MORAST_LEER;
1026 Feld[x][y+1] = EL_MORAST_VOLL;
1029 else if (element==EL_FELSBROCKEN && Feld[x][y+1]==EL_MORAST_LEER)
1031 InitMovingField(x,y,MV_DOWN);
1032 Store[x][y] = EL_MORAST_VOLL;
1034 else if (element==EL_SIEB_VOLL)
1038 InitMovingField(x,y,MV_DOWN);
1039 Feld[x][y] = EL_CHANGED(Store2[x][y]);
1040 Store[x][y] = EL_SIEB_LEER;
1043 else if (CAN_CHANGE(element) && Feld[x][y+1]==EL_SIEB_LEER)
1045 InitMovingField(x,y,MV_DOWN);
1046 Store[x][y] = EL_SIEB_VOLL;
1047 Store2[x][y+1] = element;
1050 else if (CAN_SMASH(element) && Feld[x][y+1]==EL_SALZSAEURE)
1053 InitMovingField(x,y,MV_DOWN);
1054 Store[x][y] = EL_SALZSAEURE;
1056 else if (CAN_SMASH(element) && Feld[x][y+1]==EL_BLOCKED)
1060 else if (IS_FREE(x,y+1))
1062 InitMovingField(x,y,MV_DOWN);
1064 else if (element==EL_TROPFEN)
1066 Feld[x][y] = EL_AMOEBING;
1067 Store[x][y] = EL_AMOEBE_NASS;
1069 else if (IS_SLIPPERY(Feld[x][y+1]) && !Store[x][y+1])
1071 int left = (x>0 && IS_FREE(x-1,y) &&
1072 (IS_FREE(x-1,y+1) || Feld[x-1][y+1]==EL_SALZSAEURE));
1073 int right = (x<lev_fieldx-1 && IS_FREE(x+1,y) &&
1074 (IS_FREE(x+1,y+1) || Feld[x+1][y+1]==EL_SALZSAEURE));
1079 left = !(right=RND(2));
1080 InitMovingField(x,y,left ? MV_LEFT : MV_RIGHT);
1084 else if (CAN_MOVE(element))
1090 if (!MovDelay[x][y]) /* neuer Schritt / noch nicht gewartet */
1092 if (element==EL_ZOMBIE || element==EL_KAEFER || element==EL_FLIEGER)
1095 if (MovDelay[x][y] && (element==EL_KAEFER || element==EL_FLIEGER))
1096 DrawLevelField(x,y);
1100 if (MovDelay[x][y]) /* neuer Schritt / in Wartezustand */
1104 if (element==EL_ZOMBIE || element==EL_MAMPFER)
1106 int phase = MovDelay[x][y] % 8;
1111 if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1112 DrawGraphic(SCROLLX(x),SCROLLY(y),
1113 el2gfx(element)+phase);
1115 if (element==EL_MAMPFER && MovDelay[x][y]%4==3)
1116 PlaySoundLevel(x,y,SND_NJAM);
1123 if (element==EL_KAEFER)
1125 PlaySoundLevel(x,y,SND_KLAPPER);
1127 else if (element==EL_FLIEGER)
1129 PlaySoundLevel(x,y,SND_ROEHR);
1132 /* neuer Schritt / Wartezustand beendet */
1134 Moving2Blocked(x,y,&newx,&newy); /* wohin soll's gehen? */
1136 if (PLAYER(newx,newy)) /* Spieler erwischt */
1142 else if (element==EL_MAMPFER && IN_LEV_FIELD(newx,newy) &&
1143 Feld[newx][newy]==EL_DIAMANT)
1145 if (IS_MOVING(newx,newy))
1146 RemoveMovingField(newx,newy);
1149 Feld[newx][newy] = EL_LEERRAUM;
1150 DrawLevelField(newx,newy);
1153 else if (element==EL_PACMAN && IN_LEV_FIELD(newx,newy) &&
1154 IS_AMOEBOID(Feld[newx][newy]))
1156 if (AmoebaNr[newx][newy] && Feld[newx][newy]==EL_AMOEBE_VOLL)
1157 AmoebaCnt[AmoebaNr[newx][newy]]--;
1159 Feld[newx][newy] = EL_LEERRAUM;
1160 DrawLevelField(newx,newy);
1162 else if (element==EL_ZOMBIE && IN_LEV_FIELD(newx,newy) &&
1163 MovDir[x][y]==MV_DOWN && Feld[newx][newy]==EL_SALZSAEURE)
1166 Store[x][y] = EL_SALZSAEURE;
1168 else if (!IN_LEV_FIELD(newx,newy) || !IS_FREE(newx,newy))
1169 { /* gegen Wand gelaufen */
1171 DrawLevelField(x,y);
1175 InitMovingField(x,y,MovDir[x][y]);
1179 ContinueMoving(x,y);
1182 void ContinueMoving(int x, int y)
1184 int element = Feld[x][y];
1185 int direction = MovDir[x][y];
1186 int dx = (direction==MV_LEFT ? -1 : direction==MV_RIGHT ? +1 : 0);
1187 int dy = (direction==MV_UP ? -1 : direction==MV_DOWN ? +1 : 0);
1188 int horiz_move = (dx!=0);
1189 int newx = x + dx, newy = y + dy;
1190 int step = (horiz_move ? dx : dy)*TILEX/4;
1192 if (CAN_FALL(element) && horiz_move)
1194 else if (element==EL_TROPFEN)
1196 else if (Store[x][y]==EL_MORAST_VOLL || Store[x][y]==EL_MORAST_LEER)
1199 MovPos[x][y] += step;
1201 if (ABS(MovPos[x][y])>=TILEX) /* Zielfeld erreicht */
1203 Feld[x][y]=EL_LEERRAUM;
1204 Feld[newx][newy]=element;
1206 if (Store[x][y]==EL_MORAST_VOLL)
1209 Feld[newx][newy] = EL_MORAST_VOLL;
1210 element = EL_MORAST_VOLL;
1212 else if (Store[x][y]==EL_MORAST_LEER)
1215 Feld[x][y] = EL_MORAST_LEER;
1217 else if (Store[x][y]==EL_SIEB_VOLL)
1220 Feld[newx][newy] = EL_SIEB_VOLL;
1221 element = EL_SIEB_VOLL;
1223 else if (Store[x][y]==EL_SIEB_LEER)
1225 Store[x][y] = Store2[x][y] = 0;
1226 Feld[x][y] = EL_SIEB_LEER;
1228 else if (Store[x][y]==EL_SALZSAEURE)
1231 Feld[newx][newy] = EL_SALZSAEURE;
1232 element = EL_SALZSAEURE;
1234 else if (Store[x][y]==EL_AMOEBE_NASS)
1237 Feld[x][y] = EL_AMOEBE_NASS;
1240 MovPos[x][y] = MovDir[x][y] = 0;
1242 if (!CAN_MOVE(element))
1243 MovDir[newx][newy] = 0;
1245 DrawLevelField(x,y);
1246 DrawLevelField(newx,newy);
1248 Stop[newx][newy]=TRUE;
1251 if (DONT_TOUCH(element)) /* Käfer oder Flieger */
1253 TestIfBadThingHitsHero();
1254 TestIfBadThingHitsOtherBadThing(newx,newy);
1257 if (CAN_SMASH(element) && direction==MV_DOWN &&
1258 (newy==lev_fieldy-1 || !IS_FREE(x,newy+1)))
1261 else /* noch in Bewegung */
1263 DrawLevelField(x,y);
1268 int AmoebeNachbarNr(int ax, int ay)
1271 int element = Feld[ax][ay];
1273 static int xy[4][2] =
1283 int x = ax+xy[i%4][0];
1284 int y = ay+xy[i%4][1];
1286 if (!IN_LEV_FIELD(x,y))
1289 if (Feld[x][y]==element && AmoebaNr[x][y]>0)
1290 group_nr = AmoebaNr[x][y];
1296 void AmoebenVereinigen(int ax, int ay)
1299 int new_group_nr = AmoebaNr[ax][ay];
1300 static int xy[4][2] =
1316 if (!IN_LEV_FIELD(x,y))
1319 if ((Feld[x][y]==EL_AMOEBE_VOLL || Feld[x][y]==EL_AMOEBE_TOT) &&
1320 AmoebaNr[x][y] != new_group_nr)
1322 int old_group_nr = AmoebaNr[x][y];
1324 AmoebaCnt[new_group_nr] += AmoebaCnt[old_group_nr];
1325 AmoebaCnt[old_group_nr] = 0;
1327 for(yy=0;yy<lev_fieldy;yy++) for(xx=0;xx<lev_fieldx;xx++)
1328 if (AmoebaNr[xx][yy]==old_group_nr)
1329 AmoebaNr[xx][yy] = new_group_nr;
1334 void AmoebeUmwandeln(int ax, int ay)
1337 int group_nr = AmoebaNr[ax][ay];
1338 static int xy[4][2] =
1346 if (Feld[ax][ay]==EL_AMOEBE_TOT)
1348 for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
1350 if (Feld[x][y]==EL_AMOEBE_TOT && AmoebaNr[x][y]==group_nr)
1353 Feld[x][y] = EL_AMOEBA2DIAM;
1365 if (!IN_LEV_FIELD(x,y))
1368 if (Feld[x][y]==EL_AMOEBA2DIAM)
1374 void AmoebeWaechst(int x, int y)
1376 static long sound_delay = 0;
1377 static int sound_delay_value = 0;
1379 CheckExploding=TRUE;
1381 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
1385 if (DelayReached(&sound_delay,sound_delay_value))
1387 PlaySoundLevel(x,y,SND_AMOEBE);
1388 sound_delay_value = 30;
1392 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
1395 if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1396 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_AMOEBING+3-MovDelay[x][y]);
1398 if (!MovDelay[x][y])
1400 Feld[x][y] = Store[x][y];
1402 DrawLevelField(x,y);
1407 void AmoebeAbleger(int ax, int ay)
1410 int element = Feld[ax][ay];
1411 int newax = ax, neway = ay;
1412 static int xy[4][2] =
1420 CheckExploding=TRUE;
1422 if (!level.tempo_amoebe)
1424 Feld[ax][ay] = EL_AMOEBE_TOT;
1425 DrawLevelField(ax,ay);
1429 if (!MovDelay[ax][ay]) /* neue Amoebe / noch nicht gewartet */
1430 MovDelay[ax][ay] = RND(33*20/(1+level.tempo_amoebe));
1432 if (MovDelay[ax][ay]) /* neue Amoebe / in Wartezustand */
1435 if (MovDelay[ax][ay])
1439 if (element==EL_AMOEBE_NASS) /* tropfende Amöbe */
1442 int x = ax+xy[start][0];
1443 int y = ay+xy[start][1];
1445 if (!IN_LEV_FIELD(x,y))
1449 Feld[x][y]==EL_ERDREICH || Feld[x][y]==EL_MORAST_LEER)
1455 if (newax==ax && neway==ay)
1458 else /* normale oder "gefüllte" Amöbe */
1461 BOOL waiting_for_player = FALSE;
1465 int j = (start+i)%4;
1466 int x = ax+xy[j][0];
1467 int y = ay+xy[j][1];
1469 if (!IN_LEV_FIELD(x,y))
1473 Feld[x][y]==EL_ERDREICH || Feld[x][y]==EL_MORAST_LEER)
1479 else if (PLAYER(x,y))
1480 waiting_for_player = TRUE;
1483 if (newax==ax && neway==ay)
1485 if (i==4 && !waiting_for_player)
1487 Feld[ax][ay] = EL_AMOEBE_TOT;
1488 DrawLevelField(ax,ay);
1490 if (element==EL_AMOEBE_VOLL && --AmoebaCnt[AmoebaNr[ax][ay]]<=0)
1491 AmoebeUmwandeln(ax,ay);
1495 else if (element==EL_AMOEBE_VOLL)
1497 int new_group_nr = AmoebaNr[ax][ay];
1499 AmoebaNr[newax][neway] = new_group_nr;
1500 AmoebaCnt[new_group_nr]++;
1501 AmoebenVereinigen(newax,neway);
1505 if (element!=EL_AMOEBE_NASS || neway<ay || !IS_FREE(newax,neway) ||
1506 (neway==lev_fieldy-1 && newax!=ax))
1508 Feld[newax][neway] = EL_AMOEBING;
1509 Store[newax][neway] = element;
1512 Feld[newax][neway] = EL_TROPFEN;
1515 InitMovingField(ax,ay,MV_DOWN);
1516 Feld[ax][ay] = EL_TROPFEN;
1517 Store[ax][ay] = EL_AMOEBE_NASS;
1518 ContinueMoving(ax,ay);
1522 DrawLevelField(newax,neway);
1525 void Life(int ax, int ay)
1528 static int life[4] = { 2,3,3,3 }; /* "Life"-Parameter */
1530 int element = Feld[ax][ay];
1532 CheckExploding=TRUE;
1537 if (!MovDelay[ax][ay]) /* neue Phase / noch nicht gewartet */
1538 MovDelay[ax][ay] = life_time;
1540 if (MovDelay[ax][ay]) /* neue Phase / in Wartezustand */
1543 if (MovDelay[ax][ay])
1547 for(y1=-1;y1<2;y1++) for(x1=-1;x1<2;x1++)
1549 int xx = ax+x1, yy = ay+y1;
1552 if (!IN_LEV_FIELD(xx,yy))
1555 for(y2=-1;y2<2;y2++) for(x2=-1;x2<2;x2++)
1557 int x = xx+x2, y = yy+y2;
1559 if (!IN_LEV_FIELD(x,y) || (x==xx && y==yy))
1562 if (((Feld[x][y]==element || (element==EL_LIFE && PLAYER(x,y))) &&
1564 (IS_FREE(x,y) && Stop[x][y]))
1568 if (xx==ax && yy==ay) /* mittleres Feld mit Amoebe */
1570 if (nachbarn<life[0] || nachbarn>life[1])
1572 Feld[xx][yy] = EL_LEERRAUM;
1574 DrawLevelField(xx,yy);
1575 Stop[xx][yy] = TRUE;
1578 else if (IS_FREE(xx,yy) || Feld[xx][yy]==EL_ERDREICH)
1579 { /* Randfeld ohne Amoebe */
1580 if (nachbarn>=life[2] && nachbarn<=life[3])
1582 Feld[xx][yy] = element;
1583 MovDelay[xx][yy] = (element==EL_LIFE ? 0 : life_time-1);
1585 DrawLevelField(xx,yy);
1586 Stop[xx][yy] = TRUE;
1592 void Ablenk(int x, int y)
1594 CheckExploding=TRUE;
1596 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
1597 MovDelay[x][y] = 33*(level.dauer_ablenk/10);
1598 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
1603 if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1604 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_ABLENK+MovDelay[x][y]%4);
1605 if (!(MovDelay[x][y]%4))
1606 PlaySoundLevel(x,y,SND_MIEP);
1611 Feld[x][y]=EL_ABLENK_AUS;
1612 DrawLevelField(x,y);
1617 void Birne(int x, int y)
1619 CheckExploding=TRUE;
1621 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
1622 MovDelay[x][y] = 400;
1624 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
1629 if (!(MovDelay[x][y]%5))
1631 if (!(MovDelay[x][y]%10))
1632 Feld[x][y]=EL_ABLENK_EIN;
1634 Feld[x][y]=EL_ABLENK_AUS;
1635 DrawLevelField(x,y);
1636 Feld[x][y]=EL_ABLENK_EIN;
1642 Feld[x][y]=EL_ABLENK_AUS;
1643 DrawLevelField(x,y);
1648 void Blubber(int x, int y)
1650 CheckExploding=TRUE;
1652 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
1653 MovDelay[x][y] = 20;
1655 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
1660 blubber = MovDelay[x][y]/5;
1661 if (!(MovDelay[x][y]%5) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1662 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_GEBLUBBER+3-blubber);
1666 void NussKnacken(int x, int y)
1668 CheckExploding=TRUE;
1670 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
1673 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
1676 if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1677 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_CRACKINGNUT+3-MovDelay[x][y]);
1679 if (!MovDelay[x][y])
1681 Feld[x][y] = EL_EDELSTEIN;
1682 DrawLevelField(x,y);
1687 void SiebAktivieren(int x, int y)
1689 CheckExploding=TRUE;
1693 if (SiebAktiv%2 && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1694 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_SIEB_VOLL+3-(SiebAktiv%8)/2);
1698 PlaySoundLevel(x,y,SND_MIEP);
1704 Feld[x][y] = EL_SIEB_TOT;
1705 DrawLevelField(x,y);
1709 void AusgangstuerPruefen(int x, int y)
1711 CheckExploding=TRUE;
1714 Feld[x][y] = EL_AUSGANG_ACT;
1717 void AusgangstuerOeffnen(int x, int y)
1719 CheckExploding=TRUE;
1721 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
1722 MovDelay[x][y] = 20;
1724 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
1729 tuer = MovDelay[x][y]/5;
1730 if (!(MovDelay[x][y]%5) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1731 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_AUSGANG_ZU+3-tuer);
1733 if (!MovDelay[x][y])
1735 Feld[x][y] = EL_AUSGANG_AUF;
1736 DrawLevelField(x,y);
1741 int GameActions(int mx, int my, int button)
1743 static long time_delay=0, action_delay=0;
1746 if (TimeLeft>0 && DelayReached(&time_delay,100) && !tape.pausing)
1750 if (tape.recording || tape.playing)
1751 DrawVideoDisplay(VIDEO_STATE_TIME_ON,level.time-TimeLeft);
1754 PlaySoundStereo(SND_GONG,PSND_MAX_RIGHT);
1756 DrawText(DX_TIME,DY_TIME,int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
1763 Action = (CheckMoving || CheckExploding || SiebAktiv);
1766 if (Action && DelayReached(&action_delay,3))
1769 if (DelayReached(&action_delay,3))
1773 if (tape.pausing || (tape.playing && !TapePlayDelay()))
1775 else if (tape.recording)
1778 CheckMoving = CheckExploding = FALSE;
1779 for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
1782 for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
1784 element = Feld[x][y];
1786 if (element==EL_LEERRAUM || element==EL_ERDREICH)
1789 if (!IS_MOVING(x,y) && (CAN_FALL(element) || CAN_MOVE(element)))
1791 else if (IS_MOVING(x,y))
1792 ContinueMoving(x,y);
1793 else if (element==EL_DYNAMIT)
1795 else if (element==EL_EXPLODING)
1796 Explode(x,y,Frame[x][y]);
1797 else if (element==EL_AMOEBING)
1799 else if (IS_AMOEBALIVE(element))
1801 else if (element==EL_LIFE || element==EL_LIFE_ASYNC)
1803 else if (element==EL_ABLENK_EIN)
1805 else if (element==EL_SALZSAEURE)
1807 else if (element==EL_BLURB_LEFT || element==EL_BLURB_RIGHT)
1809 else if (element==EL_CRACKINGNUT)
1811 else if (element==EL_AUSGANG_ZU)
1812 AusgangstuerPruefen(x,y);
1813 else if (element==EL_AUSGANG_ACT)
1814 AusgangstuerOeffnen(x,y);
1816 if (SiebAktiv && (element==EL_SIEB_LEER ||
1817 element==EL_SIEB_VOLL ||
1818 Store[x][y]==EL_SIEB_LEER))
1819 SiebAktivieren(x,y);
1825 if (CheckMoving || CheckExploding)
1832 void ScrollLevel(int dx, int dy)
1836 XCopyArea(display,drawto_field,drawto_field,gc,
1837 SX+TILEX*(dx==-1),SY+TILEY*(dy==-1),
1838 SXSIZE-TILEX*(dx!=0),SYSIZE-TILEY*(dy!=0),
1839 SX+TILEX*(dx==1),SY+TILEY*(dy==1));
1843 x = dx==1 ? 0 : SCR_FIELDX-1;
1844 for(y=0;y<SCR_FIELDY;y++)
1845 DrawScreenField(x,y);
1849 y = dy==1 ? 0 : SCR_FIELDY-1;
1850 for(x=0;x<SCR_FIELDY;x++)
1851 DrawScreenField(x,y);
1854 redraw_mask|=REDRAW_FIELD;
1857 BOOL MoveFigureOneStep(int dx, int dy)
1859 int oldJX,oldJY, newJX = JX+dx,newJY = JY+dy;
1864 return(MF_NO_ACTION);
1865 if (!IN_LEV_FIELD(newJX,newJY))
1866 return(MF_NO_ACTION);
1868 element = MovingOrBlocked2Element(newJX,newJY);
1870 if (DONT_GO_TO(element))
1872 if (element==EL_SALZSAEURE && dx==0 && dy==1)
1875 Feld[JX][JY] = EL_SPIELFIGUR;
1876 InitMovingField(JX,JY,MV_DOWN);
1877 Store[JX][JY] = EL_SALZSAEURE;
1878 ContinueMoving(JX,JY);
1880 PlaySoundLevel(JX,JY,SND_AUTSCH);
1881 PlaySoundLevel(JX,JY,SND_LACHEN);
1891 can_move = DigField(newJX,newJY,DF_DIG);
1892 if (can_move != MF_MOVING)
1900 if (Store[oldJX][oldJY])
1902 DrawGraphic(SCROLLX(oldJX),SCROLLY(oldJY),el2gfx(Store[oldJX][oldJY]));
1903 DrawGraphicThruMask(SCROLLX(oldJX),SCROLLY(oldJY),
1904 el2gfx(Feld[oldJX][oldJY]));
1906 else if (Feld[oldJX][oldJY]==EL_DYNAMIT)
1907 DrawDynamite(oldJX,oldJY);
1909 DrawLevelField(oldJX,oldJY);
1914 BOOL MoveFigure(int dx, int dy)
1916 static long move_delay = 0;
1917 int moved = MF_NO_ACTION;
1919 if (GameOver || (!dx && !dy))
1922 if (!DelayReached(&move_delay,10) && !tape.playing)
1925 if (moved |= MoveFigureOneStep(dx,0))
1926 moved |= MoveFigureOneStep(0,dy);
1929 moved |= MoveFigureOneStep(0,dy);
1930 moved |= MoveFigureOneStep(dx,0);
1933 if (moved & MF_MOVING)
1935 int old_scroll_x=scroll_x, old_scroll_y=scroll_y;
1937 if (scroll_x!=JX-MIDPOSX && JX>=MIDPOSX-1 && JX<=lev_fieldx-MIDPOSX)
1938 scroll_x = JX-MIDPOSX;
1939 if (scroll_y!=JY-MIDPOSY && JY>=MIDPOSY-1 && JY<=lev_fieldy-MIDPOSY)
1940 scroll_y = JY-MIDPOSY;
1942 if (scroll_x!=old_scroll_x || scroll_y!=old_scroll_y)
1943 ScrollLevel(old_scroll_x-scroll_x,old_scroll_y-scroll_y);
1945 if (Feld[JX][JY]==EL_LEERRAUM)
1946 DrawLevelElement(JX,JY,EL_SPIELFIGUR);
1948 DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR);
1951 TestIfHeroHitsBadThing();
1961 void TestIfHeroHitsBadThing()
1963 int i, killx = JX,killy = JY;
1964 static int xy[4][2] =
1971 static int harmless[4] =
1985 if (!IN_LEV_FIELD(x,y))
1988 element = Feld[x][y];
1990 if (DONT_TOUCH(element))
1992 if (MovDir[x][y]==harmless[i])
2001 if (killx!=JX || killy!=JY)
2005 void TestIfBadThingHitsHero()
2007 TestIfHeroHitsBadThing();
2010 void TestIfBadThingHitsOtherBadThing(int badx, int bady)
2012 int i, killx=badx, killy=bady;
2013 static int xy[4][2] =
2027 if (!IN_LEV_FIELD(x,y))
2031 if (IS_AMOEBOID(element) || element==EL_LIFE ||
2032 element==EL_AMOEBING || element==EL_TROPFEN)
2040 if (killx!=badx || killy!=bady)
2049 if (IS_PFORTE(Feld[JX][JY]))
2050 Feld[JX][JY] = EL_LEERRAUM;
2052 PlaySoundLevel(JX,JY,SND_AUTSCH);
2053 PlaySoundLevel(JX,JY,SND_LACHEN);
2059 int DigField(int x, int y, int mode)
2061 int dx=x-JX, dy=y-JY;
2063 static long push_delay = 0;
2064 static int push_delay_value = 20;
2066 if (mode==DF_NO_PUSH)
2069 return(MF_NO_ACTION);
2073 return(MF_NO_ACTION);
2075 element = Feld[x][y];
2083 Feld[x][y]=EL_LEERRAUM;
2087 Feld[x][y]=EL_LEERRAUM;
2091 RaiseScore(level.score[SC_EDELSTEIN]);
2092 DrawText(DX_EMERALDS,DY_EMERALDS,int2str(Gems,3),FS_SMALL,FC_YELLOW);
2093 PlaySoundLevel(x,y,SND_PONG);
2096 Feld[x][y]=EL_LEERRAUM;
2101 RaiseScore(level.score[SC_DIAMANT]);
2102 DrawText(DX_EMERALDS,DY_EMERALDS,int2str(Gems,3),FS_SMALL,FC_YELLOW);
2103 PlaySoundLevel(x,y,SND_PONG);
2105 case EL_DYNAMIT_AUS:
2106 Feld[x][y]=EL_LEERRAUM;
2109 RaiseScore(level.score[SC_DYNAMIT]);
2110 DrawText(DX_DYNAMITE,DY_DYNAMITE,int2str(Dynamite,3),FS_SMALL,FC_YELLOW);
2111 PlaySoundLevel(x,y,SND_PONG);
2113 case EL_SCHLUESSEL1:
2114 case EL_SCHLUESSEL2:
2115 case EL_SCHLUESSEL3:
2116 case EL_SCHLUESSEL4:
2118 int key_nr = element-EL_SCHLUESSEL1;
2120 Feld[x][y] = EL_LEERRAUM;
2123 RaiseScore(level.score[SC_SCHLUESSEL]);
2124 DrawMiniGraphicExtHiRes(drawto,gc,
2125 DX_KEYS+key_nr*MINI_TILEX,DY_KEYS,
2126 GFX_SCHLUESSEL1+key_nr);
2127 DrawMiniGraphicExtHiRes(window,gc,
2128 DX_KEYS+key_nr*MINI_TILEX,DY_KEYS,
2129 GFX_SCHLUESSEL1+key_nr);
2130 PlaySoundLevel(x,y,SND_PONG);
2134 Feld[x][y] = EL_ABLENK_EIN;
2135 CheckExploding=TRUE;
2138 DrawLevelField(x,y);
2141 case EL_FELSBROCKEN:
2146 return(MF_NO_ACTION);
2147 if (dy || !IN_LEV_FIELD(x+dx,y+dy) || Feld[x+dx][y+dy]!=EL_LEERRAUM)
2148 return(MF_NO_ACTION);
2150 if (Counter() > push_delay+4*push_delay_value)
2151 push_delay = Counter();
2152 if (!DelayReached(&push_delay,push_delay_value) && !tape.playing)
2153 return(MF_NO_ACTION);
2155 Feld[x][y] = EL_LEERRAUM;
2156 Feld[x+dx][y+dy] = element;
2157 push_delay_value = 10+RND(30);
2159 DrawLevelField(x+dx,y+dy);
2160 if (element==EL_FELSBROCKEN)
2161 PlaySoundLevel(x+dx,y+dy,SND_PUSCH);
2162 else if (element==EL_KOKOSNUSS)
2163 PlaySoundLevel(x+dx,y+dy,SND_KNURK);
2165 PlaySoundLevel(x+dx,y+dy,SND_KLOPF);
2171 if (!Key[element-EL_PFORTE1])
2172 return(MF_NO_ACTION);
2178 if (!Key[element-EL_PFORTE1X])
2179 return(MF_NO_ACTION);
2182 case EL_AUSGANG_ACT:
2183 /* Tür ist (noch) nicht offen! */
2184 return(MF_NO_ACTION);
2186 case EL_AUSGANG_AUF:
2187 if (mode==DF_SNAP || Gems>0)
2188 return(MF_NO_ACTION);
2189 LevelSolved = GameOver = TRUE;
2190 PlaySoundLevel(x,y,SND_BUING);
2193 Feld[x][y] = EL_BIRNE_EIN;
2194 DrawLevelField(x,y);
2195 PlaySoundLevel(x,y,SND_DENG);
2199 Feld[x][y] = EL_ZEIT_LEER;
2200 DrawLevelField(x,y);
2201 PlaySoundStereo(SND_GONG,PSND_MAX_RIGHT);
2205 return(MF_NO_ACTION);
2212 BOOL SnapField(int dx, int dy)
2214 int x = JX+dx, y = JY+dy;
2215 static int snapped = FALSE;
2217 if (GameOver || !IN_LEV_FIELD(x,y))
2229 if (!DigField(x,y,DF_SNAP))
2233 DrawLevelField(x,y);
2239 BOOL PlaceBomb(void)
2241 if (Dynamite==0 || Feld[JX][JY]==EL_DYNAMIT)
2244 if (Feld[JX][JY]!=EL_LEERRAUM)
2245 Store[JX][JY] = Feld[JX][JY];
2246 Feld[JX][JY] = EL_DYNAMIT;
2247 MovDelay[JX][JY] = 48;
2249 DrawText(DX_DYNAMITE,DY_DYNAMITE,int2str(Dynamite,3),FS_SMALL,FC_YELLOW);
2250 DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_DYNAMIT);
2251 CheckExploding = TRUE;
2255 void PlaySoundLevel(int x, int y, int sound_nr)
2257 int sx = SCROLLX(x), sy = SCROLLY(y);
2260 if (!sound_loops_on && IS_LOOP_SOUND(sound_nr))
2263 if (!IN_LEV_FIELD(x,y))
2266 volume = PSND_MAX_VOLUME;
2267 stereo = (sx-SCR_FIELDX/2)*12;
2269 if (!IN_SCR_FIELD(sx,sy))
2271 if (sx<0 || sx>=SCR_FIELDX)
2272 volume = PSND_MAX_VOLUME - 2*ABS(sx-SCR_FIELDX/2);
2274 volume = PSND_MAX_VOLUME - 2*ABS(sy-SCR_FIELDY/2);
2277 PlaySoundExt(sound_nr, volume, stereo, PSND_NO_LOOP);
2280 void RaiseScore(int value)
2283 DrawText(DX_SCORE,DY_SCORE,int2str(Score,5),FS_SMALL,FC_YELLOW);
2287 void TapeInitRecording()
2289 time_t zeit1 = time(NULL);
2290 struct tm *zeit2 = localtime(&zeit1);
2292 if (tape.recording || tape.playing)
2295 tape.level_nr = level_nr;
2296 tape.recording = TRUE;
2297 tape.pausing = TRUE;
2299 10000*(zeit2->tm_year%100) + 100*zeit2->tm_mon + zeit2->tm_mday;
2301 DrawVideoDisplay(VIDEO_STATE_REC_ON | VIDEO_STATE_PAUSE_ON,0);
2302 DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
2303 DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
2306 void TapeStartRecording()
2310 tape.pos[tape.counter].delay = 0;
2311 tape.recording = TRUE;
2312 tape.playing = FALSE;
2313 tape.pausing = FALSE;
2314 tape.random_seed = InitRND(NEW_RANDOMIZE);
2315 DrawVideoDisplay(VIDEO_STATE_REC_ON | VIDEO_STATE_PAUSE_OFF,0);
2318 void TapeStopRecording()
2320 if (!tape.recording)
2323 tape.length = tape.counter;
2324 tape.recording = FALSE;
2325 tape.pausing = FALSE;
2326 DrawVideoDisplay(VIDEO_STATE_REC_OFF,0);
2331 void TapeRecordAction(int joy)
2333 if (!tape.recording || tape.pausing)
2336 if (tape.counter>=MAX_TAPELEN-1)
2338 TapeStopRecording();
2344 tape.pos[tape.counter].joystickdata = joy;
2346 tape.pos[tape.counter].delay = 0;
2350 void TapeRecordDelay()
2352 if (!tape.recording || tape.pausing)
2355 if (tape.counter>=MAX_TAPELEN)
2357 TapeStopRecording();
2361 tape.pos[tape.counter].delay++;
2363 if (tape.pos[tape.counter].delay>=255)
2365 tape.pos[tape.counter].joystickdata = 0;
2367 tape.pos[tape.counter].delay = 0;
2371 void TapeTogglePause()
2373 if (!tape.recording && !tape.playing)
2378 tape.pausing = FALSE;
2379 DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
2380 if (game_status==MAINMENU)
2381 HandleMainMenu(SX+16,SY+7*32+16,0,0,MB_MENU_CHOICE);
2385 tape.pausing = TRUE;
2386 DrawVideoDisplay(VIDEO_STATE_PAUSE_ON,0);
2390 void TapeInitPlaying()
2392 if (tape.recording || tape.playing || TAPE_IS_EMPTY(tape))
2395 tape.playing = TRUE;
2396 tape.pausing = TRUE;
2397 DrawVideoDisplay(VIDEO_STATE_PLAY_ON | VIDEO_STATE_PAUSE_ON,0);
2398 DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
2399 DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
2402 void TapeStartPlaying()
2407 tape.recording = FALSE;
2408 tape.playing = TRUE;
2409 tape.pausing = FALSE;
2410 InitRND(tape.random_seed);
2411 DrawVideoDisplay(VIDEO_STATE_PLAY_ON | VIDEO_STATE_PAUSE_OFF,0);
2414 void TapeStopPlaying()
2419 tape.playing = FALSE;
2420 tape.pausing = FALSE;
2421 DrawVideoDisplay(VIDEO_STATE_PLAY_OFF,0);
2424 int TapePlayAction()
2426 if (!tape.playing || tape.pausing)
2429 if (tape.counter>=tape.length)
2435 if (!tape.pos[tape.counter].delay)
2438 return(tape.pos[tape.counter-1].joystickdata);
2444 BOOL TapePlayDelay()
2446 if (!tape.playing || tape.pausing)
2449 if (tape.counter>=tape.length)
2455 if (tape.pos[tape.counter].delay)
2457 tape.pos[tape.counter].delay--;
2466 TapeStopRecording();
2468 DrawVideoDisplay(VIDEO_ALL_OFF,0);
2469 if (tape.date && tape.length)
2471 DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
2472 DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);