#include "init.h"
#include "tools.h"
#include "screens.h"
+#include "events.h"
#include "files.h"
#include "tape.h"
#include "network.h"
#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
-#define GAME_CTRL_ID_SAVE 6
+#define GAME_CTRL_ID_UNDO 3
+#define GAME_CTRL_ID_REDO 4
+#define GAME_CTRL_ID_SAVE 5
+#define GAME_CTRL_ID_PAUSE2 6
#define GAME_CTRL_ID_LOAD 7
+#define SOUND_CTRL_ID_MUSIC 8
+#define SOUND_CTRL_ID_LOOPS 9
+#define SOUND_CTRL_ID_SIMPLE 10
-#define NUM_GAME_BUTTONS 8
+#define NUM_GAME_BUTTONS 11
/* forward declaration for internal use */
CheckTriggeredElementChange(x, y, element, CE_CREATION_OF_X);
}
-static inline void InitField_WithBug1(int x, int y, boolean init_game)
+inline static void InitField_WithBug1(int x, int y, boolean init_game)
{
InitField(x, y, init_game);
InitMovDir(x, y);
}
-static inline void InitField_WithBug2(int x, int y, boolean init_game)
+inline static void InitField_WithBug2(int x, int y, boolean init_game)
{
int old_element = Feld[x][y];
void UpdateAndDisplayGameControlValues()
{
- if (tape.warp_forward)
+ if (tape.deactivate_display)
return;
UpdateGameControlValues();
setup.scroll_delay ? setup.scroll_delay_value : 0);
game.scroll_delay_value =
MIN(MAX(MIN_SCROLL_DELAY, game.scroll_delay_value), MAX_SCROLL_DELAY);
+
+ /* ---------- initialize game engine snapshots ---------------------------- */
+ for (i = 0; i < MAX_PLAYERS; i++)
+ game.snapshot.last_action[i] = 0;
+ game.snapshot.changed_action = FALSE;
+ game.snapshot.mode =
+ (strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_STEP) ?
+ SNAPSHOT_MODE_EVERY_STEP :
+ strEqual(setup.engine_snapshot_mode, STR_SNAPSHOT_MODE_EVERY_MOVE) ?
+ SNAPSHOT_MODE_EVERY_MOVE : SNAPSHOT_MODE_OFF);
}
int get_num_special_action(int element, int action_first, int action_last)
{
int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
+ int fade_mask = REDRAW_FIELD;
boolean emulate_bd = TRUE; /* unless non-BOULDERDASH elements found */
boolean emulate_sb = TRUE; /* unless non-SOKOBAN elements found */
int initial_move_dir = MV_DOWN;
int i, j, x, y;
- game_status = GAME_MODE_PLAYING;
+ // required here to update video display before fading (FIX THIS)
+ DrawMaskedBorder(REDRAW_DOOR_2);
- StopAnimation();
+ game_status = GAME_MODE_PLAYING;
if (!game.restart_level)
CloseDoor(DOOR_CLOSE_1);
+ /* needed if different viewport properties defined for playing */
+ ChangeViewportPropertiesIfNeeded();
+
if (level_editor_test_game)
FadeSkipNextFadeIn();
else
FadeSetEnterScreen();
- FadeOut(REDRAW_FIELD);
+ if (CheckIfGlobalBorderHasChanged())
+ fade_mask = REDRAW_ALL;
- /* needed if different viewport properties defined for playing */
- ChangeViewportPropertiesIfNeeded();
+ FadeOut(fade_mask);
+
+ OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW);
+
+ ClearField();
DrawCompleteVideoDisplay();
/* blit playfield from scroll buffer to normal back buffer for fading in */
BlitScreenToBitmap(backbuffer);
-
- redraw_mask |= REDRAW_FROM_BACKBUFFER;
/* !!! FIX THIS (END) !!! */
- FadeIn(REDRAW_FIELD);
+ DrawMaskedBorder(fade_mask);
+
+ FadeIn(fade_mask);
#if 1
// full screen redraw is required at this point in the following cases:
{
UnmapGameButtons();
UnmapTapeButtons();
+
+ FreeGameButtons();
+ CreateGameButtons();
+
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();
}
game.restart_level = FALSE;
+
+ SaveEngineSnapshotToListInitial();
}
void UpdateEngineValues(int actual_scroll_x, int actual_scroll_y)
local_player->LevelSolved_GameEnd = TRUE;
- CloseDoor(DOOR_CLOSE_1);
+ if (!global.use_envelope_request)
+ CloseDoor(DOOR_CLOSE_1);
if (local_player->LevelSolved_SaveTape)
{
SaveTapeChecked(tape.level_nr); /* ask to save tape */
}
+ CloseDoor(DOOR_CLOSE_ALL);
+
if (level_editor_test_game)
{
game_status = GAME_MODE_MAIN;
- DrawAndFadeInMainMenu(REDRAW_FIELD);
+ DrawMainMenu();
return;
}
game_status = GAME_MODE_MAIN;
- DrawAndFadeInMainMenu(REDRAW_FIELD);
+ DrawMainMenu();
return;
}
TapeErase();
}
- DrawAndFadeInMainMenu(REDRAW_FIELD);
+ DrawMainMenu();
}
}
}
}
- RedrawPlayfield(TRUE, 0,0,0,0);
+ RedrawPlayfield();
}
else
{
}
}
+static void CheckSaveEngineSnapshot(struct PlayerInfo *player)
+{
+ static boolean player_was_moving = FALSE;
+ static boolean player_was_snapping = FALSE;
+ static boolean player_was_dropping = FALSE;
+
+ if ((!player->is_moving && player_was_moving) ||
+ (player->MovPos == 0 && player_was_moving) ||
+ (player->is_snapping && !player_was_snapping) ||
+ (player->is_dropping && !player_was_dropping))
+ {
+ if (!SaveEngineSnapshotToList())
+ return;
+
+ player_was_moving = FALSE;
+ player_was_snapping = TRUE;
+ player_was_dropping = TRUE;
+ }
+ else
+ {
+ if (player->is_moving)
+ player_was_moving = TRUE;
+
+ if (!player->is_snapping)
+ player_was_snapping = FALSE;
+
+ if (!player->is_dropping)
+ player_was_dropping = FALSE;
+ }
+}
+
static void CheckSingleStepMode(struct PlayerInfo *player)
{
if (tape.single_step && tape.recording && !tape.pausing)
SnapField(player, 0, 0); /* stop snapping */
}
}
+
+ CheckSaveEngineSnapshot(player);
}
static byte PlayerActions(struct PlayerInfo *player, byte player_action)
if (tape.playing && tape.warp_forward && !tape.pausing)
game_frame_delay_value = 0;
+#if 0
+ /* ---------- main game synchronization point ---------- */
+
+ int skip = WaitUntilDelayReached(&game_frame_delay, game_frame_delay_value);
+
+ printf("::: skip == %d\n", skip);
+
+#else
/* ---------- main game synchronization point ---------- */
WaitUntilDelayReached(&game_frame_delay, game_frame_delay_value);
+#endif
if (network_playing && !network_player_action_received)
{
#endif
#endif
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ // allow engine snapshot in case of changed movement attempt
+ if ((game.snapshot.last_action[i] & KEY_MOTION) !=
+ (stored_player[i].effective_action & KEY_MOTION))
+ game.snapshot.changed_action = TRUE;
+
+ // allow engine snapshot in case of snapping/dropping attempt
+ if ((game.snapshot.last_action[i] & KEY_BUTTON) == 0 &&
+ (stored_player[i].effective_action & KEY_BUTTON) != 0)
+ game.snapshot.changed_action = TRUE;
+
+ game.snapshot.last_action[i] = stored_player[i].effective_action;
+ }
+
if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
{
GameActions_EM_Main();
}
else
{
- GameActions_RND();
+ GameActions_RND_Main();
+ }
+
+ BlitScreenToBitmap(backbuffer);
+
+ CheckLevelTime();
+
+ AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */
+
+ if (options.debug) /* calculate frames per second */
+ {
+ static unsigned int fps_counter = 0;
+ static int fps_frames = 0;
+ unsigned int fps_delay_ms = Counter() - fps_counter;
+
+ fps_frames++;
+
+ if (fps_delay_ms >= 500) /* calculate fps every 0.5 seconds */
+ {
+ global.frames_per_second = 1000 * (float)fps_frames / fps_delay_ms;
+
+ fps_frames = 0;
+ fps_counter = Counter();
+ }
+
+ redraw_mask |= REDRAW_FPS;
}
}
effective_action[i] = stored_player[i].effective_action;
GameActions_EM(effective_action, warp_mode);
-
- CheckLevelTime();
-
- AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */
}
void GameActions_SP_Main()
effective_action[i] = stored_player[i].effective_action;
GameActions_SP(effective_action, warp_mode);
+}
- CheckLevelTime();
-
- AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */
+void GameActions_RND_Main()
+{
+ GameActions_RND();
}
void GameActions_RND()
}
#endif
- CheckLevelTime();
-
DrawAllPlayers();
PlayAllPlayersSound();
- if (options.debug) /* calculate frames per second */
- {
- static unsigned int fps_counter = 0;
- static int fps_frames = 0;
- unsigned int fps_delay_ms = Counter() - fps_counter;
-
- fps_frames++;
-
- if (fps_delay_ms >= 500) /* calculate fps every 0.5 seconds */
- {
- global.frames_per_second = 1000 * (float)fps_frames / fps_delay_ms;
-
- fps_frames = 0;
- fps_counter = Counter();
- }
-
- redraw_mask |= REDRAW_FPS;
- }
-
- AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */
-
if (local_player->show_envelope != 0 && local_player->MovPos == 0)
{
ShowEnvelope(local_player->show_envelope - EL_ENVELOPE_1);
void ScrollLevel(int dx, int dy)
{
- int softscroll_offset = (setup.soft_scrolling ? 2 * TILEX_VAR : 0);
+ int scroll_offset = 2 * TILEX_VAR;
int x, y;
BlitBitmap(drawto_field, drawto_field,
- FX + TILEX_VAR * (dx == -1) - softscroll_offset,
- FY + TILEY_VAR * (dy == -1) - softscroll_offset,
- SXSIZE - TILEX_VAR * (dx != 0) + 2 * softscroll_offset,
- SYSIZE - TILEY_VAR * (dy != 0) + 2 * softscroll_offset,
- FX + TILEX_VAR * (dx == 1) - softscroll_offset,
- FY + TILEY_VAR * (dy == 1) - softscroll_offset);
+ FX + TILEX_VAR * (dx == -1) - scroll_offset,
+ FY + TILEY_VAR * (dy == -1) - scroll_offset,
+ SXSIZE - TILEX_VAR * (dx != 0) + 2 * scroll_offset,
+ SYSIZE - TILEY_VAR * (dy != 0) + 2 * scroll_offset,
+ FX + TILEX_VAR * (dx == 1) - scroll_offset,
+ FY + TILEY_VAR * (dy == 1) - scroll_offset);
if (dx != 0)
{
if (tape.single_step && tape.recording && !tape.pausing &&
!player->programmed_action)
TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
+
+ if (!player->programmed_action)
+ CheckSaveEngineSnapshot(player);
}
}
game_status = GAME_MODE_MAIN;
- DrawAndFadeInMainMenu(REDRAW_FIELD);
+ DrawMainMenu();
}
else
{
game_status = GAME_MODE_MAIN;
- DrawAndFadeInMainMenu(REDRAW_FIELD);
+ DrawMainMenu();
}
}
}
}
}
-void FreeEngineSnapshot()
+void FreeEngineSnapshotSingle()
{
- FreeEngineSnapshotBuffers();
+ FreeSnapshotSingle();
setString(&snapshot_level_identifier, NULL);
snapshot_level_nr = -1;
}
-void SaveEngineSnapshot()
+void FreeEngineSnapshotList()
{
- /* do not save snapshots from editor */
- if (level_editor_test_game)
- return;
+ FreeSnapshotList();
+}
- /* free previous snapshot buffers, if needed */
- FreeEngineSnapshotBuffers();
+ListNode *SaveEngineSnapshotBuffers()
+{
+ ListNode *buffers = NULL;
/* copy some special values to a structure better suited for the snapshot */
if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
SaveEngineSnapshotValues_EM();
if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
- SaveEngineSnapshotValues_SP();
+ SaveEngineSnapshotValues_SP(&buffers);
/* save values stored in special snapshot structure */
if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_rnd));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_rnd));
if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_em));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_em));
if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_sp));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_sp));
/* save further RND engine values */
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(stored_player));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(game));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(tape));
-
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ZX));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ZY));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExitX));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExitY));
-
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FrameCounter));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimeFrames));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimePlayed));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimeLeft));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TapeTime));
-
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenMovDir));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenMovPos));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenGfxPos));
-
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollStepSize));
-
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AllPlayersGone));
-
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt2));
-
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Feld));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovPos));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovDir));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovDelay));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangeDelay));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangePage));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(CustomValue));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Store));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Store2));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(StorePlayer));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Back));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AmoebaNr));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(WasJustMoving));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(WasJustFalling));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(CheckCollision));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(CheckImpact));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Stop));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Pushed));
-
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangeCount));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangeEvent));
-
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExplodePhase));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExplodeDelay));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExplodeField));
-
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RunnerVisit));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(PlayerVisit));
-
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxFrame));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxRandom));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxElement));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxAction));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxDir));
-
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(scroll_x));
- SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(scroll_y));
-
- /* save level identification information */
-
- setString(&snapshot_level_identifier, leveldir_current->identifier);
- snapshot_level_nr = level_nr;
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(stored_player));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(game));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(tape));
+
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ZX));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ZY));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExitX));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExitY));
+
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(FrameCounter));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(TimeFrames));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(TimePlayed));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(TimeLeft));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(TapeTime));
+
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ScreenMovDir));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ScreenMovPos));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ScreenGfxPos));
+
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ScrollStepSize));
+
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AllPlayersGone));
+
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt2));
+
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Feld));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(MovPos));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(MovDir));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(MovDelay));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ChangeDelay));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ChangePage));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(CustomValue));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Store));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Store2));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(StorePlayer));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Back));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AmoebaNr));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(WasJustMoving));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(WasJustFalling));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(CheckCollision));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(CheckImpact));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Stop));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Pushed));
+
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ChangeCount));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ChangeEvent));
+
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExplodePhase));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExplodeDelay));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExplodeField));
+
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(RunnerVisit));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(PlayerVisit));
+
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxFrame));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxRandom));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxElement));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxAction));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxDir));
+
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(scroll_x));
+ SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(scroll_y));
#if 0
ListNode *node = engine_snapshot_list_rnd;
printf("::: size of engine snapshot: %d bytes\n", num_bytes);
#endif
+
+ return buffers;
+}
+
+void SaveEngineSnapshotSingle()
+{
+ ListNode *buffers = SaveEngineSnapshotBuffers();
+
+ /* finally save all snapshot buffers to single snapshot */
+ SaveSnapshotSingle(buffers);
+
+ /* save level identification information */
+ setString(&snapshot_level_identifier, leveldir_current->identifier);
+ snapshot_level_nr = level_nr;
+}
+
+static boolean SaveEngineSnapshotToListExt(boolean initial_snapshot)
+{
+ boolean save_snapshot =
+ (initial_snapshot ||
+ (game.snapshot.mode == SNAPSHOT_MODE_EVERY_STEP) ||
+ (game.snapshot.mode == SNAPSHOT_MODE_EVERY_MOVE &&
+ game.snapshot.changed_action));
+
+ game.snapshot.changed_action = FALSE;
+
+ if (game.snapshot.mode == SNAPSHOT_MODE_OFF ||
+ tape.quick_resume ||
+ !save_snapshot)
+ return FALSE;
+
+ ListNode *buffers = SaveEngineSnapshotBuffers();
+
+ /* finally save all snapshot buffers to snapshot list */
+ SaveSnapshotToList(buffers);
+
+ return TRUE;
+}
+
+boolean SaveEngineSnapshotToList()
+{
+ return SaveEngineSnapshotToListExt(FALSE);
}
-void LoadEngineSnapshot()
+void SaveEngineSnapshotToListInitial()
{
- /* restore generically stored snapshot buffers */
+ FreeEngineSnapshotList();
- LoadEngineSnapshotBuffers();
+ SaveEngineSnapshotToListExt(TRUE);
+}
+void LoadEngineSnapshotValues()
+{
/* restore special values from snapshot structure */
if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
LoadEngineSnapshotValues_SP();
}
-boolean CheckEngineSnapshot()
+void LoadEngineSnapshotSingle()
+{
+ LoadSnapshotSingle();
+
+ LoadEngineSnapshotValues();
+}
+
+void LoadEngineSnapshot_Undo(int steps)
+{
+ LoadSnapshotFromList_Older(steps);
+
+ LoadEngineSnapshotValues();
+}
+
+void LoadEngineSnapshot_Redo(int steps)
+{
+ LoadSnapshotFromList_Newer(steps);
+
+ LoadEngineSnapshotValues();
+}
+
+boolean CheckEngineSnapshotSingle()
{
return (strEqual(snapshot_level_identifier, leveldir_current->identifier) &&
snapshot_level_nr == level_nr);
}
+boolean CheckEngineSnapshotList()
+{
+ return CheckSnapshotList();
+}
+
/* ---------- new game button stuff ---------------------------------------- */
GAME_CTRL_ID_PLAY, "play game"
},
{
- IMG_GAME_BUTTON_GFX_SOUND_MUSIC, &game.button.sound_music,
- SOUND_CTRL_ID_MUSIC, "background music on/off"
+ IMG_GAME_BUTTON_GFX_UNDO, &game.button.undo,
+ GAME_CTRL_ID_UNDO, "undo step"
},
{
- IMG_GAME_BUTTON_GFX_SOUND_LOOPS, &game.button.sound_loops,
- SOUND_CTRL_ID_LOOPS, "sound loops on/off"
- },
- {
- IMG_GAME_BUTTON_GFX_SOUND_SIMPLE, &game.button.sound_simple,
- SOUND_CTRL_ID_SIMPLE, "normal sounds on/off"
+ IMG_GAME_BUTTON_GFX_REDO, &game.button.redo,
+ GAME_CTRL_ID_REDO, "redo step"
},
{
IMG_GAME_BUTTON_GFX_SAVE, &game.button.save,
GAME_CTRL_ID_SAVE, "save game"
},
+ {
+ IMG_GAME_BUTTON_GFX_PAUSE2, &game.button.pause2,
+ GAME_CTRL_ID_PAUSE2, "pause game"
+ },
{
IMG_GAME_BUTTON_GFX_LOAD, &game.button.load,
GAME_CTRL_ID_LOAD, "load game"
+ },
+ {
+ IMG_GAME_BUTTON_GFX_SOUND_MUSIC, &game.button.sound_music,
+ SOUND_CTRL_ID_MUSIC, "background music on/off"
+ },
+ {
+ IMG_GAME_BUTTON_GFX_SOUND_LOOPS, &game.button.sound_loops,
+ SOUND_CTRL_ID_LOOPS, "sound loops on/off"
+ },
+ {
+ IMG_GAME_BUTTON_GFX_SOUND_SIMPLE, &game.button.sound_simple,
+ SOUND_CTRL_ID_SIMPLE, "normal sounds on/off"
}
};
}
if (id == GAME_CTRL_ID_STOP ||
- id == GAME_CTRL_ID_PAUSE ||
id == GAME_CTRL_ID_PLAY ||
id == GAME_CTRL_ID_SAVE ||
id == GAME_CTRL_ID_LOAD)
checked = FALSE;
event_mask = GD_EVENT_RELEASED;
}
+ else if (id == GAME_CTRL_ID_UNDO ||
+ id == GAME_CTRL_ID_REDO)
+ {
+ button_type = GD_TYPE_NORMAL_BUTTON;
+ checked = FALSE;
+ event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
+ }
else
{
button_type = GD_TYPE_CHECK_BUTTON;
FreeGadget(game_gadget[i]);
}
+static void MapGameButtonsAtSamePosition(int id)
+{
+ int i;
+
+ for (i = 0; i < NUM_GAME_BUTTONS; i++)
+ if (i != id &&
+ gamebutton_info[i].pos->x == gamebutton_info[id].pos->x &&
+ gamebutton_info[i].pos->y == gamebutton_info[id].pos->y)
+ MapGadget(game_gadget[i]);
+}
+
+static void UnmapGameButtonsAtSamePosition(int id)
+{
+ int i;
+
+ for (i = 0; i < NUM_GAME_BUTTONS; i++)
+ if (i != id &&
+ gamebutton_info[i].pos->x == gamebutton_info[id].pos->x &&
+ gamebutton_info[i].pos->y == gamebutton_info[id].pos->y)
+ UnmapGadget(game_gadget[i]);
+}
+
+void MapUndoRedoButtons()
+{
+ UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_UNDO);
+ UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_REDO);
+
+ MapGadget(game_gadget[GAME_CTRL_ID_UNDO]);
+ MapGadget(game_gadget[GAME_CTRL_ID_REDO]);
+}
+
+void UnmapUndoRedoButtons()
+{
+ UnmapGadget(game_gadget[GAME_CTRL_ID_UNDO]);
+ UnmapGadget(game_gadget[GAME_CTRL_ID_REDO]);
+
+ MapGameButtonsAtSamePosition(GAME_CTRL_ID_UNDO);
+ MapGameButtonsAtSamePosition(GAME_CTRL_ID_REDO);
+}
+
void MapGameButtons()
{
int i;
for (i = 0; i < NUM_GAME_BUTTONS; i++)
- MapGadget(game_gadget[i]);
+ if (i != GAME_CTRL_ID_UNDO &&
+ i != GAME_CTRL_ID_REDO)
+ MapGadget(game_gadget[i]);
+
+ if (setup.show_snapshot_buttons)
+ {
+ UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_SAVE);
+ UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_PAUSE2);
+ UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_LOAD);
+ }
+ else
+ {
+ UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_STOP);
+ UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_PAUSE);
+ UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_PLAY);
+ }
+
+ RedrawGameButtons();
}
void UnmapGameButtons()
redraw_mask &= ~REDRAW_ALL;
}
-static void HandleGameButtonsExt(int id)
+void GameUndoRedoExt()
+{
+ ClearPlayerAction();
+
+ tape.pausing = TRUE;
+
+ RedrawPlayfield();
+ UpdateAndDisplayGameControlValues();
+
+ DrawCompleteVideoDisplay();
+ DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime);
+ DrawVideoDisplay(VIDEO_STATE_FRAME_ON, FrameCounter);
+ DrawVideoDisplay((tape.single_step ? VIDEO_STATE_1STEP_ON :
+ VIDEO_STATE_1STEP_OFF), 0);
+
+ BackToFront();
+}
+
+void GameUndo(int steps)
+{
+ if (!CheckEngineSnapshotList())
+ return;
+
+ LoadEngineSnapshot_Undo(steps);
+
+ GameUndoRedoExt();
+}
+
+void GameRedo(int steps)
+{
+ if (!CheckEngineSnapshotList())
+ return;
+
+ LoadEngineSnapshot_Redo(steps);
+
+ GameUndoRedoExt();
+}
+
+static void HandleGameButtonsExt(int id, int button)
{
+ int steps = BUTTON_STEPSIZE(button);
boolean handle_game_buttons =
(game_status == GAME_MODE_PLAYING ||
(game_status == GAME_MODE_MAIN && tape.show_game_buttons));
break;
case GAME_CTRL_ID_PAUSE:
+ case GAME_CTRL_ID_PAUSE2:
if (options.network && game_status == GAME_MODE_PLAYING)
{
#if defined(NETWORK_AVALIABLE)
SendToServer_ContinuePlaying();
else
#endif
- {
- tape.pausing = FALSE;
- DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF, 0);
- }
+ TapeTogglePause(TAPE_TOGGLE_MANUAL);
}
break;
+ case GAME_CTRL_ID_UNDO:
+ GameUndo(steps);
+ break;
+
+ case GAME_CTRL_ID_REDO:
+ GameRedo(steps);
+ break;
+
+ case GAME_CTRL_ID_SAVE:
+ TapeQuickSave();
+ break;
+
+ case GAME_CTRL_ID_LOAD:
+ TapeQuickLoad();
+ break;
+
case SOUND_CTRL_ID_MUSIC:
if (setup.sound_music)
{
}
break;
- case GAME_CTRL_ID_SAVE:
- TapeQuickSave();
- break;
-
- case GAME_CTRL_ID_LOAD:
- TapeQuickLoad();
- break;
-
default:
break;
}
static void HandleGameButtons(struct GadgetInfo *gi)
{
- HandleGameButtonsExt(gi->custom_id);
+ HandleGameButtonsExt(gi->custom_id, gi->event.button);
}
void HandleSoundButtonKeys(Key key)