#define USE_NEW_AMOEBA_CODE FALSE
/* EXPERIMENTAL STUFF */
-#define USE_NEW_STUFF ( * 1)
+#define USE_NEW_STUFF ( 1)
#define USE_NEW_SP_SLIPPERY (USE_NEW_STUFF * 1)
-#define USE_NEW_COLLECT_COUNT (USE_NEW_STUFF * 1)
+#define USE_NEW_CUSTOM_VALUE (USE_NEW_STUFF * 1)
#define USE_NEW_PLAYER_ANIM (USE_NEW_STUFF * 1)
#define USE_NEW_ALL_SLIPPERY (USE_NEW_STUFF * 1)
#define USE_NEW_PLAYER_SPEED (USE_NEW_STUFF * 1)
#define USE_NEW_DELAYED_ACTION (USE_NEW_STUFF * 1)
+#define USE_NEW_SNAP_DELAY (USE_NEW_STUFF * 1)
/* for DigField() */
#define DF_NO_PUSH 0
RND(element_info[e].move_delay_random))
#define GET_MAX_MOVE_DELAY(e) ( (element_info[e].move_delay_fixed) + \
(element_info[e].move_delay_random))
+#define GET_NEW_CUSTOM_VALUE(e) ( (element_info[e].ce_value_fixed_initial) +\
+ RND(element_info[e].ce_value_random_initial))
#define GET_CHANGE_DELAY(c) ( ((c)->delay_fixed * (c)->delay_frames) + \
RND((c)->delay_random * (c)->delay_frames))
static void ChangeElement(int, int, int);
-static boolean CheckTriggeredElementChangeExt(int, int, int,int,int);
-#define CheckTriggeredElementChange(e, ev) \
- CheckTriggeredElementChangeExt(e, ev, CH_PLAYER_ANY, CH_SIDE_ANY, -1)
-#define CheckTriggeredElementChangeByPlayer(e, ev, p, s) \
- CheckTriggeredElementChangeExt(e, ev, p, s, -1)
-#define CheckTriggeredElementChangeBySide(e, ev, s) \
- CheckTriggeredElementChangeExt(e, ev, CH_PLAYER_ANY, s, -1)
-#define CheckTriggeredElementChangeByPage(e, ev, p) \
- CheckTriggeredElementChangeExt(e, ev, CH_PLAYER_ANY, CH_SIDE_ANY, p)
+static boolean CheckTriggeredElementChangeExt(int, int, int, int, int,int,int);
+#define CheckTriggeredElementChange(x, y, e, ev) \
+ CheckTriggeredElementChangeExt(x,y,e,ev, CH_PLAYER_ANY,CH_SIDE_ANY, -1)
+#define CheckTriggeredElementChangeByPlayer(x, y, e, ev, p, s) \
+ CheckTriggeredElementChangeExt(x, y, e, ev, p, s, -1)
+#define CheckTriggeredElementChangeBySide(x, y, e, ev, s) \
+ CheckTriggeredElementChangeExt(x, y, e, ev, CH_PLAYER_ANY, s, -1)
+#define CheckTriggeredElementChangeByPage(x, y, e, ev, p) \
+ CheckTriggeredElementChangeExt(x,y,e,ev, CH_PLAYER_ANY, CH_SIDE_ANY, p)
static boolean CheckElementChangeExt(int, int, int, int, int, int, int);
#define CheckElementChange(x, y, e, te, ev) \
{ EL_SP_GRAVITY_OFF_PORT_UP, MV_DOWN },
{ EL_SP_GRAVITY_OFF_PORT_DOWN, MV_UP },
- { EL_UNDEFINED, MV_NO_MOVING }
+ { EL_UNDEFINED, MV_NONE }
};
static boolean trigger_events[MAX_NUM_ELEMENTS][NUM_CHANGE_EVENTS];
static int belt_move_dir[3] =
{
MV_LEFT,
- MV_NO_MOVING,
+ MV_NONE,
MV_RIGHT
};
break;
default:
+#if 1
+ if (IS_CUSTOM_ELEMENT(element))
+ {
+ if (CAN_MOVE(element))
+ InitMovDir(x, y);
+
+#if USE_NEW_CUSTOM_VALUE
+ if (!element_info[element].use_last_ce_value)
+ CustomValue[x][y] = GET_NEW_CUSTOM_VALUE(Feld[x][y]);
+#endif
+ }
+#else
if (IS_CUSTOM_ELEMENT(element) && CAN_MOVE(element))
InitMovDir(x, y);
+#endif
else if (IS_GROUP_ELEMENT(element))
{
struct ElementGroupInfo *group = element_info[element].group;
break;
}
-#if USE_NEW_COLLECT_COUNT
- Count[x][y] = element_info[Feld[x][y]].collect_count_initial;
+#if 0
+
+#if USE_NEW_CUSTOM_VALUE
+
+#if 1
+ CustomValue[x][y] = GET_NEW_CUSTOM_VALUE(Feld[x][y]);
+#else
+ CustomValue[x][y] = element_info[Feld[x][y]].custom_value_initial;
+#endif
+
+#endif
+
#endif
}
{
ei->change_page[j].actual_trigger_element = EL_EMPTY;
ei->change_page[j].actual_trigger_player = EL_PLAYER_1;
+ ei->change_page[j].actual_trigger_side = CH_SIDE_NONE;
+ ei->change_page[j].actual_trigger_ce_value = 0;
}
}
player->dynabombs_left = 0;
player->dynabomb_xl = FALSE;
- player->MovDir = MV_NO_MOVING;
+ player->MovDir = MV_NONE;
player->MovPos = 0;
player->GfxPos = 0;
- player->GfxDir = MV_NO_MOVING;
+ player->GfxDir = MV_NONE;
player->GfxAction = ACTION_DEFAULT;
player->Frame = 0;
player->StepFrame = 0;
player->step_counter = 0;
- player->last_move_dir = MV_NO_MOVING;
+ player->last_move_dir = MV_NONE;
player->is_waiting = FALSE;
player->is_moving = FALSE;
#if defined(NETWORK_AVALIABLE)
/* initial null action */
if (network_playing)
- SendToServer_MovePlayer(MV_NO_MOVING);
+ SendToServer_MovePlayer(MV_NONE);
#endif
ZX = ZY = -1;
TimeLeft = level.time;
TapeTime = 0;
- ScreenMovDir = MV_NO_MOVING;
+ ScreenMovDir = MV_NONE;
ScreenMovPos = 0;
ScreenGfxPos = 0;
game.light_time_left = 0;
game.timegate_time_left = 0;
game.switchgate_pos = 0;
- game.balloon_dir = MV_NO_MOVING;
+ game.wind_direction = level.wind_direction_initial;
game.gravity = level.initial_gravity;
game.explosions_delayed = TRUE;
for (i = 0; i < NUM_BELTS; i++)
{
- game.belt_dir[i] = MV_NO_MOVING;
+ game.belt_dir[i] = MV_NONE;
game.belt_dir_nr[i] = 3; /* not moving, next moving left */
}
MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
ChangeDelay[x][y] = 0;
ChangePage[x][y] = -1;
-#if USE_NEW_COLLECT_COUNT
- Count[x][y] = 0; /* initialized in InitField() */
+#if USE_NEW_CUSTOM_VALUE
+ CustomValue[x][y] = 0; /* initialized in InitField() */
#endif
Store[x][y] = Store2[x][y] = StorePlayer[x][y] = Back[x][y] = 0;
AmoebaNr[x][y] = 0;
GfxRandom[x][y] = INIT_GFX_RANDOM();
GfxElement[x][y] = EL_UNDEFINED;
GfxAction[x][y] = ACTION_DEFAULT;
- GfxDir[x][y] = MV_NO_MOVING;
+ GfxDir[x][y] = MV_NONE;
}
}
/* correct non-moving belts to start moving left */
for (i = 0; i < NUM_BELTS; i++)
- if (game.belt_dir[i] == MV_NO_MOVING)
+ if (game.belt_dir[i] == MV_NONE)
game.belt_dir_nr[i] = 3; /* not moving, next moving left */
/* check if any connected player was not found in playfield */
for (yy = 0; yy < 3; yy++) for (xx = 0; xx < 3; xx++)
{
- content = element_info[element].content[xx][yy];
+ content = element_info[element].content.e[xx][yy];
is_player = ELEM_IS_PLAYER(content);
if (is_player && (found_rating < 2 || element < found_element))
for (i = 0; i < element_info[element].num_change_pages; i++)
{
- content= element_info[element].change_page[i].target_content[xx][yy];
+ content =
+ element_info[element].change_page[i].target_content.e[xx][yy];
+
is_player = ELEM_IS_PLAYER(content);
if (is_player && (found_rating < 1 || element < found_element))
if (move_direction_initial == MV_START_PREVIOUS)
{
- if (MovDir[x][y] != MV_NO_MOVING)
+ if (MovDir[x][y] != MV_NONE)
return;
move_direction_initial = MV_START_AUTOMATIC;
MovDir[newx][newy] = MovDir[x][y];
-#if USE_NEW_COLLECT_COUNT
- Count[newx][newy] = Count[x][y];
+#if USE_NEW_CUSTOM_VALUE
+ CustomValue[newx][newy] = CustomValue[x][y];
#endif
GfxFrame[newx][newy] = GfxFrame[x][y];
MovDir[x][y] = 0;
MovDelay[x][y] = 0;
-#if USE_NEW_COLLECT_COUNT
- Count[x][y] = 0;
+#if USE_NEW_CUSTOM_VALUE
+ CustomValue[x][y] = 0;
#endif
AmoebaNr[x][y] = 0;
GfxElement[x][y] = EL_UNDEFINED;
GfxAction[x][y] = ACTION_DEFAULT;
- GfxDir[x][y] = MV_NO_MOVING;
+ GfxDir[x][y] = MV_NONE;
}
void RemoveMovingField(int x, int y)
CE_LEFT_BY_PLAYER,
player->index_bit, leave_side);
- CheckTriggeredElementChangeByPlayer(old_element, CE_PLAYER_LEAVES_X,
+ CheckTriggeredElementChangeByPlayer(old_jx, old_jy, old_element,
+ CE_PLAYER_LEAVES_X,
player->index_bit, leave_side);
Feld[jx][jy] = el_player;
CheckElementChangeByPlayer(jx, jy, element, CE_ENTERED_BY_PLAYER,
player->index_bit, enter_side);
- CheckTriggeredElementChangeByPlayer(element, CE_PLAYER_ENTERS_X,
+ CheckTriggeredElementChangeByPlayer(jx, jy, element, CE_PLAYER_ENTERS_X,
player->index_bit, enter_side);
}
else if (center_element == EL_AMOEBA_TO_DIAMOND)
Store[x][y] = level.amoeba_content;
else if (center_element == EL_YAMYAM)
- Store[x][y] = level.yamyam_content[game.yamyam_content_nr][xx][yy];
+ Store[x][y] = level.yamyam_content[game.yamyam_content_nr].e[xx][yy];
else if (IS_CUSTOM_ELEMENT(center_element) &&
- element_info[center_element].content[xx][yy] != EL_EMPTY)
- Store[x][y] = element_info[center_element].content[xx][yy];
+ element_info[center_element].content.e[xx][yy] != EL_EMPTY)
+ Store[x][y] = element_info[center_element].content.e[xx][yy];
else if (element == EL_WALL_EMERALD)
Store[x][y] = EL_EMERALD;
else if (element == EL_WALL_DIAMOND)
else if (element == EL_WALL_CRYSTAL)
Store[x][y] = EL_CRYSTAL;
else if (IS_CUSTOM_ELEMENT(element) && !CAN_EXPLODE(element))
- Store[x][y] = element_info[element].content[1][1];
+ Store[x][y] = element_info[element].content.e[1][1];
else
Store[x][y] = EL_EMPTY;
Back[x][y] = 0;
MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0;
- GfxDir[x][y] = MV_NO_MOVING;
+ GfxDir[x][y] = MV_NONE;
ChangeDelay[x][y] = 0;
ChangePage[x][y] = -1;
-#if USE_NEW_COLLECT_COUNT
- Count[x][y] = 0;
+#if USE_NEW_CUSTOM_VALUE
+ CustomValue[x][y] = 0;
#endif
InitField_WithBug2(x, y, FALSE);
break;
}
- CheckTriggeredElementChange(element, CE_EXPLOSION_OF_X);
+ CheckTriggeredElementChange(x, y, element, CE_EXPLOSION_OF_X);
}
void SplashAcid(int x, int y)
for (i = 0; i < NUM_BELTS; i++)
{
- if (IS_BELT(element) && game.belt_dir[i] != MV_NO_MOVING)
+ if (IS_BELT(element) && game.belt_dir[i] != MV_NONE)
{
int e_belt_nr = getBeltNrFromBeltElement(element);
int belt_nr = i;
static int belt_move_dir[4] =
{
MV_LEFT,
- MV_NO_MOVING,
+ MV_NONE,
MV_RIGHT,
- MV_NO_MOVING,
+ MV_NONE,
};
int element = Feld[x][y];
DrawLevelField(xx, yy);
}
}
- else if (IS_BELT(element) && belt_dir != MV_NO_MOVING)
+ else if (IS_BELT(element) && belt_dir != MV_NONE)
{
int e_belt_nr = getBeltNrFromBeltElement(element);
DrawLevelField(xx, yy);
}
}
- else if (IS_BELT_ACTIVE(element) && belt_dir == MV_NO_MOVING)
+ else if (IS_BELT_ACTIVE(element) && belt_dir == MV_NONE)
{
int e_belt_nr = getBeltNrFromBeltActiveElement(element);
CheckElementChangeBySide(x, y + 1, smashed, element,
CE_SWITCHED, CH_SIDE_TOP);
- CheckTriggeredElementChangeBySide(smashed, CE_SWITCH_OF_X,
+ CheckTriggeredElementChangeBySide(x, y + 1, smashed, CE_SWITCH_OF_X,
CH_SIDE_TOP);
}
}
}
else if (element == EL_BALLOON)
{
- MovDir[x][y] = game.balloon_dir;
+ MovDir[x][y] = game.wind_direction;
MovDelay[x][y] = 0;
}
else if (element == EL_SPRING)
if (MovDir[x][y] & MV_HORIZONTAL &&
(!SPRING_CAN_ENTER_FIELD(element, move_x, move_y) ||
SPRING_CAN_ENTER_FIELD(element, x, y + 1)))
- MovDir[x][y] = MV_NO_MOVING;
+ MovDir[x][y] = MV_NONE;
MovDelay[x][y] = 0;
}
}
}
- MovDir[x][y] = MV_NO_MOVING;
+ MovDir[x][y] = MV_NONE;
if (attr_x < x)
MovDir[x][y] |= (AllPlayersGone ? MV_RIGHT : MV_LEFT);
else if (attr_x > x)
MovDir[x][y] = move_pattern;
MovDelay[x][y] = GET_NEW_MOVE_DELAY(element);
}
+ else if (move_pattern & MV_WIND_DIRECTION)
+ {
+ MovDir[x][y] = game.wind_direction;
+ MovDelay[x][y] = GET_NEW_MOVE_DELAY(element);
+ }
else if (move_pattern == MV_ALONG_LEFT_SIDE)
{
if (CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, left_x, left_y))
}
}
- MovDir[x][y] = MV_NO_MOVING;
+ MovDir[x][y] = MV_NONE;
if (attr_x < x)
MovDir[x][y] |= (move_away ? MV_RIGHT : MV_LEFT);
else if (attr_x > x)
move_pattern == MV_WHEN_DROPPED)
{
if (!CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, move_x, move_y))
- MovDir[x][y] = MV_NO_MOVING;
+ MovDir[x][y] = MV_NONE;
MovDelay[x][y] = 0;
}
};
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 new_move_dir = MV_NONE;
int start_test = RND(4);
int i;
}
else if (IS_FREE(x, y + 1) && element == EL_SPRING && level.use_spring_bug)
{
- if (MovDir[x][y] == MV_NO_MOVING)
+ if (MovDir[x][y] == MV_NONE)
{
InitMovingField(x, y, MV_DOWN);
started_moving = TRUE;
/* not "else if" because of elements that can fall and move (EL_SPRING) */
#if 0
- if (CAN_MOVE(element) && !started_moving && MovDir[x][y] != MV_NO_MOVING)
+ if (CAN_MOVE(element) && !started_moving && MovDir[x][y] != MV_NONE)
#else
if (CAN_MOVE(element) && !started_moving)
#endif
#if 0
#if DEBUG
- if (MovDir[x][y] == MV_NO_MOVING)
+ if (MovDir[x][y] == MV_NONE)
{
printf("StartMoving(): %d,%d: element %d ['%s'] not moving\n",
x, y, element, element_info[element].token_name);
if (DigField(local_player, x, y, newx, newy, 0,0, DF_DIG) == MF_MOVING)
DrawLevelField(newx, newy);
else
- GfxDir[x][y] = MovDir[x][y] = MV_NO_MOVING;
+ GfxDir[x][y] = MovDir[x][y] = MV_NONE;
}
else if (!IS_FREE(newx, newy))
{
Feld[x][y] = EL_MAGIC_WALL_DEAD;
element = Feld[newx][newy] = Store[x][y];
-#if USE_NEW_COLLECT_COUNT
+#if USE_NEW_CUSTOM_VALUE
InitField(newx, newy, FALSE);
#endif
}
Feld[x][y] = EL_BD_MAGIC_WALL_DEAD;
element = Feld[newx][newy] = Store[x][y];
-#if USE_NEW_COLLECT_COUNT
+#if USE_NEW_CUSTOM_VALUE
InitField(newx, newy, FALSE);
#endif
}
Changed[newx][newy] = Changed[x][y];
ChangeEvent[newx][newy] = ChangeEvent[x][y];
-#if USE_NEW_COLLECT_COUNT
- Count[newx][newy] = Count[x][y];
+#if USE_NEW_CUSTOM_VALUE
+ CustomValue[newx][newy] = CustomValue[x][y];
#endif
}
Changed[x][y] = FALSE;
ChangeEvent[x][y] = -1;
-#if USE_NEW_COLLECT_COUNT
- Count[x][y] = 0;
+#if USE_NEW_CUSTOM_VALUE
+ CustomValue[x][y] = 0;
#endif
/* copy animation control values to new field */
CheckElementChangeByPlayer(newx, newy, element, CE_PUSHED_BY_PLAYER,
player->index_bit, dig_side);
- CheckTriggeredElementChangeByPlayer(element, CE_PLAYER_PUSHES_X,
+ CheckTriggeredElementChangeByPlayer(newx,newy, element, CE_PLAYER_PUSHES_X,
player->index_bit, dig_side);
}
void Life(int ax, int ay)
{
int x1, y1, x2, y2;
+#if 0
static int life[4] = { 2, 3, 3, 3 }; /* parameters for "game of life" */
+#endif
int life_time = 40;
int element = Feld[ax][ay];
int graphic = el2img(element);
+ int *life_parameter = (element == EL_GAME_OF_LIFE ? level.game_of_life :
+ level.biomaze);
boolean changed = FALSE;
if (IS_ANIMATED(graphic))
if (xx == ax && yy == ay) /* field in the middle */
{
- if (nachbarn < life[0] || nachbarn > life[1])
+ if (nachbarn < life_parameter[0] ||
+ nachbarn > life_parameter[1])
{
Feld[xx][yy] = EL_EMPTY;
if (!Stop[xx][yy])
}
else if (IS_FREE(xx, yy) || CAN_GROW_INTO(Feld[xx][yy]))
{ /* free border field */
- if (nachbarn >= life[2] && nachbarn <= life[3])
+ if (nachbarn >= life_parameter[2] &&
+ nachbarn <= life_parameter[3])
{
Feld[xx][yy] = element;
MovDelay[xx][yy] = (element == EL_GAME_OF_LIFE ? 0 : life_time-1);
Feld[x][y] = Store[x][y];
Store[x][y] = 0;
- GfxDir[x][y] = MovDir[x][y] = MV_NO_MOVING;
+ GfxDir[x][y] = MovDir[x][y] = MV_NONE;
DrawLevelField(x, y);
}
}
int action_arg_number_max =
(action_type == CA_SET_PLAYER_SPEED ? MOVE_STEPSIZE_MAX :
- action_type == CA_SET_GEMS ? 999 :
- action_type == CA_SET_TIME ? 9999 :
- action_type == CA_SET_SCORE ? 99999 :
+ action_type == CA_SET_LEVEL_GEMS ? 999 :
+ action_type == CA_SET_LEVEL_TIME ? 9999 :
+ action_type == CA_SET_LEVEL_SCORE ? 99999 :
action_type == CA_SET_CE_SCORE ? 9999 :
- action_type == CA_SET_CE_COUNT ? 9999 :
+ action_type == CA_SET_CE_VALUE ? 9999 :
CA_ARG_MAX);
int action_arg_number_reset =
(action_type == CA_SET_PLAYER_SPEED ? TILEX/game.initial_move_delay_value :
- action_type == CA_SET_GEMS ? level.gems_needed :
- action_type == CA_SET_TIME ? level.time :
- action_type == CA_SET_SCORE ? 0 :
+ action_type == CA_SET_LEVEL_GEMS ? level.gems_needed :
+ action_type == CA_SET_LEVEL_TIME ? level.time :
+ action_type == CA_SET_LEVEL_SCORE ? 0 :
action_type == CA_SET_CE_SCORE ? 0 :
- action_type == CA_SET_CE_COUNT ? ei->collect_count_initial :
+#if 1
+ action_type == CA_SET_CE_VALUE ? GET_NEW_CUSTOM_VALUE(element) :
+#else
+ action_type == CA_SET_CE_VALUE ? ei->custom_value_initial :
+#endif
0);
- int action_arg_number_normal =
- (action_type == CA_SET_PLAYER_SPEED ? MOVE_STEPSIZE_NORMAL :
- action_arg_number_reset);
-
int action_arg_number =
(action_arg <= CA_ARG_MAX ? action_arg :
+ action_arg >= CA_ARG_SPEED_VERY_SLOW &&
+ action_arg <= CA_ARG_SPEED_EVEN_FASTER ? (action_arg - CA_ARG_SPEED) :
+ action_arg == CA_ARG_SPEED_RESET ? action_arg_number_reset :
action_arg == CA_ARG_NUMBER_MIN ? action_arg_number_min :
action_arg == CA_ARG_NUMBER_MAX ? action_arg_number_max :
action_arg == CA_ARG_NUMBER_RESET ? action_arg_number_reset :
- action_arg == CA_ARG_NUMBER_NORMAL ? action_arg_number_normal :
action_arg == CA_ARG_NUMBER_CE_SCORE ? ei->collect_score :
-#if USE_NEW_COLLECT_COUNT
- action_arg == CA_ARG_NUMBER_CE_COUNT ? Count[x][y] :
+#if USE_NEW_CUSTOM_VALUE
+ action_arg == CA_ARG_NUMBER_CE_VALUE ? CustomValue[x][y] :
#else
- action_arg == CA_ARG_NUMBER_CE_COUNT ? ei->collect_count_initial :
+ action_arg == CA_ARG_NUMBER_CE_VALUE ? ei->custom_value_initial :
#endif
action_arg == CA_ARG_NUMBER_CE_DELAY ? GET_CHANGE_DELAY(change) :
+ action_arg == CA_ARG_ELEMENT_TARGET ? GET_NEW_CUSTOM_VALUE(change->target_element) :
+ action_arg == CA_ARG_ELEMENT_TRIGGER ? change->actual_trigger_ce_value :
-1);
int action_arg_number_old =
- (action_type == CA_SET_GEMS ? local_player->gems_still_needed :
- action_type == CA_SET_TIME ? TimeLeft :
- action_type == CA_SET_SCORE ? local_player->score :
+ (action_type == CA_SET_LEVEL_GEMS ? local_player->gems_still_needed :
+ action_type == CA_SET_LEVEL_TIME ? TimeLeft :
+ action_type == CA_SET_LEVEL_SCORE ? local_player->score :
action_type == CA_SET_CE_SCORE ? ei->collect_score :
- action_type == CA_SET_CE_COUNT ? Count[x][y] :
+ action_type == CA_SET_CE_VALUE ? CustomValue[x][y] :
0);
int action_arg_number_new =
action_mode, action_arg_number,
action_arg_number_min, action_arg_number_max);
- /* (for explicit player choice, set invalid value to "no player") */
int action_arg_player_bits =
- (action_arg == CA_ARG_PLAYER_ANY ? action_arg - CA_ARG_PLAYER :
+ (action_arg == CA_ARG_PLAYER_ANY ? PLAYER_BITS_ANY :
action_arg >= CA_ARG_PLAYER_1 &&
action_arg <= CA_ARG_PLAYER_4 ? action_arg - CA_ARG_PLAYER :
action_arg >= CA_ARG_1 &&
- action_arg <= CA_ARG_PLAYER_4 ? (1 << (action_arg - 1)) :
+ action_arg <= CA_ARG_PLAYER_4 ? (1 << (action_arg - CA_ARG_1)) :
action_arg_element >= EL_PLAYER_1 &&
action_arg_element <= EL_PLAYER_4 ?
(1 << (action_arg_element - EL_PLAYER_1)) :
- 0);
+ PLAYER_BITS_ANY);
- /* (for implicit player choice, set invalid value to "all players") */
int trigger_player_bits =
(change->actual_trigger_player >= EL_PLAYER_1 &&
change->actual_trigger_player <= EL_PLAYER_4 ?
break;
}
- case CA_DEL_KEY:
+ case CA_REMOVE_KEY:
{
int element = getSpecialActionElement(action_arg_element,
action_arg_number, EL_KEY_1);
break;
}
+#if 1
+ case CA_SET_PLAYER_SPEED:
+ {
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (trigger_player_bits & (1 << i))
+ {
+ int move_stepsize = TILEX / stored_player[i].move_delay_value;
+
+ if (action_arg == CA_ARG_SPEED_SLOWER ||
+ action_arg == CA_ARG_SPEED_FASTER)
+ {
+ action_arg_number = 2;
+ action_mode = (action_arg == CA_ARG_SPEED_SLOWER ? CA_MODE_DIVIDE :
+ CA_MODE_MULTIPLY);
+ }
+
+ move_stepsize =
+ getModifiedActionNumber(move_stepsize,
+ action_mode,
+ action_arg_number,
+ action_arg_number_min,
+ action_arg_number_max);
+
+ /* make sure that value is power of 2 */
+ move_stepsize = (1 << log_2(move_stepsize));
+
+ /* do no immediately change -- the player might just be moving */
+ stored_player[i].move_delay_value_next = TILEX / move_stepsize;
+
+#if 0
+ printf("::: move_delay_value == %d [%d]\n",
+ stored_player[i].move_delay_value_next, action_arg_number);
+#endif
+ }
+ }
+
+ break;
+ }
+#else
case CA_SET_PLAYER_SPEED:
{
for (i = 0; i < MAX_PLAYERS; i++)
break;
}
+#endif
+
+ case CA_SET_PLAYER_GRAVITY:
+ {
+ game.gravity = (action_arg == CA_ARG_GRAVITY_OFF ? FALSE :
+ action_arg == CA_ARG_GRAVITY_ON ? TRUE :
+ action_arg == CA_ARG_GRAVITY_TOGGLE ? !game.gravity :
+ game.gravity);
+ break;
+ }
- case CA_SET_GEMS:
+ case CA_SET_WIND_DIRECTION:
+ {
+ game.wind_direction = (action_arg >= CA_ARG_DIRECTION_NONE &&
+ action_arg <= CA_ARG_DIRECTION_DOWN ?
+ action_arg - CA_ARG_DIRECTION :
+ action_arg == CA_ARG_DIRECTION_TRIGGER ?
+ MV_DIR_OPPOSITE(change->actual_trigger_side) :
+ game.wind_direction);
+
+ break;
+ }
+
+ case CA_SET_LEVEL_GEMS:
{
local_player->gems_still_needed = action_arg_number_new;
break;
}
- case CA_SET_TIME:
+ case CA_SET_LEVEL_TIME:
{
if (level.time > 0) /* only modify limited time value */
{
break;
}
- case CA_SET_SCORE:
+ case CA_SET_LEVEL_SCORE:
{
local_player->score = action_arg_number_new;
break;
}
- case CA_SET_CE_COUNT:
+ case CA_SET_CE_VALUE:
{
-#if USE_NEW_COLLECT_COUNT
- int count_last = Count[x][y];
+#if USE_NEW_CUSTOM_VALUE
+ int last_custom_value = CustomValue[x][y];
- Count[x][y] = action_arg_number_new;
+ CustomValue[x][y] = action_arg_number_new;
#if 0
- printf("::: Count == %d\n", Count[x][y]);
+ printf("::: Count == %d\n", CustomValue[x][y]);
#endif
- if (Count[x][y] == 0 && count_last > 0)
+ if (CustomValue[x][y] == 0 && last_custom_value > 0)
{
#if 0
- printf("::: CE_COUNT_AT_ZERO\n");
+ printf("::: CE_VALUE_GETS_ZERO\n");
#endif
- CheckElementChange(x, y, element, EL_UNDEFINED, CE_COUNT_AT_ZERO);
- CheckTriggeredElementChange(element, CE_COUNT_AT_ZERO_OF_X);
+ CheckElementChange(x, y, element, EL_UNDEFINED, CE_VALUE_GETS_ZERO);
+ CheckTriggeredElementChange(x, y, element, CE_VALUE_GETS_ZERO_OF_X);
}
#endif
break;
}
+#if 0
case CA_SET_DYNABOMB_NUMBER:
{
printf("::: CA_SET_DYNABOMB_NUMBER -- not yet implemented\n");
break;
}
-
- case CA_TOGGLE_PLAYER_GRAVITY:
- {
- game.gravity = !game.gravity;
-
- break;
- }
-
- case CA_ENABLE_PLAYER_GRAVITY:
- {
- game.gravity = TRUE;
-
- break;
- }
-
- case CA_DISABLE_PLAYER_GRAVITY:
- {
- game.gravity = FALSE;
-
- break;
- }
+#endif
default:
break;
int x, int y, int target_element)
{
int previous_move_direction = MovDir[x][y];
+#if USE_NEW_CUSTOM_VALUE
+ int last_ce_value = CustomValue[x][y];
+#endif
boolean add_player = (ELEM_IS_PLAYER(target_element) &&
IS_WALKABLE(Feld[x][y]));
if (element_info[Feld[x][y]].move_direction_initial == MV_START_PREVIOUS)
MovDir[x][y] = previous_move_direction;
+#if USE_NEW_CUSTOM_VALUE
+ if (element_info[Feld[x][y]].use_last_ce_value)
+ CustomValue[x][y] = last_ce_value;
+#endif
+
InitField_WithBug1(x, y, FALSE);
DrawLevelField(x, y);
/* reset actual trigger element, trigger player and action element */
change->actual_trigger_element = EL_EMPTY;
change->actual_trigger_player = EL_PLAYER_1;
+ change->actual_trigger_side = CH_SIDE_NONE;
+ change->actual_trigger_ce_value = 0;
}
#if 1
boolean is_destructible;
int ex = x + xx - 1;
int ey = y + yy - 1;
- int content_element = change->target_content[xx][yy];
+ int content_element = change->target_content.e[xx][yy];
int e;
can_replace[xx][yy] = TRUE;
ChangeEvent[ex][ey] = ChangeEvent[x][y];
- content_element = change->target_content[xx][yy];
+ content_element = change->target_content.e[xx][yy];
target_element = GET_TARGET_ELEMENT(content_element, change);
ChangeElementNowExt(change, ex, ey, target_element);
}
/* this uses direct change before indirect change */
- CheckTriggeredElementChangeByPage(old_element, CE_CHANGE_OF_X, page);
+ CheckTriggeredElementChangeByPage(x, y, old_element, CE_CHANGE_OF_X, page);
return TRUE;
}
#endif
-static boolean CheckTriggeredElementChangeExt(int trigger_element,
+static boolean CheckTriggeredElementChangeExt(int x, int y,
+ int trigger_element,
int trigger_event,
int trigger_player,
int trigger_side,
{
change->actual_trigger_element = trigger_element;
change->actual_trigger_player = EL_PLAYER_1 + log_2(trigger_player);
+ change->actual_trigger_side = trigger_side;
+ change->actual_trigger_ce_value = CustomValue[x][y];
if ((change->can_change && !change_done) || change->has_action)
{
{
change->actual_trigger_element = trigger_element;
change->actual_trigger_player = EL_PLAYER_1 + log_2(trigger_player);
+ change->actual_trigger_side = trigger_side;
+ change->actual_trigger_ce_value = CustomValue[x][y];
if (change->can_change && !change_done)
{
RemoveField(x, y);
}
+#if USE_NEW_SNAP_DELAY
+ if (Feld[x][y] == EL_ELEMENT_SNAPPING)
+ {
+ MovDelay[x][y]--;
+ if (MovDelay[x][y] <= 0)
+ {
+ RemoveField(x, y);
+ DrawLevelField(x, y);
+ }
+ }
+#endif
+
#if DEBUG
if (ChangePage[x][y] != -1 && ChangeDelay[x][y] != 1)
{
CheckForDragon(x, y);
else if (element == EL_EXPLOSION)
; /* drawing of correct explosion animation is handled separately */
+ else if (element == EL_ELEMENT_SNAPPING)
+ {
+#if 1
+ graphic = el_act_dir2img(GfxElement[x][y], GfxAction[x][y],GfxDir[x][y]);
+
+ DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+#endif
+ }
else if (IS_ANIMATED(graphic) && !IS_CHANGING(x, y))
DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
player->MovDir = (dx < 0 ? MV_LEFT :
dx > 0 ? MV_RIGHT :
dy < 0 ? MV_UP :
- dy > 0 ? MV_DOWN : MV_NO_MOVING);
+ dy > 0 ? MV_DOWN : MV_NONE);
if (!IN_LEV_FIELD(new_jx, new_jy))
return MF_NO_ACTION;
player->move_delay = -1; /* set to "uninitialized" value */
/* store if player is automatically moved to next field */
- player->is_auto_moving = (player->programmed_action != MV_NO_MOVING);
+ player->is_auto_moving = (player->programmed_action != MV_NONE);
/* remove the last programmed player action */
player->programmed_action = 0;
CE_LEFT_BY_PLAYER,
player->index_bit, leave_side);
- CheckTriggeredElementChangeByPlayer(old_element, CE_PLAYER_LEAVES_X,
+ CheckTriggeredElementChangeByPlayer(old_jx, old_jy, old_element,
+ CE_PLAYER_LEAVES_X,
player->index_bit, leave_side);
if (IS_CUSTOM_ELEMENT(new_element))
CheckElementChangeByPlayer(jx, jy, new_element, CE_ENTERED_BY_PLAYER,
player->index_bit, enter_side);
- CheckTriggeredElementChangeByPlayer(new_element, CE_PLAYER_ENTERS_X,
+ CheckTriggeredElementChangeByPlayer(jx, jy, new_element,
+ CE_PLAYER_ENTERS_X,
player->index_bit, enter_side);
}
redraw_mask |= REDRAW_FIELD;
}
else
- ScreenMovDir = MV_NO_MOVING;
+ ScreenMovDir = MV_NONE;
}
void TestIfPlayerTouchesCustomElement(int x, int y)
CheckElementChangeByPlayer(xx, yy, border_element, CE_TOUCHED_BY_PLAYER,
player->index_bit, border_side);
- CheckTriggeredElementChangeByPlayer(border_element, CE_PLAYER_TOUCHES_X,
+ CheckTriggeredElementChangeByPlayer(xx, yy, border_element,
+ CE_PLAYER_TOUCHES_X,
player->index_bit, border_side);
}
else if (IS_PLAYER(xx, yy))
CheckElementChangeByPlayer(x, y, center_element, CE_TOUCHED_BY_PLAYER,
player->index_bit, center_side);
- CheckTriggeredElementChangeByPlayer(center_element, CE_PLAYER_TOUCHES_X,
+ CheckTriggeredElementChangeByPlayer(x, y, center_element,
+ CE_PLAYER_TOUCHES_X,
player->index_bit, center_side);
break;
}
continue;
test_move_dir =
- (IS_MOVING(test_x, test_y) ? MovDir[test_x][test_y] : MV_NO_MOVING);
+ (IS_MOVING(test_x, test_y) ? MovDir[test_x][test_y] : MV_NONE);
test_element = MovingOrBlocked2ElementIfNotLeaving(test_x, test_y);
continue;
test_move_dir =
- (IS_MOVING(test_x, test_y) ? MovDir[test_x][test_y] : MV_NO_MOVING);
+ (IS_MOVING(test_x, test_y) ? MovDir[test_x][test_y] : MV_NONE);
test_element = Feld[test_x][test_y];
void TestIfPlayerTouchesBadThing(int x, int y)
{
- TestIfGoodThingHitsBadThing(x, y, MV_NO_MOVING);
+ TestIfGoodThingHitsBadThing(x, y, MV_NONE);
}
void TestIfPlayerRunsIntoBadThing(int x, int y, int move_dir)
void TestIfBadThingTouchesPlayer(int x, int y)
{
- TestIfBadThingHitsGoodThing(x, y, MV_NO_MOVING);
+ TestIfBadThingHitsGoodThing(x, y, MV_NONE);
}
void TestIfBadThingRunsIntoPlayer(int x, int y, int move_dir)
void TestIfFriendTouchesBadThing(int x, int y)
{
- TestIfGoodThingHitsBadThing(x, y, MV_NO_MOVING);
+ TestIfGoodThingHitsBadThing(x, y, MV_NONE);
}
void TestIfBadThingTouchesFriend(int x, int y)
{
- TestIfBadThingHitsGoodThing(x, y, MV_NO_MOVING);
+ TestIfBadThingHitsGoodThing(x, y, MV_NONE);
}
void TestIfBadThingTouchesOtherBadThing(int bad_x, int bad_y)
ExitY = ZY = jy;
}
+#if USE_NEW_SNAP_DELAY
+static void setFieldForSnapping(int x, int y, int element, int direction)
+{
+ struct ElementInfo *ei = &element_info[element];
+ int direction_bit = MV_DIR_BIT(direction);
+ int graphic_snapping = ei->direction_graphic[ACTION_SNAPPING][direction_bit];
+ int action = (graphic_snapping != IMG_EMPTY_SPACE ? ACTION_SNAPPING :
+ IS_DIGGABLE(element) ? ACTION_DIGGING : ACTION_COLLECTING);
+
+ Feld[x][y] = EL_ELEMENT_SNAPPING;
+ MovDelay[x][y] = MOVE_DELAY_NORMAL_SPEED + 1 - 1;
+
+ ResetGfxAnimation(x, y);
+
+ GfxElement[x][y] = element;
+ GfxAction[x][y] = action;
+ GfxDir[x][y] = direction;
+ GfxFrame[x][y] = -1;
+}
+#endif
+
/*
=============================================================================
checkDiagonalPushing()
int jx = oldx, jy = oldy;
int dx = x - jx, dy = y - jy;
int nextx = x + dx, nexty = y + dy;
- int move_direction = (dx == -1 ? MV_LEFT :
+ int move_direction = (dx == -1 ? MV_LEFT :
dx == +1 ? MV_RIGHT :
- dy == -1 ? MV_UP :
- dy == +1 ? MV_DOWN : MV_NO_MOVING);
+ dy == -1 ? MV_UP :
+ dy == +1 ? MV_DOWN : MV_NONE);
int opposite_direction = MV_DIR_OPPOSITE(move_direction);
int dig_side = MV_DIR_OPPOSITE(move_direction);
int old_element = Feld[jx][jy];
return MF_NO_ACTION; /* field has no opening in this direction */
element = Feld[x][y];
-#if USE_NEW_COLLECT_COUNT
- collect_count = Count[x][y];
+#if USE_NEW_CUSTOM_VALUE
+
+#if 1
+ collect_count = element_info[element].collect_count_initial;
+#else
+ collect_count = CustomValue[x][y];
+#endif
+
#else
collect_count = element_info[element].collect_count_initial;
#endif
#if 0
if (element != EL_BLOCKED &&
- Count[x][y] != element_info[element].collect_count_initial)
+ CustomValue[x][y] != element_info[element].collect_count_initial)
printf("::: %d: %d != %d\n",
element,
- Count[x][y],
+ CustomValue[x][y],
element_info[element].collect_count_initial);
#endif
PlayLevelSoundElementAction(x, y, element, ACTION_DIGGING);
- CheckTriggeredElementChangeByPlayer(element, CE_PLAYER_DIGS_X,
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_DIGS_X,
player->index_bit, dig_side);
if (mode == DF_SNAP)
+ {
TestIfElementTouchesCustomElement(x, y); /* for empty space */
+
+#if USE_NEW_SNAP_DELAY
+ if (level.block_snap_field)
+ setFieldForSnapping(x, y, element, move_direction);
+#endif
+ }
}
else if (IS_COLLECTIBLE(element))
{
}
else if (element == EL_EXTRA_TIME && level.time > 0)
{
- TimeLeft += 10;
+ TimeLeft += level.extra_time;
DrawGameValue_Time(TimeLeft);
}
else if (element == EL_SHIELD_NORMAL || element == EL_SHIELD_DEADLY)
{
- player->shield_normal_time_left += 10;
+ player->shield_normal_time_left += level.shield_normal_time;
if (element == EL_SHIELD_DEADLY)
- player->shield_deadly_time_left += 10;
+ player->shield_deadly_time_left += level.shield_deadly_time;
}
else if (element == EL_DYNAMITE || element == EL_SP_DISK_RED)
{
PlayLevelSoundElementAction(x, y, element, ACTION_COLLECTING);
if (is_player)
- CheckTriggeredElementChangeByPlayer(element, CE_PLAYER_COLLECTS_X,
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_COLLECTS_X,
player->index_bit, dig_side);
if (mode == DF_SNAP)
+ {
TestIfElementTouchesCustomElement(x, y); /* for empty space */
+
+#if USE_NEW_SNAP_DELAY
+ if (level.block_snap_field)
+ setFieldForSnapping(x, y, element, move_direction);
+#endif
+ }
}
else if (IS_PUSHABLE(element))
{
{
CheckElementChangeByPlayer(x, y, element, CE_PUSHED_BY_PLAYER,
player->index_bit, dig_side);
- CheckTriggeredElementChangeByPlayer(element, CE_PLAYER_PUSHES_X,
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_PUSHES_X,
player->index_bit, dig_side);
}
}
{
if (PLAYER_SWITCHING(player, x, y))
{
- CheckTriggeredElementChangeByPlayer(element, CE_PLAYER_PRESSES_X,
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_PRESSES_X,
player->index_bit, dig_side);
return MF_ACTION;
{
ActivateTimegateSwitch(x, y);
}
- else if (element == EL_BALLOON_SWITCH_LEFT ||
+ else if (element == EL_BALLOON_SWITCH_LEFT ||
element == EL_BALLOON_SWITCH_RIGHT ||
- element == EL_BALLOON_SWITCH_UP ||
- element == EL_BALLOON_SWITCH_DOWN ||
+ element == EL_BALLOON_SWITCH_UP ||
+ element == EL_BALLOON_SWITCH_DOWN ||
+ element == EL_BALLOON_SWITCH_NONE ||
element == EL_BALLOON_SWITCH_ANY)
{
- if (element == EL_BALLOON_SWITCH_ANY)
- game.balloon_dir = move_direction;
- else
- game.balloon_dir = (element == EL_BALLOON_SWITCH_LEFT ? MV_LEFT :
- element == EL_BALLOON_SWITCH_RIGHT ? MV_RIGHT :
- element == EL_BALLOON_SWITCH_UP ? MV_UP :
- element == EL_BALLOON_SWITCH_DOWN ? MV_DOWN :
- MV_NO_MOVING);
+ game.wind_direction = (element == EL_BALLOON_SWITCH_LEFT ? MV_LEFT :
+ element == EL_BALLOON_SWITCH_RIGHT ? MV_RIGHT :
+ element == EL_BALLOON_SWITCH_UP ? MV_UP :
+ element == EL_BALLOON_SWITCH_DOWN ? MV_DOWN :
+ element == EL_BALLOON_SWITCH_NONE ? MV_NONE :
+ move_direction);
}
else if (element == EL_LAMP)
{
else if (element == EL_TIME_ORB_FULL)
{
Feld[x][y] = EL_TIME_ORB_EMPTY;
- TimeLeft += 10;
- DrawGameValue_Time(TimeLeft);
+
+ if (level.time > 0 || level.use_time_orb_bug)
+ {
+ TimeLeft += level.time_orb_time;
+ DrawGameValue_Time(TimeLeft);
+ }
ResetGfxAnimation(x, y);
DrawLevelField(x, y);
}
- CheckTriggeredElementChangeByPlayer(element, CE_SWITCH_OF_X,
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_SWITCH_OF_X,
player->index_bit, dig_side);
- CheckTriggeredElementChangeByPlayer(element, CE_PLAYER_PRESSES_X,
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_PRESSES_X,
player->index_bit, dig_side);
return MF_ACTION;
CheckElementChangeByPlayer(x, y, element, CE_SWITCHED,
player->index_bit, dig_side);
- CheckTriggeredElementChangeByPlayer(element, CE_SWITCH_OF_X,
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_SWITCH_OF_X,
player->index_bit, dig_side);
}
CheckElementChangeByPlayer(x, y, element, CE_PRESSED_BY_PLAYER,
player->index_bit, dig_side);
- CheckTriggeredElementChangeByPlayer(element, CE_PLAYER_PRESSES_X,
+ CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_PRESSES_X,
player->index_bit, dig_side);
return MF_NO_ACTION;
{
int jx = player->jx, jy = player->jy;
int x = jx + dx, y = jy + dy;
- int snap_direction = (dx == -1 ? MV_LEFT :
+ int snap_direction = (dx == -1 ? MV_LEFT :
dx == +1 ? MV_RIGHT :
- dy == -1 ? MV_UP :
- dy == +1 ? MV_DOWN : MV_NO_MOVING);
+ dy == -1 ? MV_UP :
+ dy == +1 ? MV_DOWN : MV_NONE);
if (player->MovPos != 0 && game.engine_version >= VERSION_IDENT(2,2,0,0))
return FALSE;
CheckElementChangeByPlayer(dropx, dropy, new_element, CE_DROPPED_BY_PLAYER,
player->index_bit, drop_side);
- CheckTriggeredElementChangeByPlayer(new_element, CE_PLAYER_DROPS_X,
+ CheckTriggeredElementChangeByPlayer(dropx, dropy, new_element,
+ CE_PLAYER_DROPS_X,
player->index_bit, drop_side);
TestIfElementTouchesCustomElement(dropx, dropy);