X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fgame.c;h=fada15db70f1733e76a78b67ac8cfdfea807e05f;hp=e9f9d041c82b9475046f91eb1b1d7560e27b2006;hb=3ae3dff29ac1a6022b1e5af414ba2c99391148c8;hpb=4f767d54c7ac468e9a42e22caf716111be1ceba9 diff --git a/src/game.c b/src/game.c index e9f9d041..fada15db 100644 --- a/src/game.c +++ b/src/game.c @@ -91,13 +91,21 @@ #define SC_SCHLUESSEL 9 #define SC_ZEITBONUS 10 -/* values for game_emulation */ -#define EMU_NONE 0 -#define EMU_BOULDERDASH 1 -#define EMU_SOKOBAN 2 +/* game button identifiers */ +#define GAME_CTRL_ID_STOP 0 +#define GAME_CTRL_ID_PAUSE 1 +#define GAME_CTRL_ID_PLAY 2 +#define SOUND_CTRL_ID_MUSIC 3 +#define SOUND_CTRL_ID_LOOPS 4 +#define SOUND_CTRL_ID_SIMPLE 5 -/* to control special behaviour of certain game elements */ -int game_emulation = EMU_NONE; +#define NUM_GAME_BUTTONS 6 + +/* forward declaration for internal use */ +static void MapGameButtons(); +static void HandleGameButtons(struct GadgetInfo *); + +static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS]; @@ -153,6 +161,7 @@ static unsigned int getStateCheckSum(int counter) + void GetPlayerConfig() { if (sound_status == SOUND_OFF) @@ -169,11 +178,151 @@ void GetPlayerConfig() InitJoysticks(); } +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! */ + case EL_SPIELER1: + case EL_SPIELER2: + case EL_SPIELER3: + case EL_SPIELER4: + if (init_game) + { + struct PlayerInfo *player = &stored_player[Feld[x][y] - EL_SPIELER1]; + int jx = player->jx, jy = player->jy; + + player->present = TRUE; + + /* + if (!network_playing || player->connected) + */ + + if (!options.network || player->connected) + { + player->active = TRUE; + + /* remove potentially duplicate players */ + if (StorePlayer[jx][jy] == Feld[x][y]) + StorePlayer[jx][jy] = 0; + + StorePlayer[x][y] = Feld[x][y]; + + if (options.verbose) + { + printf("Player %d activated.\n", player->element_nr); + printf("[Local player is %d and currently %s.]\n", + local_player->element_nr, + local_player->active ? "active" : "not active"); + } + } + + Feld[x][y] = EL_LEERRAUM; + player->jx = player->last_jx = x; + player->jy = player->last_jy = y; + } + break; + + case EL_BADEWANNE: + if (x < lev_fieldx-1 && Feld[x+1][y] == EL_SALZSAEURE) + Feld[x][y] = EL_BADEWANNE1; + else if (x > 0 && Feld[x-1][y] == EL_SALZSAEURE) + Feld[x][y] = EL_BADEWANNE2; + else if (y > 0 && Feld[x][y-1] == EL_BADEWANNE1) + Feld[x][y] = EL_BADEWANNE3; + else if (y > 0 && Feld[x][y-1] == EL_SALZSAEURE) + Feld[x][y] = EL_BADEWANNE4; + else if (y > 0 && Feld[x][y-1] == EL_BADEWANNE2) + Feld[x][y] = EL_BADEWANNE5; + break; + + case EL_KAEFER_R: + case EL_KAEFER_O: + case EL_KAEFER_L: + case EL_KAEFER_U: + case EL_KAEFER: + case EL_FLIEGER_R: + case EL_FLIEGER_O: + case EL_FLIEGER_L: + case EL_FLIEGER_U: + case EL_FLIEGER: + case EL_BUTTERFLY_R: + case EL_BUTTERFLY_O: + case EL_BUTTERFLY_L: + case EL_BUTTERFLY_U: + case EL_BUTTERFLY: + case EL_FIREFLY_R: + case EL_FIREFLY_O: + case EL_FIREFLY_L: + case EL_FIREFLY_U: + case EL_FIREFLY: + case EL_PACMAN_R: + case EL_PACMAN_O: + case EL_PACMAN_L: + case EL_PACMAN_U: + case EL_MAMPFER: + case EL_MAMPFER2: + case EL_ROBOT: + case EL_PACMAN: + case EL_SP_SNIKSNAK: + case EL_SP_ELECTRON: + InitMovDir(x, y); + break; + + case EL_AMOEBE_VOLL: + case EL_AMOEBE_BD: + InitAmoebaNr(x, y); + break; + + case EL_TROPFEN: + if (y == lev_fieldy - 1) + { + Feld[x][y] = EL_AMOEBING; + Store[x][y] = EL_AMOEBE_NASS; + } + break; + + case EL_DYNAMIT: + MovDelay[x][y] = 96; + break; + + case EL_BIRNE_AUS: + local_player->lights_still_needed++; + break; + + case EL_SOKOBAN_FELD_LEER: + local_player->sokobanfields_still_needed++; + break; + + case EL_MAULWURF: + case EL_PINGUIN: + local_player->friends_still_needed++; + break; + + case EL_SCHWEIN: + case EL_DRACHE: + MovDir[x][y] = 1 << RND(4); + break; + + case EL_SP_EMPTY: + Feld[x][y] = EL_LEERRAUM; + break; + + default: + break; + } +} + 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); @@ -238,22 +387,30 @@ void InitGame() network_player_action_received = FALSE; +#ifndef MSDOS /* initial null action */ if (network_playing) SendToServer_MovePlayer(MV_NO_MOVING); +#endif ZX = ZY = -1; MampferNr = 0; FrameCounter = 0; TimeFrames = 0; + TimePlayed = 0; TimeLeft = level.time; ScreenMovDir = MV_NO_MOVING; ScreenMovPos = 0; ScreenGfxPos = 0; - AllPlayersGone = SiebAktiv = FALSE; + MoveSpeed = (level.double_speed ? 4 : 8); + ScrollStepSize = TILEX / MoveSpeed; + + AllPlayersGone = FALSE; + SiebAktiv = FALSE; + SiebCount = 0; for (i=0; ijx, jy = player->jy; - - player->present = TRUE; - - /* - if (!network_playing || player->connected) - */ - - if (!options.network || player->connected) - { - player->active = TRUE; - - /* remove potentially duplicate players */ - if (StorePlayer[jx][jy] == Feld[x][y]) - StorePlayer[jx][jy] = 0; - - StorePlayer[x][y] = Feld[x][y]; - - if (options.verbose) - { - printf("Player %d activated.\n", player->element_nr); - printf("[Local player is %d and currently %s.]\n", - local_player->element_nr, - local_player->active ? "active" : "not active"); - } - } - - Feld[x][y] = EL_LEERRAUM; - player->jx = player->last_jx = x; - player->jy = player->last_jy = y; - - break; - } - case EL_BADEWANNE: - if (x < lev_fieldx-1 && Feld[x+1][y] == EL_SALZSAEURE) - Feld[x][y] = EL_BADEWANNE1; - else if (x > 0 && Feld[x-1][y] == EL_SALZSAEURE) - Feld[x][y] = EL_BADEWANNE2; - else if (y > 0 && Feld[x][y-1] == EL_BADEWANNE1) - Feld[x][y] = EL_BADEWANNE3; - else if (y > 0 && Feld[x][y-1] == EL_SALZSAEURE) - Feld[x][y] = EL_BADEWANNE4; - else if (y > 0 && Feld[x][y-1] == EL_BADEWANNE2) - Feld[x][y] = EL_BADEWANNE5; - break; - case EL_KAEFER_R: - case EL_KAEFER_O: - case EL_KAEFER_L: - case EL_KAEFER_U: - case EL_KAEFER: - case EL_FLIEGER_R: - case EL_FLIEGER_O: - case EL_FLIEGER_L: - case EL_FLIEGER_U: - case EL_FLIEGER: - case EL_BUTTERFLY_R: - case EL_BUTTERFLY_O: - case EL_BUTTERFLY_L: - case EL_BUTTERFLY_U: - case EL_BUTTERFLY: - case EL_FIREFLY_R: - case EL_FIREFLY_O: - case EL_FIREFLY_L: - case EL_FIREFLY_U: - case EL_FIREFLY: - case EL_PACMAN_R: - case EL_PACMAN_O: - case EL_PACMAN_L: - case EL_PACMAN_U: - case EL_MAMPFER: - case EL_MAMPFER2: - case EL_ROBOT: - case EL_PACMAN: - InitMovDir(x, y); - break; - case EL_AMOEBE_VOLL: - case EL_AMOEBE_BD: - InitAmoebaNr(x, y); - break; - case EL_TROPFEN: - if (y == lev_fieldy - 1) - { - Feld[x][y] = EL_AMOEBING; - Store[x][y] = EL_AMOEBE_NASS; - } - break; - case EL_DYNAMIT: - MovDelay[x][y] = 96; - break; - case EL_BIRNE_AUS: - local_player->lights_still_needed++; - break; - case EL_SOKOBAN_FELD_LEER: - local_player->sokobanfields_still_needed++; - break; - case EL_MAULWURF: - case EL_PINGUIN: - local_player->friends_still_needed++; - break; - case EL_SCHWEIN: - case EL_DRACHE: - MovDir[x][y] = 1 << RND(4); - break; - default: - break; + if (emulate_bd && !IS_BD_ELEMENT(Feld[x][y])) + emulate_bd = FALSE; + if (emulate_sb && !IS_SB_ELEMENT(Feld[x][y])) + emulate_sb = FALSE; + if (emulate_sp && !IS_SP_ELEMENT(Feld[x][y])) + emulate_sp = FALSE; + + InitField(x, y, TRUE); } } @@ -427,20 +473,38 @@ void InitGame() } } - /* when in single player mode, eliminate all but the first active player */ - if (!options.network && !setup.team_mode) + if (tape.playing) { + /* when playing a tape, eliminate all players who do not participate */ + + for (i=0; ijx, jy = player->jy; + + player->active = FALSE; + StorePlayer[jx][jy] = 0; + Feld[jx][jy] = EL_LEERRAUM; + } + } + } + else if (!options.network && !setup.team_mode) /* && !tape.playing */ + { + /* when in single player mode, eliminate all but the first active player */ + for (i=0; ijx, jy = player->jy; - - if (player->active) + if (stored_player[j].active) { + struct PlayerInfo *player = &stored_player[j]; + int jx = player->jx, jy = player->jy; + player->active = FALSE; StorePlayer[jx][jy] = 0; Feld[jx][jy] = EL_LEERRAUM; @@ -450,6 +514,14 @@ void InitGame() } } + /* when recording the game, store which players take part in the game */ + if (tape.recording) + { + for (i=0; ijx >= MIDPOSX-1) - scroll_x = (local_player->jx <= lev_fieldx-MIDPOSX ? + if (BorderElement == EL_LEERRAUM) + { + SBX_Left = 0; + SBX_Right = lev_fieldx - SCR_FIELDX; + SBY_Upper = 0; + SBY_Lower = lev_fieldy - SCR_FIELDY; + } + else + { + SBX_Left = -1; + SBX_Right = lev_fieldx - SCR_FIELDX + 1; + SBY_Upper = -1; + SBY_Lower = lev_fieldy - SCR_FIELDY + 1; + } + + if (lev_fieldx + (SBX_Left == -1 ? 2 : 0) <= SCR_FIELDX) + SBX_Left = SBX_Right = -1 * (SCR_FIELDX - lev_fieldx) / 2; + + if (lev_fieldy + (SBY_Upper == -1 ? 2 : 0) <= 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); @@ -504,19 +602,33 @@ void InitGame() DOOR_GFX_PAGEX1 + XX_TIME, DOOR_GFX_PAGEY1 + YY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW); + + +#if 0 DrawGameButton(BUTTON_GAME_STOP); DrawGameButton(BUTTON_GAME_PAUSE); DrawGameButton(BUTTON_GAME_PLAY); DrawSoundDisplay(BUTTON_SOUND_MUSIC | (setup.sound_music ? BUTTON_ON : 0)); DrawSoundDisplay(BUTTON_SOUND_LOOPS | (setup.sound_loops ? BUTTON_ON : 0)); DrawSoundDisplay(BUTTON_SOUND_SIMPLE | (setup.sound_simple ? BUTTON_ON : 0)); +#else + UnmapGameButtons(); + game_gadget[SOUND_CTRL_ID_MUSIC]->checked = setup.sound_music; + game_gadget[SOUND_CTRL_ID_LOOPS]->checked = setup.sound_loops; + game_gadget[SOUND_CTRL_ID_SIMPLE]->checked = setup.sound_simple; + MapGameButtons(); + MapTapeButtons(); +#endif + XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc, DX + GAME_CONTROL_XPOS, DY + GAME_CONTROL_YPOS, GAME_CONTROL_XSIZE, 2 * GAME_CONTROL_YSIZE, 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]); @@ -556,6 +668,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: @@ -563,6 +676,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: @@ -570,6 +684,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: @@ -577,6 +692,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: @@ -584,6 +700,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 && @@ -604,7 +729,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; @@ -656,7 +782,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; @@ -670,6 +796,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(); @@ -706,15 +855,15 @@ void GameWon() BackToFront(); } -boolean NewHiScore() +int NewHiScore() { int k, l; int position = -1; LoadScore(level_nr); - if (!strcmp(setup.player_name, EMPTY_ALIAS) || - local_player->score < highscore[MAX_SCORE_ENTRIES-1].Score) + if (strcmp(setup.player_name, EMPTY_PLAYER_NAME) == 0 || + local_player->score < highscore[MAX_SCORE_ENTRIES - 1].Score) return -1; for (k=0; k0) + if (Feld[x][y] == element && AmoebaNr[x][y] > 0) group_nr = AmoebaNr[x][y]; } @@ -2296,13 +2505,13 @@ void AmoebenVereinigen(int ax, int ay) { 0, +1 } }; - if (!new_group_nr) + if (new_group_nr == 0) return; for (i=0; i<4; i++) { - x = ax+xy[i%4][0]; - y = ay+xy[i%4][1]; + x = ax + xy[i][0]; + y = ay + xy[i][1]; if (!IN_LEV_FIELD(x, y)) continue; @@ -2314,14 +2523,22 @@ void AmoebenVereinigen(int ax, int ay) { int old_group_nr = AmoebaNr[x][y]; + if (old_group_nr == 0) + return; + AmoebaCnt[new_group_nr] += AmoebaCnt[old_group_nr]; AmoebaCnt[old_group_nr] = 0; AmoebaCnt2[new_group_nr] += AmoebaCnt2[old_group_nr]; AmoebaCnt2[old_group_nr] = 0; - for (yy=0; yy= 200 && element == EL_AMOEBE_BD) + if (element == EL_AMOEBE_BD && AmoebaCnt2[new_group_nr] >= 200) { - AmoebeUmwandeln2(newax, neway, EL_FELSBROCKEN); + AmoebeUmwandelnBD(newax, neway, EL_FELSBROCKEN); return; } } } - if (element!=EL_AMOEBE_NASS || newayeffective_action = summarized_player_action; @@ -3190,9 +3544,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 @@ -3285,6 +3639,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) { @@ -3315,44 +3675,57 @@ void GameActions() if (SiebAktiv) { - if (!(SiebAktiv%4)) + if (!(SiebCount % 4)) PlaySoundLevel(sieb_x, sieb_y, SND_MIEP); - SiebAktiv--; - if (!SiebAktiv) + + if (SiebCount > 0) { - for (y=0; y0 && 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; ijy = new_jy; StorePlayer[jx][jy] = player->element_nr; - player->MovPos = (dx > 0 || dy > 0 ? -1 : 1) * 7*TILEX/8; + player->MovPos = (dx > 0 || dy > 0 ? -1 : 1) * (TILEX - TILEX / MoveSpeed); ScrollFigure(player, SCROLL_INIT); @@ -3503,10 +3876,15 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy) /* should only happen if pre-1.2 tape recordings are played */ /* this is only for backward compatibility */ + int old_move_speed = MoveSpeed; + #if DEBUG printf("THIS SHOULD ONLY HAPPEN WITH PRE-1.2 LEVEL TAPES.\n"); #endif + /* scroll remaining steps with finest movement resolution */ + MoveSpeed = 8; + while (player->MovPos) { ScrollFigure(player, SCROLL_GO_ON); @@ -3515,6 +3893,8 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy) DrawAllPlayers(); BackToFront(); } + + MoveSpeed = old_move_speed; } if (player->last_move_dir & (MV_LEFT | MV_RIGHT)) @@ -3549,13 +3929,13 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy) { if (jx != old_jx) /* player has moved horizontally */ { - if ((player->MovDir == 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); @@ -3567,13 +3947,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); @@ -3649,7 +4029,7 @@ void ScrollFigure(struct PlayerInfo *player, int mode) else if (!FrameReached(&player->actual_frame_counter, 1)) return; - player->MovPos += (player->MovPos > 0 ? -1 : 1) * TILEX/8; + player->MovPos += (player->MovPos > 0 ? -1 : 1) * TILEX / MoveSpeed; player->GfxPos = ScrollStepSize * (player->MovPos / ScrollStepSize); if (Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING) @@ -3674,7 +4054,7 @@ void ScrollFigure(struct PlayerInfo *player, int mode) void ScrollScreen(struct PlayerInfo *player, int mode) { - static long screen_frame_counter = 0; + static unsigned long screen_frame_counter = 0; if (mode == SCROLL_INIT) { @@ -3689,7 +4069,7 @@ void ScrollScreen(struct PlayerInfo *player, int mode) if (ScreenMovPos) { - ScreenMovPos += (ScreenMovPos > 0 ? -1 : 1) * TILEX/8; + ScreenMovPos += (ScreenMovPos > 0 ? -1 : 1) * TILEX / MoveSpeed; ScreenGfxPos = ScrollStepSize * (ScreenMovPos / ScrollStepSize); redraw_mask |= REDRAW_FIELD; } @@ -3926,10 +4306,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: @@ -3938,6 +4326,7 @@ int DigField(struct PlayerInfo *player, case EL_EDELSTEIN_ROT: case EL_EDELSTEIN_LILA: case EL_DIAMANT: + case EL_SP_INFOTRON: RemoveField(x, y); local_player->gems_still_needed -= (element == EL_DIAMANT ? 3 : 1); if (local_player->gems_still_needed < 0) @@ -3946,17 +4335,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: @@ -4009,10 +4412,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; @@ -4043,6 +4475,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; @@ -4063,6 +4497,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 */ @@ -4108,6 +4578,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; @@ -4186,7 +4657,6 @@ int DigField(struct PlayerInfo *player, default: return MF_NO_ACTION; - break; } player->push_delay = 0; @@ -4255,7 +4725,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 { @@ -4358,3 +4833,237 @@ void RaiseScoreElement(int element) break; } } + +/* ---------- new game button stuff ---------------------------------------- */ + +/* graphic position values for game buttons */ +#define GAME_BUTTON_XSIZE 30 +#define GAME_BUTTON_YSIZE 30 +#define GAME_BUTTON_XPOS 5 +#define GAME_BUTTON_YPOS 215 +#define SOUND_BUTTON_XPOS 5 +#define SOUND_BUTTON_YPOS (GAME_BUTTON_YPOS + GAME_BUTTON_YSIZE) + +#define GAME_BUTTON_STOP_XPOS (GAME_BUTTON_XPOS + 0 * GAME_BUTTON_XSIZE) +#define GAME_BUTTON_PAUSE_XPOS (GAME_BUTTON_XPOS + 1 * GAME_BUTTON_XSIZE) +#define GAME_BUTTON_PLAY_XPOS (GAME_BUTTON_XPOS + 2 * GAME_BUTTON_XSIZE) +#define SOUND_BUTTON_MUSIC_XPOS (SOUND_BUTTON_XPOS + 0 * GAME_BUTTON_XSIZE) +#define SOUND_BUTTON_LOOPS_XPOS (SOUND_BUTTON_XPOS + 1 * GAME_BUTTON_XSIZE) +#define SOUND_BUTTON_SIMPLE_XPOS (SOUND_BUTTON_XPOS + 2 * GAME_BUTTON_XSIZE) + +static struct +{ + int x, y; + int gadget_id; + char *infotext; +} gamebutton_info[NUM_GAME_BUTTONS] = +{ + { + GAME_BUTTON_STOP_XPOS, GAME_BUTTON_YPOS, + GAME_CTRL_ID_STOP, + "stop game" + }, + { + GAME_BUTTON_PAUSE_XPOS, GAME_BUTTON_YPOS, + GAME_CTRL_ID_PAUSE, + "pause game" + }, + { + GAME_BUTTON_PLAY_XPOS, GAME_BUTTON_YPOS, + GAME_CTRL_ID_PLAY, + "play game" + }, + { + SOUND_BUTTON_MUSIC_XPOS, SOUND_BUTTON_YPOS, + SOUND_CTRL_ID_MUSIC, + "background music on/off" + }, + { + SOUND_BUTTON_LOOPS_XPOS, SOUND_BUTTON_YPOS, + SOUND_CTRL_ID_LOOPS, + "sound loops on/off" + }, + { + SOUND_BUTTON_SIMPLE_XPOS, SOUND_BUTTON_YPOS, + SOUND_CTRL_ID_SIMPLE, + "normal sounds on/off" + } +}; + +void CreateGameButtons() +{ + int i; + + for (i=0; icustom_id; + + if (game_status != PLAYING) + return; + + switch (id) + { + case GAME_CTRL_ID_STOP: + if (AllPlayersGone) + { + CloseDoor(DOOR_CLOSE_1); + game_status = MAINMENU; + DrawMainMenu(); + break; + } + + if (Request("Do you really want to quit the game ?", + REQ_ASK | REQ_STAY_CLOSED)) + { +#ifndef MSDOS + if (options.network) + SendToServer_StopPlaying(); + else +#endif + { + game_status = MAINMENU; + DrawMainMenu(); + } + } + else + OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK); + break; + + case GAME_CTRL_ID_PAUSE: + if (options.network) + { +#ifndef MSDOS + if (tape.pausing) + SendToServer_ContinuePlaying(); + else + SendToServer_PausePlaying(); +#endif + } + else + TapeTogglePause(); + break; + + case GAME_CTRL_ID_PLAY: + if (tape.pausing) + { +#ifndef MSDOS + if (options.network) + SendToServer_ContinuePlaying(); + else +#endif + { + tape.pausing = FALSE; + DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0); + } + } + break; + + case SOUND_CTRL_ID_MUSIC: + if (setup.sound_music) + { + setup.sound_music = FALSE; + FadeSound(background_loop[level_nr % num_bg_loops]); + } + else if (sound_loops_allowed) + { + setup.sound = setup.sound_music = TRUE; + PlaySoundLoop(background_loop[level_nr % num_bg_loops]); + } + break; + + case SOUND_CTRL_ID_LOOPS: + if (setup.sound_loops) + setup.sound_loops = FALSE; + else if (sound_loops_allowed) + setup.sound = setup.sound_loops = TRUE; + break; + + case SOUND_CTRL_ID_SIMPLE: + if (setup.sound_simple) + setup.sound_simple = FALSE; + else if (sound_status==SOUND_AVAILABLE) + setup.sound = setup.sound_simple = TRUE; + break; + + default: + break; + } +}