/* for Explode() */
#define EX_PHASE_START 0
-#define EX_NO_EXPLOSION 0
-#define EX_NORMAL 1
-#define EX_CENTER 2
-#define EX_BORDER 3
+#define EX_TYPE_NONE 0
+#define EX_TYPE_NORMAL (1 << 0)
+#define EX_TYPE_CENTER (1 << 1)
+#define EX_TYPE_BORDER (1 << 2)
+#define EX_TYPE_CROSS (1 << 3)
+#define EX_TYPE_SINGLE_TILE (EX_TYPE_CENTER | EX_TYPE_BORDER)
/* special positions in the game control window (relative to control window) */
#define XX_LEVEL 37
ei->change->post_change_function = ch_delay->post_change_function;
ei->change_events |= CH_EVENT_BIT(CE_DELAY);
+
+#if 1
+ SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE, TRUE);
+#endif
}
#if 1
ExplodePhase[x][y] = 0;
ExplodeDelay[x][y] = 0;
- ExplodeField[x][y] = EX_NO_EXPLOSION;
+ ExplodeField[x][y] = EX_TYPE_NONE;
RunnerVisit[x][y] = 0;
PlayerVisit[x][y] = 0;
if (!IS_CUSTOM_ELEMENT(i))
{
int num_phase = 8;
- int delay = ((IS_SP_ELEMENT(i) &&
+ int delay = (((IS_SP_ELEMENT(i) && i != EL_EMPTY_SPACE) &&
game.engine_version >= VERSION_IDENT(3,1,0,0)) ||
game.emulation == EMU_SUPAPLEX ? 3 : 2);
int last_phase = (num_phase + 1) * delay;
int element = (element_raw == EL_SP_MURPHY ? EL_PLAYER_1 : element_raw);
struct PlayerInfo *player = &stored_player[element - EL_PLAYER_1];
boolean ffwd_delay = (tape.playing && tape.fast_forward);
- boolean no_delay = (tape.index_search);
+ boolean no_delay = (tape.warp_forward);
int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
int wait_delay_value = (no_delay ? 0 : frame_delay_value);
int old_jx, old_jy;
else
{
#if 1
+#if 0
int offset = (setup.scroll_delay ? 3 : 0);
int jx = local_player->jx;
int jy = local_player->jy;
+#endif
int scroll_xx = -999, scroll_yy = -999;
ScrollScreen(NULL, SCROLL_GO_ON); /* scroll last frame to full tile */
/* --- This is only really needed (and now handled) in "Impact()". --- */
/* do not explode moving elements that left the explode field in time */
if (game.engine_version >= VERSION_IDENT(2,2,0,7) &&
- center_element == EL_EMPTY && (mode == EX_NORMAL || mode == EX_CENTER))
+ center_element == EL_EMPTY &&
+ (mode == EX_TYPE_NORMAL || mode == EX_TYPE_CENTER))
return;
#endif
- if (mode == EX_NORMAL || mode == EX_CENTER)
+ if (mode == EX_TYPE_NORMAL || mode == EX_TYPE_CENTER)
PlayLevelSoundAction(ex, ey, ACTION_EXPLODING);
/* remove things displayed in background while burning dynamite */
int element;
#if 1
- if (!IN_LEV_FIELD(x, y) || (mode != EX_NORMAL && (x != ex || y != ey)))
+#if 1
+ if (!IN_LEV_FIELD(x, y) ||
+ (mode & EX_TYPE_SINGLE_TILE && (x != ex || y != ey)) ||
+ (mode == EX_TYPE_CROSS && (x != ex && y != ey)))
continue;
#else
if (!IN_LEV_FIELD(x, y) ||
- ((mode != EX_NORMAL || center_element == EL_AMOEBA_TO_DIAMOND) &&
+ (mode != EX_TYPE_NORMAL && (x != ex || y != ey)))
+ continue;
+#endif
+#else
+ if (!IN_LEV_FIELD(x, y) ||
+ ((mode != EX_TYPE_NORMAL ||
+ center_element == EL_AMOEBA_TO_DIAMOND) &&
(x != ex || y != ey)))
continue;
#endif
Store[x][y] = EL_EMPTY;
if (x != ex || y != ey ||
- center_element == EL_AMOEBA_TO_DIAMOND || mode == EX_BORDER)
+ center_element == EL_AMOEBA_TO_DIAMOND || mode == EX_TYPE_BORDER)
Store2[x][y] = element;
#if 0
{
int element;
+#if 0
+ printf("::: done: phase == %d\n", phase);
+#endif
+
#if 0
printf("::: explosion %d,%d done [%d]\n", x, y, FrameCounter);
#endif
player->dynabombs_left++;
}
- Explode(ex, ey, EX_PHASE_START, EX_CENTER);
+ Explode(ex, ey, EX_PHASE_START, EX_TYPE_CENTER);
for (i = 0; i < NUM_DIRECTIONS; i++)
{
if (element == EL_EXPLOSION && IS_ACTIVE_BOMB(Store2[x][y]))
continue;
- Explode(x, y, EX_PHASE_START, EX_BORDER);
+ Explode(x, y, EX_PHASE_START, EX_TYPE_BORDER);
/* !!! extend EL_SAND to anything diggable (but maybe not SP_BASE) !!! */
if (element != EL_EMPTY &&
case EL_PACMAN:
case EL_MOLE:
RaiseScoreElement(element);
- Explode(x, y, EX_PHASE_START, EX_NORMAL);
+ Explode(x, y, EX_PHASE_START, EX_TYPE_NORMAL);
break;
case EL_DYNABOMB_PLAYER_1_ACTIVE:
case EL_DYNABOMB_PLAYER_2_ACTIVE:
case EL_AMOEBA_TO_DIAMOND:
#endif
if (IS_PLAYER(x, y))
- Explode(x, y, EX_PHASE_START, EX_NORMAL);
+ Explode(x, y, EX_PHASE_START, EX_TYPE_NORMAL);
else
- Explode(x, y, EX_PHASE_START, EX_CENTER);
+ Explode(x, y, EX_PHASE_START, EX_TYPE_CENTER);
break;
default:
- if (CAN_EXPLODE_DYNA(element))
+ if (CAN_EXPLODE_CROSS(element))
+#if 1
+ Explode(x, y, EX_PHASE_START, EX_TYPE_CROSS);
+#else
DynaExplode(x, y);
+#endif
else if (CAN_EXPLODE_1X1(element))
- Explode(x, y, EX_PHASE_START, EX_CENTER);
+ Explode(x, y, EX_PHASE_START, EX_TYPE_CENTER);
else
- Explode(x, y, EX_PHASE_START, EX_NORMAL);
+ Explode(x, y, EX_PHASE_START, EX_TYPE_NORMAL);
break;
}
{
int flamed = MovingOrBlocked2Element(xx, yy);
+ /* !!! */
+#if 0
+ if (IS_CLASSIC_ENEMY(flamed) || CAN_EXPLODE_BY_DRAGONFIRE(flamed))
+ Bang(xx, yy);
+ else if (IS_MOVING(xx, yy) || IS_BLOCKED(xx, yy))
+ RemoveMovingField(xx, yy);
+ else
+ RemoveField(xx, yy);
+#else
if (IS_CLASSIC_ENEMY(flamed) || CAN_EXPLODE_BY_DRAGONFIRE(flamed))
Bang(xx, yy);
else
RemoveMovingField(xx, yy);
+#endif
+
+#if 0
+ if (ChangeDelay[xx][yy])
+ printf("::: !!! [%d]\n", (IS_MOVING(xx, yy) ||
+ Feld[xx][yy] == EL_BLOCKED));
+#endif
+#if 1
+ ChangeDelay[xx][yy] = 0;
+#endif
Feld[xx][yy] = EL_FLAMES;
if (IN_SCR_FIELD(sx, sy))
{
MovDelay[x][y] = 50;
+ /* !!! */
+#if 0
+ RemoveField(newx, newy);
+#endif
Feld[newx][newy] = EL_FLAMES;
if (IN_LEV_FIELD(newx1, newy1) && Feld[newx1][newy1] == EL_EMPTY)
+ {
+#if 0
+ RemoveField(newx1, newy1);
+#endif
Feld[newx1][newy1] = EL_FLAMES;
+ }
if (IN_LEV_FIELD(newx2, newy2) && Feld[newx2][newy2] == EL_EMPTY)
+ {
+#if 0
+ RemoveField(newx2, newy2);
+#endif
Feld[newx2][newy2] = EL_FLAMES;
+ }
return;
}
MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
MovDelay[newx][newy] = 0;
- /* copy element change control values to new field */
- ChangeDelay[newx][newy] = ChangeDelay[x][y];
- ChangePage[newx][newy] = ChangePage[x][y];
- Changed[newx][newy] = Changed[x][y];
- ChangeEvent[newx][newy] = ChangeEvent[x][y];
+ if (CAN_CHANGE(element))
+ {
+ /* copy element change control values to new field */
+ ChangeDelay[newx][newy] = ChangeDelay[x][y];
+ ChangePage[newx][newy] = ChangePage[x][y];
+ Changed[newx][newy] = Changed[x][y];
+ ChangeEvent[newx][newy] = ChangeEvent[x][y];
+ }
ChangeDelay[x][y] = 0;
ChangePage[x][y] = -1;
struct ElementInfo *ei = &element_info[element];
struct ElementChangeInfo *change = &ei->change_page[page];
-#if 0
#ifdef DEBUG
- if (!CAN_CHANGE(element))
+ if (!CAN_CHANGE(element) && !CAN_CHANGE(Back[x][y]))
{
printf("\n\n");
printf("ChangeElement(): %d,%d: element = %d ('%s')\n",
printf("\n\n");
}
#endif
+
+ /* this can happen with classic bombs on walkable, changing elements */
+ if (!CAN_CHANGE(element))
+ {
+#if 0
+ if (!CAN_CHANGE(Back[x][y])) /* prevent permanent repetition */
+ ChangeDelay[x][y] = 0;
#endif
+ return;
+ }
+
if (ChangeDelay[x][y] == 0) /* initialize element change */
{
ChangeDelay[x][y] = ( change->delay_fixed * change->delay_frames +
element = Feld[x][y];
}
+#if 1
+ if (Feld[x][y] != element) /* check if element has already changed */
+ {
+#if 0
+ printf("::: %d ('%s') != %d ('%s') [%d]\n",
+ Feld[x][y], element_info[Feld[x][y]].token_name,
+ element, element_info[element].token_name,
+ trigger_event);
+#endif
+
+ return FALSE;
+ }
+#endif
+
#if 1
if (trigger_page < 0)
{
action_delay_value =
(tape.playing && tape.fast_forward ? FfwdFrameDelay : GameFrameDelay);
- if (tape.playing && tape.index_search && !tape.pausing)
+ if (tape.playing && tape.warp_forward && !tape.pausing)
action_delay_value = 0;
/* ---------- main game synchronization point ---------- */
CheckDynamite(x, y);
#if 0
else if (element == EL_EXPLOSION && !game.explosions_delayed)
- Explode(x, y, ExplodePhase[x][y], EX_NORMAL);
+ Explode(x, y, ExplodePhase[x][y], EX_TYPE_NORMAL);
#endif
else if (element == EL_AMOEBA_GROWING)
AmoebeWaechst(x, y);
if (ExplodeField[x][y])
Explode(x, y, EX_PHASE_START, ExplodeField[x][y]);
else if (element == EL_EXPLOSION)
- Explode(x, y, ExplodePhase[x][y], EX_NORMAL);
+ Explode(x, y, ExplodePhase[x][y], EX_TYPE_NORMAL);
- ExplodeField[x][y] = EX_NO_EXPLOSION;
+ ExplodeField[x][y] = EX_TYPE_NONE;
}
game.explosions_delayed = TRUE;
!(element_info[Feld[jx][jy]].access_direction & MV_DOWN)));
#if 0
- printf("::: checking gravity NOW [%d, %d, %d] [%d] ...\n",
+ printf("::: checking gravity NOW [%d, %d, %d] [%d] [%d / %d] ...\n",
player_can_fall_down,
player_is_standing_on_valid_field,
player_is_moving_to_valid_field,
- (player_is_moving_to_valid_field ? Feld[new_jx][new_jy] : -1));
+ (player_is_moving_to_valid_field ? Feld[new_jx][new_jy] : -1),
+ player->effective_action,
+ player->can_fall_into_acid);
#endif
if (player_can_fall_down &&
int leave_side = trigger_sides[MV_DIR_BIT(move_direction)][1];
#if 1
+ CheckTriggeredElementChangePlayer(old_jx, old_jy, Feld[old_jx][old_jy],
+ CE_OTHER_GETS_LEFT,
+ player->index_bit, leave_side);
+
if (IS_CUSTOM_ELEMENT(Feld[old_jx][old_jy]))
- {
- CheckTriggeredElementChangePlayer(old_jx, old_jy, Feld[old_jx][old_jy],
- CE_OTHER_GETS_LEFT,
- player->index_bit, leave_side);
CheckElementChangePlayer(old_jx, old_jy, Feld[old_jx][old_jy],
CE_LEFT_BY_PLAYER,
player->index_bit, leave_side);
- }
+
+ CheckTriggeredElementChangePlayer(jx, jy, Feld[jx][jy],
+ CE_OTHER_GETS_ENTERED,
+ player->index_bit, enter_side);
if (IS_CUSTOM_ELEMENT(Feld[jx][jy]))
- {
- CheckTriggeredElementChangePlayer(jx, jy, Feld[jx][jy],
- CE_OTHER_GETS_ENTERED,
- player->index_bit, enter_side);
CheckElementChangePlayer(jx, jy, Feld[jx][jy], CE_ENTERED_BY_PLAYER,
player->index_bit, enter_side);
- }
#endif
}
int old_jy = last_jy;
#if 1
+ CheckTriggeredElementChangePlayer(old_jx, old_jy, Feld[old_jx][old_jy],
+ CE_OTHER_GETS_LEFT,
+ player->index_bit, leave_side);
+
if (IS_CUSTOM_ELEMENT(Feld[old_jx][old_jy]))
- {
- CheckTriggeredElementChangePlayer(old_jx, old_jy, Feld[old_jx][old_jy],
- CE_OTHER_GETS_LEFT,
- player->index_bit, leave_side);
CheckElementChangePlayer(old_jx, old_jy, Feld[old_jx][old_jy],
CE_LEFT_BY_PLAYER,
player->index_bit, leave_side);
- }
+
+ CheckTriggeredElementChangePlayer(jx, jy, Feld[jx][jy],
+ CE_OTHER_GETS_ENTERED,
+ player->index_bit, enter_side);
if (IS_CUSTOM_ELEMENT(Feld[jx][jy]))
- {
- CheckTriggeredElementChangePlayer(jx, jy, Feld[jx][jy],
- CE_OTHER_GETS_ENTERED,
- player->index_bit, enter_side);
CheckElementChangePlayer(jx, jy, Feld[jx][jy], CE_ENTERED_BY_PLAYER,
player->index_bit, enter_side);
- }
#endif
}
PlayLevelSoundElementAction(x, y, element, ACTION_DIGGING);
CheckTriggeredElementChangePlayer(x, y, element, CE_OTHER_GETS_DIGGED,
- player->index_bit, CH_SIDE_ANY);
+ player->index_bit, dig_side);
#if 1
if (mode == DF_SNAP)
CheckTriggeredElementChangePlayer(x, y, element,
CE_OTHER_GETS_COLLECTED,
- player->index_bit, CH_SIDE_ANY);
+ player->index_bit, dig_side);
#if 1
if (mode == DF_SNAP)
boolean DropElement(struct PlayerInfo *player)
{
+ static int trigger_sides[4] =
+ {
+ CH_SIDE_LEFT, /* dropping left */
+ CH_SIDE_RIGHT, /* dropping right */
+ CH_SIDE_TOP, /* dropping up */
+ CH_SIDE_BOTTOM, /* dropping down */
+ };
int jx = player->jx, jy = player->jy;
+ int drop_direction = player->MovDir;
+ int drop_side = trigger_sides[MV_DIR_BIT(drop_direction)];
int old_element = Feld[jx][jy];
int new_element = (player->inventory_size > 0 ?
player->inventory_element[player->inventory_size - 1] :
CheckTriggeredElementChangePlayer(jx, jy, new_element,
CE_OTHER_GETS_DROPPED,
- player->index_bit, CH_SIDE_ANY);
+ player->index_bit, drop_side);
CheckElementChangePlayer(jx, jy, new_element, CE_DROPPED_BY_PLAYER,
- player->index_bit, CH_SIDE_ANY);
+ player->index_bit, drop_side);
TestIfElementTouchesCustomElement(jx, jy);
}
{
#if 1
- if (tape.playing && tape.index_search)
- {
- SetDrawDeactivationMask(REDRAW_NONE);
- audio.sound_deactivated = FALSE;
- }
+ if (tape.playing && tape.deactivate_display)
+ TapeDeactivateDisplayOff(TRUE);
#endif
OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
#if 1
- if (tape.playing && tape.index_search)
- {
- SetDrawDeactivationMask(REDRAW_FIELD);
- audio.sound_deactivated = TRUE;
- }
+ if (tape.playing && tape.deactivate_display)
+ TapeDeactivateDisplayOn();
#endif
}