#else
for (i = 0; i < MAX_PLAYERS; i++)
{
- if (stored_player[i].active && !tape.player_participates[i])
+ if (stored_player[i].active &&
+ !tape.player_participates[i])
{
struct PlayerInfo *player = &stored_player[i];
int jx = player->jx, jy = player->jy;
/* blit playfield from scroll buffer to normal back buffer for fading in */
BlitScreenToBitmap_EM(backbuffer);
}
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+ {
+ InitGameEngine_SP();
+
+ /* blit playfield from scroll buffer to normal back buffer for fading in */
+ BlitScreenToBitmap_SP(backbuffer);
+ }
else
{
DrawLevel();
if (quick_relocation)
{
- int offset = game.scroll_delay_value;
-
if (!IN_VIS_FIELD(SCREENX(x), SCREENY(y)) || center_screen)
{
if (!level.shifted_relocation || center_screen)
}
else
{
+#if 1
+ if (!level.shifted_relocation || center_screen)
+ {
+ /* quick relocation (without scrolling), with centering of screen */
+
+ scroll_x = (x < SBX_Left + MIDPOSX ? SBX_Left :
+ x > SBX_Right + MIDPOSX ? SBX_Right :
+ x - MIDPOSX);
+
+ scroll_y = (y < SBY_Upper + MIDPOSY ? SBY_Upper :
+ y > SBY_Lower + MIDPOSY ? SBY_Lower :
+ y - MIDPOSY);
+ }
+ else
+ {
+ /* quick relocation (without scrolling), but do not center screen */
+
+ int center_scroll_x = (old_x < SBX_Left + MIDPOSX ? SBX_Left :
+ old_x > SBX_Right + MIDPOSX ? SBX_Right :
+ old_x - MIDPOSX);
+
+ int center_scroll_y = (old_y < SBY_Upper + MIDPOSY ? SBY_Upper :
+ old_y > SBY_Lower + MIDPOSY ? SBY_Lower :
+ old_y - MIDPOSY);
+
+ int offset_x = x + (scroll_x - center_scroll_x);
+ int offset_y = y + (scroll_y - center_scroll_y);
+
+ scroll_x = (offset_x < SBX_Left + MIDPOSX ? SBX_Left :
+ offset_x > SBX_Right + MIDPOSX ? SBX_Right :
+ offset_x - MIDPOSX);
+
+ scroll_y = (offset_y < SBY_Upper + MIDPOSY ? SBY_Upper :
+ offset_y > SBY_Lower + MIDPOSY ? SBY_Lower :
+ offset_y - MIDPOSY);
+ }
+#else
/* quick relocation (without scrolling), inside visible screen area */
+ int offset = game.scroll_delay_value;
+
if ((move_dir == MV_LEFT && scroll_x > x - MIDPOSX + offset) ||
(move_dir == MV_RIGHT && scroll_x < x - MIDPOSX - offset))
scroll_x = x - MIDPOSX + (scroll_x < x - MIDPOSX ? -offset : +offset);
/* don't scroll over playfield boundaries */
if (scroll_y < SBY_Upper || scroll_y > SBY_Lower)
scroll_y = (scroll_y < SBY_Upper ? SBY_Upper : SBY_Lower);
+#endif
}
RedrawPlayfield(TRUE, 0,0,0,0);
Feld[jx][jy] = el_player;
InitPlayerField(jx, jy, el_player, TRUE);
+ /* "InitPlayerField()" above sets Feld[jx][jy] to EL_EMPTY, but it may be
+ possible that the relocation target field did not contain a player element,
+ but a walkable element, to which the new player was relocated -- in this
+ case, restore that (already initialized!) element on the player field */
if (!ELEM_IS_PLAYER(element)) /* player may be set on walkable element */
{
- Feld[jx][jy] = element;
+ Feld[jx][jy] = element; /* restore previously existing element */
+#if 0
+ /* !!! do not initialize already initialized element a second time !!! */
+ /* (this causes at least problems with "element creation" CE trigger for
+ already existing elements, and existing Sokoban fields counted twice) */
InitField(jx, jy, FALSE);
+#endif
}
/* only visually relocate centered player */
if (tape.single_step && tape.recording && !tape.pausing)
{
+#if 1
+ /* as it is called "single step mode", just return to pause mode when the
+ player stopped moving after one tile (or never starts moving at all) */
+ if (!player->is_moving)
+#else
+ /* this is buggy: there are quite some cases where the single step mode
+ does not return to pause mode (like pushing things that don't move
+ or simply by trying to run against a wall) */
if (button1 || (dropped && !moved))
+#endif
{
TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
SnapField(player, 0, 0); /* stop snapping */
{
int i;
+ /* !!! SAME CODE AS IN "GameActions()" -- FIX THIS !!! */
if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
{
if (level.native_em_level->lev->home == 0) /* all players at home */
level.native_em_level->ply[3]->alive == 0) /* all dead */
AllPlayersGone = TRUE;
}
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+ {
+ if (game_sp_info.LevelSolved &&
+ !game_sp_info.GameOver) /* game won */
+ {
+ PlayerWins(local_player);
+
+ game_sp_info.GameOver = TRUE;
+
+ AllPlayersGone = TRUE;
+ }
+
+ if (game_sp_info.GameOver) /* game lost */
+ AllPlayersGone = TRUE;
+ }
if (TimeFrames >= FRAMES_PER_SECOND)
{
if (game.restart_level)
StartGameActions(options.network, setup.autorecord, level.random_seed);
+ /* !!! SAME CODE AS IN "CheckLevelTime()" -- FIX THIS !!! */
if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
{
if (level.native_em_level->lev->home == 0) /* all players at home */
level.native_em_level->ply[3]->alive == 0) /* all dead */
AllPlayersGone = TRUE;
}
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+ {
+ if (game_sp_info.LevelSolved &&
+ !game_sp_info.GameOver) /* game won */
+ {
+ PlayerWins(local_player);
+
+ game_sp_info.GameOver = TRUE;
+
+ AllPlayersGone = TRUE;
+ }
+
+ if (game_sp_info.GameOver) /* game lost */
+ AllPlayersGone = TRUE;
+ }
if (local_player->LevelSolved && !local_player->LevelSolved_GameEnd)
GameWon();
game.set_centered_player = TRUE;
}
-#if 0 /* USE_NEW_PLAYER_ASSIGNMENTS */
- for (i = 0; i < MAX_PLAYERS; i++)
- {
- summarized_player_action |= stored_player[i].mapped_action;
-
- if (!network_playing)
- stored_player[i].effective_action = stored_player[i].mapped_action;
- }
-#else
for (i = 0; i < MAX_PLAYERS; i++)
{
summarized_player_action |= stored_player[i].action;
if (!network_playing)
stored_player[i].effective_action = stored_player[i].action;
}
-#endif
#if defined(NETWORK_AVALIABLE)
if (network_playing)
(i == game.centered_player_nr ? summarized_player_action : 0);
}
-#if 0 /* USE_NEW_PLAYER_ASSIGNMENTS */
- if (recorded_player_action != NULL)
- for (i = 0; i < MAX_PLAYERS; i++)
- stored_player[i].effective_action =
- recorded_player_action[map_player_action[i]];
-#else
if (recorded_player_action != NULL)
for (i = 0; i < MAX_PLAYERS; i++)
- stored_player[i].effective_action =
- recorded_player_action[i];
-#endif
+ stored_player[i].effective_action = recorded_player_action[i];
for (i = 0; i < MAX_PLAYERS; i++)
{
-#if 0 /* USE_NEW_PLAYER_ASSIGNMENTS */
- tape_action[i] = stored_player[i].action;
-#else
tape_action[i] = stored_player[i].effective_action;
-#endif
/* (this can only happen in the R'n'D game engine) */
if (tape.recording && tape_action[i] && !tape.player_participates[i])
#if USE_NEW_PLAYER_ASSIGNMENTS
{
-#if 0
-
- for (i = 0; i < MAX_PLAYERS; i++)
- stored_player[i].mapped_action = stored_player[map_player_action[i]].action;
-
-#else
-
-#if 1
- byte unmapped_action[MAX_PLAYERS];
-
- for (i = 0; i < MAX_PLAYERS; i++)
- unmapped_action[i] = stored_player[i].effective_action;
+ byte mapped_action[MAX_PLAYERS];
for (i = 0; i < MAX_PLAYERS; i++)
- stored_player[i].effective_action = unmapped_action[map_player_action[i]];
-#endif
+ mapped_action[i] = stored_player[map_player_action[i]].effective_action;
-#if 0
for (i = 0; i < MAX_PLAYERS; i++)
- printf("::: %d: %d [%d]\n", i, stored_player[i].effective_action,
- map_player_action[i]);
-#endif
-#endif
+ stored_player[i].effective_action = mapped_action[i];
}
-#else
- for (i = 0; i < MAX_PLAYERS; i++)
- stored_player[i].mapped_action = stored_player[i].action;
#endif
if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
{
GameActions_EM_Main();
}
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+ {
+ GameActions_SP_Main();
+ }
else
{
GameActions_RND();
AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */
}
+void GameActions_SP_Main()
+{
+ byte effective_action[MAX_PLAYERS];
+ boolean warp_mode = (tape.playing && tape.warp_forward && !tape.pausing);
+ int i;
+
+ for (i = 0; i < MAX_PLAYERS; i++)
+ 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()
{
int magic_wall_x = 0, magic_wall_y = 0;
PlayLevelSoundElementAction(nextx, nexty, EL_SOKOBAN_FIELD_EMPTY,
ACTION_FILLING);
+#if 1
+ if (local_player->sokobanfields_still_needed == 0 &&
+ (game.emulation == EMU_SOKOBAN || level.auto_exit_sokoban))
+#else
if (local_player->sokobanfields_still_needed == 0 &&
game.emulation == EMU_SOKOBAN)
+#endif
{
PlayerWins(player);