int2str(TimeLeft, 3), FONT_TEXT_2);
}
+#if 1
+
+static void resolve_group_element(int group_element, int recursion_depth)
+{
+ 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;
+ }
+
+ 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;
+ }
+
+#if 1
+ 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
+}
+
+#else
+
+static void resolve_group_element(int group_element, int recursion_depth)
+{
+ static short element_list_count[NUM_FILE_ELEMENTS];
+ struct ElementGroupInfo *group = element_info[group_element].group;
+ int i, j;
+
+ if (group == NULL)
+ return;
+
+ if (recursion_depth > NUM_GROUP_ELEMENTS) /* recursion too deep */
+ return;
+
+ if (recursion_depth == 0) /* initialization */
+ for (i = 0; i < NUM_FILE_ELEMENTS; i++)
+ element_list_count[i] = 0;
+
+ for (i = 0; i < group->num_elements; i++)
+ {
+ int element = group->element[i];
+
+ if (IS_GROUP_ELEMENT(element))
+ resolve_group_element(element, recursion_depth + 1);
+ else if (element < NUM_FILE_ELEMENTS)
+ element_list_count[group->element[i]]++;
+ }
+
+ if (recursion_depth == 0) /* finalization */
+ {
+ group->num_elements_resolved = 0;
+
+ for (i = 0; i < NUM_FILE_ELEMENTS; i++)
+ for (j = 0; j < element_list_count[i]; j++)
+ if (group->num_elements_resolved < NUM_FILE_ELEMENTS)
+ group->element_resolved[group->num_elements_resolved++] = i;
+
+#if 1
+ if (group_element <= EL_GROUP_8)
+ {
+ 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
+ }
+}
+
+#endif
+
/*
=============================================================================
printf(" => game.engine_version == %06d\n", game.engine_version);
#endif
+ /* ---------- recursively resolve group elements ------------------------- */
+
+ 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->is_collecting = FALSE;
player->is_pushing = FALSE;
player->is_switching = FALSE;
+ player->is_dropping = FALSE;
player->is_bored = FALSE;
player->is_sleeping = FALSE;
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;
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)
MovDir[x][y] = old_move_dir;
}
}
- else if (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;
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)
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
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 */
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;
}
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;
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);
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)
{
/* 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();
new_element = Feld[jx][jy];
if (IS_CUSTOM_ELEMENT(new_element) && CAN_MOVE(new_element) &&
- element_info[new_element].move_pattern == MV_PROJECTILE)
+ element_info[new_element].move_pattern == MV_WHEN_DROPPED)
{
int move_stepsize = element_info[new_element].move_stepsize;
int direction, dx, dy, nextx, nexty;
#endif
+ player->is_dropping = TRUE;
return TRUE;