X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=4514b646f2ca304e1f51546cab27cd22dcf5a6dc;hb=0c2b6a7610933f9098ec233f7b4c2b52eac3535c;hp=fbaccc24f0d04bdff5a5f8a33fa7d002435dbd54;hpb=1d5a33fc89d071c8e8a242ff3b51258f1b6b0e1e;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index fbaccc24..4514b646 100644 --- a/src/game.c +++ b/src/game.c @@ -91,14 +91,6 @@ #define SC_SCHLUESSEL 9 #define SC_ZEITBONUS 10 -/* values for game_emulation */ -#define EMU_NONE 0 -#define EMU_BOULDERDASH 1 -#define EMU_SOKOBAN 2 - -/* to control special behaviour of certain game elements */ -int game_emulation = EMU_NONE; - @@ -176,6 +168,7 @@ static void InitField(int x, int y, boolean init_game) switch (Feld[x][y]) { case EL_SPIELFIGUR: + case EL_SP_MURPHY: if (init_game) Feld[x][y] = EL_SPIELER1; /* no break! */ @@ -260,6 +253,8 @@ static void InitField(int x, int y, boolean init_game) case EL_MAMPFER2: case EL_ROBOT: case EL_PACMAN: + case EL_SP_SNIKSNAK: + case EL_SP_ELECTRON: InitMovDir(x, y); break; @@ -298,6 +293,10 @@ static void InitField(int x, int y, boolean init_game) MovDir[x][y] = 1 << RND(4); break; + case EL_SP_EMPTY: + Feld[x][y] = EL_LEERRAUM; + break; + default: break; } @@ -308,6 +307,7 @@ void InitGame() int i, j, x, y; boolean emulate_bd = TRUE; /* unless non-BOULDERDASH elements found */ boolean emulate_sb = TRUE; /* unless non-SOKOBAN elements found */ + boolean emulate_sp = TRUE; /* unless non-SUPAPLEX elements found */ /* don't play tapes over network */ network_playing = (options.network && !tape.playing); @@ -383,12 +383,24 @@ void InitGame() MampferNr = 0; FrameCounter = 0; TimeFrames = 0; + TimePlayed = 0; TimeLeft = level.time; ScreenMovDir = MV_NO_MOVING; ScreenMovPos = 0; ScreenGfxPos = 0; + if (level.high_speed) + { + MoveSpeed = 4; + ScrollStepSize = TILEX/4; + } + else + { + MoveSpeed = 8; + ScrollStepSize = TILEX/8; + } + AllPlayersGone = FALSE; SiebAktiv = FALSE; SiebCount = 0; @@ -410,14 +422,19 @@ void InitGame() } } - for(y=0; yjx >= MIDPOSX-1) - scroll_x = (local_player->jx <= lev_fieldx-MIDPOSX ? + if (lev_fieldx < SCR_FIELDX) + SBX_Left = SBX_Right = -1 * (SCR_FIELDX - lev_fieldx) / 2; + + if (lev_fieldy < SCR_FIELDY) + SBY_Upper = SBY_Lower = -1 * (SCR_FIELDY - lev_fieldy) / 2; + + scroll_x = SBX_Left; + scroll_y = SBY_Upper; + if (local_player->jx >= SBX_Left + MIDPOSX) + scroll_x = (local_player->jx <= SBX_Right + MIDPOSX ? local_player->jx - MIDPOSX : - lev_fieldx - SCR_FIELDX + 1); - if (local_player->jy >= MIDPOSY-1) - scroll_y = (local_player->jy <= lev_fieldy-MIDPOSY ? + SBX_Right); + if (local_player->jy >= SBY_Upper + MIDPOSY) + scroll_y = (local_player->jy <= SBY_Lower + MIDPOSY ? local_player->jy - MIDPOSY : - lev_fieldy - SCR_FIELDY + 1); + SBY_Lower); CloseDoor(DOOR_CLOSE_1); @@ -564,7 +607,7 @@ void InitGame() DOOR_GFX_PAGEX1 + GAME_CONTROL_XPOS, DOOR_GFX_PAGEY1 + GAME_CONTROL_YPOS); - OpenDoor(DOOR_OPEN_1); + OpenDoor(DOOR_OPEN_ALL); if (setup.sound_music) PlaySoundLoop(background_loop[level_nr % num_bg_loops]); @@ -604,6 +647,7 @@ void InitMovDir(int x, int y) Feld[x][y] = EL_KAEFER; MovDir[x][y] = direction[0][element - EL_KAEFER_R]; break; + case EL_FLIEGER_R: case EL_FLIEGER_O: case EL_FLIEGER_L: @@ -611,6 +655,7 @@ void InitMovDir(int x, int y) Feld[x][y] = EL_FLIEGER; MovDir[x][y] = direction[0][element - EL_FLIEGER_R]; break; + case EL_BUTTERFLY_R: case EL_BUTTERFLY_O: case EL_BUTTERFLY_L: @@ -618,6 +663,7 @@ void InitMovDir(int x, int y) Feld[x][y] = EL_BUTTERFLY; MovDir[x][y] = direction[0][element - EL_BUTTERFLY_R]; break; + case EL_FIREFLY_R: case EL_FIREFLY_O: case EL_FIREFLY_L: @@ -625,6 +671,7 @@ void InitMovDir(int x, int y) Feld[x][y] = EL_FIREFLY; MovDir[x][y] = direction[0][element - EL_FIREFLY_R]; break; + case EL_PACMAN_R: case EL_PACMAN_O: case EL_PACMAN_L: @@ -632,6 +679,15 @@ void InitMovDir(int x, int y) Feld[x][y] = EL_PACMAN; MovDir[x][y] = direction[0][element - EL_PACMAN_R]; break; + + case EL_SP_SNIKSNAK: + MovDir[x][y] = MV_UP; + break; + + case EL_SP_ELECTRON: + MovDir[x][y] = MV_LEFT; + break; + default: MovDir[x][y] = 1 << RND(4); if (element != EL_KAEFER && @@ -652,7 +708,8 @@ void InitMovDir(int x, int y) MovDir[x][y] = direction[0][i]; break; } - else if (element == EL_FLIEGER || element == EL_FIREFLY) + else if (element == EL_FLIEGER || element == EL_FIREFLY || + element == EL_SP_SNIKSNAK || element == EL_SP_ELECTRON) { MovDir[x][y] = direction[1][i]; break; @@ -704,7 +761,7 @@ void GameWon() { if (!setup.sound_loops) PlaySoundStereo(SND_SIRR, PSND_MAX_RIGHT); - if (TimeLeft && !(TimeLeft % 10)) + if (TimeLeft > 0 && !(TimeLeft % 10)) RaiseScore(level.score[SC_ZEITBONUS]); if (TimeLeft > 100 && !(TimeLeft % 10)) TimeLeft -= 10; @@ -718,6 +775,29 @@ void GameWon() if (setup.sound_loops) StopSound(SND_SIRR); } + else if (level.time == 0) /* level without time limit */ + { + if (setup.sound_loops) + PlaySoundExt(SND_SIRR, PSND_MAX_VOLUME, PSND_MAX_RIGHT, PSND_LOOP); + + while(TimePlayed < 999) + { + if (!setup.sound_loops) + PlaySoundStereo(SND_SIRR, PSND_MAX_RIGHT); + if (TimePlayed < 999 && !(TimePlayed % 10)) + RaiseScore(level.score[SC_ZEITBONUS]); + if (TimePlayed < 900 && !(TimePlayed % 10)) + TimePlayed += 10; + else + TimePlayed++; + DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FS_SMALL, FC_YELLOW); + BackToFront(); + Delay(10); + } + + if (setup.sound_loops) + StopSound(SND_SIRR); + } FadeSounds(); @@ -754,7 +834,7 @@ void GameWon() BackToFront(); } -boolean NewHiScore() +int NewHiScore() { int k, l; int position = -1; @@ -938,7 +1018,9 @@ void DrawDynamite(int x, int y) phase = 7 - phase; } - if (Store[x][y]) + if (game_emulation == EMU_SUPAPLEX) + DrawGraphic(sx, sy, GFX_SP_DISK_RED); + else if (Store[x][y]) DrawGraphicThruMask(sx, sy, graphic + phase); else DrawGraphic(sx, sy, graphic + phase); @@ -994,7 +1076,7 @@ void Explode(int ex, int ey, int phase, int mode) RemoveMovingField(x, y); } - if (!IN_LEV_FIELD(x, y) || IS_MASSIV(element) || element == EL_BURNING) + if (!IN_LEV_FIELD(x, y) || IS_MASSIVE(element) || element == EL_BURNING) continue; if ((mode!=EX_NORMAL || center_element == EL_AMOEBA2DIAM) && @@ -1022,6 +1104,9 @@ void Explode(int ex, int ey, int phase, int mode) Store[x][y] = EL_EDELSTEIN_GELB; break; } + + if (game_emulation == EMU_SUPAPLEX) + Store[x][y] = EL_LEERRAUM; } else if (center_element == EL_MAULWURF) Store[x][y] = EL_EDELSTEIN_ROT; @@ -1031,6 +1116,8 @@ void Explode(int ex, int ey, int phase, int mode) Store[x][y] = ((x == ex && y == ey) ? EL_DIAMANT : EL_EDELSTEIN); else if (center_element == EL_BUTTERFLY) Store[x][y] = EL_EDELSTEIN_BD; + else if (center_element == EL_SP_ELECTRON) + Store[x][y] = EL_SP_INFOTRON; else if (center_element == EL_MAMPFER) Store[x][y] = level.mampfer_inhalt[MampferNr][x-ex+1][y-ey+1]; else if (center_element == EL_AMOEBA2DIAM) @@ -1112,12 +1199,19 @@ void Explode(int ex, int ey, int phase, int mode) InitMovDir(x, y); DrawLevelField(x, y); } - else if (!(phase%delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y))) + else if (!(phase % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y))) { + int graphic = GFX_EXPLOSION; + + if (game_emulation == EMU_SUPAPLEX) + graphic = (Store[x][y] == EL_SP_INFOTRON ? + GFX_SP_EXPLODE_INFOTRON : + GFX_SP_EXPLODE_EMPTY); + if (phase == delay) ErdreichAnbroeckeln(SCREENX(x), SCREENY(y)); - DrawGraphic(SCREENX(x), SCREENY(y), GFX_EXPLOSION+(phase/delay-1)); + DrawGraphic(SCREENX(x), SCREENY(y), graphic + (phase / delay - 1)); } } @@ -1145,7 +1239,7 @@ void DynaExplode(int ex, int ey) int y = ey+j*xy[i%4][1]; int element; - if (!IN_LEV_FIELD(x, y) || IS_MASSIV(Feld[x][y])) + if (!IN_LEV_FIELD(x, y) || IS_MASSIVE(Feld[x][y])) break; element = Feld[x][y]; @@ -1166,7 +1260,10 @@ void Bang(int x, int y) { int element = Feld[x][y]; - PlaySoundLevel(x, y, SND_ROAAAR); + if (game_emulation == EMU_SUPAPLEX) + PlaySoundLevel(x, y, SND_SP_BOOOM); + else + PlaySoundLevel(x, y, SND_ROAAAR); if (IS_PLAYER(x, y)) /* remove objects that might cause smaller explosion */ element = EL_LEERRAUM; @@ -1269,7 +1366,8 @@ void Impact(int x, int y) return; } - if (element == EL_BOMBE && (lastline || object_hit)) /* element is bomb */ + if ((element == EL_BOMBE || element == EL_SP_DISK_ORANGE) && + (lastline || object_hit)) /* element is bomb */ { Bang(x, y); return; @@ -1327,10 +1425,11 @@ void Impact(int x, int y) return; } } - else if (element == EL_FELSBROCKEN) + else if (element == EL_FELSBROCKEN || element == EL_SP_ZONK) { - if (IS_ENEMY(smashed) || smashed == EL_BOMBE || smashed == EL_SONDE || - smashed == EL_SCHWEIN || smashed == EL_DRACHE) + if (IS_ENEMY(smashed) || + smashed == EL_BOMBE || smashed == EL_SP_DISK_ORANGE || + smashed == EL_SONDE || smashed == EL_SCHWEIN || smashed == EL_DRACHE) { Bang(x, y+1); return; @@ -1380,6 +1479,7 @@ void Impact(int x, int y) case EL_EDELSTEIN_ROT: case EL_EDELSTEIN_LILA: case EL_DIAMANT: + case EL_SP_INFOTRON: sound = SND_PLING; break; case EL_KOKOSNUSS: @@ -1388,6 +1488,9 @@ void Impact(int x, int y) case EL_FELSBROCKEN: sound = SND_KLOPF; break; + case EL_SP_ZONK: + sound = SND_SP_ZONKDOWN; + break; case EL_SCHLUESSEL: case EL_SCHLUESSEL1: case EL_SCHLUESSEL2: @@ -1469,7 +1572,8 @@ void TurnRound(int x, int y) else if (element == EL_BUTTERFLY) /* && MovDir[x][y] == left_dir) */ MovDelay[x][y] = 1; } - else if (element == EL_FLIEGER || element == EL_FIREFLY) + else if (element == EL_FLIEGER || element == EL_FIREFLY || + element == EL_SP_SNIKSNAK || element == EL_SP_ELECTRON) { TestIfBadThingHitsOtherBadThing(x, y); @@ -1480,7 +1584,9 @@ void TurnRound(int x, int y) !IS_FREE_OR_PLAYER(move_x, move_y)) MovDir[x][y] = right_dir; - if (element == EL_FLIEGER && MovDir[x][y] != old_move_dir) + if ((element == EL_FLIEGER || + element == EL_SP_SNIKSNAK || element == EL_SP_ELECTRON) + && MovDir[x][y] != old_move_dir) MovDelay[x][y] = 9; else if (element == EL_FIREFLY) /* && MovDir[x][y] == right_dir) */ MovDelay[x][y] = 1; @@ -1958,7 +2064,9 @@ void StartMoving(int x, int y) if (element!=EL_MAMPFER && element!=EL_MAMPFER2 && element!=EL_PACMAN) { TurnRound(x, y); - if (MovDelay[x][y] && (element == EL_KAEFER || element == EL_FLIEGER)) + if (MovDelay[x][y] && (element == EL_KAEFER || element == EL_FLIEGER || + element == EL_SP_SNIKSNAK || + element == EL_SP_ELECTRON)) DrawLevelField(x, y); } } @@ -1967,8 +2075,8 @@ void StartMoving(int x, int y) { MovDelay[x][y]--; - if (element == EL_ROBOT || element == EL_MAMPFER || - element == EL_MAMPFER2) + if (element == EL_ROBOT || + element == EL_MAMPFER || element == EL_MAMPFER2) { int phase = MovDelay[x][y] % 8; @@ -1982,6 +2090,8 @@ void StartMoving(int x, int y) && MovDelay[x][y]%4 == 3) PlaySoundLevel(x, y, SND_NJAM); } + else if (element == EL_SP_ELECTRON) + DrawGraphicAnimation(x, y, GFX2_SP_ELECTRON, 8, 2, ANIM_NORMAL); else if (element == EL_DRACHE) { int i; @@ -2203,12 +2313,15 @@ void StartMoving(int x, int y) TurnRound(x, y); - if (element == EL_KAEFER || element == EL_FLIEGER) + if (element == EL_KAEFER || element == EL_FLIEGER || + element == EL_SP_SNIKSNAK) DrawLevelField(x, y); else if (element == EL_BUTTERFLY || element == EL_FIREFLY) DrawGraphicAnimation(x, y, el2gfx(element), 2, 4, ANIM_NORMAL); else if (element == EL_SONDE) DrawGraphicAnimation(x, y, GFX_SONDE_START, 8, 2, ANIM_NORMAL); + else if (element == EL_SP_ELECTRON) + DrawGraphicAnimation(x, y, GFX2_SP_ELECTRON, 8, 2, ANIM_NORMAL); return; } @@ -2233,7 +2346,7 @@ void ContinueMoving(int x, int y) int newx = x + dx, newy = y + dy; int step = (horiz_move ? dx : dy) * TILEX/8; - if (CAN_FALL(element) && horiz_move) + if (CAN_FALL(element) && horiz_move && !IS_SP_ELEMENT(element)) step*=2; else if (element == EL_TROPFEN) step/=2; @@ -2596,7 +2709,7 @@ void AmoebeAbleger(int ax, int ay) if (newax == ax && neway == ay) /* amoeba cannot grow */ { - if (i == 4 && !waiting_for_player) + if (i == 4 && (!waiting_for_player || game_emulation == EMU_BOULDERDASH)) { Feld[ax][ay] = EL_AMOEBE_TOT; DrawLevelField(ax, ay); @@ -3093,6 +3206,68 @@ void CheckForDragon(int x, int y) } } +static void CheckBuggyBase(int x, int y) +{ + int element = Feld[x][y]; + + if (element == EL_SP_BUG) + { + if (!MovDelay[x][y]) /* start activating buggy base */ + MovDelay[x][y] = 2 * FRAMES_PER_SECOND + RND(5 * FRAMES_PER_SECOND); + + if (MovDelay[x][y]) /* wait some time before activating base */ + { + MovDelay[x][y]--; + if (MovDelay[x][y] < 5 && IN_SCR_FIELD(SCREENX(x), SCREENY(y))) + DrawGraphic(SCREENX(x), SCREENY(y), GFX_SP_BUG_WARNING); + if (MovDelay[x][y]) + return; + + Feld[x][y] = EL_SP_BUG_ACTIVE; + } + } + else if (element == EL_SP_BUG_ACTIVE) + { + if (!MovDelay[x][y]) /* start activating buggy base */ + MovDelay[x][y] = 1 * FRAMES_PER_SECOND + RND(1 * FRAMES_PER_SECOND); + + if (MovDelay[x][y]) /* wait some time before activating base */ + { + MovDelay[x][y]--; + if (MovDelay[x][y]) + { + int i; + static int xy[4][2] = + { + { 0, -1 }, + { -1, 0 }, + { +1, 0 }, + { 0, +1 } + }; + + if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) + DrawGraphic(SCREENX(x),SCREENY(y), GFX_SP_BUG_ACTIVE + SimpleRND(4)); + + for (i=0; i<4; i++) + { + int xx = x + xy[i][0], yy = y + xy[i][1]; + + if (IS_PLAYER(xx, yy)) + { + PlaySoundLevel(x, y, SND_SP_BUG); + break; + } + } + + return; + } + + Feld[x][y] = EL_SP_BUG; + DrawLevelField(x, y); + } + } +} + static void PlayerActions(struct PlayerInfo *player, byte player_action) { static byte stored_player_action[MAX_PLAYERS]; @@ -3336,9 +3511,9 @@ void GameActions() extern unsigned int last_RND(); printf("DEBUG: %03d last RND was %d \t [state checksum is %d]\n", - level.time - TimeLeft, + TimePlayed, last_RND(), - getStateCheckSum(level.time - TimeLeft)); + getStateCheckSum(TimePlayed)); } */ #endif @@ -3431,6 +3606,12 @@ void GameActions() MauerAbleger(x, y); else if (element == EL_BURNING) CheckForDragon(x, y); + else if (element == EL_SP_BUG || element == EL_SP_BUG_ACTIVE) + CheckBuggyBase(x, y); + else if (element == EL_SP_TERMINAL) + DrawGraphicAnimation(x, y, GFX2_SP_TERMINAL, 7, 12, ANIM_NORMAL); + else if (element == EL_SP_TERMINAL_ACTIVE) + DrawGraphicAnimation(x, y, GFX2_SP_TERMINAL_ACTIVE, 7, 4, ANIM_NORMAL); if (SiebAktiv) { @@ -3489,22 +3670,29 @@ void GameActions() } } - if (TimeLeft > 0 && TimeFrames >= (1000 / GameFrameDelay) && !tape.pausing) + if (TimeFrames >= (1000 / GameFrameDelay) && !tape.pausing) { TimeFrames = 0; - TimeLeft--; + TimePlayed++; if (tape.recording || tape.playing) - DrawVideoDisplay(VIDEO_STATE_TIME_ON, level.time-TimeLeft); + DrawVideoDisplay(VIDEO_STATE_TIME_ON, TimePlayed); - if (TimeLeft<=10) - PlaySoundStereo(SND_GONG, PSND_MAX_RIGHT); + if (TimeLeft > 0) + { + TimeLeft--; - DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW); + if (TimeLeft <= 10) + PlaySoundStereo(SND_GONG, PSND_MAX_RIGHT); - if (!TimeLeft) - for (i=0; iMovDir == MV_LEFT && scroll_x > jx-MIDPOSX+offset) || - (player->MovDir == MV_RIGHT && scroll_x < jx-MIDPOSX-offset)) + if ((player->MovDir == MV_LEFT && scroll_x > jx - MIDPOSX + offset) || + (player->MovDir == MV_RIGHT && scroll_x < jx - MIDPOSX - offset)) scroll_x = jx-MIDPOSX + (scroll_x < jx-MIDPOSX ? -offset : +offset); /* don't scroll over playfield boundaries */ - if (scroll_x < -1 || scroll_x > lev_fieldx - SCR_FIELDX + 1) - scroll_x = (scroll_x < -1 ? -1 : lev_fieldx - SCR_FIELDX + 1); + if (scroll_x < SBX_Left || scroll_x > SBX_Right) + scroll_x = (scroll_x < SBX_Left ? SBX_Left : SBX_Right); /* don't scroll more than one field at a time */ scroll_x = old_scroll_x + SIGN(scroll_x - old_scroll_x); @@ -3726,13 +3914,13 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy) } else /* player has moved vertically */ { - if ((player->MovDir == MV_UP && scroll_y > jy-MIDPOSY+offset) || - (player->MovDir == MV_DOWN && scroll_y < jy-MIDPOSY-offset)) + if ((player->MovDir == MV_UP && scroll_y > jy - MIDPOSY + offset) || + (player->MovDir == MV_DOWN && scroll_y < jy - MIDPOSY - offset)) scroll_y = jy-MIDPOSY + (scroll_y < jy-MIDPOSY ? -offset : +offset); /* don't scroll over playfield boundaries */ - if (scroll_y < -1 || scroll_y > lev_fieldy - SCR_FIELDY + 1) - scroll_y = (scroll_y < -1 ? -1 : lev_fieldy - SCR_FIELDY + 1); + if (scroll_y < SBY_Upper || scroll_y > SBY_Lower) + scroll_y = (scroll_y < SBY_Upper ? SBY_Upper : SBY_Lower); /* don't scroll more than one field at a time */ scroll_y = old_scroll_y + SIGN(scroll_y - old_scroll_y); @@ -4085,10 +4273,18 @@ int DigField(struct PlayerInfo *player, switch(element) { case EL_LEERRAUM: + PlaySoundLevel(x, y, SND_EMPTY); break; case EL_ERDREICH: Feld[x][y] = EL_LEERRAUM; + PlaySoundLevel(x, y, SND_SCHLURF); + break; + + case EL_SP_BASE: + case EL_SP_BUG: + Feld[x][y] = EL_LEERRAUM; + PlaySoundLevel(x, y, SND_SP_BASE); break; case EL_EDELSTEIN: @@ -4106,17 +4302,31 @@ int DigField(struct PlayerInfo *player, DrawText(DX_EMERALDS, DY_EMERALDS, int2str(local_player->gems_still_needed, 3), FS_SMALL, FC_YELLOW); + if (element == EL_SP_INFOTRON) + PlaySoundLevel(x, y, SND_SP_INFOTRON); + else + PlaySoundLevel(x, y, SND_PONG); + break; + + case EL_SPEED_PILL: + RemoveField(x, y); + MoveSpeed = 4; + ScrollStepSize = TILEX/4; PlaySoundLevel(x, y, SND_PONG); break; case EL_DYNAMIT_AUS: + case EL_SP_DISK_RED: RemoveField(x, y); player->dynamite++; RaiseScoreElement(EL_DYNAMIT); DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->dynamite, 3), FS_SMALL, FC_YELLOW); - PlaySoundLevel(x, y, SND_PONG); + if (element == EL_SP_DISK_RED) + PlaySoundLevel(x, y, SND_SP_INFOTRON); + else + PlaySoundLevel(x, y, SND_PONG); break; case EL_DYNABOMB_NR: @@ -4169,10 +4379,39 @@ int DigField(struct PlayerInfo *player, return MF_ACTION; break; + case EL_SP_TERMINAL: + { + int xx, yy; + + for (yy=0; yygems_still_needed > 0) + return MF_NO_ACTION; + + player->LevelSolved = player->GameOver = TRUE; + PlaySoundStereo(SND_SP_EXIT, PSND_MAX_RIGHT); + break; + case EL_FELSBROCKEN: case EL_BOMBE: case EL_KOKOSNUSS: case EL_ZEIT_LEER: + case EL_SP_ZONK: + case EL_SP_DISK_ORANGE: if (dy || mode == DF_SNAP) return MF_NO_ACTION; @@ -4203,6 +4442,8 @@ int DigField(struct PlayerInfo *player, PlaySoundLevel(x+dx, y+dy, SND_PUSCH); else if (element == EL_KOKOSNUSS) PlaySoundLevel(x+dx, y+dy, SND_KNURK); + else if (IS_SP_ELEMENT(element)) + PlaySoundLevel(x+dx, y+dy, SND_SP_ZONKPUSH); else PlaySoundLevel(x+dx, y+dy, SND_KLOPF); break; @@ -4223,6 +4464,42 @@ int DigField(struct PlayerInfo *player, return MF_NO_ACTION; break; + case EL_SP_PORT1_LEFT: + case EL_SP_PORT2_LEFT: + case EL_SP_PORT1_RIGHT: + case EL_SP_PORT2_RIGHT: + case EL_SP_PORT1_UP: + case EL_SP_PORT2_UP: + case EL_SP_PORT1_DOWN: + case EL_SP_PORT2_DOWN: + case EL_SP_PORT_X: + case EL_SP_PORT_Y: + case EL_SP_PORT_XY: + if ((dx == -1 && + element != EL_SP_PORT1_LEFT && + element != EL_SP_PORT2_LEFT && + element != EL_SP_PORT_X && + element != EL_SP_PORT_XY) || + (dx == +1 && + element != EL_SP_PORT1_RIGHT && + element != EL_SP_PORT2_RIGHT && + element != EL_SP_PORT_X && + element != EL_SP_PORT_XY) || + (dy == -1 && + element != EL_SP_PORT1_UP && + element != EL_SP_PORT2_UP && + element != EL_SP_PORT_Y && + element != EL_SP_PORT_XY) || + (dy == +1 && + element != EL_SP_PORT1_DOWN && + element != EL_SP_PORT2_DOWN && + element != EL_SP_PORT_Y && + element != EL_SP_PORT_XY) || + !IN_LEV_FIELD(x + dx, y + dy) || + !IS_FREE(x + dx, y + dy)) + return MF_NO_ACTION; + break; + case EL_AUSGANG_ZU: case EL_AUSGANG_ACT: /* door is not (yet) open */ @@ -4268,6 +4545,7 @@ int DigField(struct PlayerInfo *player, case EL_SOKOBAN_FELD_VOLL: case EL_SOKOBAN_OBJEKT: case EL_SONDE: + case EL_SP_DISK_YELLOW: if (mode == DF_SNAP) return MF_NO_ACTION; @@ -4345,12 +4623,7 @@ int DigField(struct PlayerInfo *player, break; default: - if (IS_EATABLE(element)) /* other kinds of 'dirt' */ - Feld[x][y] = EL_LEERRAUM; - else - return MF_NO_ACTION; - - break; + return MF_NO_ACTION; } player->push_delay = 0; @@ -4419,7 +4692,12 @@ boolean PlaceBomb(struct PlayerInfo *player) DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->dynamite, 3), FS_SMALL, FC_YELLOW); if (IN_SCR_FIELD(SCREENX(jx), SCREENY(jy))) - DrawGraphicThruMask(SCREENX(jx), SCREENY(jy), GFX_DYNAMIT); + { + if (game_emulation == EMU_SUPAPLEX) + DrawGraphic(SCREENX(jx), SCREENY(jy), GFX_SP_DISK_RED); + else + DrawGraphicThruMask(SCREENX(jx), SCREENY(jy), GFX_DYNAMIT); + } } else {