#define USE_GFX_RESET_GFX_ANIMATION (USE_NEW_STUFF * 1)
#define USE_BOTH_SWITCHGATE_SWITCHES (USE_NEW_STUFF * 1)
#define USE_PLAYER_GRAVITY (USE_NEW_STUFF * 1)
+#define USE_FIXED_BORDER_RUNNING_GFX (USE_NEW_STUFF * 1)
+#define USE_QUICKSAND_BD_ROCK_BUGFIX (USE_NEW_STUFF * 0)
#define USE_QUICKSAND_IMPACT_BUGFIX (USE_NEW_STUFF * 0)
+#define USE_CODE_THAT_BREAKS_SNAKE_BITE (USE_NEW_STUFF * 1)
+
+#define USE_UFAST_PLAYER_EXIT_BUGFIX (USE_NEW_STUFF * 1)
+#define USE_NEW_GAME_WON (USE_NEW_STUFF * 1)
+
+
/* for DigField() */
#define DF_NO_PUSH 0
#define DF_DIG 1
#define EX_TYPE_DYNA (1 << 4)
#define EX_TYPE_SINGLE_TILE (EX_TYPE_CENTER | EX_TYPE_BORDER)
+#define PANEL_DEACTIVATED(p) ((p).x < 0 || (p).y < 0)
+
/* special positions in the game control window (relative to control window) */
-#define XX_LEVEL 37
-#define YY_LEVEL 20
-#define XX_EMERALDS 29
-#define YY_EMERALDS 54
-#define XX_DYNAMITE 29
-#define YY_DYNAMITE 89
-#define XX_KEYS 18
-#define YY_KEYS 123
-#define XX_SCORE 15
-#define YY_SCORE 159
-#define XX_TIME1 29
-#define XX_TIME2 30
-#define YY_TIME 194
+#define XX_LEVEL1 (game.panel.level.x)
+#define XX_LEVEL2 (game.panel.level.x - 1)
+#define YY_LEVEL (game.panel.level.y)
+#define XX_EMERALDS (game.panel.gems.x)
+#define YY_EMERALDS (game.panel.gems.y)
+#define XX_DYNAMITE (game.panel.inventory.x)
+#define YY_DYNAMITE (game.panel.inventory.y)
+#define XX_KEYS (game.panel.keys.x)
+#define YY_KEYS (game.panel.keys.y)
+#define XX_SCORE (game.panel.score.x)
+#define YY_SCORE (game.panel.score.y)
+#define XX_TIME1 (game.panel.time.x)
+#define XX_TIME2 (game.panel.time.x + 1)
+#define YY_TIME (game.panel.time.y)
/* special positions in the game control window (relative to main window) */
-#define DX_LEVEL (DX + XX_LEVEL)
+#define DX_LEVEL1 (DX + XX_LEVEL1)
+#define DX_LEVEL2 (DX + XX_LEVEL2)
#define DY_LEVEL (DY + YY_LEVEL)
#define DX_EMERALDS (DX + XX_EMERALDS)
#define DY_EMERALDS (DY + YY_EMERALDS)
#define MOVE_DELAY_HIGH_SPEED 4
#define MOVE_DELAY_MAX_SPEED 1
-#if 0
-#define DOUBLE_MOVE_DELAY(x) (x = (x <= MOVE_DELAY_HIGH_SPEED ? x * 2 : x))
-#define HALVE_MOVE_DELAY(x) (x = (x >= MOVE_DELAY_HIGH_SPEED ? x / 2 : x))
-#else
#define DOUBLE_MOVE_DELAY(x) (x = (x < MOVE_DELAY_MIN_SPEED ? x * 2 : x))
#define HALVE_MOVE_DELAY(x) (x = (x > MOVE_DELAY_MAX_SPEED ? x / 2 : x))
-#endif
-#define DOUBLE_PLAYER_SPEED(p) (HALVE_MOVE_DELAY((p)->move_delay_value))
+
+#define DOUBLE_PLAYER_SPEED(p) (HALVE_MOVE_DELAY( (p)->move_delay_value))
#define HALVE_PLAYER_SPEED(p) (DOUBLE_MOVE_DELAY((p)->move_delay_value))
/* values for other actions */
RND((c)->delay_random))
-#if 1
#define GET_VALID_RUNTIME_ELEMENT(e) \
((e) >= NUM_RUNTIME_ELEMENTS ? EL_UNKNOWN : (e))
-#else
-#define GET_VALID_FILE_ELEMENT(e) \
- ((e) >= NUM_FILE_ELEMENTS ? EL_UNKNOWN : (e))
-#endif
-#define GET_TARGET_ELEMENT(e, ch, cv, cs) \
+#define RESOLVED_REFERENCE_ELEMENT(be, e) \
+ ((be) + (e) - EL_SELF < EL_CUSTOM_START ? EL_CUSTOM_START : \
+ (be) + (e) - EL_SELF > EL_CUSTOM_END ? EL_CUSTOM_END : \
+ (be) + (e) - EL_SELF)
+
+#define GET_TARGET_ELEMENT(be, e, ch, cv, cs) \
((e) == EL_TRIGGER_PLAYER ? (ch)->actual_trigger_player : \
(e) == EL_TRIGGER_ELEMENT ? (ch)->actual_trigger_element : \
(e) == EL_TRIGGER_CE_VALUE ? (ch)->actual_trigger_ce_value : \
(e) == EL_TRIGGER_CE_SCORE ? (ch)->actual_trigger_ce_score : \
(e) == EL_CURRENT_CE_VALUE ? (cv) : \
- (e) == EL_CURRENT_CE_SCORE ? (cs) : (e))
+ (e) == EL_CURRENT_CE_SCORE ? (cs) : \
+ (e) >= EL_LAST_CE_8 && (e) <= EL_NEXT_CE_8 ? \
+ RESOLVED_REFERENCE_ELEMENT(be, e) : \
+ (e))
#define CAN_GROW_INTO(e) \
((e) == EL_SAND || (IS_DIGGABLE(e) && level.grow_into_diggable))
(IN_LEV_FIELD(x, y) && (Feld[x][y] == EL_EMC_SPRING_BUMPER || \
Feld[x][y] == EL_EMC_SPRING_BUMPER_ACTIVE))
-#if 0
-#define GROUP_NR(e) ((e) - EL_GROUP_START)
-#define IS_IN_GROUP(e, nr) (element_info[e].in_group[nr] == TRUE)
-#define IS_IN_GROUP_EL(e, ge) (IS_IN_GROUP(e, (ge) - EL_GROUP_START))
-
-#define IS_EQUAL_OR_IN_GROUP(e, ge) \
- (IS_GROUP_ELEMENT(ge) ? IS_IN_GROUP(e, GROUP_NR(ge)) : (e) == (ge))
-#endif
-
#define MOVE_ENTER_EL(e) (element_info[e].move_enter_element)
#define CE_ENTER_FIELD_COND(e, x, y) \
static void InitMagicBallDelay(int, int);
static void ActivateMagicBall(int, int);
-static void InitDiagonalMovingElement(int, int);
-
struct ChangingElementInfo
{
int element;
0,
NULL,
NULL,
- InitDiagonalMovingElement
+ NULL,
},
{
break;
default:
-#if 1
if (IS_CUSTOM_ELEMENT(element))
{
if (CAN_MOVE(element))
CustomValue[x][y] = GET_NEW_CE_VALUE(Feld[x][y]);
#endif
}
-#else
- if (IS_CUSTOM_ELEMENT(element) && CAN_MOVE(element))
- InitMovDir(x, y);
-#endif
else if (IS_GROUP_ELEMENT(element))
{
-#if 1
Feld[x][y] = get_element_from_group_element(element);
InitField(x, y, init_game);
-#else
- struct ElementGroupInfo *group = element_info[element].group;
- int last_anim_random_frame = gfx.anim_random_frame;
- int element_pos;
-
- if (group->choice_mode == ANIM_RANDOM)
- gfx.anim_random_frame = RND(group->num_elements_resolved);
-
- element_pos = getAnimationFrame(group->num_elements_resolved, 1,
- group->choice_mode, 0,
- group->choice_pos);
-
- if (group->choice_mode == ANIM_RANDOM)
- gfx.anim_random_frame = last_anim_random_frame;
-
- group->choice_pos++;
-
- Feld[x][y] = group->element_resolved[element_pos];
-
- InitField(x, y, init_game);
-#endif
}
+
break;
}
-#if 1
if (!init_game)
CheckTriggeredElementChange(x, y, element, CE_CREATION_OF_X);
-#endif
-
-#if 0
-
-#if USE_NEW_CUSTOM_VALUE
-
-#if 1
- CustomValue[x][y] = GET_NEW_CE_VALUE(Feld[x][y]);
-#else
- CustomValue[x][y] = element_info[Feld[x][y]].custom_value_initial;
-#endif
-
-#endif
-
-#endif
}
static inline void InitField_WithBug1(int x, int y, boolean init_game)
{
int xpos = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2;
+ if (PANEL_DEACTIVATED(game.panel.gems))
+ return;
+
DrawText(DX_EMERALDS + xpos, DY_EMERALDS, int2str(value, 3), FONT_TEXT_2);
}
{
int xpos = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2;
+ if (PANEL_DEACTIVATED(game.panel.inventory))
+ return;
+
DrawText(DX_DYNAMITE + xpos, DY_DYNAMITE, int2str(value, 3), FONT_TEXT_2);
}
int base_key_graphic = EL_KEY_1;
int i;
+ if (PANEL_DEACTIVATED(game.panel.keys))
+ return;
+
if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
base_key_graphic = EL_EM_KEY_1;
/* currently only 4 of 8 possible keys are displayed */
for (i = 0; i < STD_NUM_KEYS; i++)
{
+ int x = XX_KEYS + i * MINI_TILEX;
+ int y = YY_KEYS;
+
if (key[i])
- DrawMiniGraphicExt(drawto, DX_KEYS + i * MINI_TILEX, DY_KEYS,
- el2edimg(base_key_graphic + i));
+ DrawMiniGraphicExt(drawto, DX + x,DY + y, el2edimg(base_key_graphic + i));
else
BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
- DOOR_GFX_PAGEX5 + XX_KEYS + i * MINI_TILEX, YY_KEYS,
- MINI_TILEX, MINI_TILEY, DX_KEYS + i * MINI_TILEX, DY_KEYS);
+ DOOR_GFX_PAGEX5 + x, y, MINI_TILEX, MINI_TILEY, DX + x,DY + y);
}
}
{
int xpos = (5 * 14 - 5 * getFontWidth(FONT_TEXT_2)) / 2;
+ if (PANEL_DEACTIVATED(game.panel.score))
+ return;
+
DrawText(DX_SCORE + xpos, DY_SCORE, int2str(value, 5), FONT_TEXT_2);
}
int xpos3 = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2;
int xpos4 = (4 * 10 - 4 * getFontWidth(FONT_LEVEL_NUMBER)) / 2;
+ if (PANEL_DEACTIVATED(game.panel.time))
+ return;
+
/* clear background if value just changed its size */
if (value == 999 || value == 1000)
- ClearRectangle(drawto, DX_TIME1, DY_TIME, 14 * 3, 14);
+ ClearRectangleOnBackground(drawto, DX_TIME1, DY_TIME, 14 * 3, 14);
if (value < 1000)
DrawText(DX_TIME1 + xpos3, DY_TIME, int2str(value, 3), FONT_TEXT_2);
inline void DrawGameValue_Level(int value)
{
+ if (PANEL_DEACTIVATED(game.panel.level))
+ return;
+
if (level_nr < 100)
- DrawText(DX_LEVEL, DY_LEVEL, int2str(value, 2), FONT_TEXT_2);
+ DrawText(DX_LEVEL1, DY_LEVEL, int2str(value, 2), FONT_TEXT_2);
else
- {
- /* misuse area for displaying emeralds to draw bigger level number */
- DrawTextExt(drawto, DX_EMERALDS, DY_EMERALDS,
- int2str(value, 3), FONT_LEVEL_NUMBER, BLIT_OPAQUE);
-
- /* now copy it to the area for displaying level number */
- BlitBitmap(drawto, drawto,
- DX_EMERALDS, DY_EMERALDS + 1,
- getFontWidth(FONT_LEVEL_NUMBER) * 3,
- getFontHeight(FONT_LEVEL_NUMBER) - 1,
- DX_LEVEL - 1, DY_LEVEL + 1);
-
- /* restore the area for displaying emeralds */
- DrawGameValue_Emeralds(local_player->gems_still_needed);
-
- /* yes, this is all really ugly :-) */
- }
+ DrawText(DX_LEVEL2, DY_LEVEL, int2str(value, 3), FONT_LEVEL_NUMBER);
}
void DrawAllGameValues(int emeralds, int dynamite, int score, int time,
DrawGameValue_Time(time);
DrawGameValue_Keys(key);
+
+ redraw_mask |= REDRAW_DOOR_1;
}
void DrawGameDoorValues()
{
+ int time_value = (level.time == 0 ? TimePlayed : TimeLeft);
int dynamite_state = 0;
int key_bits = 0;
int i, j;
return;
}
-#if 0
- DrawGameValue_Level(level_nr);
-
- DrawGameValue_Emeralds(local_player->gems_still_needed);
- DrawGameValue_Dynamite(local_player->inventory_size);
- DrawGameValue_Score(local_player->score);
- DrawGameValue_Time(TimeLeft);
-
-#else
-
if (game.centered_player_nr == -1)
{
for (i = 0; i < MAX_PLAYERS; i++)
dynamite_state += stored_player[i].inventory_size;
}
-
-#if 0
- DrawGameValue_Keys(stored_player[i].key);
-#endif
}
else
{
}
DrawAllGameValues(local_player->gems_still_needed, dynamite_state,
- local_player->score, TimeLeft, key_bits);
-#endif
+ local_player->score, time_value, key_bits);
}
-#if 0
-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_UNKNOWN;
-
- return;
- }
-
- if (recursion_depth == 0) /* initialization */
- {
- group = element_info[group_element].group;
- group_nr = group_element - EL_GROUP_START;
-
- group->num_elements_resolved = 0;
- group->choice_pos = 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;
- element_info[element].in_group[group_nr] = TRUE;
- }
- }
-}
-#endif
/*
=============================================================================
printf(" => game.engine_version == %06d\n", game.engine_version);
#endif
-#if 0
- /* ---------- 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);
-#endif
-
/* ---------- initialize player's initial move delay --------------------- */
-#if 1
/* dynamically adjust player properties according to level information */
for (i = 0; i < MAX_PLAYERS; i++)
game.initial_move_delay_value[i] =
get_move_delay_from_stepsize(level.initial_player_stepsize[i]);
-#else
- /* dynamically adjust player properties according to level information */
- game.initial_move_delay_value =
- (level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED);
-#endif
/* dynamically adjust player properties according to game engine version */
for (i = 0; i < MAX_PLAYERS; i++)
for (l = 0; l < group->num_elements_resolved; l++)
trigger_events[group->element_resolved[l]][k] = TRUE;
}
+ else if (trigger_element == EL_ANY_ELEMENT)
+ for (l = 0; l < MAX_NUM_ELEMENTS; l++)
+ trigger_events[l][k] = TRUE;
else
trigger_events[trigger_element][k] = TRUE;
}
{
if (!IS_CUSTOM_ELEMENT(i))
{
- element_info[i].push_delay_fixed = game.default_push_delay_fixed;
- element_info[i].push_delay_random = game.default_push_delay_random;
+ /* set default push delay values (corrected since version 3.0.7-1) */
+ if (game.engine_version < VERSION_IDENT(3,0,7,1))
+ {
+ element_info[i].push_delay_fixed = 2;
+ element_info[i].push_delay_random = 8;
+ }
+ else
+ {
+ element_info[i].push_delay_fixed = 8;
+ element_info[i].push_delay_random = 8;
+ }
}
}
break;
}
-#if 0
- printf("::: %d->%d: %d\n", action_first, action_last, num_special_action);
-#endif
-
return num_special_action;
}
+
/*
=============================================================================
InitGame()
boolean emulate_bd = TRUE; /* unless non-BOULDERDASH elements found */
boolean emulate_sb = TRUE; /* unless non-SOKOBAN elements found */
boolean emulate_sp = TRUE; /* unless non-SUPAPLEX elements found */
+ boolean do_fading = (game_status == GAME_MODE_MAIN);
int i, j, x, y;
+ game_status = GAME_MODE_PLAYING;
+
InitGameEngine();
/* don't play tapes over network */
player->last_move_dir = MV_NONE;
+ player->is_active = FALSE;
+
player->is_waiting = FALSE;
player->is_moving = FALSE;
player->is_auto_moving = FALSE;
player->special_action_bored = ACTION_DEFAULT;
player->special_action_sleeping = ACTION_DEFAULT;
-#if 1
- /* cannot be set here -- could be modified in Init[Player]Field() below */
-#else
- /* set number of special actions for bored and sleeping animation */
- player->num_special_action_bored =
- get_num_special_action(player->artwork_element,
- ACTION_BORING_1, ACTION_BORING_LAST);
- player->num_special_action_sleeping =
- get_num_special_action(player->artwork_element,
- ACTION_SLEEPING_1, ACTION_SLEEPING_LAST);
-#endif
-
player->switch_x = -1;
player->switch_y = -1;
player->show_envelope = 0;
-#if 1
SetPlayerMoveSpeed(player, level.initial_player_stepsize[i], TRUE);
-#else
- player->move_delay = game.initial_move_delay;
- player->move_delay_value = game.initial_move_delay_value;
-
- player->move_delay_value_next = -1;
-
- player->move_delay_reset_counter = 0;
-
- player->cannot_move = FALSE;
-#endif
player->push_delay = -1; /* initialized when pushing starts */
player->push_delay_value = game.initial_push_delay_value;
player->LevelSolved = FALSE;
player->GameOver = FALSE;
+
+ player->LevelSolved_GameEnd = FALSE;
+ player->LevelSolved_SaveTape = FALSE;
+ player->LevelSolved_SaveScore = FALSE;
}
network_player_action_received = FALSE;
game.wind_direction = level.wind_direction_initial;
#if !USE_PLAYER_GRAVITY
-#if 1
game.gravity = FALSE;
-#else
- game.gravity = level.initial_gravity;
-#endif
game.explosions_delayed = TRUE;
#endif
tape.set_centered_player = TRUE;
}
-#if 0
- printf("::: focus set to player %d [%d]\n",
- game.centered_player_nr, local_player->index_nr);
-#endif
-
for (i = 0; i < NUM_BELTS; i++)
{
game.belt_dir[i] = MV_NONE;
for (i = 0; i < MAX_NUM_AMOEBA; i++)
AmoebaCnt[i] = AmoebaCnt2[i] = 0;
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (x = 0; x < lev_fieldx; x++) for (y = 0; y < lev_fieldy; y++)
-#endif
{
Feld[x][y] = level.field[x][y];
MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
GfxDir[x][y] = MV_NONE;
}
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
{
if (emulate_bd && !IS_BD_ELEMENT(Feld[x][y]))
emulate_bd = FALSE;
{
struct PlayerInfo *player = &stored_player[i];
-#if 1
/* set number of special actions for bored and sleeping animation */
player->num_special_action_bored =
get_num_special_action(player->artwork_element,
player->num_special_action_sleeping =
get_num_special_action(player->artwork_element,
ACTION_SLEEPING_1, ACTION_SLEEPING_LAST);
-#endif
-
}
game.emulation = (emulate_bd ? EMU_BOULDERDASH :
some_player->present = FALSE;
some_player->active = FALSE;
-#if 0
- player->element_nr = some_player->element_nr;
-#endif
-
player->artwork_element = some_player->artwork_element;
player->block_last_field = some_player->block_last_field;
int found_element = EL_UNDEFINED;
int player_nr = local_player->index_nr;
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
{
int element = Feld[x][y];
int content;
local_player->jy - MIDPOSY);
}
+ StopAnimation();
+
if (!game.restart_level)
CloseDoor(DOOR_CLOSE_1);
+ if (do_fading)
+ FadeOut(REDRAW_FIELD);
+
/* !!! FIX THIS (START) !!! */
if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
{
InitGameEngine_EM();
+
+ /* blit playfield from scroll buffer to normal back buffer for fading in */
+ BlitScreenToBitmap_EM(backbuffer);
}
else
{
if (game.timegate_time_left == 0)
CloseAllOpenTimegates();
+ /* blit playfield from scroll buffer to normal back buffer for fading in */
if (setup.soft_scrolling)
BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
redraw_mask |= REDRAW_FROM_BACKBUFFER;
- FadeToFront();
}
/* !!! FIX THIS (END) !!! */
+ if (do_fading)
+ FadeIn(REDRAW_FIELD);
+
+ BackToFront();
+
if (!game.restart_level)
{
/* copy default game door content to main double buffer */
DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
}
+ SetPanelBackground();
+ SetDrawBackgroundMask(REDRAW_DOOR_1);
+
DrawGameDoorValues();
if (!game.restart_level)
GfxDir[x][y] = MovDir[x][y];
}
-void InitAmoebaNr(int x, int y)
-{
- int i;
- int group_nr = AmoebeNachbarNr(x, y);
+void InitAmoebaNr(int x, int y)
+{
+ int i;
+ int group_nr = AmoebeNachbarNr(x, y);
+
+ if (group_nr == 0)
+ {
+ for (i = 1; i < MAX_NUM_AMOEBA; i++)
+ {
+ if (AmoebaCnt[i] == 0)
+ {
+ group_nr = i;
+ break;
+ }
+ }
+ }
+
+ AmoebaNr[x][y] = group_nr;
+ AmoebaCnt[group_nr]++;
+ AmoebaCnt2[group_nr]++;
+}
+
+#if USE_NEW_GAME_WON
+
+void GameWon()
+{
+ static boolean score_done = FALSE;
+ static boolean player_done = FALSE;
+ static int game_over_delay = 0;
+ int game_over_delay_value = 50;
+
+ /* do not start end game actions before the player stops moving (to exit) */
+ if (local_player->MovPos)
+ return;
+
+ if (tape.auto_play) /* tape might already be stopped here */
+ tape.auto_play_level_solved = TRUE;
+
+ if (!local_player->LevelSolved_GameEnd)
+ {
+ local_player->LevelSolved_GameEnd = TRUE;
+ local_player->LevelSolved_SaveTape = tape.recording;
+ local_player->LevelSolved_SaveScore = !tape.playing;
+
+ score_done = FALSE;
+ player_done = FALSE;
+ game_over_delay = 0;
+ }
+
+ PlaySoundStereo(SND_GAME_WINNING, SOUND_MIDDLE);
+
+ if (TimeLeft > 0)
+ {
+ if (!tape.playing)
+ {
+ if (setup.sound_loops)
+ PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MIDDLE,
+ SND_CTRL_PLAY_LOOP);
+ else
+ PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MIDDLE);
+ }
+
+ if (TimeLeft > 100 && TimeLeft % 10 == 0)
+ {
+ TimeLeft -= 10;
+ RaiseScore(level.score[SC_TIME_BONUS] * 10);
+ }
+ else
+ {
+ TimeLeft--;
+ RaiseScore(level.score[SC_TIME_BONUS]);
+ }
+
+ DrawGameValue_Time(TimeLeft);
+
+ if (TimeLeft <= 0 && !tape.playing && setup.sound_loops)
+ StopSound(SND_GAME_LEVELTIME_BONUS);
+ }
+ else if (level.time == 0 && TimePlayed < 999) /* level without time limit */
+ {
+ if (!tape.playing)
+ {
+ if (setup.sound_loops)
+ PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MIDDLE,
+ SND_CTRL_PLAY_LOOP);
+ else
+ PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MIDDLE);
+ }
+
+ if (TimePlayed < 900 && TimePlayed % 10 == 0)
+ {
+ TimePlayed += 10;
+ RaiseScore(level.score[SC_TIME_BONUS] * 10);
+ }
+ else
+ {
+ TimePlayed++;
+ RaiseScore(level.score[SC_TIME_BONUS]);
+ }
+
+ DrawGameValue_Time(TimePlayed);
+
+ if (TimePlayed >= 999 && !tape.playing && setup.sound_loops)
+ StopSound(SND_GAME_LEVELTIME_BONUS);
+ }
+ else
+ {
+ score_done = TRUE;
+ }
+
+ /* close exit door after last player */
+ if (AllPlayersGone && ExitX >= 0 && ExitY >= 0 &&
+ (Feld[ExitX][ExitY] == EL_EXIT_OPEN ||
+ Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN))
+ {
+ int element = Feld[ExitX][ExitY];
+
+ Feld[ExitX][ExitY] = (element == EL_EXIT_OPEN ? EL_EXIT_CLOSING :
+ EL_SP_EXIT_CLOSING);
+
+ PlayLevelSoundElementAction(ExitX, ExitY, element, ACTION_CLOSING);
+ }
+
+ /* player disappears */
+ if (ExitX >= 0 && ExitY >= 0 && !player_done)
+ {
+ DrawLevelField(ExitX, ExitY);
+
+ player_done = TRUE;
+ }
+
+ game_over_delay++;
+
+ if (game_over_delay < game_over_delay_value || !score_done)
+ return;
+}
+
+void GameEnd()
+{
+ int hi_pos;
+ boolean raise_level = FALSE;
+
+ CloseDoor(DOOR_CLOSE_1);
+
+ if (local_player->LevelSolved_SaveTape)
+ {
+ TapeStop();
+
+ SaveTape(tape.level_nr); /* Ask to save tape */
+ }
+
+ if (!local_player->LevelSolved_SaveScore)
+ {
+ FadeOut(REDRAW_FIELD);
+
+ game_status = GAME_MODE_MAIN;
+
+ DrawAndFadeInMainMenu(REDRAW_FIELD);
+
+ return;
+ }
+
+ if (level_nr == leveldir_current->handicap_level)
+ {
+ leveldir_current->handicap_level++;
+ SaveLevelSetup_SeriesInfo();
+ }
+
+ if (level_editor_test_game)
+ local_player->score = -1; /* no highscore when playing from editor */
+ else if (level_nr < leveldir_current->last_level)
+ raise_level = TRUE; /* advance to next level */
+
+ if ((hi_pos = NewHiScore()) >= 0)
+ {
+ game_status = GAME_MODE_SCORES;
+
+ DrawHallOfFame(hi_pos);
+
+ if (raise_level)
+ {
+ level_nr++;
+ TapeErase();
+ }
+ }
+ else
+ {
+ FadeOut(REDRAW_FIELD);
+
+ game_status = GAME_MODE_MAIN;
- if (group_nr == 0)
- {
- for (i = 1; i < MAX_NUM_AMOEBA; i++)
+ if (raise_level)
{
- if (AmoebaCnt[i] == 0)
- {
- group_nr = i;
- break;
- }
+ level_nr++;
+ TapeErase();
}
+
+ DrawAndFadeInMainMenu(REDRAW_FIELD);
}
- AmoebaNr[x][y] = group_nr;
- AmoebaCnt[group_nr]++;
- AmoebaCnt2[group_nr]++;
+ local_player->LevelSolved_SaveScore = FALSE;
}
+#else
+
void GameWon()
{
int hi_pos;
BackToFront();
-#if 0
- if (tape.playing)
- printf("::: TAPE PLAYING -> DO NOT SAVE SCORE\n");
- else
- printf("::: NO TAPE PLAYING -> SAVING SCORE\n");
-#endif
-
if (tape.playing)
return;
BackToFront();
}
+#endif
+
int NewHiScore()
{
int k, l;
/* special values for move stepsize for spring and things on conveyor belt */
if (horiz_move)
{
-#if 0
- if (element == EL_SPRING)
- step = sign * MOVE_STEPSIZE_NORMAL * 2;
- else if (CAN_FALL(element) && !CAN_MOVE(element) &&
- y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
- step = sign * MOVE_STEPSIZE_NORMAL / 2;
-#else
if (CAN_FALL(element) &&
y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
step = sign * MOVE_STEPSIZE_NORMAL / 2;
else if (element == EL_SPRING)
step = sign * MOVE_STEPSIZE_NORMAL * 2;
-#endif
}
return step;
static void ResetGfxAnimation(int x, int y)
{
-#if 0
- int element, graphic;
-#endif
-
GfxAction[x][y] = ACTION_DEFAULT;
GfxDir[x][y] = MovDir[x][y];
GfxFrame[x][y] = 0;
-#if 0
- element = Feld[x][y];
- graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
-
- if (graphic_info[graphic].anim_global_sync)
- GfxFrame[x][y] = FrameCounter;
- else if (ANIM_MODE(graphic) == ANIM_CE_VALUE)
- GfxFrame[x][y] = CustomValue[x][y];
- else if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
- GfxFrame[x][y] = element_info[element].collect_score;
- else if (ANIM_MODE(graphic) == ANIM_CE_DELAY)
- GfxFrame[x][y] = ChangeDelay[x][y];
-#endif
-
#if USE_GFX_RESET_GFX_ANIMATION
ResetGfxFrame(x, y, FALSE);
#endif
void InitMovingField(int x, int y, int direction)
{
int element = Feld[x][y];
-#if 0
- int graphic;
-#endif
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;
GfxAction[x][y] = (direction == MV_DOWN && CAN_FALL(element) ?
ACTION_FALLING : ACTION_MOVING);
-#if 0
- graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
-
- if (graphic_info[graphic].anim_global_sync)
- GfxFrame[x][y] = FrameCounter;
- else if (ANIM_MODE(graphic) == ANIM_CE_VALUE)
- GfxFrame[x][y] = CustomValue[x][y];
- else if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
- GfxFrame[x][y] = element_info[element].collect_score;
- else if (ANIM_MODE(graphic) == ANIM_CE_DELAY)
- GfxFrame[x][y] = ChangeDelay[x][y];
-#endif
-
/* this is needed for CEs with property "can move" / "not moving" */
if (getElementMoveStepsize(x, y) != 0) /* moving or being moved */
void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y)
{
int direction = MovDir[x][y];
-#if 1
int newx = x + (direction & MV_LEFT ? -1 : direction & MV_RIGHT ? +1 : 0);
int newy = y + (direction & MV_UP ? -1 : direction & MV_DOWN ? +1 : 0);
-#else
- int newx = x + (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
- int newy = y + (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
-#endif
*goes_to_x = newx;
*goes_to_y = newy;
Bang(x, y);
}
-#if 1
-
static void setMinimalPlayerBoundaries(int *sx1, int *sy1, int *sx2, int *sy2)
{
boolean num_checked_players = 0;
*sy = (sy1 + sy2) / 2;
}
-#if 0
-static void setMaxCenterDistanceForAllPlayers(int *max_dx, int *max_dy,
- int center_x, int center_y)
-{
- int sx1 = center_x, sy1 = center_y, sx2 = center_x, sy2 = center_y;
-
- setMinimalPlayerBoundaries(&sx1, &sy1, &sx2, &sy2);
-
- *max_dx = MAX(ABS(sx1 - center_x), ABS(sx2 - center_x));
- *max_dy = MAX(ABS(sy1 - center_y), ABS(sy2 - center_y));
-}
-
-static boolean checkIfAllPlayersAreVisible(int center_x, int center_y)
-{
- int max_dx, max_dy;
-
- setMaxCenterDistanceForAllPlayers(&max_dx, &max_dy, center_x, center_y);
-
- return (max_dx <= SCR_FIELDX / 2 &&
- max_dy <= SCR_FIELDY / 2);
-}
-#endif
-
-#endif
-
-#if 1
-
void DrawRelocateScreen(int x, int y, int move_dir, boolean center_screen,
boolean quick_relocation)
{
{
int offset = (setup.scroll_delay ? 3 : 0);
-#if 0
- if (center_screen)
- offset = 0;
-#endif
-
if (!IN_VIS_FIELD(SCREENX(x), SCREENY(y)) || center_screen)
{
scroll_x = (x < SBX_Left + MIDPOSX ? SBX_Left :
}
}
-#else
-
-void DrawRelocatePlayer(struct PlayerInfo *player, boolean quick_relocation)
-{
- boolean ffwd_delay = (tape.playing && tape.fast_forward);
- 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 jx = player->jx;
- int jy = player->jy;
-
- if (quick_relocation)
- {
- int offset = (setup.scroll_delay ? 3 : 0);
-
- if (!IN_VIS_FIELD(SCREENX(jx), SCREENY(jy)))
- {
- scroll_x = (player->jx < SBX_Left + MIDPOSX ? SBX_Left :
- player->jx > SBX_Right + MIDPOSX ? SBX_Right :
- player->jx - MIDPOSX);
-
- scroll_y = (player->jy < SBY_Upper + MIDPOSY ? SBY_Upper :
- player->jy > SBY_Lower + MIDPOSY ? SBY_Lower :
- player->jy - MIDPOSY);
- }
- else
- {
- if ((player->MovDir == MV_LEFT && scroll_x > jx - MIDPOSX + offset) ||
- (player->MovDir == MV_RIGHT && scroll_x < jx - MIDPOSX - offset))
- scroll_x = jx - MIDPOSX + (scroll_x < jx-MIDPOSX ? -offset : +offset);
-
- if ((player->MovDir == MV_UP && scroll_y > jy - MIDPOSY + offset) ||
- (player->MovDir == MV_DOWN && scroll_y < jy - MIDPOSY - offset))
- scroll_y = jy - MIDPOSY + (scroll_y < jy-MIDPOSY ? -offset : +offset);
-
- /* don't scroll over playfield boundaries */
- if (scroll_x < SBX_Left || scroll_x > SBX_Right)
- scroll_x = (scroll_x < SBX_Left ? SBX_Left : SBX_Right);
-
- /* don't scroll over playfield boundaries */
- if (scroll_y < SBY_Upper || scroll_y > SBY_Lower)
- scroll_y = (scroll_y < SBY_Upper ? SBY_Upper : SBY_Lower);
- }
-
- RedrawPlayfield(TRUE, 0,0,0,0);
- }
- else
- {
- int scroll_xx = (player->jx < SBX_Left + MIDPOSX ? SBX_Left :
- player->jx > SBX_Right + MIDPOSX ? SBX_Right :
- player->jx - MIDPOSX);
-
- int scroll_yy = (player->jy < SBY_Upper + MIDPOSY ? SBY_Upper :
- player->jy > SBY_Lower + MIDPOSY ? SBY_Lower :
- player->jy - MIDPOSY);
-
- ScrollScreen(NULL, SCROLL_GO_ON); /* scroll last frame to full tile */
-
- while (scroll_x != scroll_xx || scroll_y != scroll_yy)
- {
- int dx = 0, dy = 0;
- int fx = FX, fy = FY;
-
- dx = (scroll_xx < scroll_x ? +1 : scroll_xx > scroll_x ? -1 : 0);
- dy = (scroll_yy < scroll_y ? +1 : scroll_yy > scroll_y ? -1 : 0);
-
- if (dx == 0 && dy == 0) /* no scrolling needed at all */
- break;
-
- scroll_x -= dx;
- scroll_y -= dy;
-
- fx += dx * TILEX / 2;
- fy += dy * TILEY / 2;
-
- ScrollLevel(dx, dy);
- DrawAllPlayers();
-
- /* scroll in two steps of half tile size to make things smoother */
- BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
- FlushDisplay();
- Delay(wait_delay_value);
-
- /* scroll second step to align at full tile size */
- BackToFront();
- Delay(wait_delay_value);
- }
-
- DrawPlayer(player);
- BackToFront();
- Delay(wait_delay_value);
- }
-}
-
-#endif
-
void RelocatePlayer(int jx, int jy, int el_player_raw)
{
int el_player = GET_PLAYER_ELEMENT(el_player_raw);
InitField(jx, jy, FALSE);
}
-#if 1
/* only visually relocate centered player */
-#if 1
DrawRelocateScreen(player->jx, player->jy, player->MovDir, FALSE,
level.instant_relocation);
-#else
- if (player->index_nr == game.centered_player_nr)
- DrawRelocatePlayer(player, level.instant_relocation);
-#endif
-#else
- if (player == local_player) /* only visually relocate local player */
- DrawRelocatePlayer(player, level.instant_relocation);
-#endif
TestIfPlayerTouchesBadThing(jx, jy);
TestIfPlayerTouchesCustomElement(jx, jy);
PlayLevelSoundElementAction(ex, ey, artwork_element, ACTION_EXPLODING);
#endif
-#if 1
last_phase = element_info[explosion_element].explosion_delay + 1;
-#else
- last_phase = element_info[center_element].explosion_delay + 1;
-#endif
for (y = ey - 1; y <= ey + 1; y++) for (x = ex - 1; x <= ex + 1; x++)
{
if (IS_PLAYER(ex, ey) && !PLAYER_EXPLOSION_PROTECTED(ex, ey))
{
-#if 1
int player_nr = StorePlayer[ex][ey] - EL_PLAYER_1;
Store[x][y] = EL_PLAYER_IS_EXPLODING_1 + player_nr;
-#else
- switch(StorePlayer[ex][ey])
- {
- case EL_PLAYER_2:
- Store[x][y] = EL_PLAYER_IS_EXPLODING_2;
- break;
- case EL_PLAYER_3:
- Store[x][y] = EL_PLAYER_IS_EXPLODING_3;
- break;
- case EL_PLAYER_4:
- Store[x][y] = EL_PLAYER_IS_EXPLODING_4;
- break;
- case EL_PLAYER_1:
- default:
- Store[x][y] = EL_PLAYER_IS_EXPLODING_1;
- break;
- }
-#endif
if (PLAYERINFO(ex, ey)->use_murphy)
Store[x][y] = EL_EMPTY;
}
-#if 1
+
/* !!! check this case -- currently needed for rnd_rado_negundo_v,
!!! levels 015 018 019 020 021 022 023 026 027 028 !!! */
else if (ELEM_IS_PLAYER(center_element))
#endif
else
Store[x][y] = EL_EMPTY;
-#else
- else if (center_element == EL_MOLE)
- Store[x][y] = EL_EMERALD_RED;
- else if (center_element == EL_PENGUIN)
- Store[x][y] = EL_EMERALD_PURPLE;
- else if (center_element == EL_BUG)
- Store[x][y] = ((x == ex && y == ey) ? EL_DIAMOND : EL_EMERALD);
- else if (center_element == EL_BD_BUTTERFLY)
- Store[x][y] = EL_BD_DIAMOND;
- else if (center_element == EL_SP_ELECTRON)
- Store[x][y] = EL_SP_INFOTRON;
- 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].e[xx][yy];
- else if (IS_CUSTOM_ELEMENT(center_element) &&
- 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)
- Store[x][y] = EL_DIAMOND;
- else if (element == EL_WALL_BD_DIAMOND)
- Store[x][y] = EL_BD_DIAMOND;
- else if (element == EL_WALL_EMERALD_YELLOW)
- Store[x][y] = EL_EMERALD_YELLOW;
- else if (element == EL_WALL_EMERALD_RED)
- Store[x][y] = EL_EMERALD_RED;
- else if (element == EL_WALL_EMERALD_PURPLE)
- Store[x][y] = EL_EMERALD_PURPLE;
- else if (element == EL_WALL_PEARL)
- Store[x][y] = EL_PEARL;
- 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.e[1][1];
- else
- Store[x][y] = EL_EMPTY;
-#endif
if (x != ex || y != ey || mode == EX_TYPE_BORDER ||
center_element == EL_AMOEBA_TO_DIAMOND)
Feld[x][y] = EL_EXPLOSION;
GfxElement[x][y] = artwork_element;
-#if 0
- printf(":: setting gfx(%d,%d) to %d ['%s']\n",
- x, y, artwork_element, EL_NAME(artwork_element));
-#endif
-
ExplodePhase[x][y] = 1;
ExplodeDelay[x][y] = last_phase;
}
}
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
{
int element = Feld[x][y];
graphic_info[graphic].anim_mode |= ANIM_REVERSE;
}
-#if 1
SCAN_PLAYFIELD(xx, yy)
-#else
- for (yy = 0; yy < lev_fieldy; yy++) for (xx = 0; xx < lev_fieldx; xx++)
-#endif
{
int element = Feld[xx][yy];
game.switchgate_pos = !game.switchgate_pos;
-#if 1
SCAN_PLAYFIELD(xx, yy)
-#else
- for (yy = 0; yy < lev_fieldy; yy++) for (xx = 0; xx < lev_fieldx; xx++)
-#endif
{
int element = Feld[xx][yy];
{
int x, y;
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
{
int element = Feld[x][y];
{
int x, y;
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
{
int element = Feld[x][y];
{
int x, y;
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
{
int element = Feld[x][y];
game.timegate_time_left = level.time_timegate * FRAMES_PER_SECOND;
-#if 1
SCAN_PLAYFIELD(xx, yy)
-#else
- for (yy = 0; yy < lev_fieldy; yy++) for (xx = 0; xx < lev_fieldx; xx++)
-#endif
{
int element = Feld[xx][yy];
EL_BD_MAGIC_WALL_ACTIVE);
/* activate magic wall / mill */
-#if 1
SCAN_PLAYFIELD(xx, yy)
-#else
- for (yy = 0; yy < lev_fieldy; yy++) for (xx = 0; xx < lev_fieldx; xx++)
-#endif
if (Feld[xx][yy] == smashed)
Feld[xx][yy] = activated_magic_wall;
static void TurnRound(int x, int y)
{
int direction = MovDir[x][y];
-#if 0
- int element, graphic;
-#endif
TurnRoundExt(x, y);
if (MovDelay[x][y])
GfxAction[x][y] = ACTION_TURNING_FROM_LEFT + MV_DIR_TO_BIT(direction);
-#if 1
ResetGfxFrame(x, y, FALSE);
-#else
- element = Feld[x][y];
- graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
-
- if (graphic_info[graphic].anim_global_sync)
- GfxFrame[x][y] = FrameCounter;
- else if (ANIM_MODE(graphic) == ANIM_CE_VALUE)
- GfxFrame[x][y] = CustomValue[x][y];
- else if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
- GfxFrame[x][y] = element_info[element].collect_score;
- else if (ANIM_MODE(graphic) == ANIM_CE_DELAY)
- GfxFrame[x][y] = ChangeDelay[x][y];
-#endif
}
static boolean JustBeingPushed(int x, int y)
started_moving = TRUE;
Feld[x][y] = EL_QUICKSAND_EMPTYING;
+#if USE_QUICKSAND_BD_ROCK_BUGFIX
+ if (Store[x][y] != EL_ROCK && Store[x][y] != EL_BD_ROCK)
+ Store[x][y] = EL_ROCK;
+#else
Store[x][y] = EL_ROCK;
+#endif
PlayLevelSoundAction(x, y, ACTION_EMPTYING);
}
MovDelay[newx][newy] = 0;
-#if 1
if (CAN_CHANGE_OR_HAS_ACTION(element))
-#else
- if (CAN_CHANGE(element))
-#endif
{
/* copy element change control values to new field */
ChangeDelay[newx][newy] = ChangeDelay[x][y];
ChangePage[newx][newy] = ChangePage[x][y];
ChangeCount[newx][newy] = ChangeCount[x][y];
ChangeEvent[newx][newy] = ChangeEvent[x][y];
-
-#if 0
-#if USE_NEW_CUSTOM_VALUE
- CustomValue[newx][newy] = CustomValue[x][y];
-#endif
-#endif
}
-#if 1
#if USE_NEW_CUSTOM_VALUE
CustomValue[newx][newy] = CustomValue[x][y];
-#endif
#endif
ChangeDelay[x][y] = 0;
TestIfPlayerTouchesCustomElement(newx, newy);
TestIfElementTouchesCustomElement(newx, newy);
-#if 1
if (IS_CUSTOM_ELEMENT(element) && ei->move_enter_element != EL_EMPTY &&
IS_EQUAL_OR_IN_GROUP(stored_new, ei->move_enter_element))
CheckElementChangeBySide(newx, newy, element, stored_new, CE_DIGGING_X,
MV_DIR_OPPOSITE(direction));
-#endif
}
int AmoebeNachbarNr(int ax, int ay)
AmoebaCnt2[new_group_nr] += AmoebaCnt2[old_group_nr];
AmoebaCnt2[old_group_nr] = 0;
-#if 1
SCAN_PLAYFIELD(xx, yy)
-#else
- for (yy = 0; yy < lev_fieldy; yy++) for (xx = 0; xx < lev_fieldx; xx++)
-#endif
{
if (AmoebaNr[xx][yy] == old_group_nr)
AmoebaNr[xx][yy] = new_group_nr;
}
#endif
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
{
if (Feld[x][y] == EL_AMOEBA_DEAD && AmoebaNr[x][y] == group_nr)
{
}
#endif
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
{
if (AmoebaNr[x][y] == group_nr &&
(Feld[x][y] == EL_AMOEBA_DEAD ||
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);
game.ball_content_nr = (game.ball_content_nr + 1) % level.num_ball_contents;
}
-static void InitDiagonalMovingElement(int x, int y)
-{
-#if 0
- MovDelay[x][y] = level.android_move_time;
-#endif
-}
-
void CheckExit(int x, int y)
{
if (local_player->gems_still_needed > 0 ||
{
int x, y;
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
{
int element = Feld[x][y];
if (element == EL_EXPANDABLE_WALL_HORIZONTAL ||
element == EL_EXPANDABLE_WALL_ANY ||
- element == EL_EXPANDABLE_WALL)
+ element == EL_EXPANDABLE_WALL ||
+ element == EL_BD_EXPANDABLE_WALL)
{
if (links_frei)
{
action_type == CA_SET_LEVEL_GEMS ? level.gems_needed :
action_type == CA_SET_LEVEL_TIME ? level.time :
action_type == CA_SET_LEVEL_SCORE ? 0 :
-#if 1
+#if USE_NEW_CUSTOM_VALUE
action_type == CA_SET_CE_VALUE ? GET_NEW_CE_VALUE(element) :
#else
action_type == CA_SET_CE_VALUE ? ei->custom_value_initial :
{
stored_player[i].key[KEY_NR(element)] = key_state;
-#if 1
DrawGameDoorValues();
-#else
- DrawGameValue_Keys(stored_player[i].key);
-#endif
-
- redraw_mask |= REDRAW_DOOR_1;
}
}
}
action_arg_number_min,
action_arg_number_max);
-#if 1
SetPlayerMoveSpeed(&stored_player[i], move_stepsize, FALSE);
-#else
- /* 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;
-
- stored_player[i].cannot_move =
- (action_arg == CA_ARG_SPEED_NOT_MOVING ? TRUE : FALSE);
-#endif
}
}
CustomValue[x][y] = action_arg_number_new;
-#if 0
- printf("::: CE value == %d\n", CustomValue[x][y]);
-#endif
-
if (CustomValue[x][y] != last_ce_value)
{
CheckElementChange(x, y, element, EL_UNDEFINED, CE_VALUE_CHANGES);
if (CustomValue[x][y] == 0)
{
-#if 0
- printf("::: CE_VALUE_GETS_ZERO\n");
-#endif
-
CheckElementChange(x, y, element, EL_UNDEFINED, CE_VALUE_GETS_ZERO);
CheckTriggeredElementChange(x, y, element, CE_VALUE_GETS_ZERO_OF_X);
-
-#if 0
- printf("::: RESULT: %d, %d\n", Feld[x][y], ChangePage[x][y]);
-#endif
}
}
-
#endif
break;
ei->collect_score = action_arg_number_new;
-#if 0
- printf("::: CE score == %d\n", ei->collect_score);
-#endif
-
if (ei->collect_score != last_ce_score)
{
CheckElementChange(x, y, element, EL_UNDEFINED, CE_SCORE_CHANGES);
if (ei->collect_score == 0)
{
-#if 0
- printf("::: CE_SCORE_GETS_ZERO\n");
-#endif
+ int xx, yy;
CheckElementChange(x, y, element, EL_UNDEFINED, CE_SCORE_GETS_ZERO);
CheckTriggeredElementChange(x, y, element, CE_SCORE_GETS_ZERO_OF_X);
-#if 0
- printf("::: RESULT: %d, %d\n", Feld[x][y], ChangePage[x][y]);
-#endif
+ /*
+ This is a very special case that seems to be a mixture between
+ CheckElementChange() and CheckTriggeredElementChange(): while
+ the first one only affects single elements that are triggered
+ directly, the second one affects multiple elements in the playfield
+ that are triggered indirectly by another element. This is a third
+ case: Changing the CE score always affects multiple identical CEs,
+ so every affected CE must be checked, not only the single CE for
+ which the CE score was changed in the first place (as every instance
+ of that CE shares the same CE score, and therefore also can change)!
+ */
+ SCAN_PLAYFIELD(xx, yy)
+ {
+ if (Feld[xx][yy] == element)
+ CheckElementChange(xx, yy, element, EL_UNDEFINED,
+ CE_SCORE_GETS_ZERO);
+ }
}
}
-
#endif
break;
#if USE_NEW_CUSTOM_VALUE
int last_ce_value = CustomValue[x][y];
#endif
- boolean add_player = (ELEM_IS_PLAYER(new_element) &&
- IS_WALKABLE(old_element));
+ boolean new_element_is_player = ELEM_IS_PLAYER(new_element);
+ boolean add_player_onto_element = (new_element_is_player &&
+#if USE_CODE_THAT_BREAKS_SNAKE_BITE
+ /* this breaks SnakeBite when a snake is
+ halfway through a door that closes */
+ /* NOW FIXED AT LEVEL INIT IN files.c */
+ new_element != EL_SOKOBAN_FIELD_PLAYER &&
+#endif
+ IS_WALKABLE(old_element));
#if 0
/* check if element under the player changes from accessible to unaccessible
}
#endif
- if (!add_player)
+ if (!add_player_onto_element)
{
if (IS_MOVING(x, y) || IS_BLOCKED(x, y))
RemoveMovingField(x, y);
#endif
/* "ChangeCount" not set yet to allow "entered by player" change one time */
- if (ELEM_IS_PLAYER(new_element))
+ if (new_element_is_player)
RelocatePlayer(x, y, new_element);
if (is_change)
ChangeEvent[ex][ey] = ChangeEvent[x][y];
content_element = change->target_content.e[xx][yy];
- target_element = GET_TARGET_ELEMENT(content_element, change,
+ target_element = GET_TARGET_ELEMENT(element, content_element, change,
ce_value, ce_score);
CreateElementFromChange(ex, ey, target_element);
}
else
{
- target_element = GET_TARGET_ELEMENT(change->target_element, change,
+ target_element = GET_TARGET_ELEMENT(element, change->target_element, change,
ce_value, ce_score);
if (element == EL_DIAGONAL_GROWING ||
{
int x, y;
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
{
if (Feld[x][y] == element)
{
game.player_sleeping_delay_fixed +
SimpleRND(game.player_sleeping_delay_random);
-#if 1
InitPlayerGfxAnimation(player, ACTION_WAITING, move_dir);
-#else
- InitPlayerGfxAnimation(player, ACTION_WAITING, player->MovDir);
-#endif
}
if (game.player_sleeping_delay_fixed +
player->is_bored ? ACTION_BORING :
ACTION_WAITING);
-#if 1
if (player->is_sleeping && player->use_murphy)
{
/* special case for sleeping Murphy when leaning against non-free tile */
player->dir_waiting = move_dir;
}
-#endif
if (player->is_sleeping)
{
{
int i;
-#if 0
- Error(ERR_NETWORK_CLIENT, "advancing frame counter from %d to %d",
- FrameCounter, FrameCounter + 1);
-#endif
-
/* advance frame counters (global frame counter and time frame counter) */
FrameCounter++;
TimeFrames++;
}
#endif
- StopAnimation();
-
- game_status = GAME_MODE_PLAYING;
-
InitGame();
}
/* at this point we know that we really continue executing the game */
-#if 1
network_player_action_received = FALSE;
-#endif
+ /* when playing tape, read previously recorded player input from tape data */
recorded_player_action = (tape.playing ? TapePlayAction() : NULL);
+#if 1
+ /* TapePlayAction() may return NULL when toggling to "pause before death" */
+ if (tape.pausing)
+ return;
+#endif
+
if (tape.set_centered_player)
{
game.centered_player_nr_next = tape.centered_player_nr_next;
}
#endif
-#if 1
if (game.set_centered_player)
{
boolean all_players_fit_to_screen = checkIfAllPlayersFitToScreen_RND();
DrawRelocateScreen(sx, sy, MV_NONE, TRUE, setup.quick_switch);
DrawGameDoorValues();
}
-#endif
for (i = 0; i < MAX_PLAYERS; i++)
{
if (stored_player[i].programmed_action)
actual_player_action = stored_player[i].programmed_action;
-#if 1
PlayerActions(&stored_player[i], actual_player_action);
-#else
- tape_action[i] = PlayerActions(&stored_player[i], actual_player_action);
-
- if (tape.recording && tape_action[i] && !tape.player_participates[i])
- tape.player_participates[i] = TRUE; /* player just appeared from CE */
-#endif
ScrollPlayer(&stored_player[i], SCROLL_GO_ON);
}
-#if 0
- network_player_action_received = FALSE;
-#endif
-
ScrollScreen(NULL, SCROLL_GO_ON);
/* for backwards compatibility, the following code emulates a fixed bug that
}
}
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
{
ChangeCount[x][y] = 0;
ChangeEvent[x][y] = -1;
#endif
}
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
{
element = Feld[x][y];
graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
-#if 0
- printf("::: %d,%d\n", x, y);
-
- if (element == EL_ROCK)
- printf("::: Yo man! Rocks can fall!\n");
-#endif
-
-#if 1
ResetGfxFrame(x, y, TRUE);
-#else
- if (graphic_info[graphic].anim_global_sync)
- GfxFrame[x][y] = FrameCounter;
- else if (ANIM_MODE(graphic) == ANIM_CE_VALUE)
- {
- int old_gfx_frame = GfxFrame[x][y];
-
- GfxFrame[x][y] = CustomValue[x][y];
-
-#if 1
- if (GfxFrame[x][y] != old_gfx_frame)
-#endif
- DrawLevelGraphicAnimation(x, y, graphic);
- }
- else if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
- {
- int old_gfx_frame = GfxFrame[x][y];
-
- GfxFrame[x][y] = element_info[element].collect_score;
-
-#if 1
- if (GfxFrame[x][y] != old_gfx_frame)
-#endif
- DrawLevelGraphicAnimation(x, y, graphic);
- }
- else if (ANIM_MODE(graphic) == ANIM_CE_DELAY)
- {
- int old_gfx_frame = GfxFrame[x][y];
-
- GfxFrame[x][y] = ChangeDelay[x][y];
-
-#if 1
- if (GfxFrame[x][y] != old_gfx_frame)
-#endif
- DrawLevelGraphicAnimation(x, y, graphic);
- }
-#endif
if (ANIM_MODE(graphic) == ANIM_RANDOM &&
IS_NEXT_FRAME(GfxFrame[x][y], graphic))
(game.engine_version < VERSION_IDENT(3,0,7,1) || !Stop[x][y]))
{
int page = element_info[element].event_page_nr[CE_DELAY];
-#if 0
- HandleElementChange(x, y, ChangePage[x][y] != -1 ? ChangePage[x][y] : page);
-#else
-
-#if 0
- printf("::: ChangeDelay == %d\n", ChangeDelay[x][y]);
-#endif
-
-#if 0
- if (element == EL_CUSTOM_255)
- printf("::: ChangeDelay == %d\n", ChangeDelay[x][y]);
-#endif
#if 1
HandleElementChange(x, y, page);
if (HAS_ACTION(element))
ExecuteCustomElementAction(x, y, element, page);
-#endif
-
#endif
element = Feld[x][y];
else if (element == EL_EXPANDABLE_WALL ||
element == EL_EXPANDABLE_WALL_HORIZONTAL ||
element == EL_EXPANDABLE_WALL_VERTICAL ||
- element == EL_EXPANDABLE_WALL_ANY)
+ element == EL_EXPANDABLE_WALL_ANY ||
+ element == EL_BD_EXPANDABLE_WALL)
MauerAbleger(x, y);
else if (element == EL_FLAMES)
CheckForDragon(x, y);
element == EL_DIAGONAL_SHRINKING ||
element == EL_DIAGONAL_GROWING)
{
-#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);
-#if 0
- if (element == EL_CUSTOM_255 ||
- element == EL_CUSTOM_256)
- DrawLevelGraphicAnimation(x, y, graphic);
-#endif
-
if (IS_BELT_ACTIVE(element))
PlayLevelSoundAction(x, y, ACTION_ACTIVE);
{
game.explosions_delayed = FALSE;
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
{
element = Feld[x][y];
game.magic_wall_time_left--;
if (!game.magic_wall_time_left)
{
-#if 1
SCAN_PLAYFIELD(x, y)
-#else
- for (y = 0; y < lev_fieldy; y++) for (x = 0; x < lev_fieldx; x++)
-#endif
{
element = Feld[x][y];
{
int move_dir_horizontal = player->effective_action & MV_HORIZONTAL;
int move_dir_vertical = player->effective_action & MV_VERTICAL;
- boolean player_is_snapping = player->effective_action & JOY_BUTTON_1;
+ boolean player_is_snapping = (player->effective_action & JOY_BUTTON_1);
int jx = player->jx, jy = player->jy;
boolean player_is_moving_to_valid_field =
(!player_is_snapping &&
if (!player_can_move)
{
-#if 1
if (player->MovPos == 0)
{
player->is_moving = FALSE;
player->is_snapping = FALSE;
player->is_pushing = FALSE;
}
-#else
- DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH);
- SnapField(player, 0, 0);
-#endif
-
-#if 0
- return MP_NO_ACTION;
-#endif
}
#if 1
#endif
can_move = DigField(player, jx, jy, new_jx, new_jy, real_dx,real_dy, DF_DIG);
-#if 0
-#if USE_FIXED_DONT_RUN_INTO
- if (can_move == MP_DONT_RUN_INTO)
- return MP_MOVING;
-#endif
-#endif
if (can_move != MP_MOVING)
return can_move;
-#if USE_FIXED_DONT_RUN_INTO
-#endif
-
/* check if DigField() has caused relocation of the player */
if (player->jx != jx || player->jy != jy)
return MP_NO_ACTION; /* <-- !!! CHECK THIS [-> MP_ACTION ?] !!! */
PlayerVisit[jx][jy] = FrameCounter;
+#if USE_UFAST_PLAYER_EXIT_BUGFIX
+ player->is_moving = TRUE;
+#endif
+
+#if 1
+ /* should better be called in MovePlayer(), but this breaks some tapes */
ScrollPlayer(player, SCROLL_INIT);
+#endif
return MP_MOVING;
}
player->move_delay_value = original_move_delay_value;
}
+ player->is_active = FALSE;
+
if (player->last_move_dir & MV_HORIZONTAL)
{
if (!(moved |= MovePlayerOneStep(player, 0, dy, dx, dy)))
moved |= MovePlayerOneStep(player, 0, dy, dx, dy);
}
+#if USE_FIXED_BORDER_RUNNING_GFX
+ if (!moved && !player->is_active)
+ {
+ player->is_moving = FALSE;
+ player->is_digging = FALSE;
+ player->is_collecting = FALSE;
+ player->is_snapping = FALSE;
+ player->is_pushing = FALSE;
+ }
+#endif
+
jx = player->jx;
jy = player->jy;
player->is_dropping = FALSE;
player->is_dropping_pressed = FALSE;
player->drop_pressed_delay = 0;
+
+#if 0
+ /* should better be called here than above, but this breaks some tapes */
+ ScrollPlayer(player, SCROLL_INIT);
+#endif
}
else
{
else if (!FrameReached(&player->actual_frame_counter, 1))
return;
-#if 0
- printf("::: player->MovPos: %d -> %d\n",
- player->MovPos,
- player->MovPos + (player->MovPos > 0 ? -1 : 1) * move_stepsize);
-#endif
-
#if USE_NEW_PLAYER_SPEED
if (player->MovPos != 0)
{
if (player->MovPos == 0) /* player reached destination field */
{
-#if 0
- printf("::: player reached destination field\n");
-#endif
-
if (player->move_delay_reset_counter > 0)
{
player->move_delay_reset_counter--;
game.engine_version >= VERSION_IDENT(2,2,0,0))
old_element = Back[jx][jy];
-#if 0
-#if USE_FIXED_DONT_RUN_INTO
- if (player_can_move && DONT_RUN_INTO(element))
- {
- if (element == EL_ACID && dx == 0 && dy == 1)
- {
- SplashAcid(x, y);
- Feld[jx][jy] = EL_PLAYER_1;
- InitMovingField(jx, jy, MV_DOWN);
- Store[jx][jy] = EL_ACID;
- ContinueMoving(jx, jy);
- BuryPlayer(player);
- }
- else
- TestIfPlayerRunsIntoBadThing(jx, jy, player->MovDir);
-
- return MP_DONT_RUN_INTO;
- }
-#endif
-#endif
-
-#if 1
-#if USE_FIXED_DONT_RUN_INTO
- if (player_can_move && DONT_RUN_INTO(element))
- {
- TestIfPlayerRunsIntoBadThing(jx, jy, player->MovDir);
-
- return MP_DONT_RUN_INTO;
- }
-#endif
-#endif
-
if (IS_WALKABLE(old_element) && !ACCESS_FROM(old_element, move_direction))
return MP_NO_ACTION; /* field has no opening in this direction */
if (IS_PASSABLE(old_element) && !ACCESS_FROM(old_element,opposite_direction))
return MP_NO_ACTION; /* field has no opening in this direction */
-#if 1
#if USE_FIXED_DONT_RUN_INTO
if (player_can_move && element == EL_ACID && move_direction == MV_DOWN)
{
SplashAcid(x, y);
- Feld[jx][jy] = EL_PLAYER_1;
+
+ Feld[jx][jy] = player->artwork_element;
InitMovingField(jx, jy, MV_DOWN);
Store[jx][jy] = EL_ACID;
ContinueMoving(jx, jy);
return MP_DONT_RUN_INTO;
}
#endif
-#endif
-#if 0
#if USE_FIXED_DONT_RUN_INTO
if (player_can_move && DONT_RUN_INTO(element))
{
- if (element == EL_ACID && dx == 0 && dy == 1)
- {
- SplashAcid(x, y);
- Feld[jx][jy] = EL_PLAYER_1;
- InitMovingField(jx, jy, MV_DOWN);
- Store[jx][jy] = EL_ACID;
- ContinueMoving(jx, jy);
- BuryPlayer(player);
- }
- else
- TestIfPlayerRunsIntoBadThing(jx, jy, player->MovDir);
+ TestIfPlayerRunsIntoBadThing(jx, jy, player->MovDir);
return MP_DONT_RUN_INTO;
}
#endif
-#endif
#if USE_FIXED_DONT_RUN_INTO
if (IS_MOVING(x, y) || IS_PLAYER(x, y))
if (!player->key[EM_GATE_GRAY_ACTIVE_NR(element)])
return MP_NO_ACTION;
}
+ else if (IS_EMC_GATE(element))
+ {
+ if (!player->key[EMC_GATE_NR(element)])
+ return MP_NO_ACTION;
+ }
+ else if (IS_EMC_GATE_GRAY(element))
+ {
+ if (!player->key[EMC_GATE_GRAY_NR(element)])
+ return MP_NO_ACTION;
+ }
+ else if (IS_EMC_GATE_GRAY_ACTIVE(element))
+ {
+ if (!player->key[EMC_GATE_GRAY_ACTIVE_NR(element)])
+ return MP_NO_ACTION;
+ }
else if (IS_SP_PORT(element))
{
if (element == EL_SP_GRAVITY_PORT_LEFT ||
if (player->inventory_size < MAX_INVENTORY_SIZE)
player->inventory_element[player->inventory_size++] = element;
-#if 1
DrawGameDoorValues();
-#else
- DrawGameValue_Dynamite(local_player->inventory_size);
-#endif
}
else if (element == EL_DYNABOMB_INCREASE_NUMBER)
{
{
player->key[KEY_NR(element)] = TRUE;
-#if 1
DrawGameDoorValues();
-#else
- DrawGameValue_Keys(player->key);
-#endif
-
- redraw_mask |= REDRAW_DOOR_1;
}
else if (IS_ENVELOPE(element))
{
if (player->inventory_size < MAX_INVENTORY_SIZE)
player->inventory_element[player->inventory_size++] = element;
-#if 1
DrawGameDoorValues();
-#else
- DrawGameValue_Dynamite(local_player->inventory_size);
-#endif
}
else if (collect_count > 0)
{
}
player->is_pushing = TRUE;
+ player->is_active = TRUE;
if (!(IN_LEV_FIELD(nextx, nexty) &&
(IS_FREE(nextx, nexty) ||
{
int xx, yy;
-#if 1
SCAN_PLAYFIELD(xx, yy)
-#else
- for (yy = 0; yy < lev_fieldy; yy++) for (xx = 0; xx < lev_fieldx; xx++)
-#endif
{
if (Feld[xx][yy] == EL_SP_DISK_YELLOW)
Bang(xx, yy);
game.ball_state = !game.ball_state;
-#if 1
SCAN_PLAYFIELD(xx, yy)
-#else
- for (yy = 0; yy < lev_fieldy; yy++) for (xx = 0; xx < lev_fieldx; xx++)
-#endif
{
int e = Feld[xx][yy];
if (is_player) /* function can also be called by EL_PENGUIN */
{
if (Feld[x][y] != element) /* really digged/collected something */
+ {
player->is_collecting = !player->is_digging;
+ player->is_active = TRUE;
+ }
}
return MP_MOVING;
return FALSE;
player->is_snapping = TRUE;
+ player->is_active = TRUE;
if (player->MovPos == 0)
{
{
player->inventory_size--;
-#if 1
DrawGameDoorValues();
-#else
- DrawGameValue_Dynamite(local_player->inventory_size);
-#endif
if (new_element == EL_DYNAMITE)
new_element = EL_DYNAMITE_ACTIVE;
else
#endif
{
- game_status = GAME_MODE_MAIN;
- DrawMainMenu();
+ if (!ask_if_really_quit || level_editor_test_game)
+ {
+ game_status = GAME_MODE_MAIN;
+
+ DrawMainMenu();
+ }
+ else
+ {
+ FadeOut(REDRAW_FIELD);
+
+ game_status = GAME_MODE_MAIN;
+
+ DrawAndFadeInMainMenu(REDRAW_FIELD);
+ }
}
}
else