ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x, y, Tile[x][y] == EL_DIAMOND)
#define DARK_YAMYAM_CAN_ENTER_FIELD(e, x, y) \
- ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x,y, IS_FOOD_DARK_YAMYAM(Tile[x][y]))
+ ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x, y, IS_FOOD_DARK_YAMYAM(Tile[x][y]))
#define PACMAN_CAN_ENTER_FIELD(e, x, y) \
ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x, y, IS_AMOEBOID(Tile[x][y]))
static void ExecuteCustomElementAction(int, int, int, int);
static boolean ChangeElement(int, int, int, int);
-static boolean CheckTriggeredElementChangeExt(int, int, int, int, int,int,int);
+static boolean CheckTriggeredElementChangeExt(int, int, int, int, int, int, int);
#define CheckTriggeredElementChange(x, y, e, ev) \
- CheckTriggeredElementChangeExt(x,y,e,ev, CH_PLAYER_ANY,CH_SIDE_ANY, -1)
+ CheckTriggeredElementChangeExt(x,y,e,ev, CH_PLAYER_ANY, CH_SIDE_ANY, -1)
#define CheckTriggeredElementChangeByPlayer(x, y, e, ev, p, s) \
CheckTriggeredElementChangeExt(x, y, e, ev, p, s, -1)
#define CheckTriggeredElementChangeBySide(x, y, e, ev, s) \
player->active = TRUE;
// remove potentially duplicate players
- if (StorePlayer[jx][jy] == Tile[x][y])
+ if (IN_LEV_FIELD(jx, jy) && StorePlayer[jx][jy] == Tile[x][y])
StorePlayer[jx][jy] = 0;
StorePlayer[x][y] = Tile[x][y];
int element = gpc->value;
int graphic = el2panelimg(element);
int init_gfx_random = (graphic_info[graphic].anim_global_sync ?
- sync_random_frame : INIT_GFX_RANDOM());
+ sync_random_frame :
+ graphic_info[graphic].anim_global_anim_sync ?
+ getGlobalAnimSyncFrame() : INIT_GFX_RANDOM());
if (gpc->value != gpc->last_value)
{
int last_anim_random_frame = gfx.anim_random_frame;
int graphic = gpc->graphic;
int init_gfx_random = (graphic_info[graphic].anim_global_sync ?
- sync_random_frame : INIT_GFX_RANDOM());
+ sync_random_frame :
+ graphic_info[graphic].anim_global_anim_sync ?
+ getGlobalAnimSyncFrame() : INIT_GFX_RANDOM());
if (gpc->value != gpc->last_value)
{
for (j = 0; j < ei->num_change_pages; j++)
{
- ei->change_page[j].actual_trigger_element = EL_EMPTY;
- ei->change_page[j].actual_trigger_player = EL_EMPTY;
- ei->change_page[j].actual_trigger_player_bits = CH_PLAYER_NONE;
- ei->change_page[j].actual_trigger_side = CH_SIDE_NONE;
- ei->change_page[j].actual_trigger_ce_value = 0;
- ei->change_page[j].actual_trigger_ce_score = 0;
+ struct ElementChangeInfo *change = &ei->change_page[j];
+
+ change->actual_trigger_element = EL_EMPTY;
+ change->actual_trigger_player = EL_EMPTY;
+ change->actual_trigger_player_bits = CH_PLAYER_NONE;
+ change->actual_trigger_side = CH_SIDE_NONE;
+ change->actual_trigger_ce_value = 0;
+ change->actual_trigger_ce_score = 0;
}
}
for (j = 0; j < ei->num_change_pages; j++)
{
- if (!ei->change_page[j].can_change_or_has_action)
+ struct ElementChangeInfo *change = &ei->change_page[j];
+
+ if (!change->can_change_or_has_action)
continue;
- if (ei->change_page[j].has_event[CE_BY_OTHER_ACTION])
+ if (change->has_event[CE_BY_OTHER_ACTION])
{
- int trigger_element = ei->change_page[j].trigger_element;
+ int trigger_element = change->trigger_element;
for (k = 0; k < NUM_CHANGE_EVENTS; k++)
{
- if (ei->change_page[j].has_event[k])
+ if (change->has_event[k])
{
if (IS_GROUP_ELEMENT(trigger_element))
{
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 restarting = (game_status == GAME_MODE_PLAYING);
boolean emulate_bd = TRUE; // unless non-BOULDERDASH elements found
boolean emulate_sp = TRUE; // unless non-SUPAPLEX elements found
int initial_move_dir = MV_DOWN;
if (!game.restart_level)
CloseDoor(DOOR_CLOSE_1);
- SetGameStatus(GAME_MODE_PLAYING);
+ if (restarting)
+ {
+ // force fading out global animations displayed during game play
+ SetGameStatus(GAME_MODE_PSEUDO_RESTARTING);
+ }
+ else
+ {
+ SetGameStatus(GAME_MODE_PLAYING);
+ }
if (level_editor_test_game)
FadeSkipNextFadeOut();
FadeOut(fade_mask);
+ if (restarting)
+ {
+ // force restarting global animations displayed during game play
+ RestartGlobalAnimsByStatus(GAME_MODE_PSEUDO_RESTARTING);
+
+ SetGameStatus(GAME_MODE_PLAYING);
+ }
+
if (level_editor_test_game)
FadeSkipNextFadeIn();
}
game.restart_level = FALSE;
- game.restart_game_message = NULL;
game.request_active = FALSE;
game.request_active_or_moving = FALSE;
game.LevelSolved = TRUE;
game.GameOver = TRUE;
+ tape.solved = TRUE;
+
// needed here to display correct panel values while player walks into exit
LevelSolved_SetFinalGameValues();
}
if (graphic_info[graphic].anim_global_sync)
GfxFrame[x][y] = FrameCounter;
+ else if (graphic_info[graphic].anim_global_anim_sync)
+ GfxFrame[x][y] = getGlobalAnimSyncFrame();
else if (ANIM_MODE(graphic) == ANIM_CE_VALUE)
GfxFrame[x][y] = CustomValue[x][y];
else if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
void Blocked2Moving(int x, int y, int *comes_from_x, int *comes_from_y)
{
- int oldx = x, oldy = y;
int direction = MovDir[x][y];
-
- if (direction == MV_LEFT)
- oldx++;
- else if (direction == MV_RIGHT)
- oldx--;
- else if (direction == MV_UP)
- oldy++;
- else if (direction == MV_DOWN)
- oldy--;
+ int oldx = x + (direction & MV_LEFT ? +1 : direction & MV_RIGHT ? -1 : 0);
+ int oldy = y + (direction & MV_UP ? +1 : direction & MV_DOWN ? -1 : 0);
*comes_from_x = oldx;
*comes_from_y = oldy;
int oldx, oldy;
Blocked2Moving(x, y, &oldx, &oldy);
+
return Tile[oldx][oldy];
}
- else
- return element;
+
+ return element;
}
static int MovingOrBlocked2ElementIfNotLeaving(int x, int y)
{
// like MovingOrBlocked2Element(), but if element is moving
- // and (x,y) is the field the moving element is just leaving,
+ // and (x, y) is the field the moving element is just leaving,
// return EL_BLOCKED instead of the element value
int element = Tile[x][y];
*sy = (sy1 + sy2) / 2;
}
-static void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir,
+static void DrawRelocateScreen(int old_x, int old_y, int x, int y,
boolean center_screen, boolean quick_relocation)
{
unsigned int frame_delay_value_old = GetVideoFrameDelay();
}
// only visually relocate centered player
- DrawRelocateScreen(old_jx, old_jy, player->jx, player->jy, player->MovDir,
+ DrawRelocateScreen(old_jx, old_jy, player->jx, player->jy,
FALSE, level.instant_relocation);
TestIfPlayerTouchesBadThing(jx, jy);
int last_phase;
int border_element;
- // !!! eliminate this variable !!!
- int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
-
if (game.explosions_delayed)
{
ExplodeField[ex][ey] = mode;
if (phase == EX_PHASE_START) // initialize 'Store[][]' field
{
int center_element = Tile[ex][ey];
+ int ce_value = CustomValue[ex][ey];
+ int ce_score = element_info[center_element].collect_score;
int artwork_element, explosion_element; // set these values later
// remove things displayed in background while burning dynamite
else
Store[x][y] = EL_EMPTY;
+ if (IS_CUSTOM_ELEMENT(center_element))
+ Store[x][y] = (Store[x][y] == EL_CURRENT_CE_VALUE ? ce_value :
+ Store[x][y] == EL_CURRENT_CE_SCORE ? ce_score :
+ Store[x][y] >= EL_PREV_CE_8 &&
+ Store[x][y] <= EL_NEXT_CE_8 ?
+ RESOLVED_REFERENCE_ELEMENT(center_element, Store[x][y]) :
+ Store[x][y]);
+
if (x != ex || y != ey || mode == EX_TYPE_BORDER ||
center_element == EL_AMOEBA_TO_DIAMOND)
Store2[x][y] = element;
int graphic = el_act2img(GfxElement[x][y], ACTION_EXPLODING);
int frame = getGraphicAnimationFrameXY(graphic, x, y);
- if (phase == delay)
+ if (phase == 1)
TEST_DrawLevelFieldCrumbled(x, y);
if (IS_WALKABLE_OVER(Back[x][y]) && Back[x][y] != EL_EMPTY)
}
}
-static void ToggleSwitchgateSwitch(int x, int y)
+static void ToggleSwitchgateSwitch(void)
{
int xx, yy;
smashed == EL_DC_SWITCHGATE_SWITCH_UP ||
smashed == EL_DC_SWITCHGATE_SWITCH_DOWN)
{
- ToggleSwitchgateSwitch(x, y + 1);
+ ToggleSwitchgateSwitch();
}
else if (smashed == EL_LIGHT_SWITCH ||
smashed == EL_LIGHT_SWITCH_ACTIVE)
boolean can_turn_left =
CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, left_x, left_y);
boolean can_turn_right =
- CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, right_x,right_y);
+ CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, right_x, right_y);
if (element_info[element].move_stepsize == 0) // "not moving"
return;
PlayLevelSound(newx, newy, SND_PENGUIN_PASSING);
if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
- DrawGraphicThruMask(SCREENX(newx),SCREENY(newy), el2img(element), 0);
+ DrawGraphicThruMask(SCREENX(newx), SCREENY(newy), el2img(element), 0);
game.friends_still_needed--;
if (!game.friends_still_needed &&
}
else if (IS_FOOD_PENGUIN(Tile[newx][newy]))
{
- if (DigField(local_player, x, y, newx, newy, 0,0, DF_DIG) == MP_MOVING)
+ if (DigField(local_player, x, y, newx, newy, 0, 0, DF_DIG) == MP_MOVING)
TEST_DrawLevelField(newx, newy);
else
GfxDir[x][y] = MovDir[x][y] = MV_NONE;
if (pushed_by_player) // special case: moving object pushed by player
{
- MovPos[x][y] = SIGN(MovPos[x][y]) * (TILEX - ABS(PLAYERINFO(x,y)->MovPos));
+ MovPos[x][y] = SIGN(MovPos[x][y]) * (TILEX - ABS(PLAYERINFO(x, y)->MovPos));
}
else if (use_step_delay) // special case: moving object has step delay
{
CheckElementChangeByPlayer(newx, newy, element, CE_PUSHED_BY_PLAYER,
player->index_bit, push_side);
- CheckTriggeredElementChangeByPlayer(newx,newy, element, CE_PLAYER_PUSHES_X,
+ CheckTriggeredElementChangeByPlayer(newx, newy, element, CE_PLAYER_PUSHES_X,
player->index_bit, push_side);
}
}
}
-static void MauerWaechst(int x, int y)
+static void WallGrowing(int x, int y)
{
int delay = 6;
}
}
-static void MauerAbleger(int ax, int ay)
+static void CheckWallGrowing(int ax, int ay)
{
int element = Tile[ax][ay];
int graphic = el2img(element);
- boolean oben_frei = FALSE, unten_frei = FALSE;
- boolean links_frei = FALSE, rechts_frei = FALSE;
- boolean oben_massiv = FALSE, unten_massiv = FALSE;
- boolean links_massiv = FALSE, rechts_massiv = FALSE;
- boolean new_wall = FALSE;
+ boolean free_top = FALSE;
+ boolean free_bottom = FALSE;
+ boolean free_left = FALSE;
+ boolean free_right = FALSE;
+ boolean stop_top = FALSE;
+ boolean stop_bottom = FALSE;
+ boolean stop_left = FALSE;
+ boolean stop_right = FALSE;
+ boolean new_wall = FALSE;
+
+ boolean is_steelwall = (element == EL_EXPANDABLE_STEELWALL_HORIZONTAL ||
+ element == EL_EXPANDABLE_STEELWALL_VERTICAL ||
+ element == EL_EXPANDABLE_STEELWALL_ANY);
+
+ boolean grow_vertical = (element == EL_EXPANDABLE_WALL_VERTICAL ||
+ element == EL_EXPANDABLE_WALL_ANY ||
+ element == EL_EXPANDABLE_STEELWALL_VERTICAL ||
+ element == EL_EXPANDABLE_STEELWALL_ANY);
+
+ boolean grow_horizontal = (element == EL_EXPANDABLE_WALL_HORIZONTAL ||
+ element == EL_EXPANDABLE_WALL_ANY ||
+ element == EL_EXPANDABLE_WALL ||
+ element == EL_BD_EXPANDABLE_WALL ||
+ element == EL_EXPANDABLE_STEELWALL_HORIZONTAL ||
+ element == EL_EXPANDABLE_STEELWALL_ANY);
+
+ boolean stop_vertical = (element == EL_EXPANDABLE_WALL_VERTICAL ||
+ element == EL_EXPANDABLE_STEELWALL_VERTICAL);
+
+ boolean stop_horizontal = (element == EL_EXPANDABLE_WALL_HORIZONTAL ||
+ element == EL_EXPANDABLE_WALL ||
+ element == EL_EXPANDABLE_STEELWALL_HORIZONTAL);
+
+ int wall_growing = (is_steelwall ?
+ EL_EXPANDABLE_STEELWALL_GROWING :
+ EL_EXPANDABLE_WALL_GROWING);
+
+ int gfx_wall_growing_up = (is_steelwall ?
+ IMG_EXPANDABLE_STEELWALL_GROWING_UP :
+ IMG_EXPANDABLE_WALL_GROWING_UP);
+ int gfx_wall_growing_down = (is_steelwall ?
+ IMG_EXPANDABLE_STEELWALL_GROWING_DOWN :
+ IMG_EXPANDABLE_WALL_GROWING_DOWN);
+ int gfx_wall_growing_left = (is_steelwall ?
+ IMG_EXPANDABLE_STEELWALL_GROWING_LEFT :
+ IMG_EXPANDABLE_WALL_GROWING_LEFT);
+ int gfx_wall_growing_right = (is_steelwall ?
+ IMG_EXPANDABLE_STEELWALL_GROWING_RIGHT :
+ IMG_EXPANDABLE_WALL_GROWING_RIGHT);
if (IS_ANIMATED(graphic))
DrawLevelGraphicAnimationIfNeeded(ax, ay, graphic);
}
if (IN_LEV_FIELD(ax, ay - 1) && IS_FREE(ax, ay - 1))
- oben_frei = TRUE;
+ free_top = TRUE;
if (IN_LEV_FIELD(ax, ay + 1) && IS_FREE(ax, ay + 1))
- unten_frei = TRUE;
+ free_bottom = TRUE;
if (IN_LEV_FIELD(ax - 1, ay) && IS_FREE(ax - 1, ay))
- links_frei = TRUE;
+ free_left = TRUE;
if (IN_LEV_FIELD(ax + 1, ay) && IS_FREE(ax + 1, ay))
- rechts_frei = TRUE;
+ free_right = TRUE;
- if (element == EL_EXPANDABLE_WALL_VERTICAL ||
- element == EL_EXPANDABLE_WALL_ANY)
+ if (grow_vertical)
{
- if (oben_frei)
+ if (free_top)
{
- Tile[ax][ay - 1] = EL_EXPANDABLE_WALL_GROWING;
+ Tile[ax][ay - 1] = wall_growing;
Store[ax][ay - 1] = element;
GfxDir[ax][ay - 1] = MovDir[ax][ay - 1] = MV_UP;
- if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay - 1)))
- DrawLevelGraphic(ax, ay - 1, IMG_EXPANDABLE_WALL_GROWING_UP, 0);
- new_wall = TRUE;
- }
- if (unten_frei)
- {
- Tile[ax][ay + 1] = EL_EXPANDABLE_WALL_GROWING;
- Store[ax][ay + 1] = element;
- GfxDir[ax][ay + 1] = MovDir[ax][ay + 1] = MV_DOWN;
- if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay + 1)))
- DrawLevelGraphic(ax, ay + 1, IMG_EXPANDABLE_WALL_GROWING_DOWN, 0);
- new_wall = TRUE;
- }
- }
- if (element == EL_EXPANDABLE_WALL_HORIZONTAL ||
- element == EL_EXPANDABLE_WALL_ANY ||
- element == EL_EXPANDABLE_WALL ||
- element == EL_BD_EXPANDABLE_WALL)
- {
- if (links_frei)
- {
- Tile[ax - 1][ay] = EL_EXPANDABLE_WALL_GROWING;
- Store[ax - 1][ay] = element;
- GfxDir[ax - 1][ay] = MovDir[ax - 1][ay] = MV_LEFT;
- if (IN_SCR_FIELD(SCREENX(ax - 1), SCREENY(ay)))
- DrawLevelGraphic(ax - 1, ay, IMG_EXPANDABLE_WALL_GROWING_LEFT, 0);
- new_wall = TRUE;
- }
+ if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay - 1)))
+ DrawLevelGraphic(ax, ay - 1, gfx_wall_growing_up, 0);
- if (rechts_frei)
- {
- Tile[ax + 1][ay] = EL_EXPANDABLE_WALL_GROWING;
- Store[ax + 1][ay] = element;
- GfxDir[ax + 1][ay] = MovDir[ax + 1][ay] = MV_RIGHT;
- if (IN_SCR_FIELD(SCREENX(ax + 1), SCREENY(ay)))
- DrawLevelGraphic(ax + 1, ay, IMG_EXPANDABLE_WALL_GROWING_RIGHT, 0);
new_wall = TRUE;
}
- }
-
- if (element == EL_EXPANDABLE_WALL && (links_frei || rechts_frei))
- TEST_DrawLevelField(ax, ay);
-
- if (!IN_LEV_FIELD(ax, ay - 1) || IS_WALL(Tile[ax][ay - 1]))
- oben_massiv = TRUE;
- if (!IN_LEV_FIELD(ax, ay + 1) || IS_WALL(Tile[ax][ay + 1]))
- unten_massiv = TRUE;
- if (!IN_LEV_FIELD(ax - 1, ay) || IS_WALL(Tile[ax - 1][ay]))
- links_massiv = TRUE;
- if (!IN_LEV_FIELD(ax + 1, ay) || IS_WALL(Tile[ax + 1][ay]))
- rechts_massiv = TRUE;
-
- if (((oben_massiv && unten_massiv) ||
- element == EL_EXPANDABLE_WALL_HORIZONTAL ||
- element == EL_EXPANDABLE_WALL) &&
- ((links_massiv && rechts_massiv) ||
- element == EL_EXPANDABLE_WALL_VERTICAL))
- Tile[ax][ay] = EL_WALL;
-
- if (new_wall)
- PlayLevelSoundAction(ax, ay, ACTION_GROWING);
-}
-
-static void MauerAblegerStahl(int ax, int ay)
-{
- int element = Tile[ax][ay];
- int graphic = el2img(element);
- boolean oben_frei = FALSE, unten_frei = FALSE;
- boolean links_frei = FALSE, rechts_frei = FALSE;
- boolean oben_massiv = FALSE, unten_massiv = FALSE;
- boolean links_massiv = FALSE, rechts_massiv = FALSE;
- boolean new_wall = FALSE;
-
- if (IS_ANIMATED(graphic))
- DrawLevelGraphicAnimationIfNeeded(ax, ay, graphic);
-
- if (!MovDelay[ax][ay]) // start building new wall
- MovDelay[ax][ay] = 6;
-
- if (MovDelay[ax][ay]) // wait some time before building new wall
- {
- MovDelay[ax][ay]--;
- if (MovDelay[ax][ay])
- return;
- }
-
- if (IN_LEV_FIELD(ax, ay - 1) && IS_FREE(ax, ay - 1))
- oben_frei = TRUE;
- if (IN_LEV_FIELD(ax, ay + 1) && IS_FREE(ax, ay + 1))
- unten_frei = TRUE;
- if (IN_LEV_FIELD(ax - 1, ay) && IS_FREE(ax - 1, ay))
- links_frei = TRUE;
- if (IN_LEV_FIELD(ax + 1, ay) && IS_FREE(ax + 1, ay))
- rechts_frei = TRUE;
- if (element == EL_EXPANDABLE_STEELWALL_VERTICAL ||
- element == EL_EXPANDABLE_STEELWALL_ANY)
- {
- if (oben_frei)
- {
- Tile[ax][ay - 1] = EL_EXPANDABLE_STEELWALL_GROWING;
- Store[ax][ay - 1] = element;
- GfxDir[ax][ay - 1] = MovDir[ax][ay - 1] = MV_UP;
- if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay - 1)))
- DrawLevelGraphic(ax, ay - 1, IMG_EXPANDABLE_STEELWALL_GROWING_UP, 0);
- new_wall = TRUE;
- }
- if (unten_frei)
+ if (free_bottom)
{
- Tile[ax][ay + 1] = EL_EXPANDABLE_STEELWALL_GROWING;
+ Tile[ax][ay + 1] = wall_growing;
Store[ax][ay + 1] = element;
GfxDir[ax][ay + 1] = MovDir[ax][ay + 1] = MV_DOWN;
+
if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay + 1)))
- DrawLevelGraphic(ax, ay + 1, IMG_EXPANDABLE_STEELWALL_GROWING_DOWN, 0);
+ DrawLevelGraphic(ax, ay + 1, gfx_wall_growing_down, 0);
+
new_wall = TRUE;
}
}
- if (element == EL_EXPANDABLE_STEELWALL_HORIZONTAL ||
- element == EL_EXPANDABLE_STEELWALL_ANY)
+ if (grow_horizontal)
{
- if (links_frei)
+ if (free_left)
{
- Tile[ax - 1][ay] = EL_EXPANDABLE_STEELWALL_GROWING;
+ Tile[ax - 1][ay] = wall_growing;
Store[ax - 1][ay] = element;
GfxDir[ax - 1][ay] = MovDir[ax - 1][ay] = MV_LEFT;
+
if (IN_SCR_FIELD(SCREENX(ax - 1), SCREENY(ay)))
- DrawLevelGraphic(ax - 1, ay, IMG_EXPANDABLE_STEELWALL_GROWING_LEFT, 0);
+ DrawLevelGraphic(ax - 1, ay, gfx_wall_growing_left, 0);
+
new_wall = TRUE;
}
- if (rechts_frei)
+ if (free_right)
{
- Tile[ax + 1][ay] = EL_EXPANDABLE_STEELWALL_GROWING;
+ Tile[ax + 1][ay] = wall_growing;
Store[ax + 1][ay] = element;
GfxDir[ax + 1][ay] = MovDir[ax + 1][ay] = MV_RIGHT;
+
if (IN_SCR_FIELD(SCREENX(ax + 1), SCREENY(ay)))
- DrawLevelGraphic(ax + 1, ay, IMG_EXPANDABLE_STEELWALL_GROWING_RIGHT, 0);
+ DrawLevelGraphic(ax + 1, ay, gfx_wall_growing_right, 0);
+
new_wall = TRUE;
}
}
+ if (element == EL_EXPANDABLE_WALL && (free_left || free_right))
+ TEST_DrawLevelField(ax, ay);
+
if (!IN_LEV_FIELD(ax, ay - 1) || IS_WALL(Tile[ax][ay - 1]))
- oben_massiv = TRUE;
+ stop_top = TRUE;
if (!IN_LEV_FIELD(ax, ay + 1) || IS_WALL(Tile[ax][ay + 1]))
- unten_massiv = TRUE;
+ stop_bottom = TRUE;
if (!IN_LEV_FIELD(ax - 1, ay) || IS_WALL(Tile[ax - 1][ay]))
- links_massiv = TRUE;
+ stop_left = TRUE;
if (!IN_LEV_FIELD(ax + 1, ay) || IS_WALL(Tile[ax + 1][ay]))
- rechts_massiv = TRUE;
+ stop_right = TRUE;
- if (((oben_massiv && unten_massiv) ||
- element == EL_EXPANDABLE_STEELWALL_HORIZONTAL) &&
- ((links_massiv && rechts_massiv) ||
- element == EL_EXPANDABLE_STEELWALL_VERTICAL))
- Tile[ax][ay] = EL_STEELWALL;
+ if (((stop_top && stop_bottom) || stop_horizontal) &&
+ ((stop_left && stop_right) || stop_vertical))
+ Tile[ax][ay] = (is_steelwall ? EL_STEELWALL : EL_WALL);
if (new_wall)
PlayLevelSoundAction(ax, ay, ACTION_GROWING);
if (ChangeDelay[x][y] != 0) // continue element change
{
- if (change->can_change)
- {
- int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
+ int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
- if (IS_ANIMATED(graphic))
- DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+ // also needed if CE can not change, but has CE delay with CE action
+ if (IS_ANIMATED(graphic))
+ DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+ if (change->can_change)
+ {
if (change->change_function)
change->change_function(x, y);
}
}
}
+void AdvanceFrameCounter(void)
+{
+ FrameCounter++;
+}
+
+void AdvanceGfxFrame(void)
+{
+ int x, y;
+
+ SCAN_PLAYFIELD(x, y)
+ {
+ GfxFrame[x][y]++;
+ }
+}
+
+static void HandleMouseAction(struct MouseActionInfo *mouse_action,
+ struct MouseActionInfo *mouse_action_last)
+{
+ if (mouse_action->button)
+ {
+ int new_button = (mouse_action->button && mouse_action_last->button == 0);
+ int ch_button = CH_SIDE_FROM_BUTTON(mouse_action->button);
+ int x = mouse_action->lx;
+ int y = mouse_action->ly;
+ int element = Tile[x][y];
+
+ if (new_button)
+ {
+ CheckElementChangeByMouse(x, y, element, CE_CLICKED_BY_MOUSE, ch_button);
+ CheckTriggeredElementChangeByMouse(x, y, element, CE_MOUSE_CLICKED_ON_X,
+ ch_button);
+ }
+
+ CheckElementChangeByMouse(x, y, element, CE_PRESSED_BY_MOUSE, ch_button);
+ CheckTriggeredElementChangeByMouse(x, y, element, CE_MOUSE_PRESSED_ON_X,
+ ch_button);
+
+ if (level.use_step_counter)
+ {
+ boolean counted_click = FALSE;
+
+ // element clicked that can change when clicked/pressed
+ if (CAN_CHANGE_OR_HAS_ACTION(element) &&
+ (HAS_ANY_CHANGE_EVENT(element, CE_CLICKED_BY_MOUSE) ||
+ HAS_ANY_CHANGE_EVENT(element, CE_PRESSED_BY_MOUSE)))
+ counted_click = TRUE;
+
+ // element clicked that can trigger change when clicked/pressed
+ if (trigger_events[element][CE_MOUSE_CLICKED_ON_X] ||
+ trigger_events[element][CE_MOUSE_PRESSED_ON_X])
+ counted_click = TRUE;
+
+ if (new_button && counted_click)
+ CheckLevelTime_StepCounter();
+ }
+ }
+}
+
void StartGameActions(boolean init_network_game, boolean record_tape,
int random_seed)
{
TapeRecordAction(tape_action);
// remember if game was played (especially after tape stopped playing)
- if (!tape.playing && summarized_player_action)
+ if (!tape.playing && summarized_player_action && !checkGameFailed())
game.GamePlayed = TRUE;
#if USE_NEW_PLAYER_ASSIGNMENTS
void GameActions_EM_Main(void)
{
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_EM(effective_action, warp_mode);
+ GameActions_EM(effective_action);
}
void GameActions_SP_Main(void)
{
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);
+ GameActions_SP(effective_action);
for (i = 0; i < MAX_PLAYERS; i++)
{
void GameActions_MM_Main(void)
{
- boolean warp_mode = (tape.playing && tape.warp_forward && !tape.pausing);
+ AdvanceGfxFrame();
- GameActions_MM(local_player->effective_mouse_action, warp_mode);
+ GameActions_MM(local_player->effective_mouse_action);
}
void GameActions_RND_Main(void)
game.centered_player_nr = game.centered_player_nr_next;
game.set_centered_player = FALSE;
- DrawRelocateScreen(0, 0, sx, sy, MV_NONE, TRUE, setup.quick_switch);
+ DrawRelocateScreen(0, 0, sx, sy, TRUE, setup.quick_switch);
DrawGameDoorValues();
}
#endif
}
- if (mouse_action.button)
- {
- int new_button = (mouse_action.button && mouse_action_last.button == 0);
- int ch_button = CH_SIDE_FROM_BUTTON(mouse_action.button);
-
- x = mouse_action.lx;
- y = mouse_action.ly;
- element = Tile[x][y];
-
- if (new_button)
- {
- CheckElementChangeByMouse(x, y, element, CE_CLICKED_BY_MOUSE, ch_button);
- CheckTriggeredElementChangeByMouse(x, y, element, CE_MOUSE_CLICKED_ON_X,
- ch_button);
- }
-
- CheckElementChangeByMouse(x, y, element, CE_PRESSED_BY_MOUSE, ch_button);
- CheckTriggeredElementChangeByMouse(x, y, element, CE_MOUSE_PRESSED_ON_X,
- ch_button);
-
- if (level.use_step_counter)
- {
- boolean counted_click = FALSE;
-
- // element clicked that can change when clicked/pressed
- if (CAN_CHANGE_OR_HAS_ACTION(element) &&
- (HAS_ANY_CHANGE_EVENT(element, CE_CLICKED_BY_MOUSE) ||
- HAS_ANY_CHANGE_EVENT(element, CE_PRESSED_BY_MOUSE)))
- counted_click = TRUE;
-
- // element clicked that can trigger change when clicked/pressed
- if (trigger_events[element][CE_MOUSE_CLICKED_ON_X] ||
- trigger_events[element][CE_MOUSE_PRESSED_ON_X])
- counted_click = TRUE;
-
- if (new_button && counted_click)
- CheckLevelTime_StepCounter();
- }
- }
+ HandleMouseAction(&mouse_action, &mouse_action_last);
SCAN_PLAYFIELD(x, y)
{
CheckExitSP(x, y);
else if (element == EL_EXPANDABLE_WALL_GROWING ||
element == EL_EXPANDABLE_STEELWALL_GROWING)
- MauerWaechst(x, y);
+ WallGrowing(x, y);
else if (element == EL_EXPANDABLE_WALL ||
element == EL_EXPANDABLE_WALL_HORIZONTAL ||
element == EL_EXPANDABLE_WALL_VERTICAL ||
element == EL_EXPANDABLE_WALL_ANY ||
- element == EL_BD_EXPANDABLE_WALL)
- MauerAbleger(x, y);
- else if (element == EL_EXPANDABLE_STEELWALL_HORIZONTAL ||
+ element == EL_BD_EXPANDABLE_WALL ||
+ element == EL_EXPANDABLE_STEELWALL_HORIZONTAL ||
element == EL_EXPANDABLE_STEELWALL_VERTICAL ||
element == EL_EXPANDABLE_STEELWALL_ANY)
- MauerAblegerStahl(x, y);
+ CheckWallGrowing(x, y);
else if (element == EL_FLAMES)
CheckForDragon(x, y);
else if (element == EL_EXPLOSION)
element == EL_DIAGONAL_SHRINKING ||
element == EL_DIAGONAL_GROWING)
{
- graphic = el_act_dir2img(GfxElement[x][y], GfxAction[x][y],GfxDir[x][y]);
+ graphic = el_act_dir2img(GfxElement[x][y], GfxAction[x][y], GfxDir[x][y]);
DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
}
y = RND(lev_fieldy);
element = Tile[x][y];
- if (!IS_PLAYER(x,y) &&
+ if (!IS_PLAYER(x, y) &&
(element == EL_EMPTY ||
CAN_GROW_INTO(element) ||
element == EL_QUICKSAND_EMPTY ||
!AllPlayersInSight(player, new_jx, new_jy))
return MP_NO_ACTION;
- can_move = DigField(player, jx, jy, new_jx, new_jy, real_dx,real_dy, DF_DIG);
+ can_move = DigField(player, jx, jy, new_jx, new_jy, real_dx, real_dy, DF_DIG);
if (can_move != MP_MOVING)
return can_move;
CE_PLAYER_LEAVES_X,
player->index_bit, leave_side);
- if (IS_CUSTOM_ELEMENT(new_element))
- CheckElementChangeByPlayer(jx, jy, new_element, CE_ENTERED_BY_PLAYER,
- player->index_bit, enter_side);
+ // needed because pushed element has not yet reached its destination,
+ // so it would trigger a change event at its previous field location
+ if (!player->is_pushing)
+ {
+ if (IS_CUSTOM_ELEMENT(new_element))
+ CheckElementChangeByPlayer(jx, jy, new_element, CE_ENTERED_BY_PLAYER,
+ player->index_bit, enter_side);
- CheckTriggeredElementChangeByPlayer(jx, jy, new_element,
- CE_PLAYER_ENTERS_X,
- player->index_bit, enter_side);
+ CheckTriggeredElementChangeByPlayer(jx, jy, new_element,
+ CE_PLAYER_ENTERS_X,
+ player->index_bit, enter_side);
+ }
CheckTriggeredElementChangeBySide(jx, jy, player->initial_element,
CE_MOVE_OF_X, move_direction);
TestIfPlayerTouchesBadThing(jx, jy);
TestIfPlayerTouchesCustomElement(jx, jy);
- /* needed because pushed element has not yet reached its destination,
- so it would trigger a change event at its previous field location */
+ // needed because pushed element has not yet reached its destination,
+ // so it would trigger a change event at its previous field location
if (!player->is_pushing)
TestIfElementTouchesCustomElement(jx, jy); // for empty space
player->killed = TRUE;
// remove accessible field at the player's position
- Tile[jx][jy] = EL_EMPTY;
+ RemoveField(jx, jy);
// deactivate shield (else Bang()/Explode() would not work right)
player->shield_normal_time_left = 0;
return;
PlayLevelSoundElementAction(jx, jy, player->artwork_element, ACTION_DYING);
- PlayLevelSound(jx, jy, SND_GAME_LOSING);
RemovePlayer(player);
if (IS_WALKABLE(old_element) && !ACCESS_FROM(old_element, move_direction))
return MP_NO_ACTION; // field has no opening in this direction
- if (IS_PASSABLE(old_element) && !ACCESS_FROM(old_element,opposite_direction))
+ if (IS_PASSABLE(old_element) && !ACCESS_FROM(old_element, opposite_direction))
return MP_NO_ACTION; // field has no opening in this direction
if (player_can_move && element == EL_ACID && move_direction == MV_DOWN)
LevelSolved();
- PlayLevelSound(x, y, SND_GAME_SOKOBAN_SOLVING);
+ PlaySound(SND_GAME_SOKOBAN_SOLVING);
}
}
else
element == EL_DC_SWITCHGATE_SWITCH_UP ||
element == EL_DC_SWITCHGATE_SWITCH_DOWN)
{
- ToggleSwitchgateSwitch(x, y);
+ ToggleSwitchgateSwitch();
}
else if (element == EL_LIGHT_SWITCH ||
element == EL_LIGHT_SWITCH_ACTIVE)
static int getLevelMusicNr(void)
{
+ int level_pos = level_nr - leveldir_current->first_level;
+
if (levelset.music[level_nr] != MUS_UNDEFINED)
return levelset.music[level_nr]; // from config file
else
- return MAP_NOCONF_MUSIC(level_nr); // from music dir
+ return MAP_NOCONF_MUSIC(level_pos); // from music dir
}
static void FadeLevelSounds(void)
"Do you really want to quit the game?");
}
-void RequestRestartGame(char *message)
+static char *getRestartGameMessage(void)
{
- game.restart_game_message = NULL;
+ boolean play_again = hasStartedNetworkGame();
+ static char message[MAX_OUTPUT_LINESIZE];
+ char *game_over_text = "Game over!";
+ char *play_again_text = " Play it again?";
+
+ if (level.game_engine_type == GAME_ENGINE_TYPE_MM &&
+ game_mm.game_over_message != NULL)
+ game_over_text = game_mm.game_over_message;
+
+ snprintf(message, MAX_OUTPUT_LINESIZE, "%s%s", game_over_text,
+ (play_again ? play_again_text : ""));
+ return message;
+}
+
+static void RequestRestartGame(void)
+{
+ char *message = getRestartGameMessage();
boolean has_started_game = hasStartedNetworkGame();
int request_mode = (has_started_game ? REQ_ASK : REQ_CONFIRM);
+ int door_state = DOOR_CLOSE_1;
- if (Request(message, request_mode | REQ_STAY_CLOSED) && has_started_game)
+ if (Request(message, request_mode | REQ_STAY_OPEN) && has_started_game)
{
+ CloseDoor(door_state);
+
StartGameActions(network.enabled, setup.autorecord, level.random_seed);
}
else
{
- // needed in case of envelope request to close game panel
- CloseDoor(DOOR_CLOSE_1);
+ // if game was invoked from level editor, also close tape recorder door
+ if (level_editor_test_game)
+ door_state = DOOR_CLOSE_ALL;
+
+ CloseDoor(door_state);
SetGameStatus(GAME_MODE_MAIN);
}
}
-void CheckGameOver(void)
+boolean CheckRestartGame(void)
{
- static boolean last_game_over = FALSE;
static int game_over_delay = 0;
int game_over_delay_value = 50;
boolean game_over = checkGameFailed();
- // do not handle game over if request dialog is already active
- if (game.request_active)
- return;
-
- // do not ask to play again if game was never actually played
- if (!game.GamePlayed)
- return;
-
if (!game_over)
{
- last_game_over = FALSE;
game_over_delay = game_over_delay_value;
- return;
+ return FALSE;
}
if (game_over_delay > 0)
{
+ if (game_over_delay == game_over_delay_value / 2)
+ PlaySound(SND_GAME_LOSING);
+
game_over_delay--;
- return;
+ return FALSE;
}
- if (last_game_over != game_over)
- game.restart_game_message = (hasStartedNetworkGame() ?
- "Game over! Play it again?" :
- "Game over!");
+ // do not handle game over if request dialog is already active
+ if (game.request_active)
+ return FALSE;
- last_game_over = game_over;
+ // do not ask to play again if game was never actually played
+ if (!game.GamePlayed)
+ return FALSE;
+
+ // do not ask to play again if this was disabled in setup menu
+ if (!setup.ask_on_game_over)
+ return FALSE;
+
+ RequestRestartGame();
+
+ return TRUE;
}
boolean checkGameSolved(void)
if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
SaveEngineSnapshotValues_SP(&buffers);
if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
- SaveEngineSnapshotValues_MM(&buffers);
+ SaveEngineSnapshotValues_MM();
// save values stored in special snapshot structure