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 ***********************************************************/
26 extern int Movemethod;
27 extern int Movespeed[2];
29 void GetPlayerConfig()
31 int old_joystick_nr = joystick_nr;
33 if (sound_status==SOUND_OFF)
34 player.setup &= ~SETUP_SOUND;
35 if (!sound_loops_allowed)
37 player.setup &= ~SETUP_SOUND_LOOPS;
38 player.setup &= ~SETUP_SOUND_MUSIC;
41 sound_on = sound_simple_on = SETUP_SOUND_ON(player.setup);
42 sound_loops_on = SETUP_SOUND_LOOPS_ON(player.setup);
43 sound_music_on = SETUP_SOUND_MUSIC_ON(player.setup);
44 toons_on = SETUP_TOONS_ON(player.setup);
45 direct_draw_on = SETUP_DIRECT_DRAW_ON(player.setup);
46 fading_on = SETUP_FADING_ON(player.setup);
47 autorecord_on = SETUP_AUTO_RECORD_ON(player.setup);
48 joystick_nr = SETUP_2ND_JOYSTICK_ON(player.setup);
49 quick_doors = SETUP_QUICK_DOORS_ON(player.setup);
50 scroll_delay_on = SETUP_SCROLL_DELAY_ON(player.setup);
52 if (joystick_nr != old_joystick_nr)
55 close(joystick_device);
63 BOOL emulate_bd = TRUE; /* unless non-BOULDERDASH elements found */
64 BOOL emulate_sb = TRUE; /* unless non-SOKOBAN elements found */
67 Gems = level.edelsteine;
68 SokobanFields = Lights = 0;
69 DynaBombCount = DynaBombSize = DynaBombsLeft = 0;
71 Key[0] = Key[1] = Key[2] = Key[3] = FALSE;
75 TimeLeft = level.time;
76 LevelSolved = GameOver = SiebAktiv = FALSE;
80 DigField(0,0,0,0,DF_NO_PUSH);
83 for(i=0;i<MAX_NUM_AMOEBA;i++)
84 AmoebaCnt[i] = AmoebaCnt2[i] = 0;
86 for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
88 Feld[x][y] = Ur[x][y];
89 MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
90 Store[x][y] = Store2[x][y] = Frame[x][y] = AmoebaNr[x][y] = 0;
93 if (emulate_bd && !IS_BD_ELEMENT(Feld[x][y]))
95 if (emulate_sb && !IS_SB_ELEMENT(Feld[x][y]))
102 Feld[x][y] = EL_LEERRAUM;
107 Feld[x][y] = EL_LEERRAUM;
110 if (x<lev_fieldx-1 && Feld[x+1][y]==EL_SALZSAEURE)
111 Feld[x][y] = EL_BADEWANNE1;
112 else if (x>0 && Feld[x-1][y]==EL_SALZSAEURE)
113 Feld[x][y] = EL_BADEWANNE2;
114 else if (y>0 && Feld[x][y-1]==EL_BADEWANNE1)
115 Feld[x][y] = EL_BADEWANNE3;
116 else if (y>0 && Feld[x][y-1]==EL_SALZSAEURE)
117 Feld[x][y] = EL_BADEWANNE4;
118 else if (y>0 && Feld[x][y-1]==EL_BADEWANNE2)
119 Feld[x][y] = EL_BADEWANNE5;
158 Feld[x][y] = EL_AMOEBING;
159 Store[x][y] = EL_AMOEBE_NASS;
168 case EL_SOKOBAN_FELD_LEER:
176 game_emulation = (emulate_bd ? EMU_BOULDERDASH :
177 emulate_sb ? EMU_SOKOBAN : EMU_NONE);
179 scroll_x = scroll_y = -1;
182 (JX<=lev_fieldx-MIDPOSX ? JX-MIDPOSX : lev_fieldx-SCR_FIELDX+1);
185 (JY<=lev_fieldy-MIDPOSY ? JY-MIDPOSY : lev_fieldy-SCR_FIELDY+1);
187 CloseDoor(DOOR_CLOSE_1);
190 DrawLevelElement(JX,JY,EL_SPIELFIGUR);
193 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
194 DOOR_GFX_PAGEX5,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
195 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
196 DrawTextExt(pix[PIX_DB_DOOR],gc,
197 DOOR_GFX_PAGEX1+XX_LEVEL,DOOR_GFX_PAGEY1+YY_LEVEL,
198 int2str(level_nr,2),FS_SMALL,FC_YELLOW);
199 DrawTextExt(pix[PIX_DB_DOOR],gc,
200 DOOR_GFX_PAGEX1+XX_EMERALDS,DOOR_GFX_PAGEY1+YY_EMERALDS,
201 int2str(Gems,3),FS_SMALL,FC_YELLOW);
202 DrawTextExt(pix[PIX_DB_DOOR],gc,
203 DOOR_GFX_PAGEX1+XX_DYNAMITE,DOOR_GFX_PAGEY1+YY_DYNAMITE,
204 int2str(Dynamite,3),FS_SMALL,FC_YELLOW);
205 DrawTextExt(pix[PIX_DB_DOOR],gc,
206 DOOR_GFX_PAGEX1+XX_SCORE,DOOR_GFX_PAGEY1+YY_SCORE,
207 int2str(Score,5),FS_SMALL,FC_YELLOW);
208 DrawTextExt(pix[PIX_DB_DOOR],gc,
209 DOOR_GFX_PAGEX1+XX_TIME,DOOR_GFX_PAGEY1+YY_TIME,
210 int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
212 DrawGameButton(BUTTON_GAME_STOP);
213 DrawGameButton(BUTTON_GAME_PAUSE);
214 DrawGameButton(BUTTON_GAME_PLAY);
215 DrawSoundDisplay(BUTTON_SOUND_MUSIC | (BUTTON_ON * sound_music_on));
216 DrawSoundDisplay(BUTTON_SOUND_LOOPS | (BUTTON_ON * sound_loops_on));
217 DrawSoundDisplay(BUTTON_SOUND_SIMPLE | (BUTTON_ON * sound_simple_on));
218 XCopyArea(display,drawto,pix[PIX_DB_DOOR],gc,
219 DX+GAME_CONTROL_XPOS,DY+GAME_CONTROL_YPOS,
220 GAME_CONTROL_XSIZE,2*GAME_CONTROL_YSIZE,
221 DOOR_GFX_PAGEX1+GAME_CONTROL_XPOS,
222 DOOR_GFX_PAGEY1+GAME_CONTROL_YPOS);
224 OpenDoor(DOOR_OPEN_1);
227 PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
229 XAutoRepeatOff(display);
232 void InitMovDir(int x, int y)
234 int i, element = Feld[x][y];
235 static int xy[4][2] =
242 static int direction[2][4] =
244 { MV_RIGHT, MV_UP, MV_LEFT, MV_DOWN },
245 { MV_LEFT, MV_DOWN, MV_RIGHT, MV_UP }
254 Feld[x][y] = EL_KAEFER;
255 MovDir[x][y] = direction[0][element-EL_KAEFER_R];
261 Feld[x][y] = EL_FLIEGER;
262 MovDir[x][y] = direction[0][element-EL_FLIEGER_R];
268 Feld[x][y] = EL_BUTTERFLY;
269 MovDir[x][y] = direction[0][element-EL_BUTTERFLY_R];
275 Feld[x][y] = EL_FIREFLY;
276 MovDir[x][y] = direction[0][element-EL_FIREFLY_R];
282 Feld[x][y] = EL_PACMAN;
283 MovDir[x][y] = direction[0][element-EL_PACMAN_R];
286 MovDir[x][y] = 1<<RND(4);
287 if (element != EL_KAEFER &&
288 element != EL_FLIEGER &&
289 element != EL_BUTTERFLY &&
290 element != EL_FIREFLY)
300 if (!IN_LEV_FIELD(x1,y1) || !IS_FREE(x1,y1))
302 if (element==EL_KAEFER || element==EL_BUTTERFLY)
304 MovDir[x][y] = direction[0][i];
307 else if (element==EL_FLIEGER || element==EL_FIREFLY)
309 MovDir[x][y] = direction[1][i];
318 void InitAmoebaNr(int x, int y)
321 int group_nr = AmoebeNachbarNr(x,y);
325 for(i=1;i<MAX_NUM_AMOEBA;i++)
335 AmoebaNr[x][y] = group_nr;
336 AmoebaCnt[group_nr]++;
337 AmoebaCnt2[group_nr]++;
343 int bumplevel = FALSE;
350 PlaySoundExt(SND_SIRR,PSND_MAX_VOLUME,PSND_MAX_RIGHT,PSND_LOOP);
355 PlaySoundStereo(SND_SIRR,PSND_MAX_RIGHT);
356 if (TimeLeft && !(TimeLeft % 10))
357 RaiseScore(level.score[SC_ZEITBONUS]);
358 if (TimeLeft > 100 && !(TimeLeft % 10))
362 DrawText(DX_TIME,DY_TIME,int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
373 /* Hero disappears */
374 DrawLevelElement(JX,JY,Feld[JX][JY]);
381 CloseDoor(DOOR_CLOSE_1);
386 SaveLevelTape(tape.level_nr); /* Ask to save tape */
389 if (level_nr==player.handicap &&
390 level_nr<leveldir[leveldir_nr].levels-1)
394 SavePlayerInfo(PLAYER_LEVEL);
397 if ((hi_pos=NewHiScore())>=0)
399 game_status = HALLOFFAME;
400 DrawHallOfFame(hi_pos);
401 if (bumplevel && TAPE_IS_EMPTY(tape))
406 game_status = MAINMENU;
407 if (bumplevel && TAPE_IS_EMPTY(tape))
422 if (!strcmp(player.alias_name,EMPTY_ALIAS) ||
423 Score<highscore[MAX_SCORE_ENTRIES-1].Score)
426 for(k=0;k<MAX_SCORE_ENTRIES;k++)
428 if (Score>highscore[k].Score) /* Spieler kommt in Highscore-Liste */
430 if (k<MAX_SCORE_ENTRIES-1)
432 int m = MAX_SCORE_ENTRIES-1;
435 for(l=k;l<MAX_SCORE_ENTRIES;l++)
436 if (!strcmp(player.alias_name,highscore[l].Name))
438 if (m==k) /* Spieler überschreibt seine alte Position */
444 strcpy(highscore[l].Name,highscore[l-1].Name);
445 highscore[l].Score = highscore[l-1].Score;
452 sprintf(highscore[k].Name,player.alias_name);
453 highscore[k].Score = Score;
459 else if (!strcmp(player.alias_name,highscore[k].Name))
460 break; /* Spieler schon mit besserer Punktzahl in der Liste */
471 void InitMovingField(int x, int y, int direction)
473 int newx = x + (direction==MV_LEFT ? -1 : direction==MV_RIGHT ? +1 : 0);
474 int newy = y + (direction==MV_UP ? -1 : direction==MV_DOWN ? +1 : 0);
476 MovDir[x][y] = direction;
477 MovDir[newx][newy] = direction;
478 if (Feld[newx][newy]==EL_LEERRAUM)
479 Feld[newx][newy] = EL_BLOCKED;
482 void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y)
484 int direction = MovDir[x][y];
485 int newx = x + (direction==MV_LEFT ? -1 : direction==MV_RIGHT ? +1 : 0);
486 int newy = y + (direction==MV_UP ? -1 : direction==MV_DOWN ? +1 : 0);
492 void Blocked2Moving(int x, int y, int *comes_from_x, int *comes_from_y)
494 int oldx = x, oldy = y;
495 int direction = MovDir[x][y];
497 if (direction==MV_LEFT)
499 else if (direction==MV_RIGHT)
501 else if (direction==MV_UP)
503 else if (direction==MV_DOWN)
506 *comes_from_x = oldx;
507 *comes_from_y = oldy;
510 int MovingOrBlocked2Element(int x, int y)
512 int element = Feld[x][y];
514 if (element==EL_BLOCKED)
518 Blocked2Moving(x,y,&oldx,&oldy);
519 return(Feld[oldx][oldy]);
525 void RemoveMovingField(int x, int y)
527 int oldx=x,oldy=y, newx=x,newy=y;
529 if (Feld[x][y]!=EL_BLOCKED && !IS_MOVING(x,y))
534 Moving2Blocked(x,y,&newx,&newy);
535 if (Feld[newx][newy]!=EL_BLOCKED)
538 else if (Feld[x][y]==EL_BLOCKED)
540 Blocked2Moving(x,y,&oldx,&oldy);
541 if (!IS_MOVING(oldx,oldy))
545 Feld[oldx][oldy] = EL_LEERRAUM;
546 Feld[newx][newy] = EL_LEERRAUM;
547 MovPos[oldx][oldy] = MovDir[oldx][oldy] = MovDelay[oldx][oldy] = 0;
548 MovPos[newx][newy] = MovDir[newx][newy] = MovDelay[newx][newy] = 0;
549 DrawLevelField(oldx,oldy);
550 DrawLevelField(newx,newy);
553 void DrawDynamite(int x, int y)
555 if (!IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
560 DrawGraphic(SCROLLX(x),SCROLLY(y),el2gfx(Store[x][y]));
562 DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR);
564 else if (IS_PLAYER(x,y))
565 DrawGraphic(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR);
567 if (Feld[x][y]==EL_DYNAMIT)
569 int phase = (48-MovDelay[x][y])/6;
574 if (Store[x][y] || IS_PLAYER(x,y))
575 DrawGraphicThruMask(SCROLLX(x),SCROLLY(y),GFX_DYNAMIT+phase);
577 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_DYNAMIT+phase);
581 int phase = ((48-MovDelay[x][y])/3) % 8;
586 if (Store[x][y] || IS_PLAYER(x,y))
587 DrawGraphicThruMask(SCROLLX(x),SCROLLY(y),GFX_DYNABOMB+phase);
589 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_DYNABOMB+phase);
593 void CheckDynamite(int x, int y)
595 if (MovDelay[x][y]) /* neues Dynamit / in Wartezustand */
600 if (!(MovDelay[x][y] % 6))
601 PlaySoundLevel(x,y,SND_ZISCH);
603 if (Feld[x][y]==EL_DYNAMIT && !(MovDelay[x][y] % 6))
605 else if (Feld[x][y]==EL_DYNABOMB && !(MovDelay[x][y] % 3))
612 StopSound(SND_ZISCH);
616 void Explode(int ex, int ey, int phase, int mode)
619 int num_phase = 9, delay = 1;
620 int last_phase = num_phase*delay;
621 int half_phase = (num_phase/2)*delay;
623 if (phase==0) /* Feld 'Store' initialisieren */
625 int center_element = Feld[ex][ey];
627 if (center_element==EL_BLOCKED)
628 center_element = MovingOrBlocked2Element(ex,ey);
630 for(y=ey-1;y<ey+2;y++) for(x=ex-1;x<ex+2;x++)
632 int element = Feld[x][y];
634 if (!IN_LEV_FIELD(x,y) || IS_MASSIV(element))
637 if ((mode!=EX_NORMAL || center_element==EL_AMOEBA2DIAM) &&
641 if (element==EL_EXPLODING)
642 element = Store2[x][y];
644 if (IS_PLAYER(ex,ey))
645 Store[x][y] = EL_EDELSTEIN_GELB;
646 else if (center_element==EL_KAEFER)
647 Store[x][y] = ((x==ex && y==ey) ? EL_DIAMANT : EL_EDELSTEIN);
648 else if (center_element==EL_BUTTERFLY)
649 Store[x][y] = EL_EDELSTEIN_BD;
650 else if (center_element==EL_MAMPFER)
651 Store[x][y] = level.mampfer_inhalt[MampferNr][x-ex+1][y-ey+1];
652 else if (center_element==EL_AMOEBA2DIAM)
653 Store[x][y] = level.amoebe_inhalt;
654 else if (element==EL_ERZ_EDEL)
655 Store[x][y] = EL_EDELSTEIN;
656 else if (element==EL_ERZ_DIAM)
657 Store[x][y] = EL_DIAMANT;
658 else if (element==EL_ERZ_EDEL_BD)
659 Store[x][y] = EL_EDELSTEIN_BD;
660 else if (element==EL_ERZ_EDEL_GELB)
661 Store[x][y] = EL_EDELSTEIN_GELB;
662 else if (element==EL_ERZ_EDEL_ROT)
663 Store[x][y] = EL_EDELSTEIN_ROT;
664 else if (element==EL_ERZ_EDEL_LILA)
665 Store[x][y] = EL_EDELSTEIN_LILA;
666 else if (!IS_PFORTE(Store[x][y]))
667 Store[x][y] = EL_LEERRAUM;
669 if (x!=ex || y!=ey || center_element==EL_AMOEBA2DIAM || mode==EX_BORDER)
670 Store2[x][y] = element;
672 if (AmoebaNr[x][y] &&
673 (element==EL_AMOEBE_VOLL ||
674 element==EL_AMOEBE_BD ||
675 element==EL_AMOEBING))
677 AmoebaCnt[AmoebaNr[x][y]]--;
678 AmoebaCnt2[AmoebaNr[x][y]]--;
681 RemoveMovingField(x,y);
682 Feld[x][y] = EL_EXPLODING;
683 MovDir[x][y] = MovPos[x][y] = 0;
689 if (center_element==EL_MAMPFER)
690 MampferNr = (MampferNr+1) % 4;
701 Frame[x][y] = (phase<last_phase ? phase+1 : 0);
703 if (phase==half_phase)
705 int element = Store2[x][y];
709 else if (element==EL_BOMBE ||
710 element==EL_DYNAMIT ||
711 element==EL_DYNAMIT_AUS ||
712 element==EL_DYNABOMB ||
713 element==EL_DYNABOMB_NR ||
714 element==EL_DYNABOMB_SZ ||
715 element==EL_DYNABOMB_XL ||
718 Feld[x][y] = Store2[x][y];
722 else if (element==EL_AMOEBA2DIAM)
723 AmoebeUmwandeln(x,y);
726 if (phase==last_phase)
730 element = Feld[x][y] = Store[x][y];
731 Store[x][y] = Store2[x][y] = 0;
732 MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0;
733 if (CAN_MOVE(element) || COULD_MOVE(element))
737 else if (!(phase%delay) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
740 ErdreichAnbroeckeln(SCROLLX(x),SCROLLY(y));
742 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_EXPLOSION+(phase/delay-1));
746 void DynaExplode(int ex, int ey, int size)
749 static int xy[4][2] =
757 Explode(ex,ey,0,EX_CENTER);
763 int x = ex+j*xy[i%4][0];
764 int y = ey+j*xy[i%4][1];
767 if (!IN_LEV_FIELD(x,y) || IS_MASSIV(Feld[x][y]))
770 element = Feld[x][y];
771 Explode(x,y,0,EX_BORDER);
773 if (element != EL_LEERRAUM &&
774 element != EL_ERDREICH &&
775 element != EL_EXPLODING &&
784 void Bang(int x, int y)
786 int element = Feld[x][y];
788 PlaySoundLevel(x,y,SND_ROAAAR);
800 RaiseScoreElement(element);
801 Explode(x,y,0,EX_NORMAL);
807 DynaExplode(x,y,DynaBombSize);
811 Explode(x,y,0,EX_CENTER);
814 Explode(x,y,0,EX_NORMAL);
819 void Blurb(int x, int y)
821 int element = Feld[x][y];
823 if (element!=EL_BLURB_LEFT && element!=EL_BLURB_RIGHT) /* Anfang */
825 PlaySoundLevel(x,y,SND_BLURB);
826 if (IN_LEV_FIELD(x-1,y) && IS_FREE(x-1,y) &&
827 (!IN_LEV_FIELD(x-1,y-1) ||
828 !CAN_FALL(MovingOrBlocked2Element(x-1,y-1))))
830 Feld[x-1][y] = EL_BLURB_LEFT;
832 if (IN_LEV_FIELD(x+1,y) && IS_FREE(x+1,y) &&
833 (!IN_LEV_FIELD(x+1,y-1) ||
834 !CAN_FALL(MovingOrBlocked2Element(x+1,y-1))))
836 Feld[x+1][y] = EL_BLURB_RIGHT;
841 int graphic = (element==EL_BLURB_LEFT ? GFX_BLURB_LEFT : GFX_BLURB_RIGHT);
843 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
846 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
849 if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
850 DrawGraphic(SCROLLX(x),SCROLLY(y),graphic+4-MovDelay[x][y]);
854 Feld[x][y] = EL_LEERRAUM;
861 void Impact(int x, int y)
863 BOOL lastline = (y==lev_fieldy-1);
864 BOOL object_hit = FALSE;
865 int element = Feld[x][y];
867 /* Element darunter berührt? */
869 object_hit = (!IS_FREE(x,y+1) && (!IS_MOVING(x,y+1) ||
870 MovDir[x][y+1]!=MV_DOWN ||
871 MovPos[x][y+1]<=TILEY/2));
873 /* Auftreffendes Element fällt in Salzsäure */
874 if (!lastline && Feld[x][y+1]==EL_SALZSAEURE)
880 /* Auftreffendes Element ist Bombe */
881 if (element==EL_BOMBE && (lastline || object_hit))
887 /* Auftreffendes Element ist Säuretropfen */
888 if (element==EL_TROPFEN && (lastline || object_hit))
890 if (object_hit && IS_PLAYER(x,y+1))
894 Feld[x][y] = EL_AMOEBING;
895 Store[x][y] = EL_AMOEBE_NASS;
900 /* Welches Element kriegt was auf die Rübe? */
901 if (!lastline && object_hit)
903 int smashed = MovingOrBlocked2Element(x,y+1);
905 if (CAN_CHANGE(element) &&
906 (smashed==EL_SIEB_LEER || smashed==EL_SIEB2_LEER) && !SiebAktiv)
907 SiebAktiv = level.dauer_sieb * FRAMES_PER_SECOND;
909 if (IS_PLAYER(x,y+1))
914 else if (element==EL_EDELSTEIN_BD)
916 if (IS_ENEMY(smashed) && IS_BD_ELEMENT(smashed))
922 else if (element==EL_FELSBROCKEN)
924 if (IS_ENEMY(smashed))
929 else if (!IS_MOVING(x,y+1))
931 if (smashed==EL_BOMBE ||
932 smashed==EL_BIRNE_AUS || smashed==EL_BIRNE_EIN)
937 else if (smashed==EL_KOKOSNUSS)
939 Feld[x][y+1] = EL_CRACKINGNUT;
940 PlaySoundLevel(x,y,SND_KNACK);
941 RaiseScoreElement(EL_KOKOSNUSS);
944 else if (smashed==EL_DIAMANT)
946 Feld[x][y+1] = EL_LEERRAUM;
947 PlaySoundLevel(x,y,SND_QUIRK);
954 /* Geräusch beim Durchqueren des Siebes */
955 if (!lastline && (Feld[x][y+1]==EL_SIEB_LEER || Feld[x][y+1]==EL_SIEB2_LEER))
957 PlaySoundLevel(x,y,SND_QUIRK);
961 /* Geräusch beim Auftreffen */
962 if (lastline || object_hit)
969 case EL_EDELSTEIN_BD:
970 case EL_EDELSTEIN_GELB:
971 case EL_EDELSTEIN_ROT:
972 case EL_EDELSTEIN_LILA:
999 PlaySoundLevel(x,y,sound);
1003 void TurnRound(int x, int y)
1015 { 0,0 }, { 0,0 }, { 0,0 },
1020 int left,right,back;
1024 { MV_DOWN, MV_UP, MV_RIGHT },
1025 { MV_UP, MV_DOWN, MV_LEFT },
1027 { MV_LEFT, MV_RIGHT, MV_DOWN },
1028 { 0,0,0 }, { 0,0,0 }, { 0,0,0 },
1029 { MV_RIGHT, MV_LEFT, MV_UP }
1032 int element = Feld[x][y];
1033 int old_move_dir = MovDir[x][y];
1034 int left_dir = turn[old_move_dir].left;
1035 int right_dir = turn[old_move_dir].right;
1036 int back_dir = turn[old_move_dir].back;
1038 int left_dx = move_xy[left_dir].x, left_dy = move_xy[left_dir].y;
1039 int right_dx = move_xy[right_dir].x, right_dy = move_xy[right_dir].y;
1040 int move_dx = move_xy[old_move_dir].x, move_dy = move_xy[old_move_dir].y;
1042 int left_x = x+left_dx, left_y = y+left_dy;
1043 int right_x = x+right_dx, right_y = y+right_dy;
1044 int move_x = x+move_dx, move_y = y+move_dy;
1046 if (element==EL_KAEFER || element==EL_BUTTERFLY)
1048 TestIfBadThingHitsOtherBadThing(x,y);
1050 if (IN_LEV_FIELD(right_x,right_y) &&
1051 IS_FREE_OR_PLAYER(right_x,right_y))
1052 MovDir[x][y] = right_dir;
1053 else if (!IN_LEV_FIELD(move_x,move_y) ||
1054 !IS_FREE_OR_PLAYER(move_x,move_y))
1055 MovDir[x][y] = left_dir;
1057 if (element==EL_KAEFER && MovDir[x][y] != old_move_dir)
1059 else if (element==EL_BUTTERFLY) /* && MovDir[x][y]==left_dir) */
1062 else if (element==EL_FLIEGER || element==EL_FIREFLY)
1064 TestIfBadThingHitsOtherBadThing(x,y);
1066 if (IN_LEV_FIELD(left_x,left_y) &&
1067 IS_FREE_OR_PLAYER(left_x,left_y))
1068 MovDir[x][y] = left_dir;
1069 else if (!IN_LEV_FIELD(move_x,move_y) ||
1070 !IS_FREE_OR_PLAYER(move_x,move_y))
1071 MovDir[x][y] = right_dir;
1073 if (element==EL_FLIEGER && MovDir[x][y] != old_move_dir)
1075 else if (element==EL_FIREFLY) /* && MovDir[x][y]==right_dir) */
1078 else if (element==EL_MAMPFER)
1080 BOOL can_turn_left = FALSE, can_turn_right = FALSE;
1082 if (IN_LEV_FIELD(left_x,left_y) &&
1083 (IS_FREE_OR_PLAYER(left_x,left_y) ||
1084 Feld[left_x][left_y] == EL_DIAMANT))
1085 can_turn_left = TRUE;
1086 if (IN_LEV_FIELD(right_x,right_y) &&
1087 (IS_FREE_OR_PLAYER(right_x,right_y) ||
1088 Feld[right_x][right_y] == EL_DIAMANT))
1089 can_turn_right = TRUE;
1091 if (can_turn_left && can_turn_right)
1092 MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
1093 else if (can_turn_left)
1094 MovDir[x][y] = (RND(2) ? left_dir : back_dir);
1095 else if (can_turn_right)
1096 MovDir[x][y] = (RND(2) ? right_dir : back_dir);
1098 MovDir[x][y] = back_dir;
1100 MovDelay[x][y] = 8+8*RND(3);
1102 else if (element==EL_MAMPFER2)
1104 BOOL can_turn_left = FALSE, can_turn_right = FALSE;
1106 if (IN_LEV_FIELD(left_x,left_y) &&
1107 (IS_FREE_OR_PLAYER(left_x,left_y) ||
1108 IS_MAMPF2(Feld[left_x][left_y])))
1109 can_turn_left = TRUE;
1110 if (IN_LEV_FIELD(right_x,right_y) &&
1111 (IS_FREE_OR_PLAYER(right_x,right_y) ||
1112 IS_MAMPF2(Feld[right_x][right_y])))
1113 can_turn_right = TRUE;
1115 if (can_turn_left && can_turn_right)
1116 MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
1117 else if (can_turn_left)
1118 MovDir[x][y] = (RND(2) ? left_dir : back_dir);
1119 else if (can_turn_right)
1120 MovDir[x][y] = (RND(2) ? right_dir : back_dir);
1122 MovDir[x][y] = back_dir;
1124 MovDelay[x][y] = 8+8*RND(3);
1126 else if (element==EL_PACMAN)
1128 BOOL can_turn_left = FALSE, can_turn_right = FALSE;
1130 if (IN_LEV_FIELD(left_x,left_y) &&
1131 (IS_FREE_OR_PLAYER(left_x,left_y) ||
1132 IS_AMOEBOID(Feld[left_x][left_y])))
1133 can_turn_left = TRUE;
1134 if (IN_LEV_FIELD(right_x,right_y) &&
1135 (IS_FREE_OR_PLAYER(right_x,right_y) ||
1136 IS_AMOEBOID(Feld[right_x][right_y])))
1137 can_turn_right = TRUE;
1139 if (can_turn_left && can_turn_right)
1140 MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
1141 else if (can_turn_left)
1142 MovDir[x][y] = (RND(2) ? left_dir : back_dir);
1143 else if (can_turn_right)
1144 MovDir[x][y] = (RND(2) ? right_dir : back_dir);
1146 MovDir[x][y] = back_dir;
1148 MovDelay[x][y] = 3+RND(20);
1150 else if (element==EL_ZOMBIE)
1152 int attr_x = JX, attr_y = JY;
1161 MovDir[x][y] = MV_NO_MOVING;
1163 MovDir[x][y] |= (GameOver ? MV_RIGHT : MV_LEFT);
1165 MovDir[x][y] |= (GameOver ? MV_LEFT : MV_RIGHT);
1167 MovDir[x][y] |= (GameOver ? MV_DOWN : MV_UP);
1169 MovDir[x][y] |= (GameOver ? MV_UP : MV_DOWN);
1170 if ((MovDir[x][y]&(MV_LEFT|MV_RIGHT)) && (MovDir[x][y]&(MV_UP|MV_DOWN)))
1171 MovDir[x][y] &= (RND(2) ? (MV_LEFT|MV_RIGHT) : (MV_UP|MV_DOWN));
1173 Moving2Blocked(x,y,&newx,&newy);
1174 if (IN_LEV_FIELD(newx,newy) && IS_FREE_OR_PLAYER(newx,newy))
1175 MovDelay[x][y] = 4+4*!RND(3);
1181 void StartMoving(int x, int y)
1183 int element = Feld[x][y];
1188 if (CAN_FALL(element) && y<lev_fieldy-1)
1190 if (element==EL_MORAST_VOLL)
1194 InitMovingField(x,y,MV_DOWN);
1195 Feld[x][y] = EL_FELSBROCKEN;
1196 Store[x][y] = EL_MORAST_LEER;
1198 else if (Feld[x][y+1]==EL_MORAST_LEER)
1200 if (!MovDelay[x][y])
1201 MovDelay[x][y] = 16;
1210 Feld[x][y] = EL_MORAST_LEER;
1211 Feld[x][y+1] = EL_MORAST_VOLL;
1214 else if (element==EL_FELSBROCKEN && Feld[x][y+1]==EL_MORAST_LEER)
1216 InitMovingField(x,y,MV_DOWN);
1217 Store[x][y] = EL_MORAST_VOLL;
1219 else if (element==EL_SIEB_VOLL)
1223 InitMovingField(x,y,MV_DOWN);
1224 Feld[x][y] = EL_CHANGED(Store2[x][y]);
1225 Store[x][y] = EL_SIEB_LEER;
1228 else if (element==EL_SIEB2_VOLL)
1232 InitMovingField(x,y,MV_DOWN);
1233 Feld[x][y] = EL_CHANGED2(Store2[x][y]);
1234 Store[x][y] = EL_SIEB2_LEER;
1237 else if (SiebAktiv && CAN_CHANGE(element) &&
1238 (Feld[x][y+1]==EL_SIEB_LEER || Feld[x][y+1]==EL_SIEB2_LEER))
1240 InitMovingField(x,y,MV_DOWN);
1242 (Feld[x][y+1]==EL_SIEB_LEER ? EL_SIEB_VOLL : EL_SIEB2_VOLL);
1243 Store2[x][y+1] = element;
1245 else if (CAN_SMASH(element) && Feld[x][y+1]==EL_SALZSAEURE)
1248 InitMovingField(x,y,MV_DOWN);
1249 Store[x][y] = EL_SALZSAEURE;
1251 else if (CAN_SMASH(element) && Feld[x][y+1]==EL_BLOCKED && JustHit[x][y])
1255 else if (IS_FREE(x,y+1))
1257 InitMovingField(x,y,MV_DOWN);
1259 else if (element==EL_TROPFEN)
1261 Feld[x][y] = EL_AMOEBING;
1262 Store[x][y] = EL_AMOEBE_NASS;
1264 else if (IS_SLIPPERY(Feld[x][y+1]) && !Store[x][y+1])
1266 BOOL left = (x>0 && IS_FREE(x-1,y) &&
1267 (IS_FREE(x-1,y+1) || Feld[x-1][y+1]==EL_SALZSAEURE));
1268 BOOL right = (x<lev_fieldx-1 && IS_FREE(x+1,y) &&
1269 (IS_FREE(x+1,y+1) || Feld[x+1][y+1]==EL_SALZSAEURE));
1273 if (left && right && game_emulation != EMU_BOULDERDASH)
1274 left = !(right = RND(2));
1276 InitMovingField(x,y,left ? MV_LEFT : MV_RIGHT);
1280 else if (CAN_MOVE(element))
1284 if (!MovDelay[x][y]) /* neuer Schritt / noch nicht gewartet */
1286 if (element==EL_ZOMBIE || element==EL_KAEFER || element==EL_FLIEGER ||
1287 element==EL_BUTTERFLY || element==EL_FIREFLY)
1290 if (MovDelay[x][y] && (element == EL_KAEFER || element == EL_FLIEGER))
1291 DrawLevelField(x,y);
1295 if (MovDelay[x][y]) /* neuer Schritt / in Wartezustand */
1299 if (element==EL_ZOMBIE || element==EL_MAMPFER || element==EL_MAMPFER2)
1301 int phase = MovDelay[x][y] % 8;
1306 if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1307 DrawGraphic(SCROLLX(x),SCROLLY(y), el2gfx(element)+phase);
1309 if ((element==EL_MAMPFER || element==EL_MAMPFER2)
1310 && MovDelay[x][y]%4==3)
1311 PlaySoundLevel(x,y,SND_NJAM);
1313 else if (element==EL_BUTTERFLY || element==EL_FIREFLY)
1315 int phase = (FrameCounter % 4) / 2;
1317 if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1318 DrawGraphic(SCROLLX(x),SCROLLY(y), el2gfx(element)+phase);
1325 if (element==EL_KAEFER || element==EL_BUTTERFLY)
1327 PlaySoundLevel(x,y,SND_KLAPPER);
1329 else if (element==EL_FLIEGER || element==EL_FIREFLY)
1331 PlaySoundLevel(x,y,SND_ROEHR);
1334 /* neuer Schritt / Wartezustand beendet */
1336 Moving2Blocked(x,y,&newx,&newy); /* wohin soll's gehen? */
1338 if (IS_PLAYER(newx,newy)) /* Spieler erwischt */
1344 else if (element==EL_MAMPFER && IN_LEV_FIELD(newx,newy) &&
1345 Feld[newx][newy]==EL_DIAMANT)
1347 if (IS_MOVING(newx,newy))
1348 RemoveMovingField(newx,newy);
1351 Feld[newx][newy] = EL_LEERRAUM;
1352 DrawLevelField(newx,newy);
1355 else if (element==EL_MAMPFER2 && IN_LEV_FIELD(newx,newy) &&
1356 IS_MAMPF2(Feld[newx][newy]))
1358 if (AmoebaNr[newx][newy])
1360 AmoebaCnt2[AmoebaNr[newx][newy]]--;
1361 if (Feld[newx][newy]==EL_AMOEBE_VOLL || Feld[newx][newy]==EL_AMOEBE_BD)
1362 AmoebaCnt[AmoebaNr[newx][newy]]--;
1365 if (IS_MOVING(newx,newy))
1366 RemoveMovingField(newx,newy);
1369 Feld[newx][newy] = EL_LEERRAUM;
1370 DrawLevelField(newx,newy);
1373 else if (element==EL_PACMAN && IN_LEV_FIELD(newx,newy) &&
1374 IS_AMOEBOID(Feld[newx][newy]))
1376 if (AmoebaNr[newx][newy])
1378 AmoebaCnt2[AmoebaNr[newx][newy]]--;
1379 if (Feld[newx][newy]==EL_AMOEBE_VOLL || Feld[newx][newy]==EL_AMOEBE_BD)
1380 AmoebaCnt[AmoebaNr[newx][newy]]--;
1383 Feld[newx][newy] = EL_LEERRAUM;
1384 DrawLevelField(newx,newy);
1386 else if (element==EL_ZOMBIE && IN_LEV_FIELD(newx,newy) &&
1387 MovDir[x][y]==MV_DOWN && Feld[newx][newy]==EL_SALZSAEURE)
1390 Store[x][y] = EL_SALZSAEURE;
1392 else if (!IN_LEV_FIELD(newx,newy) || !IS_FREE(newx,newy))
1393 { /* gegen Wand gelaufen */
1395 if (MovDelay[x][y] && (element == EL_KAEFER || element == EL_FLIEGER))
1396 DrawLevelField(x,y);
1400 if (element==EL_ZOMBIE)
1401 PlaySoundLevel(x,y,SND_SCHLURF);
1403 InitMovingField(x,y,MovDir[x][y]);
1407 ContinueMoving(x,y);
1410 void ContinueMoving(int x, int y)
1412 int element = Feld[x][y];
1413 int direction = MovDir[x][y];
1414 int dx = (direction==MV_LEFT ? -1 : direction==MV_RIGHT ? +1 : 0);
1415 int dy = (direction==MV_UP ? -1 : direction==MV_DOWN ? +1 : 0);
1416 int horiz_move = (dx!=0);
1417 int newx = x + dx, newy = y + dy;
1418 int step = (horiz_move ? dx : dy)*TILEX/4;
1420 if (CAN_FALL(element) && horiz_move)
1422 else if (element==EL_TROPFEN)
1424 else if (Store[x][y]==EL_MORAST_VOLL || Store[x][y]==EL_MORAST_LEER)
1427 MovPos[x][y] += step;
1429 if (ABS(MovPos[x][y])>=TILEX) /* Zielfeld erreicht */
1431 Feld[x][y] = EL_LEERRAUM;
1432 Feld[newx][newy] = element;
1434 if (Store[x][y]==EL_MORAST_VOLL)
1437 Feld[newx][newy] = EL_MORAST_VOLL;
1438 element = EL_MORAST_VOLL;
1440 else if (Store[x][y]==EL_MORAST_LEER)
1443 Feld[x][y] = EL_MORAST_LEER;
1445 else if (Store[x][y]==EL_SIEB_VOLL)
1448 element = Feld[newx][newy] = (SiebAktiv ? EL_SIEB_VOLL : EL_SIEB_TOT);
1450 else if (Store[x][y]==EL_SIEB_LEER)
1452 Store[x][y] = Store2[x][y] = 0;
1453 Feld[x][y] = (SiebAktiv ? EL_SIEB_LEER : EL_SIEB_TOT);
1455 else if (Store[x][y]==EL_SIEB2_VOLL)
1458 element = Feld[newx][newy] = (SiebAktiv ? EL_SIEB2_VOLL : EL_SIEB2_TOT);
1460 else if (Store[x][y]==EL_SIEB2_LEER)
1462 Store[x][y] = Store2[x][y] = 0;
1463 Feld[x][y] = (SiebAktiv ? EL_SIEB2_LEER : EL_SIEB2_TOT);
1465 else if (Store[x][y]==EL_SALZSAEURE)
1468 Feld[newx][newy] = EL_SALZSAEURE;
1469 element = EL_SALZSAEURE;
1471 else if (Store[x][y]==EL_AMOEBE_NASS)
1474 Feld[x][y] = EL_AMOEBE_NASS;
1477 MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
1478 MovDelay[newx][newy] = 0;
1480 if (!CAN_MOVE(element))
1481 MovDir[newx][newy] = 0;
1483 DrawLevelField(x,y);
1484 DrawLevelField(newx,newy);
1486 Stop[newx][newy] = TRUE;
1487 JustHit[x][newy] = 3;
1489 if (DONT_TOUCH(element)) /* Käfer oder Flieger */
1491 TestIfBadThingHitsHero();
1492 TestIfBadThingHitsOtherBadThing(newx,newy);
1495 if (CAN_SMASH(element) && direction==MV_DOWN &&
1496 (newy==lev_fieldy-1 || !IS_FREE(x,newy+1)))
1499 else /* noch in Bewegung */
1500 DrawLevelField(x,y);
1503 int AmoebeNachbarNr(int ax, int ay)
1506 int element = Feld[ax][ay];
1508 static int xy[4][2] =
1518 int x = ax+xy[i%4][0];
1519 int y = ay+xy[i%4][1];
1521 if (!IN_LEV_FIELD(x,y))
1524 if (Feld[x][y]==element && AmoebaNr[x][y]>0)
1525 group_nr = AmoebaNr[x][y];
1531 void AmoebenVereinigen(int ax, int ay)
1534 int new_group_nr = AmoebaNr[ax][ay];
1535 static int xy[4][2] =
1551 if (!IN_LEV_FIELD(x,y))
1554 if ((Feld[x][y]==EL_AMOEBE_VOLL ||
1555 Feld[x][y]==EL_AMOEBE_BD ||
1556 Feld[x][y]==EL_AMOEBE_TOT) &&
1557 AmoebaNr[x][y] != new_group_nr)
1559 int old_group_nr = AmoebaNr[x][y];
1561 AmoebaCnt[new_group_nr] += AmoebaCnt[old_group_nr];
1562 AmoebaCnt[old_group_nr] = 0;
1563 AmoebaCnt2[new_group_nr] += AmoebaCnt2[old_group_nr];
1564 AmoebaCnt2[old_group_nr] = 0;
1566 for(yy=0;yy<lev_fieldy;yy++) for(xx=0;xx<lev_fieldx;xx++)
1567 if (AmoebaNr[xx][yy]==old_group_nr)
1568 AmoebaNr[xx][yy] = new_group_nr;
1573 void AmoebeUmwandeln(int ax, int ay)
1576 int group_nr = AmoebaNr[ax][ay];
1577 static int xy[4][2] =
1585 if (Feld[ax][ay]==EL_AMOEBE_TOT)
1587 for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
1589 if (Feld[x][y]==EL_AMOEBE_TOT && AmoebaNr[x][y]==group_nr)
1592 Feld[x][y] = EL_AMOEBA2DIAM;
1604 if (!IN_LEV_FIELD(x,y))
1607 if (Feld[x][y]==EL_AMOEBA2DIAM)
1613 void AmoebeUmwandeln2(int ax, int ay, int new_element)
1616 int group_nr = AmoebaNr[ax][ay];
1619 for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
1621 if (AmoebaNr[x][y]==group_nr &&
1622 (Feld[x][y]==EL_AMOEBE_TOT ||
1623 Feld[x][y]==EL_AMOEBE_BD ||
1624 Feld[x][y]==EL_AMOEBING))
1627 Feld[x][y] = new_element;
1628 DrawLevelField(x,y);
1634 PlaySoundLevel(ax,ay,new_element==EL_FELSBROCKEN ? SND_KLOPF : SND_PLING);
1637 void AmoebeWaechst(int x, int y)
1639 static long sound_delay = 0;
1640 static int sound_delay_value = 0;
1642 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
1646 if (DelayReached(&sound_delay,sound_delay_value))
1648 PlaySoundLevel(x,y,SND_AMOEBE);
1649 sound_delay_value = 30;
1653 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
1656 if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1657 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_AMOEBING+3-MovDelay[x][y]);
1659 if (!MovDelay[x][y])
1661 Feld[x][y] = Store[x][y];
1663 DrawLevelField(x,y);
1668 void AmoebeAbleger(int ax, int ay)
1671 int element = Feld[ax][ay];
1672 int newax = ax, neway = ay;
1673 static int xy[4][2] =
1681 if (!level.tempo_amoebe)
1683 Feld[ax][ay] = EL_AMOEBE_TOT;
1684 DrawLevelField(ax,ay);
1688 if (!MovDelay[ax][ay]) /* neue Amoebe / noch nicht gewartet */
1689 MovDelay[ax][ay] = RND(FRAMES_PER_SECOND * 25/(1+level.tempo_amoebe));
1691 if (MovDelay[ax][ay]) /* neue Amoebe / in Wartezustand */
1694 if (MovDelay[ax][ay])
1698 if (element==EL_AMOEBE_NASS) /* tropfende Amöbe */
1701 int x = ax+xy[start][0];
1702 int y = ay+xy[start][1];
1704 if (!IN_LEV_FIELD(x,y))
1708 Feld[x][y]==EL_ERDREICH || Feld[x][y]==EL_MORAST_LEER)
1714 if (newax==ax && neway==ay)
1717 else /* normale oder "gefüllte" Amöbe */
1720 BOOL waiting_for_player = FALSE;
1724 int j = (start+i)%4;
1725 int x = ax+xy[j][0];
1726 int y = ay+xy[j][1];
1728 if (!IN_LEV_FIELD(x,y))
1732 Feld[x][y]==EL_ERDREICH || Feld[x][y]==EL_MORAST_LEER)
1738 else if (IS_PLAYER(x,y))
1739 waiting_for_player = TRUE;
1742 if (newax==ax && neway==ay)
1744 if (i==4 && !waiting_for_player)
1746 Feld[ax][ay] = EL_AMOEBE_TOT;
1747 DrawLevelField(ax,ay);
1748 AmoebaCnt[AmoebaNr[ax][ay]]--;
1750 if (AmoebaCnt[AmoebaNr[ax][ay]]<=0) /* Amöbe vollständig tot */
1752 if (element==EL_AMOEBE_VOLL)
1753 AmoebeUmwandeln(ax,ay);
1754 else if (element==EL_AMOEBE_BD)
1755 AmoebeUmwandeln2(ax,ay,level.amoebe_inhalt);
1760 else if (element==EL_AMOEBE_VOLL || element==EL_AMOEBE_BD)
1762 int new_group_nr = AmoebaNr[ax][ay];
1764 AmoebaNr[newax][neway] = new_group_nr;
1765 AmoebaCnt[new_group_nr]++;
1766 AmoebaCnt2[new_group_nr]++;
1767 AmoebenVereinigen(newax,neway);
1769 if (AmoebaCnt2[new_group_nr] >= 200 && element==EL_AMOEBE_BD)
1771 AmoebeUmwandeln2(newax,neway,EL_FELSBROCKEN);
1777 if (element!=EL_AMOEBE_NASS || neway<ay || !IS_FREE(newax,neway) ||
1778 (neway==lev_fieldy-1 && newax!=ax))
1780 Feld[newax][neway] = EL_AMOEBING;
1781 Store[newax][neway] = element;
1784 Feld[newax][neway] = EL_TROPFEN;
1787 InitMovingField(ax,ay,MV_DOWN);
1788 Feld[ax][ay] = EL_TROPFEN;
1789 Store[ax][ay] = EL_AMOEBE_NASS;
1790 ContinueMoving(ax,ay);
1794 DrawLevelField(newax,neway);
1797 void Life(int ax, int ay)
1800 static int life[4] = { 2,3,3,3 }; /* "Life"-Parameter */
1802 int element = Feld[ax][ay];
1807 if (!MovDelay[ax][ay]) /* neue Phase / noch nicht gewartet */
1808 MovDelay[ax][ay] = life_time;
1810 if (MovDelay[ax][ay]) /* neue Phase / in Wartezustand */
1813 if (MovDelay[ax][ay])
1817 for(y1=-1;y1<2;y1++) for(x1=-1;x1<2;x1++)
1819 int xx = ax+x1, yy = ay+y1;
1822 if (!IN_LEV_FIELD(xx,yy))
1825 for(y2=-1;y2<2;y2++) for(x2=-1;x2<2;x2++)
1827 int x = xx+x2, y = yy+y2;
1829 if (!IN_LEV_FIELD(x,y) || (x==xx && y==yy))
1832 if (((Feld[x][y]==element || (element==EL_LIFE && IS_PLAYER(x,y))) &&
1834 (IS_FREE(x,y) && Stop[x][y]))
1838 if (xx==ax && yy==ay) /* mittleres Feld mit Amoebe */
1840 if (nachbarn<life[0] || nachbarn>life[1])
1842 Feld[xx][yy] = EL_LEERRAUM;
1844 DrawLevelField(xx,yy);
1845 Stop[xx][yy] = TRUE;
1848 else if (IS_FREE(xx,yy) || Feld[xx][yy]==EL_ERDREICH)
1849 { /* Randfeld ohne Amoebe */
1850 if (nachbarn>=life[2] && nachbarn<=life[3])
1852 Feld[xx][yy] = element;
1853 MovDelay[xx][yy] = (element==EL_LIFE ? 0 : life_time-1);
1855 DrawLevelField(xx,yy);
1856 Stop[xx][yy] = TRUE;
1862 void Ablenk(int x, int y)
1864 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
1865 MovDelay[x][y] = level.dauer_ablenk * FRAMES_PER_SECOND;
1867 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
1872 if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1873 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_ABLENK+MovDelay[x][y]%4);
1874 if (!(MovDelay[x][y]%4))
1875 PlaySoundLevel(x,y,SND_MIEP);
1880 Feld[x][y] = EL_ABLENK_AUS;
1881 DrawLevelField(x,y);
1886 void Birne(int x, int y)
1888 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
1889 MovDelay[x][y] = 400;
1891 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
1896 if (!(MovDelay[x][y]%5))
1898 if (!(MovDelay[x][y]%10))
1899 Feld[x][y]=EL_ABLENK_EIN;
1901 Feld[x][y]=EL_ABLENK_AUS;
1902 DrawLevelField(x,y);
1903 Feld[x][y]=EL_ABLENK_EIN;
1909 Feld[x][y]=EL_ABLENK_AUS;
1910 DrawLevelField(x,y);
1915 void Blubber(int x, int y)
1917 DrawGraphicAnimation(x,y, GFX_GEBLUBBER, 4, 5, ANIM_NORMAL);
1920 void NussKnacken(int x, int y)
1922 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
1925 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
1928 if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1929 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_CRACKINGNUT+3-MovDelay[x][y]);
1931 if (!MovDelay[x][y])
1933 Feld[x][y] = EL_EDELSTEIN;
1934 DrawLevelField(x,y);
1939 void SiebAktivieren(int x, int y, int typ)
1943 if (SiebAktiv%2 && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1944 DrawGraphic(SCROLLX(x),SCROLLY(y),
1945 (typ==1 ? GFX_SIEB_VOLL : GFX_SIEB2_VOLL)+3-(SiebAktiv%8)/2);
1949 Feld[x][y] = (typ==1 ? EL_SIEB_TOT : EL_SIEB2_TOT);
1950 DrawLevelField(x,y);
1954 void AusgangstuerPruefen(int x, int y)
1956 if (!Gems && !SokobanFields && !Lights)
1958 Feld[x][y] = EL_AUSGANG_ACT;
1959 PlaySoundLevel(x,y,SND_OEFFNEN);
1963 void AusgangstuerOeffnen(int x, int y)
1967 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
1968 MovDelay[x][y] = 5*speed;
1970 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
1975 tuer = MovDelay[x][y]/speed;
1976 if (!(MovDelay[x][y]%speed) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
1977 DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_AUSGANG_AUF-tuer);
1979 if (!MovDelay[x][y])
1981 Feld[x][y] = EL_AUSGANG_AUF;
1982 DrawLevelField(x,y);
1987 void AusgangstuerBlinken(int x, int y)
1989 DrawGraphicAnimation(x,y, GFX_AUSGANG_AUF, 4, 2, ANIM_OSCILLATE);
1992 void EdelsteinFunkeln(int x, int y)
1994 if (!IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)) || IS_MOVING(x,y))
1997 if (Feld[x][y] == EL_EDELSTEIN_BD)
1999 const int delay = 2;
2000 const int frames = 4;
2001 int phase = (FrameCounter % (delay*frames)) / delay;
2003 if (!(FrameCounter % delay))
2004 DrawGraphic(SCROLLX(x),SCROLLY(y), GFX_EDELSTEIN_BD - phase);
2008 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
2009 MovDelay[x][y] = 6*!SimpleRND(500);
2011 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
2015 if (direct_draw_on && MovDelay[x][y])
2016 drawto_field = backbuffer;
2018 DrawGraphic(SCROLLX(x),SCROLLY(y), el2gfx(Feld[x][y]));
2022 int src_x,src_y, dest_x,dest_y;
2023 int phase = MovDelay[x][y]-1;
2025 src_x = SX+GFX_PER_LINE*TILEX;
2026 src_y = SY+(phase > 2 ? 4-phase : phase)*TILEY;
2027 dest_x = SX+SCROLLX(x)*TILEX;
2028 dest_y = SY+SCROLLY(y)*TILEY;
2030 XSetClipOrigin(display,clip_gc[PIX_BACK],dest_x-src_x,dest_y-src_y);
2031 XCopyArea(display,pix[PIX_BACK],drawto_field,clip_gc[PIX_BACK],
2032 src_x,src_y, TILEX,TILEY, dest_x,dest_y);
2036 XCopyArea(display,backbuffer,window,gc,
2037 dest_x,dest_y, TILEX,TILEY, dest_x,dest_y);
2038 drawto_field = window;
2045 void MauerWaechst(int x, int y)
2049 if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
2050 MovDelay[x][y] = 3*speed;
2052 if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
2057 phase = 2-MovDelay[x][y]/speed;
2058 if (!(MovDelay[x][y]%speed) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
2059 DrawGraphic(SCROLLX(x),SCROLLY(y),
2060 (Store[x][y]==MV_LEFT ? GFX_MAUER_L1 : GFX_MAUER_R1)+phase);
2062 if (!MovDelay[x][y])
2064 if (Store[x][y]==MV_LEFT)
2066 if (IN_LEV_FIELD(x-1,y) && IS_MAUER(Feld[x-1][y]))
2067 DrawLevelField(x-1,y);
2071 if (IN_LEV_FIELD(x+1,y) && IS_MAUER(Feld[x+1][y]))
2072 DrawLevelField(x+1,y);
2075 Feld[x][y] = EL_MAUER_LEBT;
2077 DrawLevelField(x,y);
2082 void MauerAbleger(int ax, int ay)
2084 BOOL links_frei = FALSE, rechts_frei = FALSE;
2085 BOOL links_massiv = FALSE, rechts_massiv = FALSE;
2087 if (!MovDelay[ax][ay]) /* neue Mauer / noch nicht gewartet */
2088 MovDelay[ax][ay] = 3;
2090 if (MovDelay[ax][ay]) /* neue Mauer / in Wartezustand */
2093 if (MovDelay[ax][ay])
2097 if (IN_LEV_FIELD(ax-1,ay) && IS_FREE(ax-1,ay))
2099 if (IN_LEV_FIELD(ax+1,ay) && IS_FREE(ax+1,ay))
2104 Feld[ax-1][ay] = EL_MAUERND;
2105 Store[ax-1][ay] = MV_LEFT;
2106 if (IN_SCR_FIELD(SCROLLX(ax-1),SCROLLY(ay)))
2107 DrawGraphic(SCROLLX(ax-1),SCROLLY(ay),GFX_MAUER_L1);
2111 Feld[ax+1][ay] = EL_MAUERND;
2112 Store[ax+1][ay] = MV_RIGHT;
2113 if (IN_SCR_FIELD(SCROLLX(ax+1),SCROLLY(ay)))
2114 DrawGraphic(SCROLLX(ax+1),SCROLLY(ay),GFX_MAUER_R1);
2117 if (links_frei || rechts_frei)
2118 DrawLevelField(ax,ay);
2120 if (!IN_LEV_FIELD(ax-1,ay) || IS_MAUER(Feld[ax-1][ay]))
2121 links_massiv = TRUE;
2122 if (!IN_LEV_FIELD(ax+1,ay) || IS_MAUER(Feld[ax+1][ay]))
2123 rechts_massiv = TRUE;
2125 if (links_massiv && rechts_massiv)
2126 Feld[ax][ay] = EL_MAUERWERK;
2131 static long action_delay=0;
2132 long action_delay_value;
2134 if (game_status != PLAYING)
2138 action_delay_value =
2139 (tape.playing && tape.fast_forward ? FFWD_FRAME_DELAY : GAME_FRAME_DELAY);
2142 action_delay_value =
2143 (tape.playing && tape.fast_forward ? FFWD_FRAME_DELAY : Gamespeed);
2145 if (DelayReached(&action_delay, action_delay_value))
2148 int sieb_x = 0, sieb_y = 0;
2153 if (tape.pausing || (tape.playing && !TapePlayDelay()))
2155 else if (tape.recording)
2158 for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
2161 if (JustHit[x][y]>0)
2165 for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
2167 element = Feld[x][y];
2169 if (IS_INACTIVE(element))
2173 if (element==EL_LEERRAUM || element==EL_ERDREICH)
2177 if (!IS_MOVING(x,y) && (CAN_FALL(element) || CAN_MOVE(element)))
2181 if (IS_GEM(element))
2182 EdelsteinFunkeln(x,y);
2184 else if (IS_MOVING(x,y))
2185 ContinueMoving(x,y);
2186 else if (element==EL_DYNAMIT || element==EL_DYNABOMB)
2188 else if (element==EL_EXPLODING)
2189 Explode(x,y,Frame[x][y],EX_NORMAL);
2190 else if (element==EL_AMOEBING)
2192 else if (IS_AMOEBALIVE(element))
2194 else if (element==EL_LIFE || element==EL_LIFE_ASYNC)
2196 else if (element==EL_ABLENK_EIN)
2198 else if (element==EL_SALZSAEURE)
2200 else if (element==EL_BLURB_LEFT || element==EL_BLURB_RIGHT)
2202 else if (element==EL_CRACKINGNUT)
2204 else if (element==EL_AUSGANG_ZU)
2205 AusgangstuerPruefen(x,y);
2206 else if (element==EL_AUSGANG_ACT)
2207 AusgangstuerOeffnen(x,y);
2208 else if (element==EL_AUSGANG_AUF)
2209 AusgangstuerBlinken(x,y);
2210 else if (element==EL_MAUERND)
2212 else if (element==EL_MAUER_LEBT)
2219 if (element==EL_SIEB_LEER || element==EL_SIEB_VOLL ||
2220 Store[x][y]==EL_SIEB_LEER)
2222 SiebAktivieren(x, y, 1);
2225 else if (element==EL_SIEB2_LEER || element==EL_SIEB2_VOLL ||
2226 Store[x][y]==EL_SIEB2_LEER)
2228 SiebAktivieren(x, y, 2);
2232 if (sieb && ABS(x-JX)+ABS(y-JY) < ABS(sieb_x-JX)+ABS(sieb_y-JY))
2243 PlaySoundLevel(sieb_x,sieb_y,SND_MIEP);
2248 if (TimeLeft>0 && TimeFrames>=25 && !tape.pausing)
2253 if (tape.recording || tape.playing)
2254 DrawVideoDisplay(VIDEO_STATE_TIME_ON,level.time-TimeLeft);
2257 PlaySoundStereo(SND_GONG,PSND_MAX_RIGHT);
2259 DrawText(DX_TIME,DY_TIME,int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
2268 void ScrollLevel(int dx, int dy)
2272 XCopyArea(display,drawto_field,drawto_field,gc,
2273 SX+TILEX*(dx==-1),SY+TILEY*(dy==-1),
2274 SXSIZE-TILEX*(dx!=0),SYSIZE-TILEY*(dy!=0),
2275 SX+TILEX*(dx==1),SY+TILEY*(dy==1));
2279 x = dx==1 ? 0 : SCR_FIELDX-1;
2280 for(y=0;y<SCR_FIELDY;y++)
2281 DrawScreenField(x,y);
2285 y = dy==1 ? 0 : SCR_FIELDY-1;
2286 for(x=0;x<SCR_FIELDY;x++)
2287 DrawScreenField(x,y);
2290 redraw_mask|=REDRAW_FIELD;
2293 BOOL MoveFigureOneStep(int dx, int dy, int real_dx, int real_dy)
2295 int oldJX,oldJY, newJX = JX+dx,newJY = JY+dy;
2299 if (GameOver || (!dx && !dy))
2300 return(MF_NO_ACTION);
2301 if (!IN_LEV_FIELD(newJX,newJY))
2302 return(MF_NO_ACTION);
2304 element = MovingOrBlocked2Element(newJX,newJY);
2306 if (DONT_GO_TO(element))
2308 if (element==EL_SALZSAEURE && dx==0 && dy==1)
2311 Feld[JX][JY] = EL_SPIELFIGUR;
2312 InitMovingField(JX,JY,MV_DOWN);
2313 Store[JX][JY] = EL_SALZSAEURE;
2314 ContinueMoving(JX,JY);
2316 PlaySoundLevel(JX,JY,SND_AUTSCH);
2317 PlaySoundLevel(JX,JY,SND_LACHEN);
2327 can_move = DigField(newJX,newJY, real_dx,real_dy, DF_DIG);
2328 if (can_move != MF_MOVING)
2336 if (Store[oldJX][oldJY])
2338 DrawGraphic(SCROLLX(oldJX),SCROLLY(oldJY),el2gfx(Store[oldJX][oldJY]));
2339 DrawGraphicThruMask(SCROLLX(oldJX),SCROLLY(oldJY),
2340 el2gfx(Feld[oldJX][oldJY]));
2342 else if (Feld[oldJX][oldJY]==EL_DYNAMIT)
2343 DrawDynamite(oldJX,oldJY);
2345 DrawLevelField(oldJX,oldJY);
2350 BOOL MoveFigure(int dx, int dy)
2352 static long move_delay = 0;
2353 int moved = MF_NO_ACTION;
2355 if (GameOver || (!dx && !dy))
2359 if (!DelayReached(&move_delay,8) && !tape.playing)
2364 if (!DelayReached(&move_delay,10) && !tape.playing)
2369 if (!FrameReached(&move_delay,2) && !tape.playing)
2373 if (Movemethod == 0)
2375 if (!DelayReached(&move_delay,Movespeed[0]) && !tape.playing)
2380 if (!FrameReached(&move_delay,Movespeed[1]) && !tape.playing)
2384 if (moved |= MoveFigureOneStep(dx,0, dx,dy))
2385 moved |= MoveFigureOneStep(0,dy, dx,dy);
2388 moved |= MoveFigureOneStep(0,dy, dx,dy);
2389 moved |= MoveFigureOneStep(dx,0, dx,dy);
2392 if (moved & MF_MOVING)
2394 int old_scroll_x=scroll_x, old_scroll_y=scroll_y;
2395 int offset = (scroll_delay_on ? 3 : 0);
2398 if (scroll_x!=JX-MIDPOSX && JX>=MIDPOSX-1 && JX<=lev_fieldx-MIDPOSX)
2399 scroll_x = JX-MIDPOSX;
2400 if (scroll_y!=JY-MIDPOSY && JY>=MIDPOSY-1 && JY<=lev_fieldy-MIDPOSY)
2401 scroll_y = JY-MIDPOSY;
2405 printf("(scroll_x, scroll_y, JX, JY) == (%d, %d, %d, %d)\n",
2406 scroll_x, scroll_y, JX, JY);
2409 if ((scroll_x < JX-MIDPOSX-offset || scroll_x > JX-MIDPOSX+offset) &&
2410 JX>=MIDPOSX-1-offset && JX<=lev_fieldx-(MIDPOSX-offset))
2411 scroll_x = JX-MIDPOSX + (scroll_x < JX-MIDPOSX ? -offset : offset);
2412 if ((scroll_y < JY-MIDPOSY-offset || scroll_y > JY-MIDPOSY+offset) &&
2413 JY>=MIDPOSY-1-offset && JY<=lev_fieldy-(MIDPOSY-offset))
2414 scroll_y = JY-MIDPOSY + (scroll_y < JY-MIDPOSY ? -offset : offset);
2416 if (scroll_x!=old_scroll_x || scroll_y!=old_scroll_y)
2417 ScrollLevel(old_scroll_x-scroll_x,old_scroll_y-scroll_y);
2419 if (Feld[JX][JY]==EL_LEERRAUM)
2420 DrawLevelElement(JX,JY,EL_SPIELFIGUR);
2422 DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR);
2425 TestIfHeroHitsBadThing();
2437 void TestIfHeroHitsBadThing()
2439 int i, killx = JX,killy = JY;
2440 static int xy[4][2] =
2447 static int harmless[4] =
2461 if (!IN_LEV_FIELD(x,y))
2464 element = Feld[x][y];
2466 if (DONT_TOUCH(element))
2468 if (MovDir[x][y]==harmless[i])
2477 if (killx!=JX || killy!=JY)
2481 void TestIfBadThingHitsHero()
2483 TestIfHeroHitsBadThing();
2486 void TestIfBadThingHitsOtherBadThing(int badx, int bady)
2488 int i, killx=badx, killy=bady;
2489 static int xy[4][2] =
2503 if (!IN_LEV_FIELD(x,y))
2507 if (IS_AMOEBOID(element) || element==EL_LIFE ||
2508 element==EL_AMOEBING || element==EL_TROPFEN)
2516 if (killx!=badx || killy!=bady)
2522 if (IS_PLAYER(-1,-1))
2525 if (IS_PFORTE(Feld[JX][JY]))
2526 Feld[JX][JY] = EL_LEERRAUM;
2528 PlaySoundLevel(JX,JY,SND_AUTSCH);
2529 PlaySoundLevel(JX,JY,SND_LACHEN);
2537 int DigField(int x, int y, int real_dx, int real_dy, int mode)
2539 int dx = x-JX, dy = y-JY;
2541 static long push_delay = 0;
2542 static int push_delay_value = 5;
2544 if (mode == DF_NO_PUSH)
2547 return(MF_NO_ACTION);
2551 return(MF_NO_ACTION);
2553 element = Feld[x][y];
2560 Feld[x][y] = EL_LEERRAUM;
2563 case EL_EDELSTEIN_BD:
2564 case EL_EDELSTEIN_GELB:
2565 case EL_EDELSTEIN_ROT:
2566 case EL_EDELSTEIN_LILA:
2567 Feld[x][y] = EL_LEERRAUM;
2568 MovDelay[x][y] = 0; /* wegen EDELSTEIN_BD-Funkeln! */
2571 RaiseScoreElement(EL_EDELSTEIN);
2572 DrawText(DX_EMERALDS,DY_EMERALDS,int2str(Gems,3),FS_SMALL,FC_YELLOW);
2573 PlaySoundLevel(x,y,SND_PONG);
2576 Feld[x][y] = EL_LEERRAUM;
2580 RaiseScoreElement(EL_DIAMANT);
2581 DrawText(DX_EMERALDS,DY_EMERALDS,int2str(Gems,3),FS_SMALL,FC_YELLOW);
2582 PlaySoundLevel(x,y,SND_PONG);
2584 case EL_DYNAMIT_AUS:
2585 Feld[x][y] = EL_LEERRAUM;
2587 RaiseScoreElement(EL_DYNAMIT);
2588 DrawText(DX_DYNAMITE,DY_DYNAMITE,int2str(Dynamite,3),FS_SMALL,FC_YELLOW);
2589 PlaySoundLevel(x,y,SND_PONG);
2591 case EL_DYNABOMB_NR:
2592 Feld[x][y] = EL_LEERRAUM;
2595 RaiseScoreElement(EL_DYNAMIT);
2596 PlaySoundLevel(x,y,SND_PONG);
2598 case EL_DYNABOMB_SZ:
2599 Feld[x][y] = EL_LEERRAUM;
2601 RaiseScoreElement(EL_DYNAMIT);
2602 PlaySoundLevel(x,y,SND_PONG);
2604 case EL_DYNABOMB_XL:
2605 Feld[x][y] = EL_LEERRAUM;
2607 RaiseScoreElement(EL_DYNAMIT);
2608 PlaySoundLevel(x,y,SND_PONG);
2610 case EL_SCHLUESSEL1:
2611 case EL_SCHLUESSEL2:
2612 case EL_SCHLUESSEL3:
2613 case EL_SCHLUESSEL4:
2615 int key_nr = element-EL_SCHLUESSEL1;
2617 Feld[x][y] = EL_LEERRAUM;
2619 RaiseScoreElement(EL_SCHLUESSEL);
2620 DrawMiniGraphicExtHiRes(drawto,gc,
2621 DX_KEYS+key_nr*MINI_TILEX,DY_KEYS,
2622 GFX_SCHLUESSEL1+key_nr);
2623 DrawMiniGraphicExtHiRes(window,gc,
2624 DX_KEYS+key_nr*MINI_TILEX,DY_KEYS,
2625 GFX_SCHLUESSEL1+key_nr);
2626 PlaySoundLevel(x,y,SND_PONG);
2630 Feld[x][y] = EL_ABLENK_EIN;
2633 DrawLevelField(x,y);
2636 case EL_FELSBROCKEN:
2641 return(MF_NO_ACTION);
2642 if (dy || !IN_LEV_FIELD(x+dx,y+dy) || Feld[x+dx][y+dy] != EL_LEERRAUM)
2643 return(MF_NO_ACTION);
2647 if (IN_LEV_FIELD(JX,JY+real_dy) && !IS_SOLID(Feld[JX][JY+real_dy]))
2648 return(MF_NO_ACTION);
2651 if (push_delay == 0)
2652 push_delay = FrameCounter;
2653 if (!FrameReached(&push_delay,push_delay_value) && !tape.playing)
2654 return(MF_NO_ACTION);
2656 Feld[x][y] = EL_LEERRAUM;
2657 Feld[x+dx][y+dy] = element;
2659 push_delay_value = 2+RND(8);
2661 DrawLevelField(x+dx,y+dy);
2662 if (element==EL_FELSBROCKEN)
2663 PlaySoundLevel(x+dx,y+dy,SND_PUSCH);
2664 else if (element==EL_KOKOSNUSS)
2665 PlaySoundLevel(x+dx,y+dy,SND_KNURK);
2667 PlaySoundLevel(x+dx,y+dy,SND_KLOPF);
2673 if (!Key[element-EL_PFORTE1])
2674 return(MF_NO_ACTION);
2680 if (!Key[element-EL_PFORTE1X])
2681 return(MF_NO_ACTION);
2684 case EL_AUSGANG_ACT:
2685 /* Tür ist (noch) nicht offen! */
2686 return(MF_NO_ACTION);
2688 case EL_AUSGANG_AUF:
2690 return(MF_NO_ACTION);
2691 LevelSolved = GameOver = TRUE;
2692 PlaySoundLevel(x,y,SND_BUING);
2695 Feld[x][y] = EL_BIRNE_EIN;
2697 DrawLevelField(x,y);
2698 PlaySoundLevel(x,y,SND_DENG);
2702 Feld[x][y] = EL_ZEIT_LEER;
2704 DrawText(DX_TIME,DY_TIME,int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
2705 DrawLevelField(x,y);
2706 PlaySoundStereo(SND_GONG,PSND_MAX_RIGHT);
2709 case EL_SOKOBAN_FELD_LEER:
2711 case EL_SOKOBAN_FELD_VOLL:
2712 case EL_SOKOBAN_OBJEKT:
2714 return(MF_NO_ACTION);
2715 if (!IN_LEV_FIELD(x+dx,y+dy)
2716 || (Feld[x+dx][y+dy] != EL_LEERRAUM
2717 && Feld[x+dx][y+dy] != EL_SOKOBAN_FELD_LEER))
2718 return(MF_NO_ACTION);
2722 if (IN_LEV_FIELD(JX,JY+real_dy) && !IS_SOLID(Feld[JX][JY+real_dy]))
2723 return(MF_NO_ACTION);
2725 else if (dy && real_dx)
2727 if (IN_LEV_FIELD(JX+real_dx,JY) && !IS_SOLID(Feld[JX+real_dx][JY]))
2728 return(MF_NO_ACTION);
2731 if (push_delay == 0)
2732 push_delay = FrameCounter;
2733 if (!FrameReached(&push_delay,push_delay_value) && !tape.playing)
2734 return(MF_NO_ACTION);
2736 if (element == EL_SOKOBAN_FELD_VOLL)
2738 Feld[x][y] = EL_SOKOBAN_FELD_LEER;
2742 Feld[x][y] = EL_LEERRAUM;
2744 if (Feld[x+dx][y+dy] == EL_SOKOBAN_FELD_LEER)
2746 Feld[x+dx][y+dy] = EL_SOKOBAN_FELD_VOLL;
2748 if (element == EL_SOKOBAN_OBJEKT)
2749 PlaySoundLevel(x,y,SND_DENG);
2752 Feld[x+dx][y+dy] = EL_SOKOBAN_OBJEKT;
2754 push_delay_value = 2;
2756 DrawLevelField(x,y);
2757 DrawLevelField(x+dx,y+dy);
2758 PlaySoundLevel(x+dx,y+dy,SND_PUSCH);
2760 if (SokobanFields == 0 && game_emulation == EMU_SOKOBAN)
2762 LevelSolved = GameOver = TRUE;
2763 PlaySoundLevel(x,y,SND_BUING);
2768 return(MF_NO_ACTION);
2777 BOOL SnapField(int dx, int dy)
2779 int x = JX+dx, y = JY+dy;
2780 static int snapped = FALSE;
2782 if (GameOver || !IN_LEV_FIELD(x,y))
2794 if (!DigField(x,y, 0,0, DF_SNAP))
2798 DrawLevelField(x,y);
2804 BOOL PlaceBomb(void)
2811 element = Feld[JX][JY];
2813 if ((Dynamite==0 && DynaBombsLeft==0) ||
2814 element==EL_DYNAMIT || element==EL_DYNABOMB || element==EL_EXPLODING)
2817 if (element!=EL_LEERRAUM)
2818 Store[JX][JY] = element;
2822 Feld[JX][JY] = EL_DYNAMIT;
2823 MovDelay[JX][JY] = 48;
2825 DrawText(DX_DYNAMITE,DY_DYNAMITE,int2str(Dynamite,3),FS_SMALL,FC_YELLOW);
2826 DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_DYNAMIT);
2830 Feld[JX][JY] = EL_DYNABOMB;
2831 MovDelay[JX][JY] = 48;
2833 DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_DYNABOMB);
2839 void PlaySoundLevel(int x, int y, int sound_nr)
2841 int sx = SCROLLX(x), sy = SCROLLY(y);
2844 if ((!sound_simple_on && !IS_LOOP_SOUND(sound_nr)) ||
2845 (!sound_loops_on && IS_LOOP_SOUND(sound_nr)))
2848 if (!IN_LEV_FIELD(x,y))
2851 volume = PSND_MAX_VOLUME;
2852 stereo = (sx-SCR_FIELDX/2)*12;
2854 if (!IN_SCR_FIELD(sx,sy))
2856 if (sx<0 || sx>=SCR_FIELDX)
2857 volume = PSND_MAX_VOLUME - 2*ABS(sx-SCR_FIELDX/2);
2859 volume = PSND_MAX_VOLUME - 2*ABS(sy-SCR_FIELDY/2);
2862 PlaySoundExt(sound_nr, volume, stereo, PSND_NO_LOOP);
2865 void RaiseScore(int value)
2868 DrawText(DX_SCORE,DY_SCORE,int2str(Score,5),FS_SMALL,FC_YELLOW);
2872 void RaiseScoreElement(int element)
2877 RaiseScore(level.score[SC_EDELSTEIN]);
2880 RaiseScore(level.score[SC_DIAMANT]);
2884 RaiseScore(level.score[SC_KAEFER]);
2888 RaiseScore(level.score[SC_FLIEGER]);
2892 RaiseScore(level.score[SC_MAMPFER]);
2895 RaiseScore(level.score[SC_ZOMBIE]);
2898 RaiseScore(level.score[SC_PACMAN]);
2901 RaiseScore(level.score[SC_KOKOSNUSS]);
2904 RaiseScore(level.score[SC_DYNAMIT]);
2907 RaiseScore(level.score[SC_SCHLUESSEL]);