static void ScrollPlayer(struct PlayerInfo *, int);
static void ScrollScreen(struct PlayerInfo *, int);
-int DigField(struct PlayerInfo *, int, int, int, int, int, int, int);
+static int DigField(struct PlayerInfo *, int, int, int, int, int, int, int);
+static boolean DigFieldByCE(int, int, int);
+static boolean SnapField(struct PlayerInfo *, int, int);
+static boolean DropElement(struct PlayerInfo *);
static void InitBeltMovement(void);
static void CloseAllOpenTimegates(void);
void BuryPlayer(struct PlayerInfo *);
void RemovePlayer(struct PlayerInfo *);
-boolean SnapField(struct PlayerInfo *, int, int);
-boolean DropElement(struct PlayerInfo *);
-
static int getInvisibleActiveFromInvisibleElement(int);
static int getInvisibleFromInvisibleActiveElement(int);
Feld[x][y] = EL_EMC_MAGIC_BALL_SWITCH_ACTIVE;
break;
+ case EL_TRIGGER_PLAYER:
+ case EL_TRIGGER_ELEMENT:
+ case EL_TRIGGER_CE_VALUE:
+ case EL_TRIGGER_CE_SCORE:
+ case EL_SELF:
+ case EL_ANY_ELEMENT:
+ case EL_CURRENT_CE_VALUE:
+ case EL_CURRENT_CE_SCORE:
+ case EL_PREV_CE_1:
+ case EL_PREV_CE_2:
+ case EL_PREV_CE_3:
+ case EL_PREV_CE_4:
+ case EL_PREV_CE_5:
+ case EL_PREV_CE_6:
+ case EL_PREV_CE_7:
+ case EL_PREV_CE_8:
+ case EL_NEXT_CE_1:
+ case EL_NEXT_CE_2:
+ case EL_NEXT_CE_3:
+ case EL_NEXT_CE_4:
+ case EL_NEXT_CE_5:
+ case EL_NEXT_CE_6:
+ case EL_NEXT_CE_7:
+ case EL_NEXT_CE_8:
+ /* reference elements should not be used on the playfield */
+ Feld[x][y] = EL_EMPTY;
+ break;
+
default:
if (IS_CUSTOM_ELEMENT(element))
{
SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE_OR_HAS_ACTION, TRUE);
}
- /* ---------- initialize internal run-time variables ------------- */
+ /* ---------- initialize internal run-time variables --------------------- */
for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
{
}
}
+#if 1
+ /* ---------- initialize reference elements in change conditions --------- */
+
+ for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ int element = EL_CUSTOM_START + i;
+ struct ElementInfo *ei = &element_info[element];
+
+ for (j = 0; j < ei->num_change_pages; j++)
+ {
+ int trigger_element = ei->change_page[j].initial_trigger_element;
+
+ if (trigger_element >= EL_PREV_CE_8 &&
+ trigger_element <= EL_NEXT_CE_8)
+ trigger_element = RESOLVED_REFERENCE_ELEMENT(element, trigger_element);
+
+ ei->change_page[j].trigger_element = trigger_element;
+ }
+ }
+#endif
+
/* ---------- initialize run-time trigger player and element ------------- */
for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
else if (IS_CUSTOM_ELEMENT(element) &&
CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, newx, newy))
{
+#if 1
+ if (!DigFieldByCE(newx, newy, element))
+ return;
+#else
int new_element = Feld[newx][newy];
if (!IS_FREE(newx, newy))
}
Store[newx][newy] = EL_EMPTY;
+
#if 1
/* this makes it possible to leave the removed element again */
if (IS_EQUAL_OR_IN_GROUP(new_element, MOVE_ENTER_EL(element)))
Store[newx][newy] = (move_leave_element == EL_TRIGGER_ELEMENT ?
new_element : move_leave_element);
}
+#endif
+
#endif
if (move_pattern & MV_MAZE_RUNNER_STYLE)
=============================================================================
*/
-int DigField(struct PlayerInfo *player,
- int oldx, int oldy, int x, int y,
- int real_dx, int real_dy, int mode)
+static int DigField(struct PlayerInfo *player,
+ int oldx, int oldy, int x, int y,
+ int real_dx, int real_dy, int mode)
{
boolean is_player = (IS_PLAYER(oldx, oldy) || mode != DF_DIG);
boolean player_was_pushing = player->is_pushing;
if (!(IN_LEV_FIELD(nextx, nexty) &&
(IS_FREE(nextx, nexty) ||
- (Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY &&
- IS_SB_ELEMENT(element)))))
+ (IS_SB_ELEMENT(element) &&
+ Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY) ||
+ (IS_CUSTOM_ELEMENT(element) &&
+ CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, nextx, nexty)))))
return MP_NO_ACTION;
if (!checkDiagonalPushing(player, x, y, real_dx, real_dy))
return MP_NO_ACTION;
}
+ if (IS_CUSTOM_ELEMENT(element) &&
+ CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, nextx, nexty))
+ {
+ if (!DigFieldByCE(nextx, nexty, element))
+ return MP_NO_ACTION;
+ }
+
if (IS_SB_ELEMENT(element))
{
if (element == EL_SOKOBAN_FIELD_FULL)
return MP_MOVING;
}
-boolean SnapField(struct PlayerInfo *player, int dx, int dy)
+static boolean DigFieldByCE(int x, int y, int digging_element)
+{
+ int element = Feld[x][y];
+
+ if (!IS_FREE(x, y))
+ {
+ int action = (IS_DIGGABLE(element) ? ACTION_DIGGING :
+ IS_COLLECTIBLE(element) ? ACTION_COLLECTING :
+ ACTION_BREAKING);
+
+ /* no element can dig solid indestructible elements */
+ if (IS_INDESTRUCTIBLE(element) &&
+ !IS_DIGGABLE(element) &&
+ !IS_COLLECTIBLE(element))
+ return FALSE;
+
+ if (AmoebaNr[x][y] &&
+ (element == EL_AMOEBA_FULL ||
+ element == EL_BD_AMOEBA ||
+ element == EL_AMOEBA_GROWING))
+ {
+ AmoebaCnt[AmoebaNr[x][y]]--;
+ AmoebaCnt2[AmoebaNr[x][y]]--;
+ }
+
+ if (IS_MOVING(x, y))
+ RemoveMovingField(x, y);
+ else
+ {
+ RemoveField(x, y);
+ DrawLevelField(x, y);
+ }
+
+ /* if digged element was about to explode, prevent the explosion */
+ ExplodeField[x][y] = EX_TYPE_NONE;
+
+ PlayLevelSoundAction(x, y, action);
+ }
+
+ Store[x][y] = EL_EMPTY;
+
+#if 1
+ /* this makes it possible to leave the removed element again */
+ if (IS_EQUAL_OR_IN_GROUP(element, MOVE_ENTER_EL(digging_element)))
+ Store[x][y] = element;
+#else
+ if (IS_EQUAL_OR_IN_GROUP(element, MOVE_ENTER_EL(digging_element)))
+ {
+ int move_leave_element = element_info[digging_element].move_leave_element;
+
+ /* this makes it possible to leave the removed element again */
+ Store[x][y] = (move_leave_element == EL_TRIGGER_ELEMENT ?
+ element : move_leave_element);
+ }
+#endif
+
+ return TRUE;
+}
+
+static boolean SnapField(struct PlayerInfo *player, int dx, int dy)
{
int jx = player->jx, jy = player->jy;
int x = jx + dx, y = jy + dy;
return TRUE;
}
-boolean DropElement(struct PlayerInfo *player)
+static boolean DropElement(struct PlayerInfo *player)
{
int old_element, new_element;
int dropx = player->jx, dropy = player->jy;