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 = SNAPSHOT_MODE_MOVE;
+
FreeEngineSnapshotList();
}
static boolean player_was_snapping = FALSE;
static boolean player_was_dropping = FALSE;
- if (!tape.recording)
- return;
-
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))
{
- SaveEngineSnapshotToList();
+ if (!SaveEngineSnapshotToList())
+ return;
player_was_moving = FALSE;
player_was_snapping = TRUE;
byte tape_action[MAX_PLAYERS];
int i;
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ struct PlayerInfo *player = &stored_player[i];
+
+ // allow engine snapshot if movement attempt was stopped
+ if ((game.snapshot.last_action[i] & KEY_MOTION) != 0 &&
+ (player->action & KEY_MOTION) == 0)
+ game.snapshot.changed_action = TRUE;
+
+ // allow engine snapshot in case of snapping/dropping attempt
+ if ((game.snapshot.last_action[i] & KEY_BUTTON) == 0 &&
+ (player->action & KEY_BUTTON) != 0)
+ game.snapshot.changed_action = TRUE;
+
+ game.snapshot.last_action[i] = player->action;
+ }
+
/* detect endless loops, caused by custom element programming */
if (recursion_loop_detected && recursion_loop_depth == 0)
{
{
ListNode *buffers = NULL;
- /* do not save snapshots from editor */
- if (level_editor_test_game)
- return NULL;
-
/* copy some special values to a structure better suited for the snapshot */
if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
SaveSnapshotSingle(buffers);
}
-void SaveEngineSnapshotToList()
+boolean SaveEngineSnapshotToList()
{
+ boolean save_snapshot =
+ (FrameCounter == 0 ||
+ (game.snapshot.mode == SNAPSHOT_MODE_STEP) ||
+ (game.snapshot.mode == SNAPSHOT_MODE_MOVE &&
+ game.snapshot.changed_action));
+
+ game.snapshot.changed_action = FALSE;
+
+ if (!save_snapshot)
+ return FALSE;
+
ListNode *buffers = SaveEngineSnapshotBuffers();
/* finally save all snapshot buffers to snapshot list */
SaveSnapshotToList(buffers);
+
+ return TRUE;
}
void LoadEngineSnapshotValues()
LoadEngineSnapshotValues();
}
-void LoadEngineSnapshot_Undo()
+void LoadEngineSnapshot_Undo(int steps)
{
- LoadSnapshotFromList_Older();
+ LoadSnapshotFromList_Older(steps);
LoadEngineSnapshotValues();
}
-void LoadEngineSnapshot_Redo()
+void LoadEngineSnapshot_Redo(int steps)
{
- LoadSnapshotFromList_Newer();
+ LoadSnapshotFromList_Newer(steps);
LoadEngineSnapshotValues();
}
RedrawPlayfield();
UpdateAndDisplayGameControlValues();
+ DrawCompleteVideoDisplay();
DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime);
DrawVideoDisplay(VIDEO_STATE_FRAME_ON, FrameCounter);
BackToFront();
}
-void GameUndo()
+void GameUndo(int steps)
{
if (!CheckEngineSnapshot())
return;
- LoadEngineSnapshot_Undo();
+ LoadEngineSnapshot_Undo(steps);
GameUndoRedoExt();
}
-void GameRedo()
+void GameRedo(int steps)
{
if (!CheckEngineSnapshot())
return;
- LoadEngineSnapshot_Redo();
+ LoadEngineSnapshot_Redo(steps);
GameUndoRedoExt();
}
-static void HandleGameButtonsExt(int id)
+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_UNDO:
- GameUndo();
+ GameUndo(steps);
break;
case GAME_CTRL_ID_REDO:
- GameRedo();
+ GameRedo(steps);
break;
case GAME_CTRL_ID_SAVE:
static void HandleGameButtons(struct GadgetInfo *gi)
{
- HandleGameButtonsExt(gi->custom_id);
+ HandleGameButtonsExt(gi->custom_id, gi->event.button);
}
void HandleSoundButtonKeys(Key key)