#define GET_NEW_MOVE_DELAY(e) ( (element_info[e].move_delay_fixed) + \
RND(element_info[e].move_delay_random))
+#define ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, condition) \
+ (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
+ (condition) || \
+ (DONT_COLLIDE_WITH(e) && \
+ IS_FREE_OR_PLAYER(x, y))))
+
+#define ELEMENT_CAN_ENTER_FIELD_GENERIC_2(x, y, condition) \
+ (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
+ (condition)))
+
+#define ELEMENT_CAN_ENTER_FIELD(e, x, y) \
+ ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, 1)
+
+#define ELEMENT_CAN_ENTER_FIELD_OR_ACID(e, x, y) \
+ ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, (Feld[x][y] == EL_ACID))
+
+#define ELEMENT_CAN_ENTER_FIELD_OR_ACID_2(x, y) \
+ ELEMENT_CAN_ENTER_FIELD_GENERIC_2(x, y, (Feld[x][y] == EL_ACID))
+
+#define ENEMY_CAN_ENTER_FIELD(x, y) (IN_LEV_FIELD(x, y) && IS_FREE(x, y))
+
+#define YAMYAM_CAN_ENTER_FIELD(x, y) \
+ (IN_LEV_FIELD(x, y) && (IS_FREE_OR_PLAYER(x, y) || \
+ Feld[x][y] == EL_DIAMOND))
+
+#define DARK_YAMYAM_CAN_ENTER_FIELD(x, y) \
+ (IN_LEV_FIELD(x, y) && (IS_FREE_OR_PLAYER(x, y) || \
+ IS_FOOD_DARK_YAMYAM(Feld[x][y])))
+
+#define PACMAN_CAN_ENTER_FIELD(x, y) \
+ (IN_LEV_FIELD(x, y) && (IS_FREE_OR_PLAYER(x, y) || \
+ IS_AMOEBOID(Feld[x][y])))
+
+#define PIG_CAN_ENTER_FIELD(x, y) \
+ (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
+ IS_FOOD_PIG(Feld[x][y])))
+
+#define PENGUIN_CAN_ENTER_FIELD(x, y) \
+ (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
+ IS_FOOD_PENGUIN(Feld[x][y]) || \
+ Feld[x][y] == EL_EXIT_OPEN || \
+ Feld[x][y] == EL_ACID))
+
+#define MOLE_CAN_ENTER_FIELD(x, y, condition) \
+ (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || (condition)))
+
+#define IN_LEV_FIELD_AND_IS_FREE(x, y) (IN_LEV_FIELD(x, y) && IS_FREE(x, y))
+#define IN_LEV_FIELD_AND_NOT_FREE(x, y) (IN_LEV_FIELD(x, y) && !IS_FREE(x, y))
+
/* game button identifiers */
#define GAME_CTRL_ID_STOP 0
#define GAME_CTRL_ID_PAUSE 1
static void KillHeroUnlessProtected(int, int);
static void CheckTriggeredElementChange(int, int);
+static void CheckPlayerElementChange(int, int, int, int);
static void ChangeElementDoIt(int, int, int);
static void PlaySoundLevel(int, int, int);
player->actual_frame_counter = 0;
player->last_move_dir = MV_NO_MOVING;
- player->is_moving = FALSE;
player->is_moving = FALSE;
player->is_waiting = FALSE;
void InitMovingField(int x, int y, int direction)
{
int element = Feld[x][y];
- int newx = x + (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
- int newy = y + (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
+ int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
+ int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
+ int newx = x + dx;
+ int newy = y + dy;
if (!JustStopped[x][y] || direction != MovDir[x][y])
ResetGfxAnimation(x, y);
DrawLevelField(x, y);
}
-#if 1
if (impact && CAN_EXPLODE_IMPACT(element))
-#else
- if ((element == EL_BOMB ||
- element == EL_SP_DISK_ORANGE ||
- element == EL_DX_SUPABOMB) &&
- (lastline || object_hit)) /* element is bomb */
-#endif
{
Bang(x, y);
return;
return;
}
-#if 1
if (object_hit) /* check which object was hit */
-#else
- if (!lastline && object_hit) /* check which object was hit */
-#endif
{
if (CAN_PASS_MAGIC_WALL(element) &&
(smashed == EL_MAGIC_WALL ||
Bang(x, y + 1);
return;
}
-#if 1
else if (CAN_SMASH_EVERYTHING(element))
-#else
- else if (element == EL_ROCK ||
- element == EL_SP_ZONK ||
- element == EL_BD_ROCK)
-#endif
{
if (IS_CLASSIC_ENEMY(smashed) ||
-#if 1
CAN_EXPLODE_SMASHED(smashed))
-#else
- smashed == EL_BOMB ||
- smashed == EL_SP_DISK_ORANGE ||
- smashed == EL_DX_SUPABOMB ||
- smashed == EL_SATELLITE ||
- smashed == EL_PIG ||
- smashed == EL_DRAGON ||
- smashed == EL_MOLE)
-#endif
{
Bang(x, y + 1);
return;
}
-#if 1
else if (!IS_MOVING(x, y + 1) && !IS_BLOCKED(x, y + 1))
-#else
- else if (!IS_MOVING(x, y + 1))
-#endif
{
if (smashed == EL_LAMP ||
smashed == EL_LAMP_ACTIVE)
}
else if (smashed == EL_DIAMOND)
{
-#if 1
Feld[x][y + 1] = EL_DIAMOND_BREAKING;
-#else
- Feld[x][y + 1] = EL_EMPTY;
-#endif
PlaySoundLevel(x, y, SND_DIAMOND_BREAKING);
return;
}
{ MV_UP, MV_DOWN, MV_LEFT },
{ 0, 0, 0 },
{ MV_LEFT, MV_RIGHT, MV_DOWN },
- { 0,0,0 }, { 0,0,0 }, { 0,0,0 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
+ { 0, 0, 0 },
{ MV_RIGHT, MV_LEFT, MV_UP }
};
int right_x = x + right_dx, right_y = y + right_dy;
int move_x = x + move_dx, move_y = y + move_dy;
+ int xx, yy;
+
if (element == EL_BUG || element == EL_BD_BUTTERFLY)
{
TestIfBadThingTouchesOtherBadThing(x, y);
- if (IN_LEV_FIELD(right_x, right_y) &&
- IS_FREE(right_x, right_y))
+ if (ENEMY_CAN_ENTER_FIELD(right_x, right_y))
MovDir[x][y] = right_dir;
- else if (!IN_LEV_FIELD(move_x, move_y) ||
- !IS_FREE(move_x, move_y))
+ else if (!ENEMY_CAN_ENTER_FIELD(move_x, move_y))
MovDir[x][y] = left_dir;
if (element == EL_BUG && MovDir[x][y] != old_move_dir)
{
TestIfBadThingTouchesOtherBadThing(x, y);
- if (IN_LEV_FIELD(left_x, left_y) &&
- IS_FREE(left_x, left_y))
+ if (ENEMY_CAN_ENTER_FIELD(left_x, left_y))
MovDir[x][y] = left_dir;
- else if (!IN_LEV_FIELD(move_x, move_y) ||
- !IS_FREE(move_x, move_y))
+ else if (!ENEMY_CAN_ENTER_FIELD(move_x, move_y))
MovDir[x][y] = right_dir;
if ((element == EL_SPACESHIP ||
- element == EL_SP_SNIKSNAK || element == EL_SP_ELECTRON)
+ element == EL_SP_SNIKSNAK ||
+ element == EL_SP_ELECTRON)
&& MovDir[x][y] != old_move_dir)
MovDelay[x][y] = 9;
else if (element == EL_BD_FIREFLY) /* && MovDir[x][y] == right_dir) */
}
else if (element == EL_YAMYAM)
{
- boolean can_turn_left = FALSE, can_turn_right = FALSE;
-
- if (IN_LEV_FIELD(left_x, left_y) &&
- (IS_FREE_OR_PLAYER(left_x, left_y) ||
- Feld[left_x][left_y] == EL_DIAMOND))
- can_turn_left = TRUE;
- if (IN_LEV_FIELD(right_x, right_y) &&
- (IS_FREE_OR_PLAYER(right_x, right_y) ||
- Feld[right_x][right_y] == EL_DIAMOND))
- can_turn_right = TRUE;
+ boolean can_turn_left = YAMYAM_CAN_ENTER_FIELD(left_x, left_y);
+ boolean can_turn_right = YAMYAM_CAN_ENTER_FIELD(right_x, right_y);
if (can_turn_left && can_turn_right)
MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
else
MovDir[x][y] = back_dir;
- MovDelay[x][y] = 16+16*RND(3);
+ MovDelay[x][y] = 16 + 16 * RND(3);
}
else if (element == EL_DARK_YAMYAM)
{
- boolean can_turn_left = FALSE, can_turn_right = FALSE;
-
- if (IN_LEV_FIELD(left_x, left_y) &&
- (IS_FREE_OR_PLAYER(left_x, left_y) ||
- IS_FOOD_DARK_YAMYAM(Feld[left_x][left_y])))
- can_turn_left = TRUE;
- if (IN_LEV_FIELD(right_x, right_y) &&
- (IS_FREE_OR_PLAYER(right_x, right_y) ||
- IS_FOOD_DARK_YAMYAM(Feld[right_x][right_y])))
- can_turn_right = TRUE;
+ boolean can_turn_left = DARK_YAMYAM_CAN_ENTER_FIELD(left_x, left_y);
+ boolean can_turn_right = DARK_YAMYAM_CAN_ENTER_FIELD(right_x, right_y);
if (can_turn_left && can_turn_right)
MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
else
MovDir[x][y] = back_dir;
- MovDelay[x][y] = 16+16*RND(3);
+ MovDelay[x][y] = 16 + 16 * RND(3);
}
else if (element == EL_PACMAN)
{
- boolean can_turn_left = FALSE, can_turn_right = FALSE;
-
- if (IN_LEV_FIELD(left_x, left_y) &&
- (IS_FREE_OR_PLAYER(left_x, left_y) ||
- IS_AMOEBOID(Feld[left_x][left_y])))
- can_turn_left = TRUE;
- if (IN_LEV_FIELD(right_x, right_y) &&
- (IS_FREE_OR_PLAYER(right_x, right_y) ||
- IS_AMOEBOID(Feld[right_x][right_y])))
- can_turn_right = TRUE;
+ boolean can_turn_left = PACMAN_CAN_ENTER_FIELD(left_x, left_y);
+ boolean can_turn_right = PACMAN_CAN_ENTER_FIELD(right_x, right_y);
if (can_turn_left && can_turn_right)
MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
else
MovDir[x][y] = back_dir;
- MovDelay[x][y] = 6+RND(40);
+ MovDelay[x][y] = 6 + RND(40);
}
else if (element == EL_PIG)
{
- boolean can_turn_left = FALSE, can_turn_right = FALSE, can_move_on = FALSE;
- boolean should_turn_left = FALSE, should_turn_right = FALSE;
- boolean should_move_on = FALSE;
+ boolean can_turn_left = PIG_CAN_ENTER_FIELD(left_x, left_y);
+ boolean can_turn_right = PIG_CAN_ENTER_FIELD(right_x, right_y);
+ boolean can_move_on = PIG_CAN_ENTER_FIELD(move_x, move_y);
+ boolean should_turn_left, should_turn_right, should_move_on;
int rnd_value = 24;
int rnd = RND(rnd_value);
- if (IN_LEV_FIELD(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_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_FOOD_PIG(Feld[move_x][move_y])))
- can_move_on = TRUE;
-
- if (can_turn_left &&
- (!can_move_on ||
- (IN_LEV_FIELD(x+back_dx+left_dx, y+back_dy+left_dy) &&
- !IS_FREE(x+back_dx+left_dx, y+back_dy+left_dy))))
- should_turn_left = TRUE;
- if (can_turn_right &&
- (!can_move_on ||
- (IN_LEV_FIELD(x+back_dx+right_dx, y+back_dy+right_dy) &&
- !IS_FREE(x+back_dx+right_dx, y+back_dy+right_dy))))
- should_turn_right = TRUE;
- if (can_move_on &&
- (!can_turn_left || !can_turn_right ||
- (IN_LEV_FIELD(x+move_dx+left_dx, y+move_dy+left_dy) &&
- !IS_FREE(x+move_dx+left_dx, y+move_dy+left_dy)) ||
- (IN_LEV_FIELD(x+move_dx+right_dx, y+move_dy+right_dy) &&
- !IS_FREE(x+move_dx+right_dx, y+move_dy+right_dy))))
- should_move_on = TRUE;
+ should_turn_left = (can_turn_left &&
+ (!can_move_on ||
+ IN_LEV_FIELD_AND_NOT_FREE(x + back_dx + left_dx,
+ y + back_dy + left_dy)));
+ should_turn_right = (can_turn_right &&
+ (!can_move_on ||
+ IN_LEV_FIELD_AND_NOT_FREE(x + back_dx + right_dx,
+ y + back_dy + right_dy)));
+ should_move_on = (can_move_on &&
+ (!can_turn_left ||
+ !can_turn_right ||
+ IN_LEV_FIELD_AND_NOT_FREE(x + move_dx + left_dx,
+ y + move_dy + left_dy) ||
+ IN_LEV_FIELD_AND_NOT_FREE(x + move_dx + right_dx,
+ y + move_dy + right_dy)));
if (should_turn_left || should_turn_right || should_move_on)
{
if (should_turn_left && should_turn_right && should_move_on)
- MovDir[x][y] = (rnd < rnd_value/3 ? left_dir :
- rnd < 2*rnd_value/3 ? right_dir :
+ MovDir[x][y] = (rnd < rnd_value / 3 ? left_dir :
+ rnd < 2 * rnd_value / 3 ? right_dir :
old_move_dir);
else if (should_turn_left && should_turn_right)
- MovDir[x][y] = (rnd < rnd_value/2 ? left_dir : right_dir);
+ MovDir[x][y] = (rnd < rnd_value / 2 ? left_dir : right_dir);
else if (should_turn_left && should_move_on)
- MovDir[x][y] = (rnd < rnd_value/2 ? left_dir : old_move_dir);
+ MovDir[x][y] = (rnd < rnd_value / 2 ? left_dir : old_move_dir);
else if (should_turn_right && should_move_on)
- MovDir[x][y] = (rnd < rnd_value/2 ? right_dir : old_move_dir);
+ MovDir[x][y] = (rnd < rnd_value / 2 ? right_dir : old_move_dir);
else if (should_turn_left)
MovDir[x][y] = left_dir;
else if (should_turn_right)
else if (should_move_on)
MovDir[x][y] = old_move_dir;
}
- else if (can_move_on && rnd > rnd_value/8)
+ else if (can_move_on && rnd > rnd_value / 8)
MovDir[x][y] = old_move_dir;
else if (can_turn_left && can_turn_right)
- MovDir[x][y] = (rnd < rnd_value/2 ? left_dir : right_dir);
- else if (can_turn_left && rnd > rnd_value/8)
+ MovDir[x][y] = (rnd < rnd_value / 2 ? left_dir : right_dir);
+ else if (can_turn_left && rnd > rnd_value / 8)
MovDir[x][y] = left_dir;
else if (can_turn_right && rnd > rnd_value/8)
MovDir[x][y] = right_dir;
else
MovDir[x][y] = back_dir;
- if (!IS_FREE(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]))
+ xx = x + move_xy[MovDir[x][y]].x;
+ yy = y + move_xy[MovDir[x][y]].y;
+
+ if (!IS_FREE(xx, yy) && !IS_FOOD_PIG(Feld[xx][yy]))
MovDir[x][y] = old_move_dir;
MovDelay[x][y] = 0;
}
else if (element == EL_DRAGON)
{
- boolean can_turn_left = FALSE, can_turn_right = FALSE, can_move_on = FALSE;
+ boolean can_turn_left = IN_LEV_FIELD_AND_IS_FREE(left_x, left_y);
+ boolean can_turn_right = IN_LEV_FIELD_AND_IS_FREE(right_x, right_y);
+ boolean can_move_on = IN_LEV_FIELD_AND_IS_FREE(move_x, move_y);
int rnd_value = 24;
int rnd = RND(rnd_value);
- if (IN_LEV_FIELD(left_x, left_y) && IS_FREE(left_x, left_y))
- can_turn_left = TRUE;
- if (IN_LEV_FIELD(right_x, right_y) && IS_FREE(right_x, right_y))
- can_turn_right = TRUE;
- if (IN_LEV_FIELD(move_x, move_y) && IS_FREE(move_x, move_y))
- can_move_on = TRUE;
-
- if (can_move_on && rnd > rnd_value/8)
+ if (can_move_on && rnd > rnd_value / 8)
MovDir[x][y] = old_move_dir;
else if (can_turn_left && can_turn_right)
- MovDir[x][y] = (rnd < rnd_value/2 ? left_dir : right_dir);
- else if (can_turn_left && rnd > rnd_value/8)
+ MovDir[x][y] = (rnd < rnd_value / 2 ? left_dir : right_dir);
+ else if (can_turn_left && rnd > rnd_value / 8)
MovDir[x][y] = left_dir;
- else if (can_turn_right && rnd > rnd_value/8)
+ else if (can_turn_right && rnd > rnd_value / 8)
MovDir[x][y] = right_dir;
else
MovDir[x][y] = back_dir;
- if (!IS_FREE(x+move_xy[MovDir[x][y]].x, y+move_xy[MovDir[x][y]].y))
+ xx = x + move_xy[MovDir[x][y]].x;
+ yy = y + move_xy[MovDir[x][y]].y;
+
+ if (!IS_FREE(xx, yy))
MovDir[x][y] = old_move_dir;
MovDelay[x][y] = 0;
}
else if (element == EL_MOLE)
{
- boolean can_turn_left = FALSE, can_turn_right = FALSE, can_move_on = FALSE;
-
- if (IN_LEV_FIELD(move_x, move_y) &&
- (IS_FREE(move_x, move_y) || IS_AMOEBOID(Feld[move_x][move_y]) ||
- Feld[move_x][move_y] == EL_AMOEBA_SHRINKING))
- can_move_on = TRUE;
-
+ boolean can_move_on =
+ (MOLE_CAN_ENTER_FIELD(move_x, move_y,
+ IS_AMOEBOID(Feld[move_x][move_y]) ||
+ Feld[move_x][move_y] == EL_AMOEBA_SHRINKING));
if (!can_move_on)
{
- if (IN_LEV_FIELD(left_x, left_y) &&
- (IS_FREE(left_x, left_y) || IS_AMOEBOID(Feld[left_x][left_y])))
- can_turn_left = TRUE;
- if (IN_LEV_FIELD(right_x, right_y) &&
- (IS_FREE(right_x, right_y) || IS_AMOEBOID(Feld[right_x][right_y])))
- can_turn_right = TRUE;
+ boolean can_turn_left =
+ (MOLE_CAN_ENTER_FIELD(left_x, left_y,
+ IS_AMOEBOID(Feld[left_x][left_y])));
+
+ boolean can_turn_right =
+ (MOLE_CAN_ENTER_FIELD(right_x, right_y,
+ IS_AMOEBOID(Feld[right_x][right_y])));
if (can_turn_left && can_turn_right)
MovDir[x][y] = (RND(2) ? left_dir : right_dir);
}
else if (element == EL_SPRING)
{
- if ((MovDir[x][y] == MV_LEFT || MovDir[x][y] == MV_RIGHT) &&
- (!IN_LEV_FIELD(move_x, move_y) || !IS_FREE(move_x, move_y) ||
- (IN_LEV_FIELD(x, y + 1) && IS_FREE(x, y + 1))))
+ if (MovDir[x][y] & MV_HORIZONTAL &&
+ (!IN_LEV_FIELD_AND_IS_FREE(move_x, move_y) ||
+ IN_LEV_FIELD_AND_IS_FREE(x, y + 1)))
MovDir[x][y] = MV_NO_MOVING;
MovDelay[x][y] = 0;
if (!player->active)
continue;
- if (attr_x == -1 || ABS(jx-x)+ABS(jy-y) < ABS(attr_x-x)+ABS(attr_y-y))
+ if (attr_x == -1 ||
+ ABS(jx - x) + ABS(jy - y) < ABS(attr_x - x) + ABS(attr_y - y))
{
attr_x = jx;
attr_y = jy;
Moving2Blocked(x, y, &newx, &newy);
if (IN_LEV_FIELD(newx, newy) && IS_FREE_OR_PLAYER(newx, newy))
- MovDelay[x][y] = 8+8*!RND(3);
+ MovDelay[x][y] = 8 + 8 * !RND(3);
else
MovDelay[x][y] = 16;
}
- else
+ else if (element == EL_PENGUIN)
+ {
+ int newx, newy;
+
+ MovDelay[x][y] = 1;
+
+ if (MovDir[x][y] & MV_HORIZONTAL && MovDir[x][y] & MV_VERTICAL)
+ {
+ boolean first_horiz = RND(2);
+ int new_move_dir = MovDir[x][y];
+
+ MovDir[x][y] =
+ new_move_dir & (first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
+ Moving2Blocked(x, y, &newx, &newy);
+
+ if (PENGUIN_CAN_ENTER_FIELD(newx, newy))
+ return;
+
+ MovDir[x][y] =
+ new_move_dir & (!first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
+ Moving2Blocked(x, y, &newx, &newy);
+
+ if (PENGUIN_CAN_ENTER_FIELD(newx, newy))
+ return;
+
+ MovDir[x][y] = old_move_dir;
+ return;
+ }
+ }
+ else /* (element == EL_SATELLITE) */
{
int newx, newy;
new_move_dir & (first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
Moving2Blocked(x, y, &newx, &newy);
- if (IN_LEV_FIELD(newx, newy) &&
- (IS_FREE(newx, newy) ||
- Feld[newx][newy] == EL_ACID ||
- (element == EL_PENGUIN &&
- (Feld[newx][newy] == EL_EXIT_OPEN ||
- IS_FOOD_PENGUIN(Feld[newx][newy])))))
+ if (ELEMENT_CAN_ENTER_FIELD_OR_ACID_2(newx, newy))
return;
MovDir[x][y] =
new_move_dir & (!first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
Moving2Blocked(x, y, &newx, &newy);
- if (IN_LEV_FIELD(newx, newy) &&
- (IS_FREE(newx, newy) ||
- Feld[newx][newy] == EL_ACID ||
- (element == EL_PENGUIN &&
- (Feld[newx][newy] == EL_EXIT_OPEN ||
- IS_FOOD_PENGUIN(Feld[newx][newy])))))
+ if (ELEMENT_CAN_ENTER_FIELD_OR_ACID_2(newx, newy))
return;
MovDir[x][y] = old_move_dir;
}
else if (element_info[element].move_pattern == MV_ALL_DIRECTIONS)
{
- boolean can_turn_left = FALSE, can_turn_right = FALSE;
-
- if (IN_LEV_FIELD(left_x, left_y) &&
- (IS_FREE(left_x, left_y) ||
- (DONT_COLLIDE_WITH(element) && IS_FREE_OR_PLAYER(left_x, left_y))))
- can_turn_left = TRUE;
- if (IN_LEV_FIELD(right_x, right_y) &&
- (IS_FREE(right_x, right_y) ||
- (DONT_COLLIDE_WITH(element) && IS_FREE_OR_PLAYER(right_x, right_y))))
- can_turn_right = TRUE;
+ boolean can_turn_left = ELEMENT_CAN_ENTER_FIELD(element, left_x, left_y);
+ boolean can_turn_right = ELEMENT_CAN_ENTER_FIELD(element, right_x,right_y);
if (can_turn_left && can_turn_right)
MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
}
else if (element_info[element].move_pattern == MV_ALONG_LEFT_SIDE)
{
- if (IN_LEV_FIELD(left_x, left_y) &&
- (IS_FREE(left_x, left_y) ||
- (DONT_COLLIDE_WITH(element) && IS_FREE_OR_PLAYER(left_x, left_y))))
+ if (ELEMENT_CAN_ENTER_FIELD(element, left_x, left_y))
MovDir[x][y] = left_dir;
- else if (!IN_LEV_FIELD(move_x, move_y) ||
- (!IS_FREE(move_x, move_y) &&
- (!DONT_COLLIDE_WITH(element) || !IS_FREE_OR_PLAYER(move_x, move_y))))
+ else if (!ELEMENT_CAN_ENTER_FIELD(element, move_x, move_y))
MovDir[x][y] = right_dir;
if (MovDir[x][y] != old_move_dir)
}
else if (element_info[element].move_pattern == MV_ALONG_RIGHT_SIDE)
{
- if (IN_LEV_FIELD(right_x, right_y) &&
- (IS_FREE(right_x, right_y) ||
- (DONT_COLLIDE_WITH(element) && IS_FREE_OR_PLAYER(right_x, right_y))))
+ if (ELEMENT_CAN_ENTER_FIELD(element, right_x, right_y))
MovDir[x][y] = right_dir;
- else if (!IN_LEV_FIELD(move_x, move_y) ||
- (!IS_FREE(move_x, move_y) &&
- (!DONT_COLLIDE_WITH(element) || !IS_FREE_OR_PLAYER(move_x, move_y))))
+ else if (!ELEMENT_CAN_ENTER_FIELD(element, move_x, move_y))
MovDir[x][y] = left_dir;
if (MovDir[x][y] != old_move_dir)
if (!player->active)
continue;
- if (attr_x == -1 || ABS(jx-x)+ABS(jy-y) < ABS(attr_x-x)+ABS(attr_y-y))
+ if (attr_x == -1 ||
+ ABS(jx - x) + ABS(jy - y) < ABS(attr_x - x) + ABS(attr_y - y))
{
attr_x = jx;
attr_y = jy;
new_move_dir & (first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
Moving2Blocked(x, y, &newx, &newy);
- if (IN_LEV_FIELD(newx, newy) && (IS_FREE(newx, newy) ||
- (DONT_COLLIDE_WITH(element) &&
- IS_FREE_OR_PLAYER(newx, newy)) ||
- Feld[newx][newy] == EL_ACID))
+ if (ELEMENT_CAN_ENTER_FIELD_OR_ACID(element, newx, newy))
return;
MovDir[x][y] =
new_move_dir & (!first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
Moving2Blocked(x, y, &newx, &newy);
- if (IN_LEV_FIELD(newx, newy) && (IS_FREE(newx, newy) ||
- (DONT_COLLIDE_WITH(element) &&
- IS_FREE_OR_PLAYER(newx, newy)) ||
- Feld[newx][newy] == EL_ACID))
+ if (ELEMENT_CAN_ENTER_FIELD_OR_ACID(element, newx, newy))
return;
MovDir[x][y] = old_move_dir;
GfxAction[x][y + 1] = ACTION_ACTIVE;
#endif
}
+#if 1
else if (CAN_SMASH(element) && Feld[x][y + 1] == EL_BLOCKED &&
JustStopped[x][y])
{
+ /*
+ printf("::: %d\n", MovDir[x][y]);
+ */
+
Impact(x, y);
}
+#endif
else if (IS_FREE(x, y + 1) && element == EL_SPRING && use_spring_bug)
{
if (MovDir[x][y] == MV_NO_MOVING)
element != EL_DX_SUPABOMB)
#endif
#else
- else if ((IS_SLIPPERY(Feld[x][y + 1]) ||
+ else if (((IS_SLIPPERY(Feld[x][y + 1]) && !IS_PLAYER(x, y + 1)) ||
(IS_EM_SLIPPERY_WALL(Feld[x][y + 1]) && IS_GEM(element))) &&
!IS_FALLING(x, y + 1) && !JustStopped[x][y + 1] &&
element != EL_DX_SUPABOMB && element != EL_SP_DISK_ORANGE)
InitMovingField(x, y, left ? MV_LEFT : MV_RIGHT);
started_moving = TRUE;
+
+#if 0
+ if (element == EL_BOMB)
+ printf("::: SLIP DOWN [%d]\n", FrameCounter);
+#endif
}
}
else if (IS_BELT_ACTIVE(Feld[x][y + 1]))
int horiz_move = (dx != 0);
int newx = x + dx, newy = y + dy;
int step = (horiz_move ? dx : dy) * TILEX / MOVE_DELAY_NORMAL_SPEED;
+ struct PlayerInfo *player = (IS_PLAYER(x, y) ? PLAYERINFO(x, y) : NULL);
+ boolean pushing = (player != NULL && player->Pushing && player->is_moving);
if (element == EL_AMOEBA_DROP || element == EL_AMOEBA_DROPPING)
step /= 2;
MovPos[x][y] += step;
+#if 1
+ if (pushing) /* special case: moving object pushed by player */
+ MovPos[x][y] = SIGN(MovPos[x][y]) * (TILEX - ABS(PLAYERINFO(x,y)->GfxPos));
+#endif
+
+#if 0
+ if (pushing)
+ printf("::: OOPS! pushing '%s'\n", element_info[element].token_name);
+#endif
+
if (ABS(MovPos[x][y]) >= TILEX) /* object reached its destination */
{
Feld[x][y] = EL_EMPTY;
DrawLevelField(x, y);
DrawLevelField(newx, newy);
- Stop[newx][newy] = TRUE;
- JustStopped[newx][newy] = 3;
+#if 0
+ if (game.engine_version >= RELEASE_IDENT(2,2,0,7) || !pushing)
+#endif
+ Stop[newx][newy] = TRUE; /* ignore this element until the next frame */
+#if 1
+ if (!pushing)
+#endif
+ JustStopped[newx][newy] = 3;
if (DONT_TOUCH(element)) /* object may be nasty to player or others */
{
for (i=0; i<MAX_NUM_ELEMENTS; i++)
{
- if (!HAS_CHANGE_EVENT(i, trigger_event) ||
+ if (!CAN_CHANGE(i) || !HAS_CHANGE_EVENT(i, trigger_event) ||
element_info[i].change.trigger != trigger_element)
continue;
}
}
+static void CheckPlayerElementChange(int x, int y, int element,
+ int trigger_event)
+{
+ if (!CAN_CHANGE(element) || !HAS_CHANGE_EVENT(element, trigger_event))
+ return;
+
+ ChangeElementDoIt(x, y, element_info[element].change.successor);
+}
+
static void PlayerActions(struct PlayerInfo *player, byte player_action)
{
static byte stored_player_action[MAX_PLAYERS];
stored_player[i].Frame++;
#endif
+#if 1
+ if (game.engine_version < RELEASE_IDENT(2,2,0,7))
+ {
+ for (i=0; i<MAX_PLAYERS; i++)
+ {
+ struct PlayerInfo *player = &stored_player[i];
+ int x = player->jx;
+ int y = player->jy;
+
+ if (player->active && player->Pushing && player->is_moving &&
+ IS_MOVING(x, y))
+ {
+ ContinueMoving(x, y);
+
+ /* continue moving after pushing (this is actually a bug) */
+ if (!IS_MOVING(x, y))
+ {
+ Stop[x][y] = FALSE;
+ }
+ }
+ }
+ }
+#endif
+
for (y=0; y<lev_fieldy; y++) for (x=0; x<lev_fieldx; x++)
{
Stop[x][y] = FALSE;
}
if (IS_MOVING(x, y) || IS_PLAYER(x, y))
+ {
+#if 0
+ if (FrameCounter == 437)
+ printf("::: ---> IS_MOVING %d\n", MovDir[x][y]);
+#endif
+
return MF_NO_ACTION;
+ }
#if 0
if (IS_TUBE(Feld[jx][jy]) || IS_TUBE(Back[jx][jy]))
switch (element)
{
+#if 0
case EL_EMPTY:
+ PlaySoundLevelElementAction(x, y, player->element_nr, ACTION_MOVING);
+ break;
+#endif
+
+#if 0
case EL_SAND:
case EL_INVISIBLE_SAND:
case EL_INVISIBLE_SAND_ACTIVE:
case EL_SP_BUGGY_BASE:
case EL_SP_BUGGY_BASE_ACTIVATING:
RemoveField(x, y);
-#if 1
+
if (mode != DF_SNAP && element != EL_EMPTY)
{
GfxElement[x][y] = (CAN_BE_CRUMBLED(element) ? EL_SAND : element);
player->is_digging = TRUE;
}
-#endif
+
PlaySoundLevelElementAction(x, y, element, ACTION_DIGGING);
break;
+#endif
case EL_EMERALD:
case EL_BD_DIAMOND:
case EL_PEARL:
case EL_CRYSTAL:
RemoveField(x, y);
-#if 1
+
if (mode != DF_SNAP)
{
GfxElement[x][y] = element;
player->is_collecting = TRUE;
}
-#endif
+
local_player->gems_still_needed -= (element == EL_DIAMOND ? 3 :
element == EL_PEARL ? 5 :
element == EL_CRYSTAL ? 8 : 1);
CheckTriggeredElementChange(element, CE_OTHER_COLLECTING);
break;
+#if 0
case EL_ENVELOPE:
Feld[x][y] = EL_EMPTY;
#if 1
#endif
CheckTriggeredElementChange(element, CE_OTHER_COLLECTING);
break;
+#endif
case EL_EXTRA_TIME:
RemoveField(x, y);
if (!checkDiagonalPushing(player, x, y, real_dx, real_dy))
return MF_NO_ACTION;
+
if (player->push_delay == 0)
player->push_delay = FrameCounter;
+
+#if 0
+ printf("want push... %d [%d]\n", FrameCounter, player->push_delay_value);
+#endif
+
#if 0
if (!FrameReached(&player->push_delay, player->push_delay_value) &&
!tape.playing &&
}
else
{
+#if 1
+ InitMovingField(x, y, (dx < 0 ? MV_LEFT :
+ dx > 0 ? MV_RIGHT :
+ dy < 0 ? MV_UP : MV_DOWN));
+ MovPos[x][y] = (dx != 0 ? dx : dy);
+#else
RemoveField(x, y);
Feld[x + dx][y + dy] = element;
+#endif
}
+#if 0
+ printf("pushing %d/%d ... %d [%d]\n", dx, dy,
+ FrameCounter, player->push_delay_value);
+#endif
+
if (element == EL_SPRING)
{
Feld[x + dx][y + dy] = EL_SPRING;
return MF_ACTION;
break;
+#if 0
case EL_SOKOBAN_FIELD_EMPTY:
break;
+#endif
case EL_SOKOBAN_OBJECT:
case EL_SOKOBAN_FIELD_FULL:
if (IS_WALKABLE(element))
{
+ PlaySoundLevelElementAction(x, y, player->element_nr, ACTION_MOVING);
break;
}
else if (IS_DIGGABLE(element))
{
RemoveField(x, y);
-#if 1
+
if (mode != DF_SNAP)
{
GfxElement[x][y] =
(CAN_BE_CRUMBLED(element) ? EL_SAND : GFX_ELEMENT(element));
player->is_digging = TRUE;
}
-#endif
+
PlaySoundLevelElementAction(x, y, element, ACTION_DIGGING);
break;
else if (IS_COLLECTIBLE(element))
{
RemoveField(x, y);
-#if 1
+
if (mode != DF_SNAP)
{
GfxElement[x][y] = element;
player->is_collecting = TRUE;
}
-#endif
+
+ RaiseScoreElement(element);
+
PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
CheckTriggeredElementChange(element, CE_OTHER_COLLECTING);
!(tape.playing && tape.file_version < FILE_VERSION_2_0))
return MF_NO_ACTION;
+#if 1
+ InitMovingField(x, y, (dx < 0 ? MV_LEFT :
+ dx > 0 ? MV_RIGHT :
+ dy < 0 ? MV_UP : MV_DOWN));
+ MovPos[x][y] = (dx != 0 ? dx : dy);
+#else
RemoveField(x, y);
Feld[x + dx][y + dy] = element;
+#endif
#if 1
if (game.engine_version < RELEASE_IDENT(2,2,0,7))
PlaySoundLevelElementAction(x, y, element, ACTION_PUSHING);
CheckTriggeredElementChange(element, CE_OTHER_PUSHING);
+ CheckPlayerElementChange(x + dx, y + dy, element, CE_PUSHED_BY_PLAYER);
break;
}
+ else
+ {
+ CheckPlayerElementChange(x, y, element, CE_PRESSED_BY_PLAYER);
+ }
return MF_NO_ACTION;
}
RaiseScore(level.score[SC_KEY]);
break;
default:
+ RaiseScore(element_info[element].score);
break;
}
}