#define EX_TYPE_DYNA (1 << 4)
#define EX_TYPE_SINGLE_TILE (EX_TYPE_CENTER | EX_TYPE_BORDER)
+#if 1
+#define PANEL_OFF() (local_player->LevelSolved_PanelOff)
+#define PANEL_DEACTIVATED(p) ((p)->x < 0 || (p)->y < 0 || PANEL_OFF())
+#define PANEL_XPOS(p) (DX + ALIGNED_MENU_XPOS(p))
+#define PANEL_YPOS(p) (DY + ALIGNED_MENU_YPOS(p))
+#else
#define PANEL_DEACTIVATED(p) ((p).x < 0 || (p).y < 0)
+#define PANEL_XPOS(p) (ALIGNED_XPOS((p).x, (p).width, (p).align))
+#define PANEL_YPOS(p) ((p).y)
+#endif
/* special positions in the game control window (relative to control window) */
-#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)
+#define XX_LEVEL1 (PANEL_XPOS(game.panel.level))
+#define XX_LEVEL2 (PANEL_XPOS(game.panel.level) - 1)
+#define XX_LEVEL (PANEL_XPOS(game.panel.level))
+#define YY_LEVEL (PANEL_YPOS(game.panel.level))
+#define XX_EMERALDS (PANEL_XPOS(game.panel.gems))
+#define YY_EMERALDS (PANEL_YPOS(game.panel.gems))
+#define XX_DYNAMITE (PANEL_XPOS(game.panel.inventory))
+#define YY_DYNAMITE (PANEL_YPOS(game.panel.inventory))
+#define XX_KEYS (PANEL_XPOS(game.panel.keys))
+#define YY_KEYS (PANEL_YPOS(game.panel.keys))
+#define XX_SCORE (PANEL_XPOS(game.panel.score))
+#define YY_SCORE (PANEL_YPOS(game.panel.score))
+#define XX_TIME1 (PANEL_XPOS(game.panel.time))
+#define XX_TIME2 (PANEL_XPOS(game.panel.time) + 1)
+#define XX_TIME (PANEL_XPOS(game.panel.time))
+#define YY_TIME (PANEL_YPOS(game.panel.time))
/* special positions in the game control window (relative to main window) */
#define DX_LEVEL1 (DX + XX_LEVEL1)
#define DX_LEVEL2 (DX + XX_LEVEL2)
+#define DX_LEVEL (DX + XX_LEVEL)
#define DY_LEVEL (DY + YY_LEVEL)
#define DX_EMERALDS (DX + XX_EMERALDS)
#define DY_EMERALDS (DY + YY_EMERALDS)
#define DY_SCORE (DY + YY_SCORE)
#define DX_TIME1 (DX + XX_TIME1)
#define DX_TIME2 (DX + XX_TIME2)
+#define DX_TIME (DX + XX_TIME)
#define DY_TIME (DY + YY_TIME)
/* values for delayed check of falling and moving elements and for collision */
#define PENGUIN_CAN_ENTER_FIELD(e, x, y) \
ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, (Feld[x][y] == EL_EXIT_OPEN || \
+ Feld[x][y] == EL_EM_EXIT_OPEN || \
Feld[x][y] == EL_STEEL_EXIT_OPEN || \
+ Feld[x][y] == EL_EM_STEEL_EXIT_OPEN || \
IS_FOOD_PENGUIN(Feld[x][y])))
#define DRAGON_CAN_ENTER_FIELD(e, x, y) \
ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, 0)
NULL,
NULL
},
+ {
+ EL_EM_EXIT_OPENING,
+ EL_EM_EXIT_OPEN,
+ 29,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_EM_EXIT_CLOSING,
+#if 1
+ EL_EMPTY,
+#else
+ EL_EM_EXIT_CLOSED,
+#endif
+ 29,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_EM_STEEL_EXIT_OPENING,
+ EL_EM_STEEL_EXIT_OPEN,
+ 29,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_EM_STEEL_EXIT_CLOSING,
+#if 1
+ EL_STEELWALL,
+#else
+ EL_EM_STEEL_EXIT_CLOSED,
+#endif
+ 29,
+ NULL,
+ NULL,
+ NULL
+ },
{
EL_SP_EXIT_OPENING,
EL_SP_EXIT_OPEN,
{ EL_AMOEBA_DROPPING, 2 },
{ EL_QUICKSAND_FILLING, 1 },
{ EL_QUICKSAND_EMPTYING, 1 },
+ { EL_QUICKSAND_FAST_FILLING, 2 },
+ { EL_QUICKSAND_FAST_EMPTYING, 2 },
{ EL_MAGIC_WALL_FILLING, 2 },
- { EL_BD_MAGIC_WALL_FILLING, 2 },
{ EL_MAGIC_WALL_EMPTYING, 2 },
+ { EL_BD_MAGIC_WALL_FILLING, 2 },
{ EL_BD_MAGIC_WALL_EMPTYING, 2 },
+ { EL_DC_MAGIC_WALL_FILLING, 2 },
+ { EL_DC_MAGIC_WALL_EMPTYING, 2 },
{ EL_UNDEFINED, 0 },
};
void GetPlayerConfig()
{
+ GameFrameDelay = setup.game_frame_delay;
+
if (!audio.sound_available)
setup.sound_simple = FALSE;
*/
}
-inline void DrawGameValue_Emeralds(int value)
+#if 1
+
+void DrawGameValue_Emeralds(int value)
{
- int xpos = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2;
+ struct TextPosInfo *pos = &game.panel.gems;
+ int font_nr = FONT_TEXT_2;
+ int font_width = getFontWidth(font_nr);
+ int digits = pos->chars;
- if (PANEL_DEACTIVATED(game.panel.gems))
+ if (PANEL_DEACTIVATED(pos))
return;
- DrawText(DX_EMERALDS + xpos, DY_EMERALDS, int2str(value, 3), FONT_TEXT_2);
+ pos->width = digits * font_width;
+
+ DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr);
}
-inline void DrawGameValue_Dynamite(int value)
+void DrawGameValue_Dynamite(int value)
{
- int xpos = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2;
+ struct TextPosInfo *pos = &game.panel.inventory;
+ int font_nr = FONT_TEXT_2;
+ int font_width = getFontWidth(font_nr);
+ int digits = pos->chars;
- if (PANEL_DEACTIVATED(game.panel.inventory))
+ if (PANEL_DEACTIVATED(pos))
return;
- DrawText(DX_DYNAMITE + xpos, DY_DYNAMITE, int2str(value, 3), FONT_TEXT_2);
+ pos->width = digits * font_width;
+
+ DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr);
}
-inline void DrawGameValue_Keys(int key[MAX_NUM_KEYS])
+void DrawGameValue_Score(int value)
{
+ struct TextPosInfo *pos = &game.panel.score;
+ int font_nr = FONT_TEXT_2;
+ int font_width = getFontWidth(font_nr);
+ int digits = pos->chars;
+
+ if (PANEL_DEACTIVATED(pos))
+ return;
+
+ pos->width = digits * font_width;
+
+ DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr);
+}
+
+void DrawGameValue_Time(int value)
+{
+ struct TextPosInfo *pos = &game.panel.time;
+ static int last_value = -1;
+ int digits1 = 3;
+ int digits2 = 4;
+ int digits = pos->chars;
+ int font1_nr = FONT_TEXT_2;
+ int font2_nr = FONT_TEXT_1;
+ int font_nr = font1_nr;
+ boolean use_dynamic_digits = (digits == -1 ? TRUE : FALSE);
+
+ if (PANEL_DEACTIVATED(pos))
+ return;
+
+ if (use_dynamic_digits) /* use dynamic number of digits */
+ {
+ digits = (value < 1000 ? digits1 : digits2);
+ font_nr = (value < 1000 ? font1_nr : font2_nr);
+ }
+
+ /* clear background if value just changed its size (dynamic digits only) */
+ if (use_dynamic_digits && (last_value < 1000) != (value < 1000))
+ {
+ int width1 = digits1 * getFontWidth(font1_nr);
+ int width2 = digits2 * getFontWidth(font2_nr);
+ int max_width = MAX(width1, width2);
+ int max_height = MAX(getFontHeight(font1_nr), getFontHeight(font2_nr));
+
+ pos->width = max_width;
+
+ ClearRectangleOnBackground(drawto, PANEL_XPOS(pos), PANEL_YPOS(pos),
+ max_width, max_height);
+ }
+
+ pos->width = digits * getFontWidth(font_nr);
+
+ DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr);
+
+ last_value = value;
+}
+
+void DrawGameValue_Level(int value)
+{
+ struct TextPosInfo *pos = &game.panel.level;
+ int digits1 = 2;
+ int digits2 = 3;
+ int digits = pos->chars;
+ int font1_nr = FONT_TEXT_2;
+ int font2_nr = FONT_TEXT_1;
+ int font_nr = font1_nr;
+ boolean use_dynamic_digits = (digits == -1 ? TRUE : FALSE);
+
+ if (PANEL_DEACTIVATED(pos))
+ return;
+
+ if (use_dynamic_digits) /* use dynamic number of digits */
+ {
+ digits = (level_nr < 100 ? digits1 : digits2);
+ font_nr = (level_nr < 100 ? font1_nr : font2_nr);
+ }
+
+ pos->width = digits * getFontWidth(font_nr);
+
+ DrawText(PANEL_XPOS(pos), PANEL_YPOS(pos), int2str(value, digits), font_nr);
+}
+
+void DrawGameValue_Keys(int key[MAX_NUM_KEYS])
+{
+ struct TextPosInfo *pos = &game.panel.keys;
int base_key_graphic = EL_KEY_1;
int i;
- if (PANEL_DEACTIVATED(game.panel.keys))
+ if (PANEL_DEACTIVATED(pos))
return;
if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
base_key_graphic = EL_EM_KEY_1;
+ pos->width = 4 * MINI_TILEX;
+
/* 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;
+ int src_x = DOOR_GFX_PAGEX5 + 18;
+ int src_y = DOOR_GFX_PAGEY1 + 123;
+ int dst_x = PANEL_XPOS(pos) + i * MINI_TILEX;
+ int dst_y = PANEL_YPOS(pos);
if (key[i])
- DrawMiniGraphicExt(drawto, DX + x,DY + y, el2edimg(base_key_graphic + i));
+ DrawMiniGraphicExt(drawto, dst_x, dst_y, el2edimg(base_key_graphic + i));
else
- BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
- DOOR_GFX_PAGEX5 + x, y, MINI_TILEX, MINI_TILEY, DX + x,DY + y);
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto, src_x, src_y,
+ MINI_TILEX, MINI_TILEY, dst_x, dst_y);
}
}
-inline void DrawGameValue_Score(int value)
+#else
+
+void DrawGameValue_Emeralds(int value)
{
- int xpos = (5 * 14 - 5 * getFontWidth(FONT_TEXT_2)) / 2;
+ int font_nr = FONT_TEXT_2;
+ int xpos = (3 * 14 - 3 * getFontWidth(font_nr)) / 2;
+
+ if (PANEL_DEACTIVATED(game.panel.gems))
+ return;
+
+ DrawText(DX_EMERALDS + xpos, DY_EMERALDS, int2str(value, 3), font_nr);
+}
+
+void DrawGameValue_Dynamite(int value)
+{
+ int font_nr = FONT_TEXT_2;
+ int xpos = (3 * 14 - 3 * getFontWidth(font_nr)) / 2;
+
+ if (PANEL_DEACTIVATED(game.panel.inventory))
+ return;
+
+ DrawText(DX_DYNAMITE + xpos, DY_DYNAMITE, int2str(value, 3), font_nr);
+}
+
+void DrawGameValue_Score(int value)
+{
+ int font_nr = FONT_TEXT_2;
+ int xpos = (5 * 14 - 5 * getFontWidth(font_nr)) / 2;
if (PANEL_DEACTIVATED(game.panel.score))
return;
- DrawText(DX_SCORE + xpos, DY_SCORE, int2str(value, 5), FONT_TEXT_2);
+ DrawText(DX_SCORE + xpos, DY_SCORE, int2str(value, 5), font_nr);
}
-inline void DrawGameValue_Time(int value)
+void DrawGameValue_Time(int value)
{
- int xpos3 = (3 * 14 - 3 * getFontWidth(FONT_TEXT_2)) / 2;
- int xpos4 = (4 * 10 - 4 * getFontWidth(FONT_LEVEL_NUMBER)) / 2;
+ int font1_nr = FONT_TEXT_2;
+#if 1
+ int font2_nr = FONT_TEXT_1;
+#else
+ int font2_nr = FONT_LEVEL_NUMBER;
+#endif
+ int xpos3 = (3 * 14 - 3 * getFontWidth(font1_nr)) / 2;
+ int xpos4 = (4 * 10 - 4 * getFontWidth(font2_nr)) / 2;
if (PANEL_DEACTIVATED(game.panel.time))
return;
ClearRectangleOnBackground(drawto, DX_TIME1, DY_TIME, 14 * 3, 14);
if (value < 1000)
- DrawText(DX_TIME1 + xpos3, DY_TIME, int2str(value, 3), FONT_TEXT_2);
+ DrawText(DX_TIME1 + xpos3, DY_TIME, int2str(value, 3), font1_nr);
else
- DrawText(DX_TIME2 + xpos4, DY_TIME, int2str(value, 4), FONT_LEVEL_NUMBER);
+ DrawText(DX_TIME2 + xpos4, DY_TIME, int2str(value, 4), font2_nr);
}
-inline void DrawGameValue_Level(int value)
+void DrawGameValue_Level(int value)
{
+ int font1_nr = FONT_TEXT_2;
+#if 1
+ int font2_nr = FONT_TEXT_1;
+#else
+ int font2_nr = FONT_LEVEL_NUMBER;
+#endif
+
if (PANEL_DEACTIVATED(game.panel.level))
return;
if (level_nr < 100)
- DrawText(DX_LEVEL1, DY_LEVEL, int2str(value, 2), FONT_TEXT_2);
+ DrawText(DX_LEVEL1, DY_LEVEL, int2str(value, 2), font1_nr);
else
- DrawText(DX_LEVEL2, DY_LEVEL, int2str(value, 3), FONT_LEVEL_NUMBER);
+ DrawText(DX_LEVEL2, DY_LEVEL, int2str(value, 3), font2_nr);
+}
+
+void DrawGameValue_Keys(int key[MAX_NUM_KEYS])
+{
+ 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 + x,DY + y, el2edimg(base_key_graphic + i));
+ else
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ DOOR_GFX_PAGEX5 + x, y, MINI_TILEX, MINI_TILEY, DX + x,DY + y);
+ }
}
+#endif
+
void DrawAllGameValues(int emeralds, int dynamite, int score, int time,
int key_bits)
{
for (j = 0; j < MAX_NUM_KEYS; j++)
player->key[j] = FALSE;
+ player->num_white_keys = 0;
+
player->dynabomb_count = 0;
player->dynabomb_size = 1;
player->dynabombs_left = 0;
player->LevelSolved = FALSE;
player->GameOver = FALSE;
+ player->LevelSolved_GameWon = FALSE;
player->LevelSolved_GameEnd = FALSE;
+ player->LevelSolved_PanelOff = FALSE;
player->LevelSolved_SaveTape = FALSE;
player->LevelSolved_SaveScore = FALSE;
}
{
static int time, time_final;
static int score, score_final;
- static int game_over_delay = 0;
- int game_over_delay_value = 50;
+ static int game_over_delay_1 = 0;
+ static int game_over_delay_2 = 0;
+ int game_over_delay_value_1 = 50;
+ int game_over_delay_value_2 = 50;
- if (!local_player->LevelSolved_GameEnd)
+ if (!local_player->LevelSolved_GameWon)
{
int i;
if (local_player->MovPos)
return;
- local_player->LevelSolved_GameEnd = TRUE;
+ local_player->LevelSolved_GameWon = TRUE;
local_player->LevelSolved_SaveTape = tape.recording;
local_player->LevelSolved_SaveScore = !tape.playing;
TapeStop();
#endif
- game_over_delay = game_over_delay_value;
+ game_over_delay_1 = game_over_delay_value_1;
+ game_over_delay_2 = game_over_delay_value_2;
time = time_final = (level.time == 0 ? TimePlayed : TimeLeft);
score = score_final = local_player->score_final;
if (ExitX >= 0 && ExitY >= 0) /* local player has left the level */
{
/* close exit door after last player */
- if (AllPlayersGone &&
- (Feld[ExitX][ExitY] == EL_EXIT_OPEN ||
- Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN ||
- Feld[ExitX][ExitY] == EL_STEEL_EXIT_OPEN))
+ if ((AllPlayersGone &&
+ (Feld[ExitX][ExitY] == EL_EXIT_OPEN ||
+ Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN ||
+ Feld[ExitX][ExitY] == EL_STEEL_EXIT_OPEN)) ||
+ Feld[ExitX][ExitY] == EL_EM_EXIT_OPEN ||
+ Feld[ExitX][ExitY] == EL_EM_STEEL_EXIT_OPEN)
{
int element = Feld[ExitX][ExitY];
- Feld[ExitX][ExitY] = (element == EL_EXIT_OPEN ? EL_EXIT_CLOSING :
- element == EL_SP_EXIT_OPEN ? EL_SP_EXIT_CLOSING:
- EL_STEEL_EXIT_CLOSING);
-
- PlayLevelSoundElementAction(ExitX, ExitY, element, ACTION_CLOSING);
+#if 0
+ if (element == EL_EM_EXIT_OPEN ||
+ element == EL_EM_STEEL_EXIT_OPEN)
+ {
+ Bang(ExitX, ExitY);
+ }
+ else
+#endif
+ {
+ Feld[ExitX][ExitY] =
+ (element == EL_EXIT_OPEN ? EL_EXIT_CLOSING :
+ element == EL_EM_EXIT_OPEN ? EL_EM_EXIT_CLOSING :
+ element == EL_SP_EXIT_OPEN ? EL_SP_EXIT_CLOSING:
+ element == EL_STEEL_EXIT_OPEN ? EL_STEEL_EXIT_CLOSING:
+ EL_EM_STEEL_EXIT_CLOSING);
+
+ PlayLevelSoundElementAction(ExitX, ExitY, element, ACTION_CLOSING);
+ }
}
/* player disappears */
PlaySound(SND_GAME_WINNING);
}
- if (game_over_delay > 0)
+ if (game_over_delay_1 > 0)
{
- game_over_delay--;
+ game_over_delay_1--;
return;
}
PlaySoundLoop(SND_GAME_LEVELTIME_BONUS);
else
PlaySound(SND_GAME_LEVELTIME_BONUS);
+
+ return;
}
+
+ local_player->LevelSolved_PanelOff = TRUE;
+
+ if (game_over_delay_2 > 0)
+ {
+ game_over_delay_2--;
+
+ return;
+ }
+
+#if 1
+ GameEnd();
+#endif
}
void GameEnd()
int hi_pos;
boolean raise_level = FALSE;
+ local_player->LevelSolved_GameEnd = TRUE;
+
CloseDoor(DOOR_CLOSE_1);
if (local_player->LevelSolved_SaveTape)
if (element == EL_BLOCKED &&
(Feld[oldx][oldy] == EL_QUICKSAND_EMPTYING ||
+ Feld[oldx][oldy] == EL_QUICKSAND_FAST_EMPTYING ||
Feld[oldx][oldy] == EL_MAGIC_WALL_EMPTYING ||
Feld[oldx][oldy] == EL_BD_MAGIC_WALL_EMPTYING ||
+ Feld[oldx][oldy] == EL_DC_MAGIC_WALL_EMPTYING ||
Feld[oldx][oldy] == EL_AMOEBA_DROPPING))
next_element = get_next_element(Feld[oldx][oldy]);
break;
case EL_DC_LANDMINE:
+#if 0
+ case EL_EM_EXIT_OPEN:
+ case EL_EM_STEEL_EXIT_OPEN:
+#endif
explosion_type = EX_TYPE_CENTER;
break;
object_hit = TRUE;
}
+
+ if (Feld[x][y + 1] == EL_QUICKSAND_FAST_EMPTYING && object_hit == FALSE)
+ {
+ RemoveMovingField(x, y + 1);
+ Feld[x][y + 1] = EL_QUICKSAND_FAST_EMPTY;
+ Feld[x][y + 2] = EL_ROCK;
+ DrawLevelField(x, y + 2);
+
+ object_hit = TRUE;
+ }
#endif
if (object_hit)
Bang(x, y);
return;
}
- else if (impact && element == EL_PEARL)
+ else if (impact && element == EL_PEARL &&
+ smashed != EL_DC_MAGIC_WALL && smashed != EL_DC_MAGIC_WALL_ACTIVE)
{
ResetGfxAnimation(x, y);
if (object_hit) /* check which object was hit */
{
- if (CAN_PASS_MAGIC_WALL(element) &&
- (smashed == EL_MAGIC_WALL ||
- smashed == EL_BD_MAGIC_WALL))
+ if ((CAN_PASS_MAGIC_WALL(element) &&
+ (smashed == EL_MAGIC_WALL ||
+ smashed == EL_BD_MAGIC_WALL)) ||
+ (CAN_PASS_DC_MAGIC_WALL(element) &&
+ smashed == EL_DC_MAGIC_WALL))
{
int xx, yy;
int activated_magic_wall =
(smashed == EL_MAGIC_WALL ? EL_MAGIC_WALL_ACTIVE :
- EL_BD_MAGIC_WALL_ACTIVE);
+ smashed == EL_BD_MAGIC_WALL ? EL_BD_MAGIC_WALL_ACTIVE :
+ EL_DC_MAGIC_WALL_ACTIVE);
/* activate magic wall / mill */
SCAN_PLAYFIELD(xx, yy)
+ {
if (Feld[xx][yy] == smashed)
Feld[xx][yy] = activated_magic_wall;
+ }
game.magic_wall_time_left = level.time_magic_wall * FRAMES_PER_SECOND;
game.magic_wall_active = TRUE;
PlayLevelSound(x, y, (smashed == EL_MAGIC_WALL ?
SND_MAGIC_WALL_ACTIVATING :
- SND_BD_MAGIC_WALL_ACTIVATING));
+ smashed == EL_BD_MAGIC_WALL ?
+ SND_BD_MAGIC_WALL_ACTIVATING :
+ SND_DC_MAGIC_WALL_ACTIVATING));
}
if (IS_PLAYER(x, y + 1))
/* play sound of magic wall / mill */
if (!last_line &&
(Feld[x][y + 1] == EL_MAGIC_WALL_ACTIVE ||
- Feld[x][y + 1] == EL_BD_MAGIC_WALL_ACTIVE))
+ Feld[x][y + 1] == EL_BD_MAGIC_WALL_ACTIVE ||
+ Feld[x][y + 1] == EL_DC_MAGIC_WALL_ACTIVE))
{
if (Feld[x][y + 1] == EL_MAGIC_WALL_ACTIVE)
PlayLevelSound(x, y, SND_MAGIC_WALL_FILLING);
else if (Feld[x][y + 1] == EL_BD_MAGIC_WALL_ACTIVE)
PlayLevelSound(x, y, SND_BD_MAGIC_WALL_FILLING);
+ else if (Feld[x][y + 1] == EL_DC_MAGIC_WALL_ACTIVE)
+ PlayLevelSound(x, y, SND_DC_MAGIC_WALL_FILLING);
return;
}
int ey = y + xy[i][1];
if (IN_LEV_FIELD(ex, ey) && (Feld[ex][ey] == EL_EXIT_OPEN ||
- Feld[ex][ey] == EL_STEEL_EXIT_OPEN))
+ Feld[ex][ey] == EL_EM_EXIT_OPEN ||
+ Feld[ex][ey] == EL_STEEL_EXIT_OPEN ||
+ Feld[ex][ey] == EL_EM_STEEL_EXIT_OPEN))
{
attr_x = ex;
attr_y = ey;
PlayLevelSoundAction(x, y, ACTION_FILLING);
}
}
+ else if (element == EL_QUICKSAND_FAST_FULL)
+ {
+ if (IS_FREE(x, y + 1))
+ {
+ InitMovingField(x, y, MV_DOWN);
+ started_moving = TRUE;
+
+ Feld[x][y] = EL_QUICKSAND_FAST_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);
+ }
+ else if (Feld[x][y + 1] == EL_QUICKSAND_FAST_EMPTY)
+ {
+ if (!MovDelay[x][y])
+ MovDelay[x][y] = TILEY + 1;
+
+ if (MovDelay[x][y])
+ {
+ MovDelay[x][y]--;
+ if (MovDelay[x][y])
+ return;
+ }
+
+ Feld[x][y] = EL_QUICKSAND_FAST_EMPTY;
+ Feld[x][y + 1] = EL_QUICKSAND_FAST_FULL;
+ Store[x][y + 1] = Store[x][y];
+ Store[x][y] = 0;
+
+ PlayLevelSoundAction(x, y, ACTION_FILLING);
+ }
+ }
else if ((element == EL_ROCK || element == EL_BD_ROCK) &&
Feld[x][y + 1] == EL_QUICKSAND_EMPTY)
{
PlayLevelSoundAction(x, y, ACTION_FILLING);
}
+ else if ((element == EL_ROCK || element == EL_BD_ROCK) &&
+ Feld[x][y + 1] == EL_QUICKSAND_FAST_EMPTY)
+ {
+ InitMovingField(x, y, MV_DOWN);
+ started_moving = TRUE;
+
+ Feld[x][y] = EL_QUICKSAND_FAST_FILLING;
+ Store[x][y] = element;
+
+ PlayLevelSoundAction(x, y, ACTION_FILLING);
+ }
else if (element == EL_MAGIC_WALL_FULL)
{
if (IS_FREE(x, y + 1))
started_moving = TRUE;
Feld[x][y] = EL_BD_MAGIC_WALL_EMPTYING;
- Store[x][y] = EL_CHANGED2(Store[x][y]);
+ Store[x][y] = EL_CHANGED_BD(Store[x][y]);
}
else if (Feld[x][y + 1] == EL_BD_MAGIC_WALL_ACTIVE)
{
Feld[x][y] = EL_BD_MAGIC_WALL_ACTIVE;
Feld[x][y + 1] = EL_BD_MAGIC_WALL_FULL;
- Store[x][y + 1] = EL_CHANGED2(Store[x][y]);
+ Store[x][y + 1] = EL_CHANGED_BD(Store[x][y]);
Store[x][y] = 0;
}
}
- else if (CAN_PASS_MAGIC_WALL(element) &&
- (Feld[x][y + 1] == EL_MAGIC_WALL_ACTIVE ||
- Feld[x][y + 1] == EL_BD_MAGIC_WALL_ACTIVE))
+ else if (element == EL_DC_MAGIC_WALL_FULL)
+ {
+ if (IS_FREE(x, y + 1))
+ {
+ InitMovingField(x, y, MV_DOWN);
+ started_moving = TRUE;
+
+ Feld[x][y] = EL_DC_MAGIC_WALL_EMPTYING;
+ Store[x][y] = EL_CHANGED_DC(Store[x][y]);
+ }
+ else if (Feld[x][y + 1] == EL_DC_MAGIC_WALL_ACTIVE)
+ {
+ if (!MovDelay[x][y])
+ MovDelay[x][y] = TILEY/4 + 1;
+
+ if (MovDelay[x][y])
+ {
+ MovDelay[x][y]--;
+ if (MovDelay[x][y])
+ return;
+ }
+
+ Feld[x][y] = EL_DC_MAGIC_WALL_ACTIVE;
+ Feld[x][y + 1] = EL_DC_MAGIC_WALL_FULL;
+ Store[x][y + 1] = EL_CHANGED_DC(Store[x][y]);
+ Store[x][y] = 0;
+ }
+ }
+ else if ((CAN_PASS_MAGIC_WALL(element) &&
+ (Feld[x][y + 1] == EL_MAGIC_WALL_ACTIVE ||
+ Feld[x][y + 1] == EL_BD_MAGIC_WALL_ACTIVE)) ||
+ (CAN_PASS_DC_MAGIC_WALL(element) &&
+ (Feld[x][y + 1] == EL_DC_MAGIC_WALL_ACTIVE)))
+
{
InitMovingField(x, y, MV_DOWN);
started_moving = TRUE;
Feld[x][y] =
(Feld[x][y + 1] == EL_MAGIC_WALL_ACTIVE ? EL_MAGIC_WALL_FILLING :
- EL_BD_MAGIC_WALL_FILLING);
+ Feld[x][y + 1] == EL_BD_MAGIC_WALL_ACTIVE ? EL_BD_MAGIC_WALL_FILLING :
+ EL_DC_MAGIC_WALL_FILLING);
Store[x][y] = element;
}
else if (CAN_FALL(element) && Feld[x][y + 1] == EL_ACID)
else if (element == EL_PENGUIN && IN_LEV_FIELD(newx, newy))
{
if (Feld[newx][newy] == EL_EXIT_OPEN ||
- Feld[newx][newy] == EL_STEEL_EXIT_OPEN)
+ Feld[newx][newy] == EL_EM_EXIT_OPEN ||
+ Feld[newx][newy] == EL_STEEL_EXIT_OPEN ||
+ Feld[newx][newy] == EL_EM_STEEL_EXIT_OPEN)
{
RemoveField(x, y);
DrawLevelField(x, y);
Feld[x][y] = get_next_element(element);
element = Feld[newx][newy] = Store[x][y];
}
+ else if (element == EL_QUICKSAND_FAST_FILLING)
+ {
+ element = Feld[newx][newy] = get_next_element(element);
+ Store[newx][newy] = Store[x][y];
+ }
+ else if (element == EL_QUICKSAND_FAST_EMPTYING)
+ {
+ Feld[x][y] = get_next_element(element);
+ element = Feld[newx][newy] = Store[x][y];
+ }
else if (element == EL_MAGIC_WALL_FILLING)
{
element = Feld[newx][newy] = get_next_element(element);
Feld[x][y] = EL_BD_MAGIC_WALL_DEAD;
element = Feld[newx][newy] = Store[x][y];
+#if USE_NEW_CUSTOM_VALUE
+ InitField(newx, newy, FALSE);
+#endif
+ }
+ else if (element == EL_DC_MAGIC_WALL_FILLING)
+ {
+ element = Feld[newx][newy] = get_next_element(element);
+ if (!game.magic_wall_active)
+ element = Feld[newx][newy] = EL_DC_MAGIC_WALL_DEAD;
+ Store[newx][newy] = Store[x][y];
+ }
+ else if (element == EL_DC_MAGIC_WALL_EMPTYING)
+ {
+ Feld[x][y] = get_next_element(element);
+ if (!game.magic_wall_active)
+ Feld[x][y] = EL_DC_MAGIC_WALL_DEAD;
+ element = Feld[newx][newy] = Store[x][y];
+
#if USE_NEW_CUSTOM_VALUE
InitField(newx, newy, FALSE);
#endif
if (IS_FREE(x, y) ||
CAN_GROW_INTO(Feld[x][y]) ||
- Feld[x][y] == EL_QUICKSAND_EMPTY)
+ Feld[x][y] == EL_QUICKSAND_EMPTY ||
+ Feld[x][y] == EL_QUICKSAND_FAST_EMPTY)
{
newax = x;
neway = y;
if (IS_FREE(x, y) ||
CAN_GROW_INTO(Feld[x][y]) ||
- Feld[x][y] == EL_QUICKSAND_EMPTY)
+ Feld[x][y] == EL_QUICKSAND_EMPTY ||
+ Feld[x][y] == EL_QUICKSAND_FAST_EMPTY)
{
newax = x;
neway = y;
PlayLevelSoundNearest(x, y, SND_CLASS_EXIT_OPENING);
}
+void CheckExitEM(int x, int y)
+{
+ if (local_player->gems_still_needed > 0 ||
+ local_player->sokobanfields_still_needed > 0 ||
+ local_player->lights_still_needed > 0)
+ {
+ int element = Feld[x][y];
+ int graphic = el2img(element);
+
+ if (IS_ANIMATED(graphic))
+ DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+
+ return;
+ }
+
+ if (AllPlayersGone) /* do not re-open exit door closed after last player */
+ return;
+
+ Feld[x][y] = EL_EM_EXIT_OPENING;
+
+ PlayLevelSoundNearest(x, y, SND_CLASS_EM_EXIT_OPENING);
+}
+
void CheckExitSteel(int x, int y)
{
if (local_player->gems_still_needed > 0 ||
PlayLevelSoundNearest(x, y, SND_CLASS_STEEL_EXIT_OPENING);
}
+void CheckExitSteelEM(int x, int y)
+{
+ if (local_player->gems_still_needed > 0 ||
+ local_player->sokobanfields_still_needed > 0 ||
+ local_player->lights_still_needed > 0)
+ {
+ int element = Feld[x][y];
+ int graphic = el2img(element);
+
+ if (IS_ANIMATED(graphic))
+ DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+
+ return;
+ }
+
+ if (AllPlayersGone) /* do not re-open exit door closed after last player */
+ return;
+
+ Feld[x][y] = EL_EM_STEEL_EXIT_OPENING;
+
+ PlayLevelSoundNearest(x, y, SND_CLASS_EM_STEEL_EXIT_OPENING);
+}
+
void CheckExitSP(int x, int y)
{
if (local_player->gems_still_needed > 0)
AllPlayersGone = TRUE;
}
- if (local_player->LevelSolved)
+ if (local_player->LevelSolved && !local_player->LevelSolved_GameEnd)
GameWon();
if (AllPlayersGone && !TAPE_IS_STOPPED(tape))
}
else if ((element == EL_ACID ||
element == EL_EXIT_OPEN ||
+ element == EL_EM_EXIT_OPEN ||
element == EL_SP_EXIT_OPEN ||
element == EL_STEEL_EXIT_OPEN ||
+ element == EL_EM_STEEL_EXIT_OPEN ||
element == EL_SP_TERMINAL ||
element == EL_SP_TERMINAL_ACTIVE ||
element == EL_EXTRA_TIME ||
Life(x, y);
else if (element == EL_EXIT_CLOSED)
CheckExit(x, y);
+ else if (element == EL_EM_EXIT_CLOSED)
+ CheckExitEM(x, y);
else if (element == EL_STEEL_EXIT_CLOSED)
CheckExitSteel(x, y);
+ else if (element == EL_EM_STEEL_EXIT_CLOSED)
+ CheckExitSteelEM(x, y);
else if (element == EL_SP_EXIT_CLOSED)
CheckExitSP(x, y);
else if (element == EL_EXPANDABLE_WALL_GROWING ||
element == EL_MAGIC_WALL_EMPTYING ||
element == EL_BD_MAGIC_WALL_FULL ||
element == EL_BD_MAGIC_WALL_ACTIVE ||
- element == EL_BD_MAGIC_WALL_EMPTYING) &&
+ element == EL_BD_MAGIC_WALL_EMPTYING ||
+ element == EL_DC_MAGIC_WALL_FULL ||
+ element == EL_DC_MAGIC_WALL_ACTIVE ||
+ element == EL_DC_MAGIC_WALL_EMPTYING) &&
ABS(x-jx) + ABS(y-jy) < ABS(magic_wall_x-jx) + ABS(magic_wall_y-jy))
{
magic_wall_x = x;
(element == EL_EMPTY ||
CAN_GROW_INTO(element) ||
element == EL_QUICKSAND_EMPTY ||
+ element == EL_QUICKSAND_FAST_EMPTY ||
element == EL_ACID_SPLASH_LEFT ||
element == EL_ACID_SPLASH_RIGHT))
{
element == EL_BD_MAGIC_WALL_ACTIVE ||
element == EL_BD_MAGIC_WALL_EMPTYING)
PlayLevelSound(magic_wall_x, magic_wall_y, SND_BD_MAGIC_WALL_ACTIVE);
+ else if (element == EL_DC_MAGIC_WALL_FULL ||
+ element == EL_DC_MAGIC_WALL_ACTIVE ||
+ element == EL_DC_MAGIC_WALL_EMPTYING)
+ PlayLevelSound(magic_wall_x, magic_wall_y, SND_DC_MAGIC_WALL_ACTIVE);
else
PlayLevelSound(magic_wall_x, magic_wall_y, SND_MAGIC_WALL_ACTIVE);
}
Feld[x][y] = EL_BD_MAGIC_WALL_DEAD;
DrawLevelField(x, y);
}
+ else if (element == EL_DC_MAGIC_WALL_ACTIVE ||
+ element == EL_DC_MAGIC_WALL_FULL)
+ {
+ Feld[x][y] = EL_DC_MAGIC_WALL_DEAD;
+ DrawLevelField(x, y);
+ }
}
game.magic_wall_active = FALSE;
void ScrollLevel(int dx, int dy)
{
+#if 1
+ static Bitmap *bitmap_db_field2 = NULL;
int softscroll_offset = (setup.soft_scrolling ? TILEX : 0);
int x, y;
+#else
+ int i, x, y;
+#endif
+
+ /* only horizontal XOR vertical scroll direction allowed */
+ if ((dx == 0 && dy == 0) || (dx != 0 && dy != 0))
+ return;
+
+#if 1
+ if (bitmap_db_field2 == NULL)
+ bitmap_db_field2 = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
+
+ BlitBitmap(drawto_field, bitmap_db_field2,
+ FX + TILEX * (dx == -1) - softscroll_offset,
+ FY + TILEY * (dy == -1) - softscroll_offset,
+ SXSIZE - TILEX * (dx != 0) + 2 * softscroll_offset,
+ SYSIZE - TILEY * (dy != 0) + 2 * softscroll_offset,
+ FX + TILEX * (dx == 1) - softscroll_offset,
+ FY + TILEY * (dy == 1) - softscroll_offset);
+ BlitBitmap(bitmap_db_field2, drawto_field,
+ FX + TILEX * (dx == 1) - softscroll_offset,
+ FY + TILEY * (dy == 1) - softscroll_offset,
+ SXSIZE - TILEX * (dx != 0) + 2 * softscroll_offset,
+ SYSIZE - TILEY * (dy != 0) + 2 * softscroll_offset,
+ FX + TILEX * (dx == 1) - softscroll_offset,
+ FY + TILEY * (dy == 1) - softscroll_offset);
+
+#else
+
+#if 1
+ int xsize = (BX2 - BX1 + 1);
+ int ysize = (BY2 - BY1 + 1);
+ int start = (dx != 0 ? (dx == -1 ? BX1 : BX2) : (dy == -1 ? BY1 : BY2));
+ int end = (dx != 0 ? (dx == -1 ? BX2 : BX1) : (dy == -1 ? BY2 : BY1));
+ int step = (start < end ? +1 : -1);
+
+ for (i = start; i != end; i += step)
+ {
+ BlitBitmap(drawto_field, drawto_field,
+ FX + TILEX * (dx != 0 ? i + step : 0),
+ FY + TILEY * (dy != 0 ? i + step : 0),
+ TILEX * (dx != 0 ? 1 : xsize),
+ TILEY * (dy != 0 ? 1 : ysize),
+ FX + TILEX * (dx != 0 ? i : 0),
+ FY + TILEY * (dy != 0 ? i : 0));
+ }
+
+#else
+
+ int softscroll_offset = (setup.soft_scrolling ? TILEX : 0);
BlitBitmap(drawto_field, drawto_field,
FX + TILEX * (dx == -1) - softscroll_offset,
FY + TILEY * (dy == -1) - softscroll_offset,
- SXSIZE - TILEX * (dx!=0) + 2 * softscroll_offset,
- SYSIZE - TILEY * (dy!=0) + 2 * softscroll_offset,
+ SXSIZE - TILEX * (dx != 0) + 2 * softscroll_offset,
+ SYSIZE - TILEY * (dy != 0) + 2 * softscroll_offset,
FX + TILEX * (dx == 1) - softscroll_offset,
FY + TILEY * (dy == 1) - softscroll_offset);
+#endif
+#endif
- if (dx)
+ if (dx != 0)
{
x = (dx == 1 ? BX1 : BX2);
for (y = BY1; y <= BY2; y++)
DrawScreenField(x, y);
}
- if (dy)
+ if (dy != 0)
{
y = (dy == 1 ? BY1 : BY2);
for (x = BX1; x <= BX2; x++)
player->last_jy = jy;
if (Feld[jx][jy] == EL_EXIT_OPEN ||
+ Feld[jx][jy] == EL_EM_EXIT_OPEN ||
Feld[jx][jy] == EL_STEEL_EXIT_OPEN ||
+ Feld[jx][jy] == EL_EM_STEEL_EXIT_OPEN ||
Feld[jx][jy] == EL_SP_EXIT_OPEN ||
Feld[jx][jy] == EL_SP_EXIT_OPENING) /* <-- special case */
{
return MP_NO_ACTION;
}
else if (element == EL_EXIT_OPEN ||
+ element == EL_EM_EXIT_OPEN ||
element == EL_STEEL_EXIT_OPEN ||
+ element == EL_EM_STEEL_EXIT_OPEN ||
element == EL_SP_EXIT_OPEN ||
element == EL_SP_EXIT_OPENING)
{
if (!player->key[EMC_GATE_GRAY_ACTIVE_NR(element)])
return MP_NO_ACTION;
}
+ else if (element == EL_DC_GATE_WHITE ||
+ element == EL_DC_GATE_WHITE_GRAY ||
+ element == EL_DC_GATE_WHITE_GRAY_ACTIVE)
+ {
+ if (player->num_white_keys == 0)
+ return MP_NO_ACTION;
+
+ player->num_white_keys--;
+ }
else if (IS_SP_PORT(element))
{
if (element == EL_SP_GRAVITY_PORT_LEFT ||
DrawGameDoorValues();
}
+ else if (element == EL_DC_KEY_WHITE)
+ {
+ player->num_white_keys++;
+
+ /* display white keys? */
+ /* DrawGameDoorValues(); */
+ }
else if (IS_ENVELOPE(element))
{
player->show_envelope = element;
case EL_EMC_KEY_6:
case EL_EMC_KEY_7:
case EL_EMC_KEY_8:
+ case EL_DC_KEY_WHITE:
RaiseScore(level.score[SC_KEY]);
break;
default: