#include "libgame/libgame.h"
#include "game.h"
+#include "init.h"
#include "tools.h"
#include "screens.h"
-#include "init.h"
#include "files.h"
#include "tape.h"
#include "network.h"
{
int i;
+ /* set game engine from tape file when re-playing, else from level file */
game.engine_version = (tape.playing ? tape.engine_version :
level.game_version);
+ /* dynamically adjust element properties according to game engine version */
+ InitElementPropertiesEngine(game.engine_version);
+
#if 0
printf("level %d: level version == %06d\n", level_nr, level.game_version);
printf(" tape version == %06d [%s] [file: %06d]\n",
game.initial_move_delay_value =
(level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED);
+#if 0
/* dynamically adjust element properties according to game engine version */
{
static int ep_em_slippery_wall[] =
(level.em_slippery_gems &&
game.engine_version > VERSION_IDENT(2,0,1)));
}
+#endif
/* initialize changing elements information */
for (i=0; i<MAX_NUM_ELEMENTS; i++)
if (setup.sound_music)
PlayMusic(level_nr);
- KeyboardAutoRepeatOff();
+ KeyboardAutoRepeatOffUnlessAutoplay();
if (options.debug)
{
if ((hi_pos = NewHiScore()) >= 0)
{
- game_status = HALLOFFAME;
+ game_status = GAME_MODE_SCORES;
DrawHallOfFame(hi_pos);
if (raise_level)
{
}
else
{
- game_status = MAINMENU;
+ game_status = GAME_MODE_MAIN;
if (raise_level)
{
level_nr++;
{
int center_element = Feld[ex][ey];
- /* remove things displayed in background while burnig dynamite */
- if (!IS_INDESTRUCTIBLE(Back[x][y]))
- Back[x][y] = 0;
+ /* remove things displayed in background while burning dynamite */
+ if (!IS_INDESTRUCTIBLE(Back[ex][ey]))
+ Back[ex][ey] = 0;
if (IS_MOVING(ex, ey) || IS_BLOCKED(ex, ey))
{
}
#if 1
+ if (IS_EXPLOSION_PROOF(element))
+ continue;
+#else
if ((IS_INDESTRUCTIBLE(element) &&
(game.engine_version < VERSION_IDENT(2,2,0) ||
(!IS_WALKABLE_OVER(element) && !IS_WALKABLE_UNDER(element)))) ||
element == EL_FLAMES)
continue;
-#else
- if (IS_INDESTRUCTIBLE(element) || element == EL_FLAMES)
- continue;
#endif
if (IS_PLAYER(x, y) && SHIELD_ON(PLAYERINFO(x, y)))
continue;
}
-#if 1
/* save walkable background elements while explosion on same tile */
if (IS_INDESTRUCTIBLE(element))
Back[x][y] = element;
-#endif
/* ignite explodable elements reached by other explosion */
if (element == EL_EXPLOSION)
element = Store2[x][y];
-#if 0
- else if (IS_INDESTRUCTIBLE(Store2[x][y])) /* hard element under bomb */
- element = Store2[x][y];
-#endif
-
-#if 0
- else if (IS_INDESTRUCTIBLE(Store[x][y])) /* hard element under bomb */
- element = Store[x][y];
-#endif
-
if (IS_PLAYER(ex, ey) && !PLAYER_PROTECTED(ex, ey))
{
switch(StorePlayer[ex][ey])
if (game.emulation == EMU_SUPAPLEX)
Store[x][y] = EL_EMPTY;
}
-#if 0
- else if (IS_INDESTRUCTIBLE(Store[x][y]))
- ;
-#endif
-#if 0
- else if (IS_INDESTRUCTIBLE(element))
- Store[x][y] = element;
-#endif
-#if 0
- else if (IS_INDESTRUCTIBLE(element) && IS_ACCESSIBLE(element))
- Store[x][y] = element;
-#endif
else if (center_element == EL_MOLE)
Store[x][y] = EL_EMERALD_RED;
else if (center_element == EL_PENGUIN)
Store[x][y] = EL_PEARL;
else if (element == EL_WALL_CRYSTAL)
Store[x][y] = EL_CRYSTAL;
-#if 1
-#if 0
-#if 0
- else if (IS_INDESTRUCTIBLE(element) && IS_ACCESSIBLE(element))
- Store[x][y] = element;
-#else
- else if (IS_INDESTRUCTIBLE(element))
- Store[x][y] = element;
-#endif
-#endif
else
Store[x][y] = EL_EMPTY;
-#else
-
-#if 0
- else if (IS_PFORTE(element))
- Store[x][y] = element;
- else
- Store[x][y] = EL_EMPTY;
-#else
- else if (!IS_PFORTE(Store[x][y]))
- Store[x][y] = EL_EMPTY;
-#endif
-
-#endif
if (x != ex || y != ey ||
center_element == EL_AMOEBA_TO_DIAMOND || mode == EX_BORDER)
if (IS_PLAYER(x, y))
KillHeroUnlessProtected(x, y);
- else if (IS_EXPLOSIVE(element))
+ else if (IS_CAN_EXPLODE(element))
{
Feld[x][y] = Store2[x][y];
Store2[x][y] = 0;
element = Feld[x][y] = Store[x][y];
Store[x][y] = Store2[x][y] = 0;
-#if 1
if (Back[x][y] && IS_INDESTRUCTIBLE(Back[x][y]))
element = Feld[x][y] = Back[x][y];
Back[x][y] = 0;
-#endif
MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0;
InitField(x, y, FALSE);
- if (CAN_MOVE(element) || COULD_MOVE(element))
+ if (CAN_MOVE(element))
InitMovDir(x, y);
DrawLevelField(x, y);
if (phase == delay)
DrawLevelFieldCrumbledSand(x, y);
-#if 1
if (IS_WALKABLE_OVER(Back[x][y]))
{
DrawLevelElement(x, y, Back[x][y]);
}
else if (!IS_WALKABLE_INSIDE(Back[x][y]))
DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame);
-#else
- if (IS_PFORTE(Store[x][y]))
- {
- DrawLevelElement(x, y, Store[x][y]);
- DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
- }
- else
- DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame);
-#endif
}
}
if (!lastline && object_hit) /* check which object was hit */
{
- if (CAN_CHANGE(element) &&
+ if (CAN_PASS_MAGIC_WALL(element) &&
(smashed == EL_MAGIC_WALL ||
smashed == EL_BD_MAGIC_WALL))
{
int rnd = RND(rnd_value);
if (IN_LEV_FIELD(left_x, left_y) &&
- (IS_FREE(left_x, left_y) || IS_GEM(Feld[left_x][left_y])))
+ (IS_FREE(left_x, left_y) || IS_FOOD_PIG(Feld[left_x][left_y])))
can_turn_left = TRUE;
if (IN_LEV_FIELD(right_x, right_y) &&
- (IS_FREE(right_x, right_y) || IS_GEM(Feld[right_x][right_y])))
+ (IS_FREE(right_x, right_y) || IS_FOOD_PIG(Feld[right_x][right_y])))
can_turn_right = TRUE;
if (IN_LEV_FIELD(move_x, move_y) &&
- (IS_FREE(move_x, move_y) || IS_GEM(Feld[move_x][move_y])))
+ (IS_FREE(move_x, move_y) || IS_FOOD_PIG(Feld[move_x][move_y])))
can_move_on = TRUE;
if (can_turn_left &&
MovDir[x][y] = back_dir;
if (!IS_FREE(x+move_xy[MovDir[x][y]].x, y+move_xy[MovDir[x][y]].y) &&
- !IS_GEM(Feld[x+move_xy[MovDir[x][y]].x][y+move_xy[MovDir[x][y]].y]))
+ !IS_FOOD_PIG(Feld[x+move_xy[MovDir[x][y]].x][y+move_xy[MovDir[x][y]].y]))
MovDir[x][y] = old_move_dir;
MovDelay[x][y] = 0;
void StartMoving(int x, int y)
{
- static boolean use_spring_bug = TRUE;
+ boolean use_spring_bug = (game.engine_version < VERSION_IDENT(2,2,0));
boolean started_moving = FALSE; /* some elements can fall _and_ move */
int element = Feld[x][y];
Store[x][y] = 0;
}
}
- else if (CAN_CHANGE(element) &&
+ else if (CAN_PASS_MAGIC_WALL(element) &&
(Feld[x][y+1] == EL_MAGIC_WALL_ACTIVE ||
Feld[x][y+1] == EL_BD_MAGIC_WALL_ACTIVE))
{
int sx = SCREENX(xx), sy = SCREENY(yy);
int flame_graphic = graphic + (i - 1);
- if (!IN_LEV_FIELD(xx, yy) ||
- IS_SOLID(Feld[xx][yy]) || Feld[xx][yy] == EL_EXPLOSION)
+ if (!IN_LEV_FIELD(xx, yy) || IS_DRAGONFIRE_PROOF(Feld[xx][yy]))
break;
if (MovDelay[x][y])
{
int flamed = MovingOrBlocked2Element(xx, yy);
- if (IS_ENEMY(flamed) || IS_EXPLOSIVE(flamed))
+ if (IS_ENEMY(flamed) || IS_CAN_EXPLODE(flamed))
Bang(xx, yy);
else
RemoveMovingField(xx, yy);
}
else if (element == EL_PIG && IN_LEV_FIELD(newx, newy))
{
- if (IS_GEM(Feld[newx][newy]))
+ if (IS_FOOD_PIG(Feld[newx][newy]))
{
if (IS_MOVING(newx, newy))
RemoveMovingField(newx, newy);
{
if (MovDir[x][y] == MV_LEFT)
{
- if (IN_LEV_FIELD(x - 1, y) && IS_MAUER(Feld[x - 1][y]))
+ if (IN_LEV_FIELD(x - 1, y) && IS_WALL(Feld[x - 1][y]))
DrawLevelField(x - 1, y);
}
else if (MovDir[x][y] == MV_RIGHT)
{
- if (IN_LEV_FIELD(x + 1, y) && IS_MAUER(Feld[x + 1][y]))
+ if (IN_LEV_FIELD(x + 1, y) && IS_WALL(Feld[x + 1][y]))
DrawLevelField(x + 1, y);
}
else if (MovDir[x][y] == MV_UP)
{
- if (IN_LEV_FIELD(x, y - 1) && IS_MAUER(Feld[x][y - 1]))
+ if (IN_LEV_FIELD(x, y - 1) && IS_WALL(Feld[x][y - 1]))
DrawLevelField(x, y - 1);
}
else
{
- if (IN_LEV_FIELD(x, y + 1) && IS_MAUER(Feld[x][y + 1]))
+ if (IN_LEV_FIELD(x, y + 1) && IS_WALL(Feld[x][y + 1]))
DrawLevelField(x, y + 1);
}
if (element == EL_EXPANDABLE_WALL && (links_frei || rechts_frei))
DrawLevelField(ax, ay);
- if (!IN_LEV_FIELD(ax, ay-1) || IS_MAUER(Feld[ax][ay-1]))
+ if (!IN_LEV_FIELD(ax, ay-1) || IS_WALL(Feld[ax][ay-1]))
oben_massiv = TRUE;
- if (!IN_LEV_FIELD(ax, ay+1) || IS_MAUER(Feld[ax][ay+1]))
+ if (!IN_LEV_FIELD(ax, ay+1) || IS_WALL(Feld[ax][ay+1]))
unten_massiv = TRUE;
- if (!IN_LEV_FIELD(ax-1, ay) || IS_MAUER(Feld[ax-1][ay]))
+ if (!IN_LEV_FIELD(ax-1, ay) || IS_WALL(Feld[ax-1][ay]))
links_massiv = TRUE;
- if (!IN_LEV_FIELD(ax+1, ay) || IS_MAUER(Feld[ax+1][ay]))
+ if (!IN_LEV_FIELD(ax+1, ay) || IS_WALL(Feld[ax+1][ay]))
rechts_massiv = TRUE;
if (((oben_massiv && unten_massiv) ||
byte *recorded_player_action;
byte summarized_player_action = 0;
- if (game_status != PLAYING)
+ if (game_status != GAME_MODE_PLAYING)
return;
action_delay_value =
HandleNetworking();
#endif
- if (game_status != PLAYING)
+ if (game_status != GAME_MODE_PLAYING)
return;
if (!network_player_action_received)
if (!player->active || (!dx && !dy))
return FALSE;
+#if 0
+ {
+ static boolean done = FALSE;
+ static old_count = -1;
+
+ if (FrameCounter < old_count)
+ done = FALSE;
+
+ if (FrameCounter < 100)
+ {
+ printf("::: wanna move [%d] [%d]\n",
+ FrameCounter, player->push_delay_value);
+ done = TRUE;
+ old_count = FrameCounter;
+ }
+ }
+#endif
+
#if 0
if (!FrameReached(&player->move_delay, player->move_delay_value) &&
!tape.playing)
if (!player->active)
return;
-#if 1
/* remove accessible field at the player's position */
Feld[jx][jy] = EL_EMPTY;
-#else
- if (IS_PFORTE(Feld[jx][jy]))
- Feld[jx][jy] = EL_EMPTY;
-#endif
/* deactivate shield (else Bang()/Explode() would not work right) */
player->shield_normal_time_left = 0;
ExitY = ZY = jy;
}
-#if 0
/*
checkDiagonalPushing()
-----------------------------------------------------------------------------
check if diagonal input device direction results in pushing of object
+ (by checking if the alternative direction is walkable, diggable, ...)
*/
-static boolean checkDiagonalPushing(int x, int y, int real_dx, int real_dy)
+static boolean checkDiagonalPushing(struct PlayerInfo *player,
+ int x, int y, int real_dx, int real_dy)
{
+ int jx, jy, dx, dy, xx, yy;
+
+ if (real_dx == 0 || real_dy == 0) /* no diagonal direction => push */
+ return TRUE;
+
+ /* diagonal direction: check alternative direction */
+ jx = player->jx;
+ jy = player->jy;
+ dx = x - jx;
+ dy = y - jy;
+ xx = jx + (dx == 0 ? real_dx : 0);
+ yy = jy + (dy == 0 ? real_dy : 0);
+
+ return (!IN_LEV_FIELD(xx, yy) || IS_SOLID_FOR_PUSHING(Feld[xx][yy]));
}
-#endif
/*
DigField()
dy == +1 ? MV_DOWN : MV_NO_MOVING);
int element;
+#if 0
+ {
+ static boolean done = FALSE;
+
+ if (FrameCounter < 10)
+ done = FALSE;
+
+ if (!done &&
+ real_dx == -1 &&
+ FrameCounter > 10)
+ {
+ printf("::: wanna move left [%d] [%d]\n",
+ FrameCounter, player->push_delay_value);
+ done = TRUE;
+ }
+ }
+#endif
+
if (player->MovPos == 0)
{
player->is_digging = FALSE;
if (IS_MOVING(x, y) || IS_PLAYER(x, y))
return MF_NO_ACTION;
- if (IS_TUBE(Feld[jx][jy]))
+#if 0
+ if (IS_TUBE(Feld[jx][jy]) || IS_TUBE(Back[jx][jy]))
+#else
+ if (IS_TUBE(Feld[jx][jy]) ||
+ (IS_TUBE(Back[jx][jy]) && game.engine_version >= VERSION_IDENT(2,2,0)))
+#endif
{
int i = 0;
+ int tube_element = (IS_TUBE(Feld[jx][jy]) ? Feld[jx][jy] : Back[jx][jy]);
int tube_leave_directions[][2] =
{
{ EL_TUBE_ANY, MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
{ -1, MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN }
};
- while (tube_leave_directions[i][0] != Feld[jx][jy])
+ while (tube_leave_directions[i][0] != tube_element)
{
i++;
if (tube_leave_directions[i][0] == -1) /* should not happen */
player->Pushing = TRUE;
+#if 0
+ if (element == EL_ROCK)
+ printf("::: wanna push [%d] [%d]\n",
+ FrameCounter, player->push_delay_value);
+#endif
+
if (!IN_LEV_FIELD(x+dx, y+dy) || !IS_FREE(x+dx, y+dy))
return MF_NO_ACTION;
- if (real_dy)
- {
- if (IN_LEV_FIELD(jx, jy+real_dy) && !IS_SOLID(Feld[jx][jy+real_dy]))
- return MF_NO_ACTION;
- }
+ if (!checkDiagonalPushing(player, x, y, real_dx, real_dy))
+ return MF_NO_ACTION;
if (player->push_delay == 0)
player->push_delay = FrameCounter;
|| !IS_SB_ELEMENT(element))))
return MF_NO_ACTION;
- if (dx && real_dy)
- {
- if (IN_LEV_FIELD(jx, jy+real_dy) && !IS_SOLID(Feld[jx][jy+real_dy]))
- return MF_NO_ACTION;
- }
- else if (dy && real_dx)
- {
- if (IN_LEV_FIELD(jx+real_dx, jy) && !IS_SOLID(Feld[jx+real_dx][jy]))
- return MF_NO_ACTION;
- }
+ if (!checkDiagonalPushing(player, x, y, real_dx, real_dy))
+ return MF_NO_ACTION;
if (player->push_delay == 0)
player->push_delay = FrameCounter;
if (!IN_LEV_FIELD(x+dx, y+dy) || !IS_FREE(x+dx, y+dy))
return MF_NO_ACTION;
- if (dx && real_dy)
- {
- if (IN_LEV_FIELD(jx, jy+real_dy) && !IS_SOLID(Feld[jx][jy+real_dy]))
- return MF_NO_ACTION;
- }
- else if (dy && real_dx)
- {
- if (IN_LEV_FIELD(jx+real_dx, jy) && !IS_SOLID(Feld[jx+real_dx][jy]))
- return MF_NO_ACTION;
- }
+ if (!checkDiagonalPushing(player, x, y, real_dx, real_dy))
+ return MF_NO_ACTION;
if (player->push_delay == 0)
player->push_delay = FrameCounter;
IS_ACTIVE_BOMB(element) || element == EL_EXPLOSION)
return FALSE;
+#if 0
+ if (element != EL_EMPTY)
+ return FALSE;
+#endif
+
if (element != EL_EMPTY)
{
#if 0
else
#endif
{
- game_status = MAINMENU;
+ game_status = GAME_MODE_MAIN;
DrawMainMenu();
}
}
{
int id = gi->custom_id;
- if (game_status != PLAYING)
+ if (game_status != GAME_MODE_PLAYING)
return;
switch (id)