#define GET_MAX_MOVE_DELAY(e) ( (element_info[e].move_delay_fixed) + \
(element_info[e].move_delay_random))
+#if 1
+#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_PLAYER(x, y) && \
+ !PLAYER_PROTECTED(x, y))))
+#else
#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))))
+#endif
#define ELEMENT_CAN_ENTER_FIELD_GENERIC_2(x, y, condition) \
(IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
Feld[x][y] == EL_EXIT_OPEN || \
Feld[x][y] == EL_ACID))
+#if 0
+#if 1
+#define MAZE_RUNNER_CAN_ENTER_FIELD(x, y) \
+ (IN_LEV_FIELD(x, y) && IS_FREE(x, y))
+#else
+#define MAZE_RUNNER_CAN_ENTER_FIELD(x, y) \
+ (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \
+ IS_FOOD_DARK_YAMYAM(Feld[x][y])))
+#endif
+#endif
+
+#define MOVE_ENTER_EL(e) (element_info[e].move_enter_element)
+#define IS_IN_GROUP(e, g) (element_info[e].in_group[g] == TRUE)
+#define IS_IN_GROUP_EL(e, ge) (IS_IN_GROUP(e, (ge) - EL_GROUP_START))
+
+#define CE_ENTER_FIELD_COND(e, x, y) \
+ (!IS_PLAYER(x, y) && \
+ (Feld[x][y] == EL_ACID || \
+ Feld[x][y] == MOVE_ENTER_EL(e) || \
+ (IS_GROUP_ELEMENT(MOVE_ENTER_EL(e)) && \
+ IS_IN_GROUP_EL(Feld[x][y], MOVE_ENTER_EL(e)))))
+
+#define CUSTOM_ELEMENT_CAN_ENTER_FIELD(e, x, y) \
+ ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, CE_ENTER_FIELD_COND(e, x, y))
+
#define MOLE_CAN_ENTER_FIELD(x, y, condition) \
(IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || (condition)))
static void TestIfPlayerTouchesCustomElement(int, int);
static void TestIfElementTouchesCustomElement(int, int);
+static void TestIfElementHitsCustomElement(int, int, int);
static void ChangeElement(int, int, int);
static boolean CheckTriggeredElementSideChange(int, int, int, int, int);
InitPlayerField(x, y, element, init_game);
break;
+ case EL_SOKOBAN_FIELD_PLAYER:
+ element = Feld[x][y] = EL_PLAYER_1;
+ InitField(x, y, init_game);
+
+ element = Feld[x][y] = EL_SOKOBAN_FIELD_EMPTY;
+ InitField(x, y, init_game);
+ break;
+
+ case EL_SOKOBAN_FIELD_EMPTY:
+ local_player->sokobanfields_still_needed++;
+ break;
+
case EL_STONEBLOCK:
if (x < lev_fieldx-1 && Feld[x+1][y] == EL_ACID)
Feld[x][y] = EL_ACID_POOL_TOPLEFT;
break;
case EL_DYNAMITE_ACTIVE:
+ case EL_SP_DISK_RED_ACTIVE:
+ case EL_DYNABOMB_PLAYER_1_ACTIVE:
+ case EL_DYNABOMB_PLAYER_2_ACTIVE:
+ case EL_DYNABOMB_PLAYER_3_ACTIVE:
+ case EL_DYNABOMB_PLAYER_4_ACTIVE:
MovDelay[x][y] = 96;
break;
local_player->lights_still_needed++;
break;
- case EL_SOKOBAN_FIELD_EMPTY:
- local_player->sokobanfields_still_needed++;
- break;
-
case EL_PENGUIN:
local_player->friends_still_needed++;
break;
default:
if (IS_CUSTOM_ELEMENT(element) && CAN_MOVE(element))
InitMovDir(x, y);
+ else if (IS_GROUP_ELEMENT(element))
+ {
+ struct ElementGroupInfo *group = element_info[element].group;
+ int random_pos = RND(group->num_elements_resolved);
+
+ Feld[x][y] = group->element_resolved[random_pos];
+
+ InitField(x, y, init_game);
+ }
break;
}
}
int2str(TimeLeft, 3), FONT_TEXT_2);
}
+static void resolve_group_element(int group_element, int recursion_depth)
+{
+ static int group_nr;
+ static struct ElementGroupInfo *group;
+ struct ElementGroupInfo *actual_group = element_info[group_element].group;
+ int i;
+
+ if (recursion_depth > NUM_GROUP_ELEMENTS) /* recursion too deep */
+ {
+ Error(ERR_WARN, "recursion too deep when resolving group element %d",
+ group_element - EL_GROUP_START + 1);
+
+ /* replace element which caused too deep recursion by question mark */
+ group->element_resolved[group->num_elements_resolved++] = EL_CHAR_QUESTION;
+
+ return;
+ }
+
+ if (recursion_depth == 0) /* initialization */
+ {
+ group = element_info[group_element].group;
+ group->num_elements_resolved = 0;
+ group_nr = group_element - EL_GROUP_START;
+ }
+
+ for (i = 0; i < actual_group->num_elements; i++)
+ {
+ int element = actual_group->element[i];
+
+ if (group->num_elements_resolved == NUM_FILE_ELEMENTS)
+ break;
+
+ if (IS_GROUP_ELEMENT(element))
+ resolve_group_element(element, recursion_depth + 1);
+ else
+ {
+ group->element_resolved[group->num_elements_resolved++] = element;
+ element_info[element].in_group[group_nr] = TRUE;
+ }
+ }
+
+#if 0
+ if (recursion_depth == 0 && group_element <= EL_GROUP_4)
+ {
+ printf("::: group %d: %d resolved elements\n",
+ group_element - EL_GROUP_START, group->num_elements_resolved);
+ for (i = 0; i < group->num_elements_resolved; i++)
+ printf("::: - %d ['%s']\n", group->element_resolved[i],
+ element_info[group->element_resolved[i]].token_name);
+ }
+#endif
+}
+
/*
=============================================================================
printf(" => game.engine_version == %06d\n", game.engine_version);
#endif
+ /* ---------- recursively resolve group elements ------------------------- */
+
+ for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+ for (j = 0; j < NUM_GROUP_ELEMENTS; j++)
+ element_info[i].in_group[j] = FALSE;
+
+ for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
+ resolve_group_element(EL_GROUP_START + i, 0);
+
/* ---------- initialize player's initial move delay --------------------- */
/* dynamically adjust player properties according to game engine version */
player->actual_frame_counter = 0;
+ player->step_counter = 0;
+
player->last_move_dir = MV_NO_MOVING;
player->is_waiting = FALSE;
player->is_collecting = FALSE;
player->is_pushing = FALSE;
player->is_switching = FALSE;
+ player->is_dropping = FALSE;
player->is_bored = FALSE;
player->is_sleeping = FALSE;
player->anim_delay_counter = 0;
player->post_delay_counter = 0;
+ player->action_waiting = ACTION_DEFAULT;
+ player->last_action_waiting = ACTION_DEFAULT;
player->special_action_bored = ACTION_DEFAULT;
player->special_action_sleeping = ACTION_DEFAULT;
player->move_delay = game.initial_move_delay;
player->move_delay_value = game.initial_move_delay_value;
+ player->move_delay_reset_counter = 0;
+
player->push_delay = 0;
player->push_delay_value = game.initial_push_delay_value;
+ player->drop_delay = 0;
+
player->last_jx = player->last_jy = 0;
player->jx = player->jy = 0;
ExplodePhase[x][y] = 0;
ExplodeField[x][y] = EX_NO_EXPLOSION;
+ RunnerVisit[x][y] = 0;
+ PlayerVisit[x][y] = 0;
+
GfxFrame[x][y] = 0;
GfxRandom[x][y] = INIT_GFX_RANDOM();
GfxElement[x][y] = EL_UNDEFINED;
default:
if (IS_CUSTOM_ELEMENT(element))
{
- if (element_info[element].move_direction_initial != MV_NO_MOVING)
- MovDir[x][y] = element_info[element].move_direction_initial;
- else if (element_info[element].move_pattern == MV_ALL_DIRECTIONS ||
- element_info[element].move_pattern == MV_TURNING_LEFT ||
- element_info[element].move_pattern == MV_TURNING_RIGHT)
+ struct ElementInfo *ei = &element_info[element];
+ int move_direction_initial = ei->move_direction_initial;
+ int move_pattern = ei->move_pattern;
+
+ if (move_direction_initial == MV_PREVIOUS)
+ {
+ if (MovDir[x][y] != MV_NO_MOVING)
+ return;
+
+ move_direction_initial = MV_AUTOMATIC;
+ }
+
+ if (move_direction_initial & MV_ANY_DIRECTION)
+ MovDir[x][y] = move_direction_initial;
+ else if (move_direction_initial == MV_RANDOM ||
+ move_pattern == MV_ALL_DIRECTIONS ||
+ move_pattern == MV_TURNING_LEFT ||
+ move_pattern == MV_TURNING_RIGHT ||
+ move_pattern == MV_TURNING_LEFT_RIGHT ||
+ move_pattern == MV_TURNING_RIGHT_LEFT ||
+ move_pattern == MV_TURNING_RANDOM)
MovDir[x][y] = 1 << RND(4);
- else if (element_info[element].move_pattern == MV_HORIZONTAL)
+ else if (move_pattern == MV_HORIZONTAL)
MovDir[x][y] = (RND(2) ? MV_LEFT : MV_RIGHT);
- else if (element_info[element].move_pattern == MV_VERTICAL)
+ else if (move_pattern == MV_VERTICAL)
MovDir[x][y] = (RND(2) ? MV_UP : MV_DOWN);
- else if (element_info[element].move_pattern & MV_ANY_DIRECTION)
+ else if (move_pattern & MV_ANY_DIRECTION)
MovDir[x][y] = element_info[element].move_pattern;
- else if (element_info[element].move_pattern == MV_ALONG_LEFT_SIDE ||
- element_info[element].move_pattern == MV_ALONG_RIGHT_SIDE)
+ else if (move_pattern == MV_ALONG_LEFT_SIDE ||
+ move_pattern == MV_ALONG_RIGHT_SIDE)
{
for (i = 0; i < 4; i++)
{
if (!IN_LEV_FIELD(x1, y1) || !IS_FREE(x1, y1))
{
- if (element_info[element].move_pattern == MV_ALONG_RIGHT_SIDE)
+ if (move_pattern == MV_ALONG_RIGHT_SIDE)
MovDir[x][y] = direction[0][i];
else
MovDir[x][y] = direction[1][i];
{
struct PlayerInfo *player = &stored_player[element - EL_PLAYER_1];
+ if (player->GameOver) /* do not reanimate dead player */
+ return;
+
#if 1
RemoveField(x, y); /* temporarily remove newly placed player */
DrawLevelField(x, y);
#endif
int frame = getGraphicAnimationFrame(graphic, phase - delay);
+#if 0
+ printf("::: %d ['%s'] -> %d\n", GfxElement[x][y],
+ element_info[GfxElement[x][y]].token_name,
+ graphic);
+#endif
+
if (phase == delay)
DrawLevelFieldCrumbledSand(x, y);
void DynaExplode(int ex, int ey)
{
int i, j;
+ int dynabomb_element = Feld[ex][ey];
int dynabomb_size = 1;
boolean dynabomb_xl = FALSE;
struct PlayerInfo *player;
{ 0, +1 }
};
- if (IS_ACTIVE_BOMB(Feld[ex][ey]))
+ if (IS_ACTIVE_BOMB(dynabomb_element))
{
- player = &stored_player[Feld[ex][ey] - EL_DYNABOMB_PLAYER_1_ACTIVE];
+ player = &stored_player[dynabomb_element - EL_DYNABOMB_PLAYER_1_ACTIVE];
dynabomb_size = player->dynabomb_size;
dynabomb_xl = player->dynabomb_xl;
player->dynabombs_left++;
Explode(x, y, EX_PHASE_START, EX_CENTER);
break;
default:
- if (CAN_EXPLODE_1X1(element))
+ if (CAN_EXPLODE_DYNA(element))
+ DynaExplode(x, y);
+ else if (CAN_EXPLODE_1X1(element))
Explode(x, y, EX_PHASE_START, EX_CENTER);
else
Explode(x, y, EX_PHASE_START, EX_NORMAL);
MovDir[x][y + 1] != MV_DOWN ||
MovPos[x][y + 1] <= TILEY / 2));
+#if 0
+ object_hit = !IS_FREE(x, y + 1);
+#endif
+
/* do not smash moving elements that left the smashed field in time */
if (game.engine_version >= VERSION_IDENT(2,2,0,7) && IS_MOVING(x, y + 1) &&
ABS(MovPos[x][y + 1] + getElementMoveStepsize(x, y + 1)) >= TILEX)
};
int element = Feld[x][y];
+ int move_pattern = element_info[element].move_pattern;
+
int old_move_dir = MovDir[x][y];
int left_dir = turn[old_move_dir].left;
int right_dir = turn[old_move_dir].right;
}
}
}
- else if (element_info[element].move_pattern == MV_ALL_DIRECTIONS ||
- element_info[element].move_pattern == MV_TURNING_LEFT ||
- element_info[element].move_pattern == MV_TURNING_RIGHT)
+ else if (move_pattern == MV_TURNING_LEFT ||
+ move_pattern == MV_TURNING_RIGHT ||
+ move_pattern == MV_TURNING_LEFT_RIGHT ||
+ move_pattern == MV_TURNING_RIGHT_LEFT ||
+ move_pattern == MV_TURNING_RANDOM ||
+ move_pattern == MV_ALL_DIRECTIONS)
{
- 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);
+ 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);
- if (element_info[element].move_pattern == MV_TURNING_LEFT)
+ if (move_pattern == MV_TURNING_LEFT)
MovDir[x][y] = left_dir;
- else if (element_info[element].move_pattern == MV_TURNING_RIGHT)
+ else if (move_pattern == MV_TURNING_RIGHT)
MovDir[x][y] = right_dir;
+ else if (move_pattern == MV_TURNING_LEFT_RIGHT)
+ MovDir[x][y] = (can_turn_left || !can_turn_right ? left_dir : right_dir);
+ else if (move_pattern == MV_TURNING_RIGHT_LEFT)
+ MovDir[x][y] = (can_turn_right || !can_turn_left ? right_dir : left_dir);
+ else if (move_pattern == MV_TURNING_RANDOM)
+ MovDir[x][y] = (can_turn_left && !can_turn_right ? left_dir :
+ can_turn_right && !can_turn_left ? right_dir :
+ RND(2) ? left_dir : right_dir);
else if (can_turn_left && can_turn_right)
MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
else if (can_turn_left)
MovDelay[x][y] = GET_NEW_MOVE_DELAY(element);
}
- else if (element_info[element].move_pattern == MV_HORIZONTAL ||
- element_info[element].move_pattern == MV_VERTICAL)
+ else if (move_pattern == MV_HORIZONTAL ||
+ move_pattern == MV_VERTICAL)
{
- if (element_info[element].move_pattern & old_move_dir)
+ if (move_pattern & old_move_dir)
MovDir[x][y] = back_dir;
- else if (element_info[element].move_pattern == MV_HORIZONTAL)
+ else if (move_pattern == MV_HORIZONTAL)
MovDir[x][y] = (RND(2) ? MV_LEFT : MV_RIGHT);
- else if (element_info[element].move_pattern == MV_VERTICAL)
+ else if (move_pattern == MV_VERTICAL)
MovDir[x][y] = (RND(2) ? MV_UP : MV_DOWN);
MovDelay[x][y] = GET_NEW_MOVE_DELAY(element);
}
- else if (element_info[element].move_pattern & MV_ANY_DIRECTION)
+ else if (move_pattern & MV_ANY_DIRECTION)
{
- MovDir[x][y] = element_info[element].move_pattern;
+ MovDir[x][y] = move_pattern;
MovDelay[x][y] = GET_NEW_MOVE_DELAY(element);
}
- else if (element_info[element].move_pattern == MV_ALONG_LEFT_SIDE)
+ else if (move_pattern == MV_ALONG_LEFT_SIDE)
{
- if (ELEMENT_CAN_ENTER_FIELD(element, left_x, left_y))
+ if (CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, left_x, left_y))
MovDir[x][y] = left_dir;
- else if (!ELEMENT_CAN_ENTER_FIELD(element, move_x, move_y))
+ else if (!CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, move_x, move_y))
MovDir[x][y] = right_dir;
if (MovDir[x][y] != old_move_dir)
MovDelay[x][y] = GET_NEW_MOVE_DELAY(element);
}
- else if (element_info[element].move_pattern == MV_ALONG_RIGHT_SIDE)
+ else if (move_pattern == MV_ALONG_RIGHT_SIDE)
{
- if (ELEMENT_CAN_ENTER_FIELD(element, right_x, right_y))
+ if (CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, right_x, right_y))
MovDir[x][y] = right_dir;
- else if (!ELEMENT_CAN_ENTER_FIELD(element, move_x, move_y))
+ else if (!CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, move_x, move_y))
MovDir[x][y] = left_dir;
if (MovDir[x][y] != old_move_dir)
MovDelay[x][y] = GET_NEW_MOVE_DELAY(element);
}
- else if (element_info[element].move_pattern == MV_TOWARDS_PLAYER ||
- element_info[element].move_pattern == MV_AWAY_FROM_PLAYER)
+ else if (move_pattern == MV_TOWARDS_PLAYER ||
+ move_pattern == MV_AWAY_FROM_PLAYER)
{
int attr_x = -1, attr_y = -1;
int newx, newy;
- boolean move_away =
- (element_info[element].move_pattern == MV_AWAY_FROM_PLAYER);
+ boolean move_away = (move_pattern == MV_AWAY_FROM_PLAYER);
if (AllPlayersGone)
{
new_move_dir & (first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
Moving2Blocked(x, y, &newx, &newy);
- if (ELEMENT_CAN_ENTER_FIELD_OR_ACID(element, newx, newy))
+ if (CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, newx, newy))
return;
MovDir[x][y] =
new_move_dir & (!first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
Moving2Blocked(x, y, &newx, &newy);
- if (ELEMENT_CAN_ENTER_FIELD_OR_ACID(element, newx, newy))
+ if (CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, newx, newy))
return;
MovDir[x][y] = old_move_dir;
}
}
- else if (element_info[element].move_pattern == MV_WHEN_PUSHED)
+ else if (move_pattern == MV_WHEN_PUSHED ||
+ move_pattern == MV_WHEN_DROPPED)
{
if (!IN_LEV_FIELD_AND_IS_FREE(move_x, move_y))
MovDir[x][y] = MV_NO_MOVING;
MovDelay[x][y] = 0;
}
+ else if (move_pattern & MV_MAZE_RUNNER_STYLE)
+ {
+ static int test_xy[7][2] =
+ {
+ { 0, -1 },
+ { -1, 0 },
+ { +1, 0 },
+ { 0, +1 },
+ { 0, -1 },
+ { -1, 0 },
+ { +1, 0 },
+ };
+ static int test_dir[7] =
+ {
+ MV_UP,
+ MV_LEFT,
+ MV_RIGHT,
+ MV_DOWN,
+ MV_UP,
+ MV_LEFT,
+ MV_RIGHT,
+ };
+ boolean hunter_mode = (move_pattern == MV_MAZE_HUNTER);
+ int move_preference = -1000000; /* start with very low preference */
+ int new_move_dir = MV_NO_MOVING;
+ int start_test = RND(4);
+ int i;
+
+ for (i = 0; i < 4; i++)
+ {
+ int move_dir = test_dir[start_test + i];
+ int move_dir_preference;
+
+ xx = x + test_xy[start_test + i][0];
+ yy = y + test_xy[start_test + i][1];
+
+ if (hunter_mode && IN_LEV_FIELD(xx, yy) &&
+ (IS_PLAYER(xx, yy) || Feld[xx][yy] == EL_PLAYER_IS_LEAVING))
+ {
+ new_move_dir = move_dir;
+
+ break;
+ }
+
+ if (!CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, xx, yy))
+ continue;
+
+ move_dir_preference = -1 * RunnerVisit[xx][yy];
+ if (hunter_mode && PlayerVisit[xx][yy] > 0)
+ move_dir_preference = PlayerVisit[xx][yy];
+
+ if (move_dir_preference > move_preference)
+ {
+ /* prefer field that has not been visited for the longest time */
+ move_preference = move_dir_preference;
+ new_move_dir = move_dir;
+ }
+ else if (move_dir_preference == move_preference &&
+ move_dir == old_move_dir)
+ {
+ /* prefer last direction when all directions are preferred equally */
+ move_preference = move_dir_preference;
+ new_move_dir = move_dir;
+ }
+ }
+
+ MovDir[x][y] = new_move_dir;
+ if (old_move_dir != new_move_dir)
+ MovDelay[x][y] = 9;
+ }
}
static void TurnRound(int x, int y)
element; also, the case of the player being the element to smash was
simply not covered here... :-/ ) */
+#if 0
+ WasJustMoving[x][y] = 0;
+ WasJustFalling[x][y] = 0;
+#endif
+
Impact(x, y);
}
else if (IS_FREE(x, y + 1) && element == EL_SPRING && use_spring_bug)
/* not "else if" because of elements that can fall and move (EL_SPRING) */
if (CAN_MOVE(element) && !started_moving)
{
+ int move_pattern = element_info[element].move_pattern;
int newx, newy;
+ Moving2Blocked(x, y, &newx, &newy);
+
#if 1
if (IS_PUSHABLE(element) && JustBeingPushed(x, y))
return;
return;
#endif
+#if 1
+ if (game.engine_version >= VERSION_IDENT(3,0,9,0) &&
+ WasJustMoving[x][y] && IN_LEV_FIELD(newx, newy) &&
+ (Feld[newx][newy] == EL_BLOCKED || IS_PLAYER(newx, newy)))
+ {
+#if 0
+ printf("::: element %d '%s' WasJustMoving %d [%d, %d, %d, %d]\n",
+ element, element_info[element].token_name,
+ WasJustMoving[x][y],
+ HAS_ANY_CHANGE_EVENT(element, CE_HITTING_SOMETHING),
+ HAS_ANY_CHANGE_EVENT(element, CE_HIT_BY_SOMETHING),
+ HAS_ANY_CHANGE_EVENT(element, CE_OTHER_IS_HITTING),
+ HAS_ANY_CHANGE_EVENT(element, CE_OTHER_GETS_HIT));
+#endif
+
+#if 1
+ WasJustMoving[x][y] = 0;
+#endif
+
+ TestIfElementHitsCustomElement(x, y, MovDir[x][y]);
+
+#if 0
+ if (Feld[x][y] != element) /* element has changed */
+ {
+ element = Feld[x][y];
+ move_pattern = element_info[element].move_pattern;
+
+ if (!CAN_MOVE(element))
+ return;
+ }
+#else
+ if (Feld[x][y] != element) /* element has changed */
+ return;
+#endif
+ }
+#endif
+
#if 0
#if 0
if (element == EL_SPRING && MovDir[x][y] == MV_DOWN)
if (element != EL_YAMYAM &&
element != EL_DARK_YAMYAM &&
element != EL_PACMAN &&
- !(element_info[element].move_pattern & MV_ANY_DIRECTION) &&
- element_info[element].move_pattern != MV_TURNING_LEFT &&
- element_info[element].move_pattern != MV_TURNING_RIGHT)
+ !(move_pattern & MV_ANY_DIRECTION) &&
+ move_pattern != MV_TURNING_LEFT &&
+ move_pattern != MV_TURNING_RIGHT &&
+ move_pattern != MV_TURNING_LEFT_RIGHT &&
+ move_pattern != MV_TURNING_RIGHT_LEFT &&
+ move_pattern != MV_TURNING_RANDOM)
{
TurnRound(x, y);
{
#if 1
TestIfBadThingRunsIntoHero(x, y, MovDir[x][y]);
+
return;
#else
/* player killed by element which is deadly when colliding with */
{
if (Feld[newx][newy] == EL_EXIT_OPEN)
{
+#if 1
+ RemoveField(x, y);
+ DrawLevelField(x, y);
+#else
Feld[x][y] = EL_EMPTY;
DrawLevelField(x, y);
+#endif
PlayLevelSound(newx, newy, SND_PENGUIN_PASSING);
if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
DrawPlayerField(x, y);
else
DrawLevelField(x, y);
+
return;
}
}
DrawPlayerField(x, y);
else
DrawLevelField(x, y);
+
return;
}
}
+
+#if 1
+
+ /*
+ else if (move_pattern & MV_MAZE_RUNNER_STYLE && IN_LEV_FIELD(newx, newy))
+ */
+
+ else if (IS_CUSTOM_ELEMENT(element) &&
+ CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, newx, newy)
+
+#if 0
+ &&
+ !IS_FREE(newx, newy)
+#endif
+
+)
+ {
+#if 0
+ printf("::: '%s' digs '%s' [%d]\n",
+ element_info[element].token_name,
+ element_info[Feld[newx][newy]].token_name,
+ StorePlayer[newx][newy]);
+#endif
+
+ if (!IS_FREE(newx, newy))
+ {
+ int new_element = Feld[newx][newy];
+ int sound;
+
+ /* no element can dig solid indestructible elements */
+ if (IS_INDESTRUCTIBLE(new_element) &&
+ !IS_DIGGABLE(new_element) &&
+ !IS_COLLECTIBLE(new_element))
+ return;
+
+ if (AmoebaNr[newx][newy] &&
+ (new_element == EL_AMOEBA_FULL ||
+ new_element == EL_BD_AMOEBA ||
+ new_element == EL_AMOEBA_GROWING))
+ {
+ AmoebaCnt[AmoebaNr[newx][newy]]--;
+ AmoebaCnt2[AmoebaNr[newx][newy]]--;
+ }
+
+ if (IS_MOVING(newx, newy))
+ RemoveMovingField(newx, newy);
+ else
+ {
+ RemoveField(newx, newy);
+ DrawLevelField(newx, newy);
+ }
+
+ sound = (IS_DIGGABLE(new_element) ? ACTION_DIGGING :
+ IS_COLLECTIBLE(new_element) ? ACTION_COLLECTING :
+ ACTION_BREAKING);
+
+ PlayLevelSoundAction(x, y, sound);
+ }
+
+ if (move_pattern & MV_MAZE_RUNNER_STYLE)
+ {
+ RunnerVisit[x][y] = FrameCounter;
+ PlayerVisit[x][y] /= 8; /* expire player visit path */
+ }
+ }
+
+#endif
+
else if (element == EL_DRAGON && IN_LEV_FIELD(newx, newy))
{
if (!IS_FREE(newx, newy))
DrawLevelField(x, y);
MovDelay[newx][newy] = 0; /* start amoeba shrinking delay */
+
return; /* wait for shrinking amoeba */
}
else /* element == EL_PACMAN */
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, newy = y + dy;
+#if 0
int nextx = newx + dx, nexty = newy + dy;
+#endif
boolean pushed = Pushed[x][y];
MovPos[x][y] += getElementMoveStepsize(x, y);
ResetGfxAnimation(x, y); /* reset animation values for old field */
+#if 1
+ if (IS_CUSTOM_ELEMENT(element) && !IS_PLAYER(x, y))
+ {
+ int new_element = element_info[element].move_leave_element;
+
+ Feld[x][y] = new_element;
+
+ if (new_element != EL_EMPTY)
+ {
+ InitField(x, y, FALSE);
+
+ TestIfElementTouchesCustomElement(x, y);
+
+ if (GFX_CRUMBLED(new_element))
+ DrawLevelFieldCrumbledSandNeighbours(x, y);
+ }
+ }
+#endif
+
#if 0
/* 2.1.1 (does not work correctly for spring) */
if (!CAN_MOVE(element))
ChangeElement(newx, newy, ChangePage[newx][newy]);
#endif
+#if 1
+
+ TestIfElementHitsCustomElement(newx, newy, direction);
+
+#else
+
if (!IN_LEV_FIELD(nextx, nexty) || !IS_FREE(nextx, nexty))
- CheckElementSideChange(newx, newy, Feld[newx][newy], direction,
- CE_COLLISION, -1);
+ {
+ int hitting_element = Feld[newx][newy];
+
+ /* !!! fix side (direction) orientation here and elsewhere !!! */
+ CheckElementSideChange(newx, newy, hitting_element,
+ direction, CE_HITTING_SOMETHING, -1);
+
+#if 0
+ if (IN_LEV_FIELD(nextx, nexty))
+ {
+ static int opposite_directions[] =
+ {
+ MV_RIGHT,
+ MV_LEFT,
+ MV_DOWN,
+ MV_UP
+ };
+ int move_dir_bit = MV_DIR_BIT(direction);
+ int opposite_direction = opposite_directions[move_dir_bit];
+ int hitting_side = direction;
+ int touched_side = opposite_direction;
+ int touched_element = MovingOrBlocked2Element(nextx, nexty);
+ boolean object_hit = (!IS_MOVING(nextx, nexty) ||
+ MovDir[nextx][nexty] != direction ||
+ ABS(MovPos[nextx][nexty]) <= TILEY / 2);
+
+ if (object_hit)
+ {
+ int i;
+
+ CheckElementSideChange(nextx, nexty, touched_element,
+ opposite_direction, CE_HIT_BY_SOMETHING, -1);
+
+ if (IS_CUSTOM_ELEMENT(hitting_element) &&
+ HAS_ANY_CHANGE_EVENT(hitting_element, CE_OTHER_IS_HITTING))
+ {
+ for (i = 0; i < element_info[hitting_element].num_change_pages; i++)
+ {
+ struct ElementChangeInfo *change =
+ &element_info[hitting_element].change_page[i];
+
+ if (change->can_change &&
+ change->events & CH_EVENT_BIT(CE_OTHER_IS_HITTING) &&
+ change->sides & touched_side &&
+ change->trigger_element == touched_element)
+ {
+ CheckElementSideChange(newx, newy, hitting_element,
+ CH_SIDE_ANY, CE_OTHER_IS_HITTING, i);
+ break;
+ }
+ }
+ }
+
+ if (IS_CUSTOM_ELEMENT(touched_element) &&
+ HAS_ANY_CHANGE_EVENT(touched_element, CE_OTHER_GETS_HIT))
+ {
+ for (i = 0; i < element_info[touched_element].num_change_pages; i++)
+ {
+ struct ElementChangeInfo *change =
+ &element_info[touched_element].change_page[i];
+
+ if (change->can_change &&
+ change->events & CH_EVENT_BIT(CE_OTHER_GETS_HIT) &&
+ change->sides & hitting_side &&
+ change->trigger_element == hitting_element)
+ {
+ CheckElementSideChange(nextx, nexty, touched_element,
+ CH_SIDE_ANY, CE_OTHER_GETS_HIT, i);
+ break;
+ }
+ }
+ }
+ }
+ }
+#endif
+ }
+#endif
TestIfPlayerTouchesCustomElement(newx, newy);
TestIfElementTouchesCustomElement(newx, newy);
static void ChangeElementNowExt(int x, int y, int target_element)
{
+ int previous_move_direction = MovDir[x][y];
+
/* check if element under player changes from accessible to unaccessible
(needed for special case of dropping element which then changes) */
if (IS_PLAYER(x, y) && !PLAYER_PROTECTED(x, y) &&
ResetGfxAnimation(x, y);
ResetRandomAnimationValue(x, y);
+ if (element_info[Feld[x][y]].move_direction_initial == MV_PREVIOUS)
+ MovDir[x][y] = previous_move_direction;
+
InitField(x, y, FALSE);
if (CAN_MOVE(Feld[x][y]))
InitMovDir(x, y);
ChangePage[x][y] = -1;
}
+#if 0
+ if (IS_MOVING(x, y) && !change->explode)
+#else
if (IS_MOVING(x, y)) /* never change a running system ;-) */
+#endif
{
ChangeDelay[x][y] = 1; /* try change after next move step */
ChangePage[x][y] = page; /* remember page to use for change */
return CheckElementSideChange(x, y, element, CH_SIDE_ANY, trigger_event, -1);
}
-static void SetPlayerWaiting(struct PlayerInfo *player, boolean is_waiting)
+static void PlayPlayerSound(struct PlayerInfo *player)
{
int jx = player->jx, jy = player->jy;
int element = player->element_nr;
- boolean was_waiting = player->is_waiting;
+ int last_action = player->last_action_waiting;
+ int action = player->action_waiting;
- if (is_waiting)
+ if (player->is_waiting)
+ {
+ if (action != last_action)
+ PlayLevelSoundElementAction(jx, jy, element, action);
+ else
+ PlayLevelSoundElementActionIfLoop(jx, jy, element, action);
+ }
+ else
{
- int action;
+ if (action != last_action)
+ StopSound(element_info[element].sound[last_action]);
+
+ if (last_action == ACTION_SLEEPING)
+ PlayLevelSoundElementAction(jx, jy, element, ACTION_AWAKENING);
+ }
+}
+
+static void PlayAllPlayersSound()
+{
+ int i;
- if (!was_waiting) /* not waiting -> waiting */
+ for (i = 0; i < MAX_PLAYERS; i++)
+ if (stored_player[i].active)
+ PlayPlayerSound(&stored_player[i]);
+}
+
+static void SetPlayerWaiting(struct PlayerInfo *player, boolean is_waiting)
+{
+ boolean last_waiting = player->is_waiting;
+ int move_dir = player->MovDir;
+
+ player->last_action_waiting = player->action_waiting;
+
+ if (is_waiting)
+ {
+ if (!last_waiting) /* not waiting -> waiting */
{
player->is_waiting = TRUE;
InitPlayerGfxAnimation(player, ACTION_WAITING, player->MovDir);
}
- if (game.player_sleeping_delay_fixed != -1 &&
- game.player_sleeping_delay_random != -1 &&
+ if (game.player_sleeping_delay_fixed +
+ game.player_sleeping_delay_random > 0 &&
player->anim_delay_counter == 0 &&
player->post_delay_counter == 0 &&
FrameCounter >= player->frame_counter_sleeping)
player->is_sleeping = TRUE;
- else if (game.player_boring_delay_fixed != -1 &&
- game.player_boring_delay_random != -1 &&
+ else if (game.player_boring_delay_fixed +
+ game.player_boring_delay_random > 0 &&
FrameCounter >= player->frame_counter_bored)
player->is_bored = TRUE;
- action = (player->is_sleeping ? ACTION_SLEEPING :
- player->is_bored ? ACTION_BORING : ACTION_WAITING);
+ player->action_waiting = (player->is_sleeping ? ACTION_SLEEPING :
+ player->is_bored ? ACTION_BORING :
+ ACTION_WAITING);
- if (!was_waiting)
- PlayLevelSoundElementAction(jx, jy, element, action);
- else
- PlayLevelSoundElementActionIfLoop(jx, jy, element, action);
- }
- else if (was_waiting) /* waiting -> not waiting */
- {
if (player->is_sleeping)
- PlayLevelSoundElementAction(jx, jy, element, ACTION_AWAKENING);
+ {
+ if (player->num_special_action_sleeping > 0)
+ {
+ if (player->anim_delay_counter == 0 && player->post_delay_counter == 0)
+ {
+ int last_special_action = player->special_action_sleeping;
+ int num_special_action = player->num_special_action_sleeping;
+ int special_action =
+ (last_special_action == ACTION_DEFAULT ? ACTION_SLEEPING_1 :
+ last_special_action == ACTION_SLEEPING ? ACTION_SLEEPING :
+ last_special_action < ACTION_SLEEPING_1 + num_special_action - 1 ?
+ last_special_action + 1 : ACTION_SLEEPING);
+ int special_graphic =
+ el_act_dir2img(player->element_nr, special_action, move_dir);
+
+ player->anim_delay_counter =
+ graphic_info[special_graphic].anim_delay_fixed +
+ SimpleRND(graphic_info[special_graphic].anim_delay_random);
+ player->post_delay_counter =
+ graphic_info[special_graphic].post_delay_fixed +
+ SimpleRND(graphic_info[special_graphic].post_delay_random);
+
+ player->special_action_sleeping = special_action;
+ }
+
+ if (player->anim_delay_counter > 0)
+ {
+ player->action_waiting = player->special_action_sleeping;
+ player->anim_delay_counter--;
+ }
+ else if (player->post_delay_counter > 0)
+ {
+ player->post_delay_counter--;
+ }
+ }
+ }
+ else if (player->is_bored)
+ {
+ if (player->num_special_action_bored > 0)
+ {
+ if (player->anim_delay_counter == 0 && player->post_delay_counter == 0)
+ {
+ int special_action =
+ ACTION_BORING_1 + SimpleRND(player->num_special_action_bored);
+ int special_graphic =
+ el_act_dir2img(player->element_nr, special_action, move_dir);
+
+ player->anim_delay_counter =
+ graphic_info[special_graphic].anim_delay_fixed +
+ SimpleRND(graphic_info[special_graphic].anim_delay_random);
+ player->post_delay_counter =
+ graphic_info[special_graphic].post_delay_fixed +
+ SimpleRND(graphic_info[special_graphic].post_delay_random);
+
+ player->special_action_bored = special_action;
+ }
+ if (player->anim_delay_counter > 0)
+ {
+ player->action_waiting = player->special_action_bored;
+ player->anim_delay_counter--;
+ }
+ else if (player->post_delay_counter > 0)
+ {
+ player->post_delay_counter--;
+ }
+ }
+ }
+ }
+ else if (last_waiting) /* waiting -> not waiting */
+ {
player->is_waiting = FALSE;
player->is_bored = FALSE;
player->is_sleeping = FALSE;
player->anim_delay_counter = 0;
player->post_delay_counter = 0;
+ player->action_waiting = ACTION_DEFAULT;
+
player->special_action_bored = ACTION_DEFAULT;
player->special_action_sleeping = ACTION_DEFAULT;
}
if (!player->active || tape.pausing)
return 0;
+#if 0
+ printf("::: [%d %d %d %d] [%d %d]\n",
+ left, right, up, down, button1, button2);
+#endif
+
if (player_action)
{
#if 0
if (player->MovPos == 0) /* needed for tape.playing */
player->is_moving = FALSE;
+ player->is_dropping = FALSE;
+
return 0;
}
StartMoving(x, y);
#if 1
+ element = Feld[x][y];
graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
#if 0
if (element == EL_MOLE)
}
DrawAllPlayers();
+ PlayAllPlayersSound();
if (options.debug) /* calculate frames per second */
{
if (stored_player[i].MovPos != 0)
stored_player[i].StepFrame += move_frames;
+
+ if (stored_player[i].drop_delay > 0)
+ stored_player[i].drop_delay--;
}
#endif
player->MovPos =
(dx > 0 || dy > 0 ? -1 : 1) * (TILEX - TILEX / player->move_delay_value);
+ player->step_counter++;
+
+ player->drop_delay = 0;
+
+ PlayerVisit[jx][jy] = FrameCounter;
+
ScrollPlayer(player, SCROLL_INIT);
#if 0
int old_jx = jx, old_jy = jy;
int moved = MF_NO_ACTION;
+#if 1
+ if (!player->active)
+ return FALSE;
+
+ if (!dx && !dy)
+ {
+ if (player->MovPos == 0)
+ {
+ player->is_moving = FALSE;
+ player->is_digging = FALSE;
+ player->is_collecting = FALSE;
+ player->is_snapping = FALSE;
+ player->is_pushing = FALSE;
+ }
+
+ return FALSE;
+ }
+#else
if (!player->active || (!dx && !dy))
return FALSE;
+#endif
#if 0
if (!FrameReached(&player->move_delay, player->move_delay_value) &&
player->is_switching = FALSE;
#endif
+ player->is_dropping = FALSE;
+
#if 1
{
if (player->MovPos == 0) /* player reached destination field */
{
+#if 1
+ if (player->move_delay_reset_counter > 0)
+ {
+ player->move_delay_reset_counter--;
+
+ if (player->move_delay_reset_counter == 0)
+ {
+ /* continue with normal speed after quickly moving through gate */
+ HALVE_PLAYER_SPEED(player);
+
+ /* be able to make the next move without delay */
+ player->move_delay = 0;
+ }
+ }
+#else
if (IS_PASSABLE(Feld[last_jx][last_jy]))
{
/* continue with normal speed after quickly moving through gate */
/* be able to make the next move without delay */
player->move_delay = 0;
}
+#endif
player->last_jx = jx;
player->last_jy = jy;
};
static int change_sides[4][2] =
{
- /* center side border side */
+ /* center side border side */
{ CH_SIDE_TOP, CH_SIDE_BOTTOM }, /* check top */
{ CH_SIDE_LEFT, CH_SIDE_RIGHT }, /* check left */
{ CH_SIDE_RIGHT, CH_SIDE_LEFT }, /* check right */
CE_OTHER_IS_TOUCHING, center_element_change_page);
}
+void TestIfElementHitsCustomElement(int x, int y, int direction)
+{
+ int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
+ int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
+ int hitx = x + dx, hity = y + dy;
+ int hitting_element = Feld[x][y];
+#if 0
+ boolean object_hit = (IN_LEV_FIELD(hitx, hity) &&
+ !IS_FREE(hitx, hity) &&
+ (!IS_MOVING(hitx, hity) ||
+ MovDir[hitx][hity] != direction ||
+ ABS(MovPos[hitx][hity]) <= TILEY / 2));
+#endif
+
+ if (IN_LEV_FIELD(hitx, hity) && IS_FREE(hitx, hity))
+ return;
+
+#if 0
+ if (IN_LEV_FIELD(hitx, hity) && !object_hit)
+ return;
+#endif
+
+ CheckElementSideChange(x, y, hitting_element,
+ direction, CE_HITTING_SOMETHING, -1);
+
+ if (IN_LEV_FIELD(hitx, hity))
+ {
+ static int opposite_directions[] =
+ {
+ MV_RIGHT,
+ MV_LEFT,
+ MV_DOWN,
+ MV_UP
+ };
+ int move_dir_bit = MV_DIR_BIT(direction);
+ int opposite_direction = opposite_directions[move_dir_bit];
+ int hitting_side = direction;
+ int touched_side = opposite_direction;
+ int touched_element = MovingOrBlocked2Element(hitx, hity);
+#if 1
+ boolean object_hit = (!IS_MOVING(hitx, hity) ||
+ MovDir[hitx][hity] != direction ||
+ ABS(MovPos[hitx][hity]) <= TILEY / 2);
+
+ object_hit = TRUE;
+#endif
+
+ if (object_hit)
+ {
+ int i;
+
+ CheckElementSideChange(hitx, hity, touched_element,
+ opposite_direction, CE_HIT_BY_SOMETHING, -1);
+
+ if (IS_CUSTOM_ELEMENT(hitting_element) &&
+ HAS_ANY_CHANGE_EVENT(hitting_element, CE_OTHER_IS_HITTING))
+ {
+ for (i = 0; i < element_info[hitting_element].num_change_pages; i++)
+ {
+ struct ElementChangeInfo *change =
+ &element_info[hitting_element].change_page[i];
+
+ if (change->can_change &&
+ change->events & CH_EVENT_BIT(CE_OTHER_IS_HITTING) &&
+ change->sides & touched_side &&
+ change->trigger_element == touched_element)
+ {
+ CheckElementSideChange(x, y, hitting_element,
+ CH_SIDE_ANY, CE_OTHER_IS_HITTING, i);
+ break;
+ }
+ }
+ }
+
+ if (IS_CUSTOM_ELEMENT(touched_element) &&
+ HAS_ANY_CHANGE_EVENT(touched_element, CE_OTHER_GETS_HIT))
+ {
+ for (i = 0; i < element_info[touched_element].num_change_pages; i++)
+ {
+ struct ElementChangeInfo *change =
+ &element_info[touched_element].change_page[i];
+
+ if (change->can_change &&
+ change->events & CH_EVENT_BIT(CE_OTHER_GETS_HIT) &&
+ change->sides & hitting_side &&
+ change->trigger_element == hitting_element)
+ {
+ CheckElementSideChange(hitx, hity, touched_element,
+ CH_SIDE_ANY, CE_OTHER_GETS_HIT, i);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
void TestIfGoodThingHitsBadThing(int good_x, int good_y, int good_move_dir)
{
int i, kill_x = -1, kill_y = -1;
/* automatically move to the next field with double speed */
player->programmed_action = move_direction;
+#if 1
+ if (player->move_delay_reset_counter == 0)
+ {
+ player->move_delay_reset_counter = 2; /* two double speed steps */
+
+ DOUBLE_PLAYER_SPEED(player);
+ }
+#else
+ player->move_delay_reset_counter = 2;
+
DOUBLE_PLAYER_SPEED(player);
+#endif
PlayLevelSound(x, y, SND_CLASS_SP_PORT_PASSING);
break;
/* automatically move to the next field with double speed */
player->programmed_action = move_direction;
+#if 1
+ if (player->move_delay_reset_counter == 0)
+ {
+ player->move_delay_reset_counter = 2; /* two double speed steps */
+
+ DOUBLE_PLAYER_SPEED(player);
+ }
+#else
+ player->move_delay_reset_counter = 2;
+
DOUBLE_PLAYER_SPEED(player);
+#endif
PlayLevelSoundAction(x, y, ACTION_PASSING);
player->MovDir = snap_direction;
- player->is_moving = FALSE;
- player->is_digging = FALSE;
- player->is_collecting = FALSE;
+#if 1
+ if (player->MovPos == 0)
+#endif
+ {
+ player->is_moving = FALSE;
+ player->is_digging = FALSE;
+ player->is_collecting = FALSE;
+ }
+
+ player->is_dropping = FALSE;
if (DigField(player, x, y, 0, 0, DF_SNAP) == MF_NO_ACTION)
return FALSE;
player->is_snapping = TRUE;
- player->is_moving = FALSE;
- player->is_digging = FALSE;
- player->is_collecting = FALSE;
+#if 1
+ if (player->MovPos == 0)
+#endif
+ {
+ player->is_moving = FALSE;
+ player->is_digging = FALSE;
+ player->is_collecting = FALSE;
+ }
DrawLevelField(x, y);
BackToFront();
boolean DropElement(struct PlayerInfo *player)
{
int jx = player->jx, jy = player->jy;
- int old_element;
+ int old_element = Feld[jx][jy];
+ int new_element;
- if (!player->active || player->MovPos)
+ /* check if player is active, not moving and ready to drop */
+ if (!player->active || player->MovPos || player->drop_delay > 0)
return FALSE;
- old_element = Feld[jx][jy];
-
/* check if player has anything that can be dropped */
if (player->inventory_size == 0 && player->dynabombs_left == 0)
return FALSE;
if (old_element != EL_EMPTY)
Back[jx][jy] = old_element; /* store old element on this field */
- MovDelay[jx][jy] = 96;
-
ResetGfxAnimation(jx, jy);
ResetRandomAnimationValue(jx, jy);
if (player->inventory_size > 0)
{
- int new_element = player->inventory_element[--player->inventory_size];
+ player->inventory_size--;
+ new_element = player->inventory_element[player->inventory_size];
+
+ if (new_element == EL_DYNAMITE)
+ new_element = EL_DYNAMITE_ACTIVE;
+ else if (new_element == EL_SP_DISK_RED)
+ new_element = EL_SP_DISK_RED_ACTIVE;
- Feld[jx][jy] = (new_element == EL_DYNAMITE ? EL_DYNAMITE_ACTIVE :
- new_element == EL_SP_DISK_RED ? EL_SP_DISK_RED_ACTIVE :
- new_element);
+ Feld[jx][jy] = new_element;
DrawText(DX_DYNAMITE, DY_DYNAMITE,
int2str(local_player->inventory_size, 3), FONT_TEXT_2);
else /* player is dropping a dyna bomb */
{
player->dynabombs_left--;
+ new_element = EL_DYNABOMB_PLAYER_1_ACTIVE + player->index_nr;
- Feld[jx][jy] =
- EL_DYNABOMB_PLAYER_1_ACTIVE + (player->element_nr - EL_PLAYER_1);
+ Feld[jx][jy] = new_element;
if (IN_SCR_FIELD(SCREENX(jx), SCREENY(jy)))
DrawGraphicThruMask(SCREENX(jx), SCREENY(jy), el2img(Feld[jx][jy]), 0);
PlayLevelSoundAction(jx, jy, ACTION_DROPPING);
}
+
+
+#if 1
+
+ if (Feld[jx][jy] == new_element) /* uninitialized unless CE change */
+ {
+ InitField(jx, jy, FALSE);
+ if (CAN_MOVE(Feld[jx][jy]))
+ InitMovDir(jx, jy);
+ }
+
+ new_element = Feld[jx][jy];
+
+ if (IS_CUSTOM_ELEMENT(new_element) && CAN_MOVE(new_element) &&
+ element_info[new_element].move_pattern == MV_WHEN_DROPPED)
+ {
+ int move_stepsize = element_info[new_element].move_stepsize;
+ int direction, dx, dy, nextx, nexty;
+
+ if (element_info[new_element].move_direction_initial == MV_AUTOMATIC)
+ MovDir[jx][jy] = player->MovDir;
+
+ direction = MovDir[jx][jy];
+ dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
+ dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
+ nextx = jx + dx;
+ nexty = jy + dy;
+
+ if (IN_LEV_FIELD(nextx, nexty) && IS_FREE(nextx, nexty))
+ {
+#if 0
+ WasJustMoving[jx][jy] = 3;
+#else
+ InitMovingField(jx, jy, direction);
+ ContinueMoving(jx, jy);
+#endif
+ }
+ else
+ {
+ Changed[jx][jy] = 0; /* allow another change */
+
+#if 1
+ TestIfElementHitsCustomElement(jx, jy, direction);
+#else
+ CheckElementSideChange(jx, jy, new_element,
+ direction, CE_HITTING_SOMETHING, -1);
+#endif
+ }
+
+ player->drop_delay = 2 * TILEX / move_stepsize + 1;
+ }
+
+#if 0
+ player->drop_delay = 8 + 8 + 8;
+#endif
+
+#endif
+
+ player->is_dropping = TRUE;
+
+
return TRUE;
}
{
int num_sounds = getSoundListSize();
- if (loop_sound_frame != NULL)
- free(loop_sound_frame);
-
- if (loop_sound_volume != NULL)
- free(loop_sound_volume);
+ checked_free(loop_sound_frame);
+ checked_free(loop_sound_volume);
- loop_sound_frame = checked_calloc(num_sounds * sizeof(int));
+ loop_sound_frame = checked_calloc(num_sounds * sizeof(int));
loop_sound_volume = checked_calloc(num_sounds * sizeof(int));
}
int sound_effect = element_info[Feld[x][y]].sound[action];
if (sound_effect != SND_UNDEFINED && IS_LOOP_SOUND(sound_effect))
- StopSoundExt(sound_effect, SND_CTRL_STOP_SOUND);
+ StopSound(sound_effect);
}
static void PlayLevelMusic()
{
-#if 1
if (levelset.music[level_nr] != MUS_UNDEFINED)
PlayMusic(levelset.music[level_nr]); /* from config file */
else
- PlayMusic(-(level_nr + 1)); /* from music dir */
-#else
- PlayMusic(level_nr);
-#endif
+ PlayMusic(MAP_NOCONF_MUSIC(level_nr)); /* from music dir */
}
void RaiseScore(int value)