// (c) 1995-2014 by Artsoft Entertainment
// Holger Schemel
// info@artsoft.org
-// http://www.artsoft.org/
+// https://www.artsoft.org/
// ----------------------------------------------------------------------------
// tools.c
// ============================================================================
#include "init.h"
#include "game.h"
#include "events.h"
-#include "cartoons.h"
+#include "anim.h"
#include "network.h"
#include "tape.h"
#include "screens.h"
-/* select level set with EMC X11 graphics before activating EM GFX debugging */
-#define DEBUG_EM_GFX 0
+#define DEBUG_FRAME_TIME FALSE
-/* tool button identifiers */
+// tool button identifiers
#define TOOL_CTRL_ID_YES 0
#define TOOL_CTRL_ID_NO 1
#define TOOL_CTRL_ID_CONFIRM 2
#define TOOL_CTRL_ID_PLAYER_2 4
#define TOOL_CTRL_ID_PLAYER_3 5
#define TOOL_CTRL_ID_PLAYER_4 6
+#define TOOL_CTRL_ID_TOUCH_YES 7
+#define TOOL_CTRL_ID_TOUCH_NO 8
+#define TOOL_CTRL_ID_TOUCH_CONFIRM 9
-#define NUM_TOOL_BUTTONS 7
+#define NUM_TOOL_BUTTONS 10
-/* constants for number of doors and door parts */
+// constants for number of doors and door parts
#define NUM_DOORS 2
#define NUM_PANELS NUM_DOORS
// #define NUM_PANELS 0
{
{
DOOR_1,
- IMG_DOOR_1_GFX_PART_1,
+ IMG_GFX_DOOR_1_PART_1,
&door_1.part_1
},
{
DOOR_1,
- IMG_DOOR_1_GFX_PART_2,
+ IMG_GFX_DOOR_1_PART_2,
&door_1.part_2
},
{
DOOR_1,
- IMG_DOOR_1_GFX_PART_3,
+ IMG_GFX_DOOR_1_PART_3,
&door_1.part_3
},
{
DOOR_1,
- IMG_DOOR_1_GFX_PART_4,
+ IMG_GFX_DOOR_1_PART_4,
&door_1.part_4
},
{
DOOR_1,
- IMG_DOOR_1_GFX_PART_5,
+ IMG_GFX_DOOR_1_PART_5,
&door_1.part_5
},
{
DOOR_1,
- IMG_DOOR_1_GFX_PART_6,
+ IMG_GFX_DOOR_1_PART_6,
&door_1.part_6
},
{
DOOR_1,
- IMG_DOOR_1_GFX_PART_7,
+ IMG_GFX_DOOR_1_PART_7,
&door_1.part_7
},
{
DOOR_1,
- IMG_DOOR_1_GFX_PART_8,
+ IMG_GFX_DOOR_1_PART_8,
&door_1.part_8
},
{
DOOR_2,
- IMG_DOOR_2_GFX_PART_1,
+ IMG_GFX_DOOR_2_PART_1,
&door_2.part_1
},
{
DOOR_2,
- IMG_DOOR_2_GFX_PART_2,
+ IMG_GFX_DOOR_2_PART_2,
&door_2.part_2
},
{
DOOR_2,
- IMG_DOOR_2_GFX_PART_3,
+ IMG_GFX_DOOR_2_PART_3,
&door_2.part_3
},
{
DOOR_2,
- IMG_DOOR_2_GFX_PART_4,
+ IMG_GFX_DOOR_2_PART_4,
&door_2.part_4
},
{
DOOR_2,
- IMG_DOOR_2_GFX_PART_5,
+ IMG_GFX_DOOR_2_PART_5,
&door_2.part_5
},
{
DOOR_2,
- IMG_DOOR_2_GFX_PART_6,
+ IMG_GFX_DOOR_2_PART_6,
&door_2.part_6
},
{
DOOR_2,
- IMG_DOOR_2_GFX_PART_7,
+ IMG_GFX_DOOR_2_PART_7,
&door_2.part_7
},
{
DOOR_2,
- IMG_DOOR_2_GFX_PART_8,
+ IMG_GFX_DOOR_2_PART_8,
&door_2.part_8
},
}
};
+static struct XY xy_topdown[] =
+{
+ { 0, -1 },
+ { -1, 0 },
+ { +1, 0 },
+ { 0, +1 }
+};
-/* forward declaration for internal use */
-static void UnmapToolButtons();
+
+// forward declaration for internal use
+static void MapToolButtons(unsigned int);
+static void UnmapToolButtons(void);
static void HandleToolButtons(struct GadgetInfo *);
static int el_act_dir2crm(int, int, int);
static int el_act2crm(int, int);
return s;
}
-void DumpTile(int x, int y)
+int getFieldbufferOffsetX_RND(int dir, int pos)
{
- int sx = SCREENX(x);
- int sy = SCREENY(y);
+ int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
+ int dx = (dir & MV_HORIZONTAL ? pos : 0);
+ int dx_var = dx * TILESIZE_VAR / TILESIZE;
+ int fx = FX;
- if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ if (EVEN(SCR_FIELDX))
+ {
+ int sbx_right = SBX_Right + (BorderElement != EL_EMPTY ? 1 : 0);
+ int ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
+
+ if (ffx < sbx_right * TILEX_VAR + TILEX_VAR / 2)
+ fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
+ else
+ fx += (dx_var > 0 ? TILEX_VAR : 0);
+ }
+ else
+ {
+ fx += dx_var;
+ }
+
+ if (full_lev_fieldx <= SCR_FIELDX)
+ {
+ if (EVEN(SCR_FIELDX))
+ fx = 2 * TILEX_VAR - (ODD(lev_fieldx) ? TILEX_VAR / 2 : 0);
+ else
+ fx = 2 * TILEX_VAR - (EVEN(lev_fieldx) ? TILEX_VAR / 2 : 0);
+ }
+
+ return fx;
+}
+
+int getFieldbufferOffsetY_RND(int dir, int pos)
+{
+ int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
+ int dy = (dir & MV_VERTICAL ? pos : 0);
+ int dy_var = dy * TILESIZE_VAR / TILESIZE;
+ int fy = FY;
+
+ if (EVEN(SCR_FIELDY))
+ {
+ int sby_lower = SBY_Lower + (BorderElement != EL_EMPTY ? 1 : 0);
+ int ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
+
+ if (ffy < sby_lower * TILEY_VAR + TILEY_VAR / 2)
+ fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
+ else
+ fy += (dy_var > 0 ? TILEY_VAR : 0);
+ }
+ else
+ {
+ fy += dy_var;
+ }
+
+ if (full_lev_fieldy <= SCR_FIELDY)
{
- x--;
- y--;
+ if (EVEN(SCR_FIELDY))
+ fy = 2 * TILEY_VAR - (ODD(lev_fieldy) ? TILEY_VAR / 2 : 0);
+ else
+ fy = 2 * TILEY_VAR - (EVEN(lev_fieldy) ? TILEY_VAR / 2 : 0);
}
- printf_line("-", 79);
- printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
- printf_line("-", 79);
+ return fy;
+}
+
+static int getLevelFromScreenX_RND(int sx)
+{
+ int fx = getFieldbufferOffsetX_RND(ScreenMovDir, ScreenGfxPos);
+ int dx = fx - FX;
+ int px = sx - SX;
+ int lx = LEVELX((px + dx) / TILESIZE_VAR);
+
+ return lx;
+}
+
+static int getLevelFromScreenY_RND(int sy)
+{
+ int fy = getFieldbufferOffsetY_RND(ScreenMovDir, ScreenGfxPos);
+ int dy = fy - FY;
+ int py = sy - SY;
+ int ly = LEVELY((py + dy) / TILESIZE_VAR);
+
+ return ly;
+}
+
+static int getLevelFromScreenX_EM(int sx)
+{
+ int level_xsize = level.native_em_level->cav->width;
+ int full_xsize = level_xsize * TILESIZE_VAR;
+
+ sx -= (full_xsize < SXSIZE ? (SXSIZE - full_xsize) / 2 : 0);
+
+ int fx = getFieldbufferOffsetX_EM();
+ int dx = fx;
+ int px = sx - SX;
+ int lx = LEVELX((px + dx) / TILESIZE_VAR);
+
+ return lx;
+}
+
+static int getLevelFromScreenY_EM(int sy)
+{
+ int level_ysize = level.native_em_level->cav->height;
+ int full_ysize = level_ysize * TILESIZE_VAR;
+
+ sy -= (full_ysize < SYSIZE ? (SYSIZE - full_ysize) / 2 : 0);
+
+ int fy = getFieldbufferOffsetY_EM();
+ int dy = fy;
+ int py = sy - SY;
+ int ly = LEVELY((py + dy) / TILESIZE_VAR);
+
+ return ly;
+}
+
+static int getLevelFromScreenX_SP(int sx)
+{
+ int menBorder = setup.sp_show_border_elements;
+ int level_xsize = level.native_sp_level->width;
+ int full_xsize = (level_xsize - (menBorder ? 0 : 1)) * TILESIZE_VAR;
+
+ sx += (full_xsize < SXSIZE ? (SXSIZE - full_xsize) / 2 : 0);
+
+ int fx = getFieldbufferOffsetX_SP();
+ int dx = fx - FX;
+ int px = sx - SX;
+ int lx = LEVELX((px + dx) / TILESIZE_VAR);
+
+ return lx;
+}
+
+static int getLevelFromScreenY_SP(int sy)
+{
+ int menBorder = setup.sp_show_border_elements;
+ int level_ysize = level.native_sp_level->height;
+ int full_ysize = (level_ysize - (menBorder ? 0 : 1)) * TILESIZE_VAR;
+
+ sy += (full_ysize < SYSIZE ? (SYSIZE - full_ysize) / 2 : 0);
+
+ int fy = getFieldbufferOffsetY_SP();
+ int dy = fy - FY;
+ int py = sy - SY;
+ int ly = LEVELY((py + dy) / TILESIZE_VAR);
+
+ return ly;
+}
+
+static int getLevelFromScreenX_MM(int sx)
+{
+ int level_xsize = level.native_mm_level->fieldx;
+ int full_xsize = level_xsize * TILESIZE_VAR;
+
+ sx -= (full_xsize < SXSIZE ? (SXSIZE - full_xsize) / 2 : 0);
+
+ int px = sx - SX;
+ int lx = (px + TILESIZE_VAR) / TILESIZE_VAR - 1;
+
+ return lx;
+}
+
+static int getLevelFromScreenY_MM(int sy)
+{
+ int level_ysize = level.native_mm_level->fieldy;
+ int full_ysize = level_ysize * TILESIZE_VAR;
+
+ sy -= (full_ysize < SYSIZE ? (SYSIZE - full_ysize) / 2 : 0);
+
+ int py = sy - SY;
+ int ly = (py + TILESIZE_VAR) / TILESIZE_VAR - 1;
+
+ return ly;
+}
+
+int getLevelFromScreenX(int x)
+{
+ if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ return getLevelFromScreenX_EM(x);
+ if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+ return getLevelFromScreenX_SP(x);
+ if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+ return getLevelFromScreenX_MM(x);
+ else
+ return getLevelFromScreenX_RND(x);
+}
+
+int getLevelFromScreenY(int y)
+{
+ if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ return getLevelFromScreenY_EM(y);
+ if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
+ return getLevelFromScreenY_SP(y);
+ if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+ return getLevelFromScreenY_MM(y);
+ else
+ return getLevelFromScreenY_RND(y);
+}
+
+int getScreenFieldSizeX(void)
+{
+ return (tape.playing ? tape.scr_fieldx : SCR_FIELDX);
+}
+
+int getScreenFieldSizeY(void)
+{
+ return (tape.playing ? tape.scr_fieldy : SCR_FIELDY);
+}
+
+void DumpTile(int x, int y)
+{
+ int sx = SCREENX(x);
+ int sy = SCREENY(y);
+ char *token_name;
+
+ Info("---");
+ Info("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)", sx, sy, x, y);
+ Info("---");
if (!IN_LEV_FIELD(x, y))
{
- printf("(not in level field)\n");
- printf("\n");
+ Info("(not in level field)");
+ Info("");
return;
}
- printf(" Feld: %d\t['%s']\n", Feld[x][y],
- element_info[Feld[x][y]].token_name);
- printf(" Back: %s\n", print_if_not_empty(Back[x][y]));
- printf(" Store: %s\n", print_if_not_empty(Store[x][y]));
- printf(" Store2: %s\n", print_if_not_empty(Store2[x][y]));
- printf(" StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
- printf(" MovPos: %d\n", MovPos[x][y]);
- printf(" MovDir: %d\n", MovDir[x][y]);
- printf(" MovDelay: %d\n", MovDelay[x][y]);
- printf(" ChangeDelay: %d\n", ChangeDelay[x][y]);
- printf(" CustomValue: %d\n", CustomValue[x][y]);
- printf(" GfxElement: %d\n", GfxElement[x][y]);
- printf(" GfxAction: %d\n", GfxAction[x][y]);
- printf(" GfxFrame: %d\n", GfxFrame[x][y]);
- printf("\n");
+ token_name = element_info[Tile[x][y]].token_name;
+
+ Info("Tile: %d\t['%s']", Tile[x][y], token_name);
+ Info("Back: %s", print_if_not_empty(Back[x][y]));
+ Info("Store: %s", print_if_not_empty(Store[x][y]));
+ Info("Store2: %s", print_if_not_empty(Store2[x][y]));
+ Info("StorePlayer: %s", print_if_not_empty(StorePlayer[x][y]));
+ Info("MovPos: %d", MovPos[x][y]);
+ Info("MovDir: %d", MovDir[x][y]);
+ Info("MovDelay: %d", MovDelay[x][y]);
+ Info("ChangeDelay: %d", ChangeDelay[x][y]);
+ Info("CustomValue: %d", CustomValue[x][y]);
+ Info("GfxElement: %d", GfxElement[x][y]);
+ Info("GfxAction: %d", GfxAction[x][y]);
+ Info("GfxFrame: %d [%d]", GfxFrame[x][y], FrameCounter);
+ Info("Player x/y: %d, %d", local_player->jx, local_player->jy);
+ Info("");
+}
+
+void DumpTileFromScreen(int sx, int sy)
+{
+ int lx = getLevelFromScreenX(sx);
+ int ly = getLevelFromScreenY(sy);
+
+ DumpTile(lx, ly);
}
void SetDrawtoField(int mode)
{
- if (mode == DRAW_FIELDBUFFER)
+ if (mode == DRAW_TO_FIELDBUFFER)
{
FX = 2 * TILEX_VAR;
FY = 2 * TILEY_VAR;
drawto_field = fieldbuffer;
}
- else /* DRAW_BACKBUFFER */
+ else // DRAW_TO_BACKBUFFER
{
FX = SX;
FY = SY;
}
}
-static void RedrawPlayfield_RND()
+int GetDrawtoField(void)
+{
+ return (drawto_field == fieldbuffer ? DRAW_TO_FIELDBUFFER : DRAW_TO_BACKBUFFER);
+}
+
+static void RedrawPlayfield_RND(void)
{
if (game.envelope_active)
return;
DrawAllPlayers();
}
-void RedrawPlayfield()
+void RedrawPlayfield(void)
{
if (game_status != GAME_MODE_PLAYING)
return;
- if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ if (level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ RedrawPlayfield_BD(TRUE);
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
RedrawPlayfield_EM(TRUE);
else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
RedrawPlayfield_SP(TRUE);
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+ RedrawPlayfield_MM();
else if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
RedrawPlayfield_RND();
gfx.sx, gfx.sy);
}
-void DrawMaskedBorder_Rect(int x, int y, int width, int height)
+static void DrawMaskedBorderExt_Rect(int x, int y, int width, int height,
+ int draw_target)
{
- Bitmap *bitmap = getGlobalBorderBitmapFromGameStatus();
+ Bitmap *src_bitmap = getGlobalBorderBitmapFromStatus(global.border_status);
+ Bitmap *dst_bitmap = gfx.masked_border_bitmap_ptr;
- BlitBitmapMasked(bitmap, backbuffer, x, y, width, height, x, y);
+ // may happen for "border.draw_masked.*" with undefined "global.border.*"
+ if (src_bitmap == NULL)
+ return;
+
+ if (x == -1 && y == -1)
+ return;
+
+ if (draw_target == DRAW_TO_SCREEN)
+ BlitToScreenMasked(src_bitmap, x, y, width, height, x, y);
+ else
+ BlitBitmapMasked(src_bitmap, dst_bitmap, x, y, width, height, x, y);
}
-void DrawMaskedBorder_FIELD()
+static void DrawMaskedBorderExt_FIELD(int draw_target)
{
- if (global.border_status >= GAME_MODE_TITLE &&
+ if (global.border_status >= GAME_MODE_MAIN &&
global.border_status <= GAME_MODE_PLAYING &&
border.draw_masked[global.border_status])
- DrawMaskedBorder_Rect(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
+ DrawMaskedBorderExt_Rect(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
+ draw_target);
}
-void DrawMaskedBorder_DOOR_1()
+static void DrawMaskedBorderExt_DOOR_1(int draw_target)
{
+ // when drawing to backbuffer, never draw border over open doors
+ if (draw_target == DRAW_TO_BACKBUFFER &&
+ (GetDoorState() & DOOR_OPEN_1))
+ return;
+
if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
(global.border_status != GAME_MODE_EDITOR ||
border.draw_masked[GFX_SPECIAL_ARG_EDITOR]))
- DrawMaskedBorder_Rect(DX, DY, DXSIZE, DYSIZE);
+ DrawMaskedBorderExt_Rect(DX, DY, DXSIZE, DYSIZE, draw_target);
}
-void DrawMaskedBorder_DOOR_2()
+static void DrawMaskedBorderExt_DOOR_2(int draw_target)
{
+ // when drawing to backbuffer, never draw border over open doors
+ if (draw_target == DRAW_TO_BACKBUFFER &&
+ (GetDoorState() & DOOR_OPEN_2))
+ return;
+
if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
global.border_status != GAME_MODE_EDITOR)
- DrawMaskedBorder_Rect(VX, VY, VXSIZE, VYSIZE);
+ DrawMaskedBorderExt_Rect(VX, VY, VXSIZE, VYSIZE, draw_target);
}
-void DrawMaskedBorder_DOOR_3()
+static void DrawMaskedBorderExt_DOOR_3(int draw_target)
{
- /* currently not available */
+ // currently not available
}
-void DrawMaskedBorder_ALL()
+static void DrawMaskedBorderExt_ALL(int draw_target)
{
- DrawMaskedBorder_FIELD();
- DrawMaskedBorder_DOOR_1();
- DrawMaskedBorder_DOOR_2();
- DrawMaskedBorder_DOOR_3();
+ DrawMaskedBorderExt_FIELD(draw_target);
+ DrawMaskedBorderExt_DOOR_1(draw_target);
+ DrawMaskedBorderExt_DOOR_2(draw_target);
+ DrawMaskedBorderExt_DOOR_3(draw_target);
}
-void DrawMaskedBorder(int redraw_mask)
+static void DrawMaskedBorderExt(int redraw_mask, int draw_target)
{
- /* never draw masked screen borders on borderless screens */
- if (effectiveGameStatus() == GAME_MODE_LOADING ||
- effectiveGameStatus() == GAME_MODE_TITLE)
+ // never draw masked screen borders on borderless screens
+ if (global.border_status == GAME_MODE_LOADING ||
+ global.border_status == GAME_MODE_TITLE)
return;
if (redraw_mask & REDRAW_ALL)
- DrawMaskedBorder_ALL();
+ DrawMaskedBorderExt_ALL(draw_target);
else
{
if (redraw_mask & REDRAW_FIELD)
- DrawMaskedBorder_FIELD();
+ DrawMaskedBorderExt_FIELD(draw_target);
if (redraw_mask & REDRAW_DOOR_1)
- DrawMaskedBorder_DOOR_1();
+ DrawMaskedBorderExt_DOOR_1(draw_target);
if (redraw_mask & REDRAW_DOOR_2)
- DrawMaskedBorder_DOOR_2();
+ DrawMaskedBorderExt_DOOR_2(draw_target);
if (redraw_mask & REDRAW_DOOR_3)
- DrawMaskedBorder_DOOR_3();
+ DrawMaskedBorderExt_DOOR_3(draw_target);
}
}
-void BlitScreenToBitmap_RND(Bitmap *target_bitmap)
+void DrawMaskedBorder_FIELD(void)
{
- int fx = FX, fy = FY;
- int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
- int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
-
- int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
- int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
- int dx_var = dx * TILESIZE_VAR / TILESIZE;
- int dy_var = dy * TILESIZE_VAR / TILESIZE;
- int ffx, ffy;
+ DrawMaskedBorderExt_FIELD(DRAW_TO_BACKBUFFER);
+}
- ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
- ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
+void DrawMaskedBorder(int redraw_mask)
+{
+ DrawMaskedBorderExt(redraw_mask, DRAW_TO_BACKBUFFER);
+}
- if (EVEN(SCR_FIELDX))
+void DrawMaskedBorderToTarget(int draw_target)
+{
+ if (draw_target == DRAW_TO_BACKBUFFER ||
+ draw_target == DRAW_TO_SCREEN)
{
- if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
- fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
- else
- fx += (dx_var > 0 ? TILEX_VAR : 0);
+ DrawMaskedBorderExt(REDRAW_ALL, draw_target);
}
else
{
- fx += dx_var;
- }
+ int last_border_status = global.border_status;
- if (EVEN(SCR_FIELDY))
- {
- if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
- fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
- else
- fy += (dy_var > 0 ? TILEY_VAR : 0);
- }
- else
- {
- fy += dy_var;
- }
+ if (draw_target == DRAW_TO_FADE_SOURCE)
+ {
+ global.border_status = gfx.fade_border_source_status;
+ gfx.masked_border_bitmap_ptr = gfx.fade_bitmap_source;
+ }
+ else if (draw_target == DRAW_TO_FADE_TARGET)
+ {
+ global.border_status = gfx.fade_border_target_status;
+ gfx.masked_border_bitmap_ptr = gfx.fade_bitmap_target;
+ }
- if (full_lev_fieldx <= SCR_FIELDX)
- {
- if (EVEN(SCR_FIELDX))
- fx = 2 * TILEX_VAR - (ODD(lev_fieldx) ? TILEX_VAR / 2 : 0);
- else
- fx = 2 * TILEX_VAR - (EVEN(lev_fieldx) ? TILEX_VAR / 2 : 0);
- }
+ // always use global border for PLAYING when restarting the game
+ if (global.border_status == GAME_MODE_PSEUDO_RESTARTING)
+ global.border_status = GAME_MODE_PLAYING;
- if (full_lev_fieldy <= SCR_FIELDY)
- {
- if (EVEN(SCR_FIELDY))
- fy = 2 * TILEY_VAR - (ODD(lev_fieldy) ? TILEY_VAR / 2 : 0);
- else
- fy = 2 * TILEY_VAR - (EVEN(lev_fieldy) ? TILEY_VAR / 2 : 0);
+ DrawMaskedBorderExt(REDRAW_ALL, draw_target);
+
+ global.border_status = last_border_status;
+ gfx.masked_border_bitmap_ptr = backbuffer;
}
+}
+void DrawTileCursor(int draw_target, int drawing_stage)
+{
+ int tile_cursor_active = (game_status == GAME_MODE_PLAYING);
+
+ DrawTileCursor_MM(draw_target, drawing_stage, tile_cursor_active);
+}
+
+void BlitScreenToBitmapExt_RND(Bitmap *target_bitmap, int fx, int fy)
+{
BlitBitmap(drawto_field, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
}
+void BlitScreenToBitmap_RND(Bitmap *target_bitmap)
+{
+ int fx = getFieldbufferOffsetX_RND(ScreenMovDir, ScreenGfxPos);
+ int fy = getFieldbufferOffsetY_RND(ScreenMovDir, ScreenGfxPos);
+
+ BlitScreenToBitmapExt_RND(target_bitmap, fx, fy);
+}
+
void BlitScreenToBitmap(Bitmap *target_bitmap)
{
- if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ if (level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ BlitScreenToBitmap_BD(target_bitmap);
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
BlitScreenToBitmap_EM(target_bitmap);
else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
BlitScreenToBitmap_SP(target_bitmap);
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+ BlitScreenToBitmap_MM(target_bitmap);
else if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
BlitScreenToBitmap_RND(target_bitmap);
redraw_mask |= REDRAW_FIELD;
}
-void DrawFramesPerSecond()
+static void DrawFramesPerSecond(void)
{
char text[100];
int font_nr = FONT_TEXT_2;
int font_width = getFontWidth(font_nr);
+ int draw_deactivation_mask = GetDrawDeactivationMask();
+ boolean draw_masked = (draw_deactivation_mask == REDRAW_NONE);
+
+ // draw FPS with leading space (needed if field buffer deactivated)
+ sprintf(text, " %04.1f fps", global.frames_per_second);
+
+ // override draw deactivation mask (required for invisible warp mode)
+ SetDrawDeactivationMask(REDRAW_NONE);
+
+ // draw opaque FPS if field buffer deactivated, else draw masked FPS
+ DrawTextExt(backbuffer, SX + SXSIZE - font_width * strlen(text), SY, text,
+ font_nr, (draw_masked ? BLIT_MASKED : BLIT_OPAQUE));
+
+ // set draw deactivation mask to previous value
+ SetDrawDeactivationMask(draw_deactivation_mask);
+
+ // force full-screen redraw in this frame
+ redraw_mask = REDRAW_ALL;
+}
+
+#if DEBUG_FRAME_TIME
+static void PrintFrameTimeDebugging(void)
+{
+ static unsigned int last_counter = 0;
+ unsigned int counter = Counter();
+ int diff_1 = counter - last_counter;
+ int diff_2 = diff_1 - GAME_FRAME_DELAY;
+ int diff_2_max = 20;
+ int diff_2_cut = MIN(ABS(diff_2), diff_2_max);
+ char diff_bar[2 * diff_2_max + 5];
+ int pos = 0;
+ int i;
+
+ diff_bar[pos++] = (diff_2 < -diff_2_max ? '<' : ' ');
+
+ for (i = 0; i < diff_2_max; i++)
+ diff_bar[pos++] = (diff_2 >= 0 ? ' ' :
+ i >= diff_2_max - diff_2_cut ? '-' : ' ');
+
+ diff_bar[pos++] = '|';
- sprintf(text, "%04.1f fps", global.frames_per_second);
+ for (i = 0; i < diff_2_max; i++)
+ diff_bar[pos++] = (diff_2 <= 0 ? ' ' : i < diff_2_cut ? '+' : ' ');
- DrawTextExt(backbuffer, WIN_XSIZE - font_width * strlen(text), 0, text,
- font_nr, BLIT_OPAQUE);
+ diff_bar[pos++] = (diff_2 > diff_2_max ? '>' : ' ');
+
+ diff_bar[pos++] = '\0';
+
+ Debug("time:frame", "%06d [%02d] [%c%02d] %s",
+ counter,
+ diff_1,
+ (diff_2 < 0 ? '-' : diff_2 > 0 ? '+' : ' '), ABS(diff_2),
+ diff_bar);
+
+ last_counter = counter;
+}
+#endif
+
+static int unifiedRedrawMask(int mask)
+{
+ if (mask & REDRAW_ALL)
+ return REDRAW_ALL;
+
+ if (mask & REDRAW_FIELD && mask & REDRAW_DOORS)
+ return REDRAW_ALL;
+
+ return mask;
+}
+
+static boolean equalRedrawMasks(int mask_1, int mask_2)
+{
+ return unifiedRedrawMask(mask_1) == unifiedRedrawMask(mask_2);
}
-void BackToFront()
+void BackToFront(void)
{
+ static int last_redraw_mask = REDRAW_NONE;
+
+ // force screen redraw in every frame to continue drawing global animations
+ // (but always use the last redraw mask to prevent unwanted side effects)
if (redraw_mask == REDRAW_NONE)
- return;
+ redraw_mask = last_redraw_mask;
+ last_redraw_mask = redraw_mask;
+
+#if 1
+ // masked border now drawn immediately when blitting backbuffer to window
+#else
// draw masked border to all viewports, if defined
DrawMaskedBorder(redraw_mask);
+#endif
// draw frames per second (only if debug mode is enabled)
if (redraw_mask & REDRAW_FPS)
DrawFramesPerSecond();
+ // remove playfield redraw before potentially merging with doors redraw
+ if (DrawingDeactivated(REAL_SX, REAL_SY))
+ redraw_mask &= ~REDRAW_FIELD;
+
// redraw complete window if both playfield and (some) doors need redraw
if (redraw_mask & REDRAW_FIELD && redraw_mask & REDRAW_DOORS)
redraw_mask = REDRAW_ALL;
}
else if (redraw_mask & REDRAW_DOORS)
{
+ // merge door areas to prevent calling screen redraw more than once
+ int x1 = WIN_XSIZE;
+ int y1 = WIN_YSIZE;
+ int x2 = 0;
+ int y2 = 0;
+
if (redraw_mask & REDRAW_DOOR_1)
- BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
+ {
+ x1 = MIN(x1, DX);
+ y1 = MIN(y1, DY);
+ x2 = MAX(x2, DX + DXSIZE);
+ y2 = MAX(y2, DY + DYSIZE);
+ }
if (redraw_mask & REDRAW_DOOR_2)
- BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
+ {
+ x1 = MIN(x1, VX);
+ y1 = MIN(y1, VY);
+ x2 = MAX(x2, VX + VXSIZE);
+ y2 = MAX(y2, VY + VYSIZE);
+ }
if (redraw_mask & REDRAW_DOOR_3)
- BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
+ {
+ x1 = MIN(x1, EX);
+ y1 = MIN(y1, EY);
+ x2 = MAX(x2, EX + EXSIZE);
+ y2 = MAX(y2, EY + EYSIZE);
+ }
+
+ // make sure that at least one pixel is blitted, and inside the screen
+ // (else nothing is blitted, causing the animations not to be updated)
+ x1 = MIN(MAX(0, x1), WIN_XSIZE - 1);
+ y1 = MIN(MAX(0, y1), WIN_YSIZE - 1);
+ x2 = MIN(MAX(1, x2), WIN_XSIZE);
+ y2 = MIN(MAX(1, y2), WIN_YSIZE);
+
+ BlitBitmap(backbuffer, window, x1, y1, x2 - x1, y2 - y1, x1, y1);
}
redraw_mask = REDRAW_NONE;
-}
-static void FadeCrossSaveBackbuffer()
-{
- BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+#if DEBUG_FRAME_TIME
+ PrintFrameTimeDebugging();
+#endif
}
-static void FadeCrossRestoreBackbuffer()
+void BackToFront_WithFrameDelay(unsigned int frame_delay_value)
{
- int redraw_mask_last = redraw_mask;
+ unsigned int frame_delay_value_old = GetVideoFrameDelay();
+
+ SetVideoFrameDelay(frame_delay_value);
- BlitBitmap(bitmap_db_cross, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ BackToFront();
- // do not change redraw mask when restoring backbuffer after cross-fading
- redraw_mask = redraw_mask_last;
+ SetVideoFrameDelay(frame_delay_value_old);
}
+static int fade_type_skip = FADE_TYPE_NONE;
+
static void FadeExt(int fade_mask, int fade_mode, int fade_type)
{
- static int fade_type_skip = FADE_TYPE_NONE;
void (*draw_border_function)(void) = NULL;
- Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL);
int x, y, width, height;
int fade_delay, post_delay;
{
if (fade_type_skip != FADE_TYPE_NONE)
{
- /* skip all fade operations until specified fade operation */
+ // skip all fade operations until specified fade operation
if (fade_type & fade_type_skip)
fade_type_skip = FADE_TYPE_NONE;
return;
}
-#if 1
- FadeCrossSaveBackbuffer();
-#endif
-
if (fading.fade_mode & FADE_TYPE_TRANSFORM)
- {
-#if 0
- FadeCrossSaveBackbuffer();
-#endif
-
return;
- }
}
redraw_mask |= fade_mask;
if (fade_type_skip != FADE_TYPE_NONE)
{
- /* skip all fade operations until specified fade operation */
+ // skip all fade operations until specified fade operation
if (fade_type & fade_type_skip)
fade_type_skip = FADE_TYPE_NONE;
height = FADE_SYSIZE;
if (border.draw_masked_when_fading)
- draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */
+ draw_border_function = DrawMaskedBorder_FIELD; // update when fading
else
- DrawMaskedBorder_FIELD(); /* draw once */
+ DrawMaskedBorder_FIELD(); // draw once
}
- else /* REDRAW_ALL */
+ else // REDRAW_ALL
{
x = 0;
y = 0;
height = WIN_YSIZE;
}
- if (!setup.fade_screens ||
- fade_delay == 0 ||
- fading.fade_mode == FADE_MODE_NONE)
- {
- if (fade_mode == FADE_MODE_FADE_OUT)
- return;
-
- BlitBitmap(backbuffer, window, x, y, width, height, x, y);
-
- redraw_mask &= ~fade_mask;
+ // when switching screens without fading, set fade delay to zero
+ if (!setup.fade_screens || fading.fade_mode == FADE_MODE_NONE)
+ fade_delay = 0;
+ // do not display black frame when fading out without fade delay
+ if (fade_mode == FADE_MODE_FADE_OUT && fade_delay == 0)
return;
- }
- FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay,
+ FadeRectangle(x, y, width, height, fade_mode, fade_delay, post_delay,
draw_border_function);
- if (fade_type == FADE_TYPE_FADE_OUT)
- FadeCrossRestoreBackbuffer();
-
redraw_mask &= ~fade_mask;
+
+ ClearAutoRepeatKeyEvents();
+}
+
+static void SetScreenStates_BeforeFadingIn(void)
+{
+ // temporarily set screen mode for animations to screen after fading in
+ global.anim_status = global.anim_status_next;
+
+ // store backbuffer with all animations that will be started after fading in
+ PrepareFadeBitmap(DRAW_TO_FADE_TARGET);
+
+ // set screen mode for animations back to fading
+ global.anim_status = GAME_MODE_PSEUDO_FADING;
+}
+
+static void SetScreenStates_AfterFadingIn(void)
+{
+ // store new source screen (to use correct masked border for fading)
+ gfx.fade_border_source_status = global.border_status;
+
+ global.anim_status = global.anim_status_next;
+}
+
+static void SetScreenStates_BeforeFadingOut(void)
+{
+ // store new target screen (to use correct masked border for fading)
+ gfx.fade_border_target_status = game_status;
+
+ // set screen mode for animations to fading
+ global.anim_status = GAME_MODE_PSEUDO_FADING;
+
+ // store backbuffer with all animations that will be stopped for fading out
+ PrepareFadeBitmap(DRAW_TO_FADE_SOURCE);
+}
+
+static void SetScreenStates_AfterFadingOut(void)
+{
+ global.border_status = game_status;
+
+ // always use global border for PLAYING when restarting the game
+ if (global.border_status == GAME_MODE_PSEUDO_RESTARTING)
+ global.border_status = GAME_MODE_PLAYING;
}
void FadeIn(int fade_mask)
{
+ SetScreenStates_BeforeFadingIn();
+
+#if 1
+ DrawMaskedBorder(REDRAW_ALL);
+#endif
+
if (fading.fade_mode & FADE_TYPE_TRANSFORM)
FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN);
else
FADE_SY = REAL_SY;
FADE_SXSIZE = FULL_SXSIZE;
FADE_SYSIZE = FULL_SYSIZE;
+
+ // activate virtual buttons depending on upcoming game status
+ if (strEqual(setup.touch.control_type, TOUCH_CONTROL_VIRTUAL_BUTTONS) &&
+ game_status == GAME_MODE_PLAYING && !tape.playing)
+ SetOverlayActive(TRUE);
+
+ SetScreenStates_AfterFadingIn();
+
+ // force update of global animation status in case of rapid screen changes
+ redraw_mask = REDRAW_ALL;
+ BackToFront();
}
void FadeOut(int fade_mask)
{
+ // update screen if areas covered by "fade_mask" and "redraw_mask" differ
+ if (!equalRedrawMasks(fade_mask, redraw_mask) &&
+ fade_type_skip != FADE_MODE_SKIP_FADE_OUT)
+ BackToFront();
+
+ // when using BD game engine, cover playfield before fading out after a game
+ if (game_bd.cover_screen)
+ CoverScreen_BD();
+
+ SetScreenStates_BeforeFadingOut();
+
+ SetTileCursorActive(FALSE);
+ SetOverlayActive(FALSE);
+
+#if 0
+ DrawMaskedBorder(REDRAW_ALL);
+#endif
+
if (fading.fade_mode & FADE_TYPE_TRANSFORM)
FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_OUT);
else
FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT);
- global.border_status = game_status;
+ SetScreenStates_AfterFadingOut();
}
static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set)
fading = fading_leave_stored;
}
-void FadeSetEnterMenu()
+void FadeSetEnterMenu(void)
{
fading = menu.enter_menu;
- FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
+ FadeSetLeaveNext(fading, TRUE); // (keep same fade mode)
}
-void FadeSetLeaveMenu()
+void FadeSetLeaveMenu(void)
{
fading = menu.leave_menu;
- FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
+ FadeSetLeaveNext(fading, TRUE); // (keep same fade mode)
}
-void FadeSetEnterScreen()
+void FadeSetEnterScreen(void)
{
fading = menu.enter_screen[game_status];
- FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */
+ FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); // store
}
-void FadeSetNextScreen()
+void FadeSetNextScreen(void)
{
- fading = menu.next_screen;
+ fading = menu.next_screen[game_status];
// (do not overwrite fade mode set by FadeSetEnterScreen)
- // FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
+ // FadeSetLeaveNext(fading, TRUE); // (keep same fade mode)
}
-void FadeSetLeaveScreen()
+void FadeSetLeaveScreen(void)
{
- FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */
+ FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); // recall
}
void FadeSetFromType(int type)
FadeSetLeaveMenu();
}
-void FadeSetDisabled()
+void FadeSetDisabled(void)
{
static struct TitleFadingInfo fading_none = { FADE_MODE_NONE, -1, -1, -1 };
fading = fading_none;
}
-void FadeSkipNextFadeIn()
+void FadeSkipNextFadeIn(void)
{
FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP);
}
-void FadeSkipNextFadeOut()
+void FadeSkipNextFadeOut(void)
{
FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
}
-Bitmap *getBitmapFromGraphicOrDefault(int graphic, int default_graphic)
+static int getGlobalGameStatus(int status)
{
+ return (status == GAME_MODE_PSEUDO_TYPENAME ? GAME_MODE_MAIN :
+ status == GAME_MODE_SCOREINFO ? GAME_MODE_SCORES :
+ status);
+}
+
+int getImageFromGraphicOrDefault(int graphic, int default_graphic)
+{
+ if (graphic == IMG_UNDEFINED)
+ return IMG_UNDEFINED;
+
boolean redefined = getImageListEntryFromImageID(graphic)->redefined;
- return (graphic == IMG_UNDEFINED ? NULL :
- graphic_info[graphic].bitmap != NULL || redefined ?
- graphic_info[graphic].bitmap :
- graphic_info[default_graphic].bitmap);
+ return (graphic_info[graphic].bitmap != NULL || redefined ?
+ graphic : default_graphic);
}
-Bitmap *getBackgroundBitmap(int graphic)
+static int getBackgroundImage(int graphic)
{
- return getBitmapFromGraphicOrDefault(graphic, IMG_BACKGROUND);
+ return getImageFromGraphicOrDefault(graphic, IMG_BACKGROUND);
}
-Bitmap *getGlobalBorderBitmap(int graphic)
+static int getGlobalBorderImage(int graphic)
{
- return getBitmapFromGraphicOrDefault(graphic, IMG_GLOBAL_BORDER);
+ return getImageFromGraphicOrDefault(graphic, IMG_GLOBAL_BORDER);
}
-Bitmap *getGlobalBorderBitmapFromGameStatus()
+Bitmap *getGlobalBorderBitmapFromStatus(int status_raw)
{
+ int status = getGlobalGameStatus(status_raw);
int graphic =
- (game_status == GAME_MODE_MAIN ||
- game_status == GAME_MODE_PSEUDO_TYPENAME ? IMG_GLOBAL_BORDER_MAIN :
- game_status == GAME_MODE_SCORES ? IMG_GLOBAL_BORDER_SCORES :
- game_status == GAME_MODE_EDITOR ? IMG_GLOBAL_BORDER_EDITOR :
- game_status == GAME_MODE_PLAYING ? IMG_GLOBAL_BORDER_PLAYING :
+ (status == GAME_MODE_MAIN ? IMG_GLOBAL_BORDER_MAIN :
+ status == GAME_MODE_SCORES ? IMG_GLOBAL_BORDER_SCORES :
+ status == GAME_MODE_EDITOR ? IMG_GLOBAL_BORDER_EDITOR :
+ status == GAME_MODE_PLAYING ? IMG_GLOBAL_BORDER_PLAYING :
IMG_GLOBAL_BORDER);
+ int graphic_final = getGlobalBorderImage(graphic);
+
+ return graphic_info[graphic_final].bitmap;
+}
+
+void SetBackgroundImage(int graphic, int redraw_mask)
+{
+ struct GraphicInfo *g = &graphic_info[graphic];
+ struct GraphicInfo g_undefined = { 0 };
+
+ if (graphic == IMG_UNDEFINED)
+ g = &g_undefined;
+
+ // always use original size bitmap for backgrounds, if existing
+ Bitmap *bitmap = (g->bitmaps != NULL &&
+ g->bitmaps[IMG_BITMAP_PTR_ORIGINAL] != NULL ?
+ g->bitmaps[IMG_BITMAP_PTR_ORIGINAL] : g->bitmap);
+
+ // remove every mask before setting mask for window, and
+ // remove window area mask before setting mask for main or door area
+ int remove_mask = (redraw_mask == REDRAW_ALL ? 0xffff : REDRAW_ALL);
- return getGlobalBorderBitmap(graphic);
+ // (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!)
+ SetBackgroundBitmap(NULL, remove_mask, 0, 0, 0, 0); // !!! FIX THIS !!!
+ SetBackgroundBitmap(bitmap, redraw_mask,
+ g->src_x, g->src_y,
+ g->width, g->height);
}
void SetWindowBackgroundImageIfDefined(int graphic)
{
if (graphic_info[graphic].bitmap)
- SetWindowBackgroundBitmap(graphic_info[graphic].bitmap);
+ SetBackgroundImage(graphic, REDRAW_ALL);
}
void SetMainBackgroundImageIfDefined(int graphic)
{
if (graphic_info[graphic].bitmap)
- SetMainBackgroundBitmap(graphic_info[graphic].bitmap);
+ SetBackgroundImage(graphic, REDRAW_FIELD);
}
void SetDoorBackgroundImageIfDefined(int graphic)
{
if (graphic_info[graphic].bitmap)
- SetDoorBackgroundBitmap(graphic_info[graphic].bitmap);
+ SetBackgroundImage(graphic, REDRAW_DOOR_1);
}
void SetWindowBackgroundImage(int graphic)
{
- SetWindowBackgroundBitmap(getBackgroundBitmap(graphic));
+ SetBackgroundImage(getBackgroundImage(graphic), REDRAW_ALL);
}
void SetMainBackgroundImage(int graphic)
{
- SetMainBackgroundBitmap(getBackgroundBitmap(graphic));
+ SetBackgroundImage(getBackgroundImage(graphic), REDRAW_FIELD);
}
void SetDoorBackgroundImage(int graphic)
{
- SetDoorBackgroundBitmap(getBackgroundBitmap(graphic));
+ SetBackgroundImage(getBackgroundImage(graphic), REDRAW_DOOR_1);
}
-void SetPanelBackground()
+void SetPanelBackground(void)
{
- struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL];
-
- BlitBitmapTiled(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
- gfx->width, gfx->height, 0, 0, DXSIZE, DYSIZE);
-
- SetDoorBackgroundBitmap(bitmap_db_panel);
+ SetDoorBackgroundImage(IMG_BACKGROUND_PANEL);
}
void DrawBackground(int x, int y, int width, int height)
{
- /* "drawto" might still point to playfield buffer here (hall of fame) */
+ // "drawto" might still point to playfield buffer here (hall of fame)
ClearRectangleOnBackground(backbuffer, x, y, width, height);
if (IN_GFX_FIELD_FULL(x, y))
static int dxsize_last = -1, dysize_last = -1;
static int vx_last = -1, vy_last = -1;
static int vxsize_last = -1, vysize_last = -1;
+static int ex_last = -1, ey_last = -1;
+static int exsize_last = -1, eysize_last = -1;
-boolean CheckIfGlobalBorderHasChanged()
+boolean CheckIfGlobalBorderHasChanged(void)
{
// if game status has not changed, global border has not changed either
if (game_status == game_status_last)
return FALSE;
// determine and store new global border bitmap for current game status
- global_border_bitmap = getGlobalBorderBitmapFromGameStatus();
+ global_border_bitmap = getGlobalBorderBitmapFromStatus(game_status);
return (global_border_bitmap_last != global_border_bitmap);
}
-boolean CheckIfGlobalBorderRedrawIsNeeded()
+#define ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED 0
+
+#if ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED
+static boolean CheckIfGlobalBorderRedrawIsNeeded(void)
{
// if game status has not changed, nothing has to be redrawn
if (game_status == game_status_last)
return FALSE;
+ // redraw if last screen was title screen
+ if (game_status_last == GAME_MODE_TITLE)
+ return TRUE;
+
// redraw if global screen border has changed
if (CheckIfGlobalBorderHasChanged())
return TRUE;
vxsize_last != VXSIZE || vysize_last != VYSIZE)
return TRUE;
+ // redraw if position or size of editor area has changed
+ if (ex_last != EX || ey_last != EY ||
+ exsize_last != EXSIZE || eysize_last != EYSIZE)
+ return TRUE;
+
return FALSE;
}
+#endif
-void RedrawGlobalBorderFromBitmap(Bitmap *bitmap)
+static void RedrawGlobalBorderFromBitmap(Bitmap *bitmap)
{
if (bitmap)
BlitBitmap(bitmap, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
}
-void RedrawGlobalBorder()
+void RedrawGlobalBorder(void)
{
- Bitmap *bitmap = getGlobalBorderBitmapFromGameStatus();
+ Bitmap *bitmap = getGlobalBorderBitmapFromStatus(game_status);
RedrawGlobalBorderFromBitmap(bitmap);
redraw_mask = REDRAW_ALL;
}
-static void RedrawGlobalBorderIfNeeded()
+static void RedrawGlobalBorderIfNeeded(void)
{
+#if ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED
if (game_status == game_status_last)
return;
+#endif
// copy current draw buffer to later copy back areas that have not changed
- BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ if (game_status_last != GAME_MODE_TITLE)
+ BlitBitmap(backbuffer, bitmap_db_store_1, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+#if ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED
if (CheckIfGlobalBorderRedrawIsNeeded())
+#else
+ // determine and store new global border bitmap for current game status
+ global_border_bitmap = getGlobalBorderBitmapFromStatus(game_status);
+#endif
{
// redraw global screen border (or clear, if defined to be empty)
RedrawGlobalBorderFromBitmap(global_border_bitmap);
+ if (game_status == GAME_MODE_EDITOR)
+ DrawSpecialEditorDoor();
+
// copy previous playfield and door areas, if they are defined on both
// previous and current screen and if they still have the same size
if (real_sx_last != -1 && real_sy_last != -1 &&
REAL_SX != -1 && REAL_SY != -1 &&
full_sxsize_last == FULL_SXSIZE && full_sysize_last == FULL_SYSIZE)
- BlitBitmap(bitmap_db_store, backbuffer,
+ BlitBitmap(bitmap_db_store_1, backbuffer,
real_sx_last, real_sy_last, FULL_SXSIZE, FULL_SYSIZE,
REAL_SX, REAL_SY);
if (dx_last != -1 && dy_last != -1 &&
DX != -1 && DY != -1 &&
dxsize_last == DXSIZE && dysize_last == DYSIZE)
- BlitBitmap(bitmap_db_store, backbuffer,
+ BlitBitmap(bitmap_db_store_1, backbuffer,
dx_last, dy_last, DXSIZE, DYSIZE, DX, DY);
- if (vx_last != -1 && vy_last != -1 &&
- VX != -1 && VY != -1 &&
- vxsize_last == VXSIZE && vysize_last == VYSIZE)
- BlitBitmap(bitmap_db_store, backbuffer,
- vx_last, vy_last, VXSIZE, VYSIZE, VX, VY);
+ if (game_status != GAME_MODE_EDITOR)
+ {
+ if (vx_last != -1 && vy_last != -1 &&
+ VX != -1 && VY != -1 &&
+ vxsize_last == VXSIZE && vysize_last == VYSIZE)
+ BlitBitmap(bitmap_db_store_1, backbuffer,
+ vx_last, vy_last, VXSIZE, VYSIZE, VX, VY);
+ }
+ else
+ {
+ if (ex_last != -1 && ey_last != -1 &&
+ EX != -1 && EY != -1 &&
+ exsize_last == EXSIZE && eysize_last == EYSIZE)
+ BlitBitmap(bitmap_db_store_1, backbuffer,
+ ex_last, ey_last, EXSIZE, EYSIZE, EX, EY);
+ }
redraw_mask = REDRAW_ALL;
}
vy_last = VY;
vxsize_last = VXSIZE;
vysize_last = VYSIZE;
+ ex_last = EX;
+ ey_last = EY;
+ exsize_last = EXSIZE;
+ eysize_last = EYSIZE;
}
-void ClearField()
+void ClearField(void)
{
RedrawGlobalBorderIfNeeded();
- /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
- /* (when entering hall of fame after playing) */
+ // !!! "drawto" might still point to playfield buffer here (see above) !!!
+ // (when entering hall of fame after playing)
DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
- /* !!! maybe this should be done before clearing the background !!! */
+ // !!! maybe this should be done before clearing the background !!!
if (game_status == GAME_MODE_PLAYING)
{
ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
- SetDrawtoField(DRAW_FIELDBUFFER);
+ SetDrawtoField(DRAW_TO_FIELDBUFFER);
}
else
{
- SetDrawtoField(DRAW_BACKBUFFER);
+ SetDrawtoField(DRAW_TO_BACKBUFFER);
}
}
redraw_mask |= REDRAW_FIELD;
}
-void SetBorderElement()
+void SetBorderElement(void)
{
int x, y;
BorderElement = EL_EMPTY;
+ // only the R'n'D game engine may use an additional steelwall border
+ if (level.game_engine_type != GAME_ENGINE_TYPE_RND)
+ return;
+
for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
{
for (x = 0; x < lev_fieldx; x++)
{
- if (!IS_INDESTRUCTIBLE(Feld[x][y]))
+ if (!IS_INDESTRUCTIBLE(Tile[x][y]))
BorderElement = EL_STEELWALL;
if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
}
}
-void FloodFillLevel(int from_x, int from_y, int fill_element,
- short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
- int max_fieldx, int max_fieldy)
+void FloodFillLevelExt(int start_x, int start_y, int fill_element,
+ int max_array_fieldx, int max_array_fieldy,
+ short field[max_array_fieldx][max_array_fieldy],
+ int max_fieldx, int max_fieldy)
{
- int i,x,y;
- int old_element;
- static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
- static int safety = 0;
+ static struct XY stack_buffer[MAX_LEV_FIELDX * MAX_LEV_FIELDY];
+ struct XY *check = xy_topdown;
+ int old_element = field[start_x][start_y];
+ int stack_pos = 0;
- /* check if starting field still has the desired content */
- if (field[from_x][from_y] == fill_element)
+ // do nothing if start field already has the desired content
+ if (old_element == fill_element)
return;
- safety++;
+ stack_buffer[stack_pos++] = (struct XY){ start_x, start_y };
- if (safety > max_fieldx * max_fieldy)
- Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
+ while (stack_pos > 0)
+ {
+ struct XY current = stack_buffer[--stack_pos];
+ int i;
- old_element = field[from_x][from_y];
- field[from_x][from_y] = fill_element;
+ field[current.x][current.y] = fill_element;
- for (i = 0; i < 4; i++)
- {
- x = from_x + check[i][0];
- y = from_y + check[i][1];
+ for (i = 0; i < 4; i++)
+ {
+ int x = current.x + check[i].x;
+ int y = current.y + check[i].y;
+
+ // check for stack buffer overflow (should not happen)
+ if (stack_pos >= MAX_LEV_FIELDX * MAX_LEV_FIELDY)
+ Fail("Stack buffer overflow in 'FloodFillLevelExt()'. Please debug.");
- if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
- FloodFillLevel(x, y, fill_element, field, max_fieldx, max_fieldy);
+ if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
+ stack_buffer[stack_pos++] = (struct XY){ x, y };
+ }
}
+}
- safety--;
+void FloodFillLevel(int from_x, int from_y, int fill_element,
+ short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
+ int max_fieldx, int max_fieldy)
+{
+ FloodFillLevelExt(from_x, from_y, fill_element,
+ MAX_LEV_FIELDX, MAX_LEV_FIELDY, field,
+ max_fieldx, max_fieldy);
}
void SetRandomAnimationValue(int x, int y)
gfx.anim_random_frame = GfxRandom[x][y];
}
+void SetAnimationFirstLevel(int first_level)
+{
+ gfx.anim_first_level = first_level;
+}
+
int getGraphicAnimationFrame(int graphic, int sync_frame)
{
- /* animation synchronized with global frame counter, not move position */
+ // animation synchronized with global frame counter, not move position
if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
sync_frame = FrameCounter;
+ else if (graphic_info[graphic].anim_global_anim_sync)
+ sync_frame = getGlobalAnimSyncFrame();
return getAnimationFrame(graphic_info[graphic].anim_frames,
graphic_info[graphic].anim_delay,
sync_frame);
}
-void getSizedGraphicSourceExt(int graphic, int frame, int tilesize,
- Bitmap **bitmap, int *x, int *y,
- boolean get_backside)
+int getGraphicAnimationFrameXY(int graphic, int lx, int ly)
+{
+ if (graphic_info[graphic].anim_mode & ANIM_TILED)
+ {
+ struct GraphicInfo *g = &graphic_info[graphic];
+ int xsize = MAX(1, g->anim_frames_per_line);
+ int ysize = MAX(1, g->anim_frames / xsize);
+ int xoffset = g->anim_start_frame % xsize;
+ int yoffset = g->anim_start_frame % ysize;
+ // may be needed if screen field is significantly larger than playfield
+ int x = (lx + xoffset + SCR_FIELDX * xsize) % xsize;
+ int y = (ly + yoffset + SCR_FIELDY * ysize) % ysize;
+ int sync_frame = y * xsize + x;
+
+ return sync_frame % g->anim_frames;
+ }
+ else if (graphic_info[graphic].anim_mode & ANIM_RANDOM_STATIC)
+ {
+ struct GraphicInfo *g = &graphic_info[graphic];
+ // may be needed if screen field is significantly larger than playfield
+ int x = (lx + SCR_FIELDX * lev_fieldx) % lev_fieldx;
+ int y = (ly + SCR_FIELDY * lev_fieldy) % lev_fieldy;
+ int sync_frame = GfxRandomStatic[x][y];
+
+ return sync_frame % g->anim_frames;
+ }
+ else
+ {
+ int sync_frame = (IN_LEV_FIELD(lx, ly) ? GfxFrame[lx][ly] : -1);
+
+ return getGraphicAnimationFrame(graphic, sync_frame);
+ }
+}
+
+void getGraphicSourceBitmap(int graphic, int tilesize, Bitmap **bitmap)
{
struct GraphicInfo *g = &graphic_info[graphic];
- Bitmap *src_bitmap = g->bitmap;
- int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
- int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
int tilesize_capped = MIN(MAX(1, tilesize), TILESIZE);
- // if no in-game graphics defined, always use standard graphic size
- if (g->bitmaps[IMG_BITMAP_GAME] == NULL)
- tilesize = TILESIZE;
-
if (tilesize == gfx.standard_tile_size)
- src_bitmap = g->bitmaps[IMG_BITMAP_STANDARD];
+ *bitmap = g->bitmaps[IMG_BITMAP_STANDARD];
else if (tilesize == game.tile_size)
- src_bitmap = g->bitmaps[IMG_BITMAP_GAME];
+ *bitmap = g->bitmaps[IMG_BITMAP_PTR_GAME];
else
- src_bitmap = g->bitmaps[IMG_BITMAP_1x1 - log_2(tilesize_capped)];
+ *bitmap = g->bitmaps[IMG_BITMAP_1x1 - log_2(tilesize_capped)];
+}
+
+void getGraphicSourceXY(int graphic, int frame, int *x, int *y,
+ boolean get_backside)
+{
+ struct GraphicInfo *g = &graphic_info[graphic];
+ int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
+ int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
- if (g->offset_y == 0) /* frames are ordered horizontally */
+ if (g->offset_y == 0) // frames are ordered horizontally
{
int max_width = g->anim_frames_per_line * g->width;
int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
- src_x = pos % max_width;
- src_y = src_y % g->height + pos / max_width * g->height;
+ *x = pos % max_width;
+ *y = src_y % g->height + pos / max_width * g->height;
}
- else if (g->offset_x == 0) /* frames are ordered vertically */
+ else if (g->offset_x == 0) // frames are ordered vertically
{
int max_height = g->anim_frames_per_line * g->height;
int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
- src_x = src_x % g->width + pos / max_height * g->width;
- src_y = pos % max_height;
+ *x = src_x % g->width + pos / max_height * g->width;
+ *y = pos % max_height;
}
- else /* frames are ordered diagonally */
+ else // frames are ordered diagonally
{
- src_x = src_x + frame * g->offset_x;
- src_y = src_y + frame * g->offset_y;
+ *x = src_x + frame * g->offset_x;
+ *y = src_y + frame * g->offset_y;
}
-
- *bitmap = src_bitmap;
- *x = src_x * tilesize / TILESIZE;
- *y = src_y * tilesize / TILESIZE;
}
-void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
- int *x, int *y, boolean get_backside)
+void getSizedGraphicSourceExt(int graphic, int frame, int tilesize,
+ Bitmap **bitmap, int *x, int *y,
+ boolean get_backside)
{
- getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y,
- get_backside);
+ struct GraphicInfo *g = &graphic_info[graphic];
+
+ // if no graphics defined at all, use fallback graphics
+ if (g->bitmaps == NULL)
+ *g = graphic_info[IMG_CHAR_EXCLAM];
+
+ // if no in-game graphics defined, always use standard graphic size
+ if (g->bitmaps[IMG_BITMAP_PTR_GAME] == NULL)
+ tilesize = TILESIZE;
+
+ getGraphicSourceBitmap(graphic, tilesize, bitmap);
+ getGraphicSourceXY(graphic, frame, x, y, get_backside);
+
+ *x = *x * tilesize / g->tile_size;
+ *y = *y * tilesize / g->tile_size;
}
void getSizedGraphicSource(int graphic, int frame, int tilesize,
getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
}
-inline static void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
- int *x, int *y, boolean get_backside)
+void getGlobalAnimGraphicSource(int graphic, int frame,
+ Bitmap **bitmap, int *x, int *y)
{
struct GraphicInfo *g = &graphic_info[graphic];
- int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
- int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
- if (TILESIZE_VAR != TILESIZE)
- return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
- get_backside);
+ // if no graphics defined at all, use fallback graphics
+ if (g->bitmaps == NULL)
+ *g = graphic_info[IMG_CHAR_EXCLAM];
- *bitmap = g->bitmap;
-
- if (g->offset_y == 0) /* frames are ordered horizontally */
- {
- int max_width = g->anim_frames_per_line * g->width;
- int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
+ // use original size graphics, if existing, else use standard size graphics
+ if (g->bitmaps[IMG_BITMAP_PTR_ORIGINAL])
+ *bitmap = g->bitmaps[IMG_BITMAP_PTR_ORIGINAL];
+ else
+ *bitmap = g->bitmaps[IMG_BITMAP_STANDARD];
- *x = pos % max_width;
- *y = src_y % g->height + pos / max_width * g->height;
- }
- else if (g->offset_x == 0) /* frames are ordered vertically */
- {
- int max_height = g->anim_frames_per_line * g->height;
- int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
+ getGraphicSourceXY(graphic, frame, x, y, FALSE);
+}
- *x = src_x % g->width + pos / max_height * g->width;
- *y = pos % max_height;
- }
- else /* frames are ordered diagonally */
- {
- *x = src_x + frame * g->offset_x;
- *y = src_y + frame * g->offset_y;
- }
+static void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
+ int *x, int *y, boolean get_backside)
+{
+ getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
+ get_backside);
}
void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
#if DEBUG
if (!IN_SCR_FIELD(x, y))
{
- printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
- printf("DrawGraphic(): This should never happen!\n");
+ Debug("draw:DrawGraphic", "x = %d, y = %d, graphic = %d", x, y, graphic);
+ Debug("draw:DrawGraphic", "This should never happen!");
+
return;
}
#endif
#if DEBUG
if (!IN_SCR_FIELD(x, y))
{
- printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
- printf("DrawGraphic(): This should never happen!\n");
+ Debug("draw:DrawFixedGraphic", "x = %d, y = %d, graphic = %d",
+ x, y, graphic);
+ Debug("draw:DrawFixedGraphic", "This should never happen!");
+
return;
}
#endif
#if DEBUG
if (!IN_SCR_FIELD(x, y))
{
- printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
- printf("DrawGraphicThruMask(): This should never happen!\n");
+ Debug("draw:DrawGraphicThruMask", "x = %d, y = %d, graphic = %d",
+ x, y, graphic);
+ Debug("draw:DrawGraphicThruMask", "This should never happen!");
+
return;
}
#endif
#if DEBUG
if (!IN_SCR_FIELD(x, y))
{
- printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
- printf("DrawGraphicThruMask(): This should never happen!\n");
+ Debug("draw:DrawFixedGraphicThruMask", "x = %d, y = %d, graphic = %d",
+ x, y, graphic);
+ Debug("draw:DrawFixedGraphicThruMask", "This should never happen!");
+
return;
}
#endif
void DrawFixedGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y,
int graphic, int frame)
{
- struct GraphicInfo *g = &graphic_info[graphic];
Bitmap *src_bitmap;
int src_x, src_y;
getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
- BlitBitmapMasked(src_bitmap, d, src_x, src_y, g->width, g->height,
+ BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY,
dst_x, dst_y);
}
MarkTileDirty(x / tilesize, y / tilesize);
}
+void DrawSizedGraphicThruMask(int x, int y, int graphic, int frame,
+ int tilesize)
+{
+ DrawSizedGraphicThruMaskExt(drawto, SX + x * tilesize, SY + y * tilesize,
+ graphic, frame, tilesize);
+ MarkTileDirty(x / tilesize, y / tilesize);
+}
+
void DrawSizedGraphicExt(DrawBuffer *d, int x, int y, int graphic, int frame,
int tilesize)
{
BlitBitmap(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
}
+void DrawSizedGraphicThruMaskExt(DrawBuffer *d, int x, int y, int graphic,
+ int frame, int tilesize)
+{
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+
+ getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
+ BlitBitmapMasked(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
+}
+
void DrawMiniGraphic(int x, int y, int graphic)
{
- DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
+ DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX, SY + y * MINI_TILEY, graphic);
MarkTileDirty(x / 2, y / 2);
}
BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
}
-inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
- int graphic, int frame,
- int cut_mode, int mask_mode)
+static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
+ int graphic, int frame,
+ int cut_mode, int mask_mode)
{
Bitmap *src_bitmap;
int src_x, src_y;
int width = TILEX, height = TILEY;
int cx = 0, cy = 0;
- if (dx || dy) /* shifted graphic */
+ if (dx || dy) // shifted graphic
{
- if (x < BX1) /* object enters playfield from the left */
+ if (x < BX1) // object enters playfield from the left
{
x = BX1;
width = dx;
cx = TILEX - dx;
dx = 0;
}
- else if (x > BX2) /* object enters playfield from the right */
+ else if (x > BX2) // object enters playfield from the right
{
x = BX2;
width = -dx;
dx = TILEX + dx;
}
- else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
+ else if (x == BX1 && dx < 0) // object leaves playfield to the left
{
width += dx;
cx = -dx;
dx = 0;
}
- else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
+ else if (x == BX2 && dx > 0) // object leaves playfield to the right
width -= dx;
- else if (dx) /* general horizontal movement */
+ else if (dx) // general horizontal movement
MarkTileDirty(x + SIGN(dx), y);
- if (y < BY1) /* object enters playfield from the top */
+ if (y < BY1) // object enters playfield from the top
{
- if (cut_mode==CUT_BELOW) /* object completely above top border */
+ if (cut_mode == CUT_BELOW) // object completely above top border
return;
y = BY1;
cy = TILEY - dy;
dy = 0;
}
- else if (y > BY2) /* object enters playfield from the bottom */
+ else if (y > BY2) // object enters playfield from the bottom
{
y = BY2;
height = -dy;
dy = TILEY + dy;
}
- else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
+ else if (y == BY1 && dy < 0) // object leaves playfield to the top
{
height += dy;
cy = -dy;
}
else if (dy > 0 && cut_mode == CUT_ABOVE)
{
- if (y == BY2) /* object completely above bottom border */
+ if (y == BY2) // object completely above bottom border
return;
height = dy;
cy = TILEY - dy;
dy = TILEY;
MarkTileDirty(x, y + 1);
- } /* object leaves playfield to the bottom */
+ } // object leaves playfield to the bottom
else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
height -= dy;
- else if (dy) /* general vertical movement */
+ else if (dy) // general vertical movement
MarkTileDirty(x, y + SIGN(dy));
}
#if DEBUG
if (!IN_SCR_FIELD(x, y))
{
- printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
- printf("DrawGraphicShifted(): This should never happen!\n");
+ Debug("draw:DrawGraphicShiftedNormal", "x = %d, y = %d, graphic = %d",
+ x, y, graphic);
+ Debug("draw:DrawGraphicShiftedNormal", "This should never happen!");
+
return;
}
#endif
}
}
-inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
- int graphic, int frame,
- int cut_mode, int mask_mode)
+static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
+ int graphic, int frame,
+ int cut_mode, int mask_mode)
{
Bitmap *src_bitmap;
int src_x, src_y;
int x2 = x + SIGN(dx);
int y2 = y + SIGN(dy);
- /* movement with two-tile animations must be sync'ed with movement position,
- not with current GfxFrame (which can be higher when using slow movement) */
+ // movement with two-tile animations must be sync'ed with movement position,
+ // not with current GfxFrame (which can be higher when using slow movement)
int anim_pos = (dx ? ABS(dx) : ABS(dy));
int anim_frames = graphic_info[graphic].anim_frames;
- /* (we also need anim_delay here for movement animations with less frames) */
+ // (we also need anim_delay here for movement animations with less frames)
int anim_delay = graphic_info[graphic].anim_delay;
int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
- boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */
- boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */
+ boolean draw_start_tile = (cut_mode != CUT_ABOVE); // only for falling!
+ boolean draw_end_tile = (cut_mode != CUT_BELOW); // only for falling!
- /* re-calculate animation frame for two-tile movement animation */
+ // re-calculate animation frame for two-tile movement animation
frame = getGraphicAnimationFrame(graphic, sync_frame);
- /* check if movement start graphic inside screen area and should be drawn */
+ // check if movement start graphic inside screen area and should be drawn
if (draw_start_tile && IN_SCR_FIELD(x1, y1))
{
getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
MarkTileDirty(x1, y1);
}
- /* check if movement end graphic inside screen area and should be drawn */
+ // check if movement end graphic inside screen area and should be drawn
if (draw_end_tile && IN_SCR_FIELD(x2, y2))
{
getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
return;
}
- if (graphic_info[graphic].double_movement) /* EM style movement images */
- DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
+ if (graphic_info[graphic].double_movement) // EM style movement images
+ DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
else
- DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
+ DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
}
-void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
- int frame, int cut_mode)
+static void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy,
+ int graphic, int frame, int cut_mode)
{
DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
}
if (IN_LEV_FIELD(lx, ly))
{
+ if (element == EL_EMPTY)
+ element = GfxElementEmpty[lx][ly];
+
SetRandomAnimationValue(lx, ly);
graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
- frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
+ frame = getGraphicAnimationFrameXY(graphic, lx, ly);
- /* do not use double (EM style) movement graphic when not moving */
+ // do not use double (EM style) movement graphic when not moving
if (graphic_info[graphic].double_movement && !dx && !dy)
{
graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
- frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
+ frame = getGraphicAnimationFrameXY(graphic, lx, ly);
}
+
+ if (game.use_masked_elements && (dx || dy))
+ mask_mode = USE_MASKING;
}
- else /* border element */
+ else // border element
{
graphic = el2img(element);
- frame = getGraphicAnimationFrame(graphic, -1);
+ frame = getGraphicAnimationFrameXY(graphic, lx, ly);
}
if (element == EL_EXPANDABLE_WALL)
{
boolean left_stopped = FALSE, right_stopped = FALSE;
- if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
+ if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Tile[lx - 1][ly]))
left_stopped = TRUE;
- if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
+ if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Tile[lx + 1][ly]))
right_stopped = TRUE;
if (left_stopped && right_stopped)
void DrawLevelFieldThruMask(int x, int y)
{
- DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
+ DrawLevelElementExt(x, y, 0, 0, Tile[x][y], NO_CUTTING, USE_MASKING);
}
-/* !!! implementation of quicksand is totally broken !!! */
+// !!! implementation of quicksand is totally broken !!!
#define IS_CRUMBLED_TILE(x, y, e) \
(GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) || \
!IS_MOVING(x, y) || \
int width, height, cx, cy;
int sx = SCREENX(x), sy = SCREENY(y);
int crumbled_border_size = graphic_info[graphic].border_size;
+ int crumbled_tile_size = graphic_info[graphic].tile_size;
+ int crumbled_border_size_var =
+ crumbled_border_size * TILESIZE_VAR / crumbled_tile_size;
int i;
getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
BorderElement);
- /* check if neighbour field is of same crumble type */
+ // check if neighbour field is of same crumble type
boolean same = (IS_CRUMBLED_TILE(xx, yy, element) &&
graphic_info[graphic].class ==
graphic_info[el_act2crm(element, ACTION_DEFAULT)].class);
- /* return if check prevents inner corner */
+ // return if check prevents inner corner
if (same == (dxx == dx && dyy == dy))
return;
}
- /* if we reach this point, we have an inner corner */
+ // if we reach this point, we have an inner corner
getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
- width = crumbled_border_size * TILESIZE_VAR / TILESIZE;
- height = crumbled_border_size * TILESIZE_VAR / TILESIZE;
+ width = crumbled_border_size_var;
+ height = crumbled_border_size_var;
cx = (dx > 0 ? TILESIZE_VAR - width : 0);
cy = (dy > 0 ? TILESIZE_VAR - height : 0);
- BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
- width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
+ if (game.use_masked_elements)
+ {
+ int graphic0 = el2img(EL_EMPTY);
+ int frame0 = getGraphicAnimationFrameXY(graphic0, x, y);
+ Bitmap *src_bitmap0;
+ int src_x0, src_y0;
+
+ getGraphicSource(graphic0, frame0, &src_bitmap0, &src_x0, &src_y0);
+
+ BlitBitmap(src_bitmap0, drawto_field, src_x0 + cx, src_y0 + cy,
+ width, height,
+ FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
+
+ BlitBitmapMasked(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+ width, height,
+ FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
+ }
+ else
+ BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+ width, height,
+ FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
}
static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
int width, height, bx, by, cx, cy;
int sx = SCREENX(x), sy = SCREENY(y);
int crumbled_border_size = graphic_info[graphic].border_size;
- int crumbled_border_size_var = crumbled_border_size * TILESIZE_VAR / TILESIZE;
+ int crumbled_tile_size = graphic_info[graphic].tile_size;
+ int crumbled_border_size_var =
+ crumbled_border_size * TILESIZE_VAR / crumbled_tile_size;
int crumbled_border_pos_var = TILESIZE_VAR - crumbled_border_size_var;
int i;
getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
- /* draw simple, sloppy, non-corner-accurate crumbled border */
+ // only needed when using masked elements
+ int graphic0 = el2img(EL_EMPTY);
+ int frame0 = getGraphicAnimationFrameXY(graphic0, x, y);
+ Bitmap *src_bitmap0;
+ int src_x0, src_y0;
+
+ if (game.use_masked_elements)
+ getGraphicSource(graphic0, frame0, &src_bitmap0, &src_x0, &src_y0);
+
+ // draw simple, sloppy, non-corner-accurate crumbled border
width = (dir == 1 || dir == 2 ? crumbled_border_size_var : TILESIZE_VAR);
height = (dir == 0 || dir == 3 ? crumbled_border_size_var : TILESIZE_VAR);
cx = (dir == 2 ? crumbled_border_pos_var : 0);
cy = (dir == 3 ? crumbled_border_pos_var : 0);
- BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, width, height,
- FX + sx * TILEX_VAR + cx,
- FY + sy * TILEY_VAR + cy);
+ if (game.use_masked_elements)
+ {
+ BlitBitmap(src_bitmap0, drawto_field, src_x0 + cx, src_y0 + cy,
+ width, height,
+ FX + sx * TILEX_VAR + cx,
+ FY + sy * TILEY_VAR + cy);
+
+ BlitBitmapMasked(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+ width, height,
+ FX + sx * TILEX_VAR + cx,
+ FY + sy * TILEY_VAR + cy);
+ }
+ else
+ BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+ width, height,
+ FX + sx * TILEX_VAR + cx,
+ FY + sy * TILEY_VAR + cy);
- /* (remaining middle border part must be at least as big as corner part) */
+ // (remaining middle border part must be at least as big as corner part)
if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
- crumbled_border_size >= TILESIZE / 3)
+ crumbled_border_size_var >= TILESIZE_VAR / 3)
return;
- /* correct corners of crumbled border, if needed */
+ // correct corners of crumbled border, if needed
for (i = -1; i <= 1; i += 2)
{
int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
BorderElement);
- /* check if neighbour field is of same crumble type */
+ // check if neighbour field is of same crumble type
if (IS_CRUMBLED_TILE(xx, yy, element) &&
graphic_info[graphic].class ==
graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
{
- /* no crumbled corner, but continued crumbled border */
+ // no crumbled corner, but continued crumbled border
int c1 = (dir == 2 || dir == 3 ? crumbled_border_pos_var : 0);
int c2 = (i == 1 ? crumbled_border_pos_var : 0);
by = cy;
}
- BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
- width, height,
- FX + sx * TILEX_VAR + cx,
- FY + sy * TILEY_VAR + cy);
+ if (game.use_masked_elements)
+ {
+ BlitBitmap(src_bitmap0, drawto_field, src_x0 + bx, src_y0 + by,
+ width, height,
+ FX + sx * TILEX_VAR + cx,
+ FY + sy * TILEY_VAR + cy);
+
+ BlitBitmapMasked(src_bitmap, drawto_field, src_x + bx, src_y + by,
+ width, height,
+ FX + sx * TILEX_VAR + cx,
+ FY + sy * TILEY_VAR + cy);
+ }
+ else
+ BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
+ width, height,
+ FX + sx * TILEX_VAR + cx,
+ FY + sy * TILEY_VAR + cy);
}
}
}
int sx = SCREENX(x), sy = SCREENY(y);
int element;
int i;
- static int xy[4][2] =
- {
- { 0, -1 },
- { -1, 0 },
- { +1, 0 },
- { 0, +1 }
- };
+ struct XY *xy = xy_topdown;
if (!IN_LEV_FIELD(x, y))
return;
element = TILE_GFX_ELEMENT(x, y);
- /* crumble field itself */
- if (IS_CRUMBLED_TILE(x, y, element))
+ if (IS_CRUMBLED_TILE(x, y, element)) // crumble field itself
{
if (!IN_SCR_FIELD(sx, sy))
return;
+ // crumble field borders towards direct neighbour fields
for (i = 0; i < 4; i++)
{
- int xx = x + xy[i][0];
- int yy = y + xy[i][1];
+ int xx = x + xy[i].x;
+ int yy = y + xy[i].y;
element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
BorderElement);
- /* check if neighbour field is of same crumble type */
+ // check if neighbour field is of same crumble type
if (IS_CRUMBLED_TILE(xx, yy, element) &&
graphic_info[graphic].class ==
graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
}
+ // crumble inner field corners towards corner neighbour fields
if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
graphic_info[graphic].anim_frames == 2)
{
MarkTileDirty(sx, sy);
}
- else /* center field not crumbled -- crumble neighbour fields */
+ else // center field is not crumbled -- crumble neighbour fields
{
+ // crumble field borders of direct neighbour fields
for (i = 0; i < 4; i++)
{
- int xx = x + xy[i][0];
- int yy = y + xy[i][1];
- int sxx = sx + xy[i][0];
- int syy = sy + xy[i][1];
+ int xx = x + xy[i].x;
+ int yy = y + xy[i].y;
+ int sxx = sx + xy[i].x;
+ int syy = sy + xy[i].y;
if (!IN_LEV_FIELD(xx, yy) ||
!IN_SCR_FIELD(sxx, syy))
continue;
- if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
+ // do not crumble fields that are being digged or snapped
+ if (Tile[xx][yy] == EL_EMPTY ||
+ Tile[xx][yy] == EL_ELEMENT_SNAPPING)
continue;
element = TILE_GFX_ELEMENT(xx, yy);
MarkTileDirty(sxx, syy);
}
+
+ // crumble inner field corners of corner neighbour fields
+ for (i = 0; i < 4; i++)
+ {
+ int dx = (i & 1 ? +1 : -1);
+ int dy = (i & 2 ? +1 : -1);
+ int xx = x + dx;
+ int yy = y + dy;
+ int sxx = sx + dx;
+ int syy = sy + dy;
+
+ if (!IN_LEV_FIELD(xx, yy) ||
+ !IN_SCR_FIELD(sxx, syy))
+ continue;
+
+ if (Tile[xx][yy] == EL_ELEMENT_SNAPPING)
+ continue;
+
+ element = TILE_GFX_ELEMENT(xx, yy);
+
+ if (!IS_CRUMBLED_TILE(xx, yy, element))
+ continue;
+
+ graphic = el_act2crm(element, ACTION_DEFAULT);
+
+ if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
+ graphic_info[graphic].anim_frames == 2)
+ DrawLevelFieldCrumbledInnerCorners(xx, yy, -dx, -dy, graphic);
+
+ MarkTileDirty(sxx, syy);
+ }
}
}
if (!IN_LEV_FIELD(x, y))
return;
- if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
+ if (Tile[x][y] == EL_ELEMENT_SNAPPING &&
GfxElement[x][y] != EL_UNDEFINED &&
GFX_CRUMBLED(GfxElement[x][y]))
{
int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
int sx = SCREENX(x), sy = SCREENY(y);
- DrawGraphic(sx, sy, graphic1, frame1);
+ DrawScreenGraphic(sx, sy, graphic1, frame1);
DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
}
void DrawLevelFieldCrumbledNeighbours(int x, int y)
{
int sx = SCREENX(x), sy = SCREENY(y);
- static int xy[4][2] =
- {
- { 0, -1 },
- { -1, 0 },
- { +1, 0 },
- { 0, +1 }
- };
+ struct XY *xy = xy_topdown;
int i;
+ // crumble direct neighbour fields (required for field borders)
for (i = 0; i < 4; i++)
{
- int xx = x + xy[i][0];
- int yy = y + xy[i][1];
- int sxx = sx + xy[i][0];
- int syy = sy + xy[i][1];
+ int xx = x + xy[i].x;
+ int yy = y + xy[i].y;
+ int sxx = sx + xy[i].x;
+ int syy = sy + xy[i].y;
if (!IN_LEV_FIELD(xx, yy) ||
!IN_SCR_FIELD(sxx, syy) ||
- !GFX_CRUMBLED(Feld[xx][yy]) ||
+ !GFX_CRUMBLED(Tile[xx][yy]) ||
IS_MOVING(xx, yy))
continue;
DrawLevelField(xx, yy);
}
+
+ // crumble corner neighbour fields (required for inner field corners)
+ for (i = 0; i < 4; i++)
+ {
+ int dx = (i & 1 ? +1 : -1);
+ int dy = (i & 2 ? +1 : -1);
+ int xx = x + dx;
+ int yy = y + dy;
+ int sxx = sx + dx;
+ int syy = sy + dy;
+
+ if (!IN_LEV_FIELD(xx, yy) ||
+ !IN_SCR_FIELD(sxx, syy) ||
+ !GFX_CRUMBLED(Tile[xx][yy]) ||
+ IS_MOVING(xx, yy))
+ continue;
+
+ int element = TILE_GFX_ELEMENT(xx, yy);
+ int graphic = el_act2crm(element, ACTION_DEFAULT);
+
+ if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
+ graphic_info[graphic].anim_frames == 2)
+ DrawLevelField(xx, yy);
+ }
}
static int getBorderElement(int x, int y)
return border[steel_position][steel_type];
}
+void DrawScreenGraphic(int x, int y, int graphic, int frame)
+{
+ if (game.use_masked_elements)
+ {
+ if (graphic != el2img(EL_EMPTY))
+ DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+ DrawGraphicThruMask(x, y, graphic, frame);
+ }
+ else
+ {
+ DrawGraphic(x, y, graphic, frame);
+ }
+}
+
+void DrawLevelGraphic(int x, int y, int graphic, int frame)
+{
+ DrawScreenGraphic(SCREENX(x), SCREENY(y), graphic, frame);
+}
+
void DrawScreenElement(int x, int y, int element)
{
- DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
+ int mask_mode = NO_MASKING;
+
+ if (game.use_masked_elements)
+ {
+ int lx = LEVELX(x), ly = LEVELY(y);
+
+ if (IN_LEV_FIELD(lx, ly) && element != EL_EMPTY)
+ {
+ DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+ mask_mode = USE_MASKING;
+ }
+ }
+
+ DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, mask_mode);
DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
}
return;
}
- element = Feld[lx][ly];
+ element = Tile[lx][ly];
content = Store[lx][ly];
if (IS_MOVING(lx, ly))
else
DrawScreenElement(x, y, EL_EMPTY);
- if (horiz_move)
- DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
- else if (cut_mode == NO_CUTTING)
- DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
+ if (cut_mode != CUT_BELOW && game.use_masked_elements)
+ {
+ int dir = MovDir[lx][ly];
+ int newx = x + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
+ int newy = y + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
+
+ if (IN_SCR_FIELD(newx, newy))
+ DrawScreenElement(newx, newy, EL_EMPTY);
+ }
+
+ if (horiz_move)
+ DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
+ else if (cut_mode == NO_CUTTING)
+ DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
else
{
DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
DrawLevelElementThruMask(newlx, newly, EL_ACID);
+
+ // prevent target field from being drawn again (but without masking)
+ // (this would happen if target field is scanned after moving element)
+ Stop[newlx][newly] = TRUE;
}
}
else if (IS_BLOCKED(lx, ly))
horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
MovDir[oldx][oldy] == MV_RIGHT);
- element_old = Feld[oldx][oldy];
+ element_old = Tile[oldx][oldy];
content_old = Store[oldx][oldy];
if (element_old == EL_QUICKSAND_EMPTYING ||
DrawScreenField(SCREENX(x), SCREENY(y));
else if (IS_MOVING(x, y))
{
- int newx,newy;
+ int newx, newy;
Moving2Blocked(x, y, &newx, &newy);
if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
}
}
+static void DrawSizedWallExt_MM(int dst_x, int dst_y, int element, int tilesize,
+ int (*el2img_function)(int), boolean masked,
+ int element_bits_draw)
+{
+ int element_base = map_mm_wall_element(element);
+ int element_bits = (IS_DF_WALL(element) ?
+ element - EL_DF_WALL_START :
+ IS_MM_WALL(element) ?
+ element - EL_MM_WALL_START : EL_EMPTY) & 0x000f;
+ int graphic = el2img_function(element_base);
+ int tilesize_draw = tilesize / 2;
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+ int i;
+
+ getSizedGraphicSource(graphic, 0, tilesize_draw, &src_bitmap, &src_x, &src_y);
+
+ for (i = 0; i < 4; i++)
+ {
+ int dst_draw_x = dst_x + (i % 2) * tilesize_draw;
+ int dst_draw_y = dst_y + (i / 2) * tilesize_draw;
+
+ if (!(element_bits_draw & (1 << i)))
+ continue;
+
+ if (element_bits & (1 << i))
+ {
+ if (masked)
+ BlitBitmapMasked(src_bitmap, drawto, src_x, src_y,
+ tilesize_draw, tilesize_draw, dst_draw_x, dst_draw_y);
+ else
+ BlitBitmap(src_bitmap, drawto, src_x, src_y,
+ tilesize_draw, tilesize_draw, dst_draw_x, dst_draw_y);
+ }
+ else
+ {
+ if (!masked)
+ ClearRectangle(drawto, dst_draw_x, dst_draw_y,
+ tilesize_draw, tilesize_draw);
+ }
+ }
+}
+
+void DrawSizedWallParts_MM(int x, int y, int element, int tilesize,
+ boolean masked, int element_bits_draw)
+{
+ DrawSizedWallExt_MM(SX + x * tilesize, SY + y * tilesize,
+ element, tilesize, el2edimg, masked, element_bits_draw);
+}
+
+static void DrawSizedWall_MM(int dst_x, int dst_y, int element, int tilesize,
+ int (*el2img_function)(int))
+{
+ DrawSizedWallExt_MM(dst_x, dst_y, element, tilesize, el2img_function, FALSE,
+ 0x000f);
+}
+
+static void DrawSizedElementExt(int x, int y, int element, int tilesize,
+ boolean masked)
+{
+ if (IS_MM_WALL(element))
+ {
+ DrawSizedWallExt_MM(SX + x * tilesize, SY + y * tilesize,
+ element, tilesize, el2edimg, masked, 0x000f);
+ }
+ else
+ {
+ int graphic = el2edimg(element);
+
+ if (masked)
+ DrawSizedGraphicThruMask(x, y, graphic, 0, tilesize);
+ else
+ DrawSizedGraphic(x, y, graphic, 0, tilesize);
+ }
+}
+
void DrawSizedElement(int x, int y, int element, int tilesize)
{
- int graphic;
+ DrawSizedElementExt(x, y, element, tilesize, FALSE);
+}
- graphic = el2edimg(element);
- DrawSizedGraphic(x, y, graphic, 0, tilesize);
+void DrawSizedElementThruMask(int x, int y, int element, int tilesize)
+{
+ DrawSizedElementExt(x, y, element, tilesize, TRUE);
}
void DrawMiniElement(int x, int y, int element)
if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
DrawSizedElement(sx, sy, EL_EMPTY, tilesize);
else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
- DrawSizedElement(sx, sy, Feld[x][y], tilesize);
+ DrawSizedElement(sx, sy, Tile[x][y], tilesize);
else
DrawSizedGraphic(sx, sy, el2edimg(getBorderElement(x, y)), 0, tilesize);
}
if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
DrawMiniElement(sx, sy, EL_EMPTY);
else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
- DrawMiniElement(sx, sy, Feld[x][y]);
+ DrawMiniElement(sx, sy, Tile[x][y]);
else
DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
}
-void DrawEnvelopeBackgroundTiles(int graphic, int startx, int starty,
- int x, int y, int xsize, int ysize,
- int tile_width, int tile_height)
+static void DrawEnvelopeBackgroundTiles(int graphic, int startx, int starty,
+ int x, int y, int xsize, int ysize,
+ int tile_width, int tile_height)
{
Bitmap *src_bitmap;
int src_x, src_y;
dst_x, dst_y);
}
-void DrawEnvelopeBackground(int graphic, int startx, int starty,
- int x, int y, int xsize, int ysize, int font_nr)
+static void DrawEnvelopeBackground(int graphic, int startx, int starty,
+ int x, int y, int xsize, int ysize,
+ int font_nr)
{
int font_width = getFontWidth(font_nr);
int font_height = getFontHeight(font_nr);
font_width, font_height);
}
-void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
+static void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
{
int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
Bitmap *src_bitmap = graphic_info[graphic].bitmap;
int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
boolean ffwd_delay = (tape.playing && tape.fast_forward);
boolean no_delay = (tape.warp_forward);
- unsigned int anim_delay = 0;
int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
- int anim_delay_value = (no_delay ? 0 : frame_delay_value) / 2;
+ int anim_delay_value = MAX(1, (no_delay ? 0 : frame_delay_value) / 2);
+ DelayCounter anim_delay = { anim_delay_value };
int font_nr = FONT_ENVELOPE_1 + envelope_nr;
int font_width = getFontWidth(font_nr);
int font_height = getFontHeight(font_nr);
int sy = SY + (SYSIZE - ysize * font_height) / 2;
int xx, yy;
- SetDrawtoField(DRAW_FIELDBUFFER);
+ SetDrawtoField(DRAW_TO_FIELDBUFFER);
BlitScreenToBitmap(backbuffer);
- SetDrawtoField(DRAW_BACKBUFFER);
+ SetDrawtoField(DRAW_TO_BACKBUFFER);
for (yy = 0; yy < ysize; yy++)
for (xx = 0; xx < xsize; xx++)
DrawEnvelopeBackground(graphic, sx, sy, xx, yy, xsize, ysize, font_nr);
- DrawTextBuffer(sx + font_width, sy + font_height,
- level.envelope[envelope_nr].text, font_nr, max_xsize,
- xsize - 2, ysize - 2, 0, mask_mode,
- level.envelope[envelope_nr].autowrap,
- level.envelope[envelope_nr].centered, FALSE);
+ DrawTextArea(sx + font_width, sy + font_height,
+ level.envelope[envelope_nr].text, font_nr, max_xsize,
+ xsize - 2, ysize - 2, 0, mask_mode,
+ level.envelope[envelope_nr].autowrap,
+ level.envelope[envelope_nr].centered, FALSE);
redraw_mask |= REDRAW_FIELD;
BackToFront();
- SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame);
+ SkipUntilDelayReached(&anim_delay, &i, last_frame);
}
+
+ ClearAutoRepeatKeyEvents();
}
void ShowEnvelope(int envelope_nr)
int anim_mode = graphic_info[graphic].anim_mode;
int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
+ boolean overlay_enabled = GetOverlayEnabled();
+
+ game.envelope_active = TRUE; // needed for RedrawPlayfield() events
- game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
+ SetOverlayEnabled(FALSE);
+ UnmapAllGadgets();
PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
if (tape.playing)
- Delay(wait_delay_value);
+ Delay_WithScreenUpdates(wait_delay_value);
else
WaitForEventToContinue();
+ RemapAllGadgets();
+ SetOverlayEnabled(overlay_enabled);
+
PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
if (anim_mode != ANIM_NONE)
game.envelope_active = FALSE;
- SetDrawtoField(DRAW_FIELDBUFFER);
+ SetDrawtoField(DRAW_TO_FIELDBUFFER);
redraw_mask |= REDRAW_FIELD;
BackToFront();
}
+static void PrepareEnvelopeRequestToScreen(Bitmap *bitmap, int sx, int sy,
+ int xsize, int ysize)
+{
+ if (!global.use_envelope_request)
+ return;
+
+ if (request.bitmap == NULL ||
+ xsize > request.xsize ||
+ ysize > request.ysize)
+ {
+ if (request.bitmap != NULL)
+ FreeBitmap(request.bitmap);
+
+ request.bitmap = CreateBitmap(xsize, ysize, DEFAULT_DEPTH);
+
+ SDL_Surface *surface = request.bitmap->surface;
+
+ if ((request.bitmap->surface_masked = SDLGetNativeSurface(surface)) == NULL)
+ Fail("SDLGetNativeSurface() failed");
+ }
+
+ BlitBitmap(bitmap, request.bitmap, sx, sy, xsize, ysize, 0, 0);
+
+ // create masked surface for request bitmap, if needed
+ if (graphic_info[IMG_BACKGROUND_REQUEST].draw_masked)
+ {
+ SDL_Surface *surface = request.bitmap->surface;
+ SDL_Surface *surface_masked = request.bitmap->surface_masked;
+
+ SDLBlitSurface(surface, surface_masked, 0, 0, xsize, ysize, 0, 0);
+ SDL_SetColorKey(surface_masked, SET_TRANSPARENT_PIXEL,
+ SDL_MapRGB(surface_masked->format, 0x00, 0x00, 0x00));
+ }
+
+ SDLFreeBitmapTextures(request.bitmap);
+ SDLCreateBitmapTextures(request.bitmap);
+
+ ResetBitmapAlpha(request.bitmap);
+
+ // set envelope request run-time values
+ request.sx = sx;
+ request.sy = sy;
+ request.xsize = xsize;
+ request.ysize = ysize;
+}
+
+void DrawEnvelopeRequestToScreen(int drawing_target)
+{
+ if (global.use_envelope_request &&
+ game.request_active &&
+ drawing_target == DRAW_TO_SCREEN)
+ {
+ struct GraphicInfo *g = &graphic_info[IMG_BACKGROUND_REQUEST];
+
+ SetBitmapAlphaNextBlit(request.bitmap, g->alpha);
+
+ if (g->draw_masked)
+ BlitToScreenMasked(request.bitmap, 0, 0, request.xsize, request.ysize,
+ request.sx, request.sy);
+ else
+ BlitToScreen(request.bitmap, 0, 0, request.xsize, request.ysize,
+ request.sx, request.sy);
+ }
+}
+
static void setRequestBasePosition(int *x, int *y)
{
int sx_base, sy_base;
setRequestPositionExt(x, y, request.width, request.height, add_border_size);
}
-void DrawEnvelopeRequest(char *text)
+static void DrawEnvelopeRequestText(int sx, int sy, char *text)
{
- int last_game_status = game_status; /* save current game status */
char *text_final = text;
char *text_door_style = NULL;
int graphic = IMG_BACKGROUND_REQUEST;
int line_length = max_text_width / font_width;
int max_lines = max_text_height / line_height;
int text_width = line_length * font_width;
- int width = request.width;
- int height = request.height;
- int tile_size = MAX(request.step_offset, 1);
- int x_steps = width / tile_size;
- int y_steps = height / tile_size;
int sx_offset = border_size;
int sy_offset = border_size;
- int sx, sy;
- int i, x, y;
+
+ // force DOOR font inside door area
+ SetFontStatus(GAME_MODE_PSEUDO_DOOR);
if (request.centered)
sx_offset = (request.width - text_width) / 2;
- if (request.wrap_single_words)
+ if (request.wrap_single_words && !request.autowrap)
{
char *src_text_ptr, *dst_text_ptr;
+ if (maxWordLengthInRequestString(text) > line_length)
+ {
+ font_nr = FONT_REQUEST_NARROW;
+ font_width = getFontWidth(font_nr);
+ line_length = max_text_width / font_width;
+ }
+
text_door_style = checked_malloc(2 * strlen(text) + 1);
src_text_ptr = text;
text_final = text_door_style;
}
+ DrawTextBuffer(sx + sx_offset, sy + sy_offset, text_final, font_nr,
+ line_length, -1, max_lines, line_spacing, mask_mode,
+ request.autowrap, request.centered, FALSE);
+
+ if (text_door_style)
+ free(text_door_style);
+
+ ResetFontStatus();
+}
+
+static void DrawEnvelopeRequest(char *text, unsigned int req_state)
+{
+ DrawBuffer *drawto_last = drawto;
+ int graphic = IMG_BACKGROUND_REQUEST;
+ int width = request.width;
+ int height = request.height;
+ int tile_size = MAX(request.step_offset, 1);
+ int x_steps = width / tile_size;
+ int y_steps = height / tile_size;
+ int sx, sy;
+ int x, y;
+
setRequestPosition(&sx, &sy, FALSE);
- ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
+ // draw complete envelope request to temporary bitmap
+ drawto = bitmap_db_store_1;
+
+ ClearRectangle(drawto, sx, sy, width, height);
for (y = 0; y < y_steps; y++)
for (x = 0; x < x_steps; x++)
x, y, x_steps, y_steps,
tile_size, tile_size);
- /* force DOOR font inside door area */
- game_status = GAME_MODE_PSEUDO_DOOR;
+ // write text for request
+ DrawEnvelopeRequestText(sx, sy, text);
- DrawTextBuffer(sx + sx_offset, sy + sy_offset, text_final, font_nr,
- line_length, -1, max_lines, line_spacing, mask_mode,
- request.autowrap, request.centered, FALSE);
-
- game_status = last_game_status; /* restore current game status */
+ MapToolButtons(req_state);
- for (i = 0; i < NUM_TOOL_BUTTONS; i++)
- RedrawGadget(tool_gadget[i]);
-
- // store readily prepared envelope request for later use when animating
- BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ // restore pointer to drawing buffer
+ drawto = drawto_last;
- if (text_door_style)
- free(text_door_style);
+ // prepare complete envelope request from temporary bitmap
+ PrepareEnvelopeRequestToScreen(bitmap_db_store_1, sx, sy, width, height);
}
-void AnimateEnvelopeRequest(int anim_mode, int action)
+static void AnimateEnvelopeRequest(int anim_mode, int action)
{
- int graphic = IMG_BACKGROUND_REQUEST;
- boolean draw_masked = graphic_info[graphic].draw_masked;
+ boolean game_ended = (game_status == GAME_MODE_PLAYING && checkGameEnded());
int delay_value_normal = request.step_delay;
int delay_value_fast = delay_value_normal / 2;
boolean ffwd_delay = (tape.playing && tape.fast_forward);
boolean no_delay = (tape.warp_forward);
int delay_value = (ffwd_delay ? delay_value_fast : delay_value_normal);
- int anim_delay_value = (no_delay ? 0 : delay_value + 500 * 0) / 2;
- unsigned int anim_delay = 0;
+ int anim_delay_value = MAX(1, (no_delay ? 0 : delay_value) / 2);
+ DelayCounter anim_delay = { anim_delay_value };
int tile_size = MAX(request.step_offset, 1);
int max_xsize = request.width / tile_size;
ystart = yend;
end = 0;
}
- else
- {
- if (action == ACTION_OPENING)
- PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
- else if (action == ACTION_CLOSING)
- PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
- }
for (i = start; i <= end; i++)
{
int dst_x, dst_y;
int xx, yy;
+ if (game_ended)
+ HandleGameActions();
+
setRequestPosition(&src_x, &src_y, FALSE);
setRequestPositionExt(&dst_x, &dst_y, width, height, FALSE);
- BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
-
for (yy = 0; yy < 2; yy++)
{
for (xx = 0; xx < 2; xx++)
int xx_size = (xx ? tile_size : xsize_size_left);
int yy_size = (yy ? tile_size : ysize_size_top);
- if (draw_masked)
- BlitBitmapMasked(bitmap_db_cross, backbuffer,
- src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
- else
- BlitBitmap(bitmap_db_cross, backbuffer,
- src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
+ // draw partial (animated) envelope request to temporary bitmap
+ BlitBitmap(bitmap_db_store_1, bitmap_db_store_2,
+ src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
}
}
+ // prepare partial (animated) envelope request from temporary bitmap
+ PrepareEnvelopeRequestToScreen(bitmap_db_store_2, dst_x, dst_y,
+ width, height);
+
redraw_mask |= REDRAW_FIELD;
- DoAnimation();
BackToFront();
- SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame);
+ SkipUntilDelayReached(&anim_delay, &i, last_frame);
}
+
+ ClearAutoRepeatKeyEvents();
}
-void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
+static void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
{
int graphic = IMG_BACKGROUND_REQUEST;
int sound_opening = SND_REQUEST_OPENING;
int sound_closing = SND_REQUEST_CLOSING;
- int anim_mode_1 = request.anim_mode; /* (higher priority) */
- int anim_mode_2 = graphic_info[graphic].anim_mode; /* (lower priority) */
+ int anim_mode_1 = request.anim_mode; // (higher priority)
+ int anim_mode_2 = graphic_info[graphic].anim_mode; // (lower priority)
int anim_mode = (anim_mode_1 != ANIM_DEFAULT ? anim_mode_1 : anim_mode_2);
int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
- if (game_status == GAME_MODE_PLAYING)
- BlitScreenToBitmap(backbuffer);
-
- SetDrawtoField(DRAW_BACKBUFFER);
-
- // SetDrawBackgroundMask(REDRAW_NONE);
-
- if (action == ACTION_OPENING)
- {
- BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
-
- if (req_state & REQ_ASK)
- {
- MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
- MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
- }
- else if (req_state & REQ_CONFIRM)
- {
- MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
- }
- else if (req_state & REQ_PLAYER)
- {
- MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
- MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
- MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
- MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
- }
-
- DrawEnvelopeRequest(text);
-
- if (game_status != GAME_MODE_MAIN)
- InitAnimation();
- }
-
- game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
+ game.envelope_active = TRUE; // needed for RedrawPlayfield() events
if (action == ACTION_OPENING)
{
}
game.envelope_active = FALSE;
-
- if (action == ACTION_CLOSING)
- {
- if (game_status != GAME_MODE_MAIN)
- StopAnimation();
-
- BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
- }
-
- // SetDrawBackgroundMask(last_draw_background_mask);
-
- redraw_mask |= REDRAW_FIELD;
-
- if (game_status == GAME_MODE_MAIN)
- DoAnimation();
-
- BackToFront();
-
- if (action == ACTION_CLOSING &&
- game_status == GAME_MODE_PLAYING &&
- level.game_engine_type == GAME_ENGINE_TYPE_RND)
- SetDrawtoField(DRAW_FIELDBUFFER);
}
-void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
+static void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
{
- Bitmap *src_bitmap;
- int src_x, src_y;
- int graphic = el2preimg(element);
+ if (IS_MM_WALL(element))
+ {
+ DrawSizedWall_MM(dst_x, dst_y, element, tilesize, el2preimg);
+ }
+ else
+ {
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+ int graphic = el2preimg(element);
- getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
- BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
+ getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
+ BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize,
+ dst_x, dst_y);
+ }
}
void DrawLevel(int draw_background_mask)
{
- int x,y;
+ int x, y;
SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
SetDrawBackgroundMask(draw_background_mask);
void DrawSizedLevel(int size_x, int size_y, int scroll_x, int scroll_y,
int tilesize)
{
- int x,y;
+ int x, y;
for (x = 0; x < size_x; x++)
for (y = 0; y < size_y; y++)
void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
{
- int x,y;
+ int x, y;
for (x = 0; x < size_x; x++)
for (y = 0; y < size_y; y++)
redraw_mask |= REDRAW_FIELD;
}
-static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y)
+static void DrawPreviewLevelPlayfield(int from_x, int from_y)
{
boolean show_level_border = (BorderElement != EL_EMPTY);
int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
return max_text_width / font_width;
}
-static void DrawPreviewLevelLabelExt(int mode)
+static void DrawPreviewLevelLabelExt(int mode, struct TextPosInfo *pos)
{
- struct TextPosInfo *pos = &menu.main.text.level_info_2;
char label_text[MAX_OUTPUT_LINESIZE + 1];
int max_len_label_text;
int font_nr = pos->font;
redraw_mask |= REDRAW_FIELD;
}
+static void DrawPreviewLevelLabel(int mode)
+{
+ DrawPreviewLevelLabelExt(mode, &menu.main.text.level_info_2);
+}
+
+static void DrawPreviewLevelInfo(int mode)
+{
+ if (mode == MICROLABEL_LEVEL_NAME)
+ DrawPreviewLevelLabelExt(mode, &menu.main.text.level_name);
+ else if (mode == MICROLABEL_LEVEL_AUTHOR)
+ DrawPreviewLevelLabelExt(mode, &menu.main.text.level_author);
+}
+
static void DrawPreviewLevelExt(boolean restart)
{
- static unsigned int scroll_delay = 0;
- static unsigned int label_delay = 0;
+ static DelayCounter scroll_delay = { 0 };
+ static DelayCounter label_delay = { 0 };
static int from_x, from_y, scroll_direction;
static int label_state, label_counter;
- unsigned int scroll_delay_value = preview.step_delay;
boolean show_level_border = (BorderElement != EL_EMPTY);
int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
- int last_game_status = game_status; /* save current game status */
+
+ scroll_delay.value = preview.step_delay;
+ label_delay.value = MICROLEVEL_LABEL_DELAY;
if (restart)
{
label_state = 1;
label_counter = 0;
- DrawPreviewLevelPlayfieldExt(from_x, from_y);
- DrawPreviewLevelLabelExt(label_state);
+ DrawPreviewLevelPlayfield(from_x, from_y);
+ DrawPreviewLevelLabel(label_state);
- /* initialize delay counters */
- DelayReached(&scroll_delay, 0);
- DelayReached(&label_delay, 0);
+ DrawPreviewLevelInfo(MICROLABEL_LEVEL_NAME);
+ DrawPreviewLevelInfo(MICROLABEL_LEVEL_AUTHOR);
+
+ // initialize delay counters
+ ResetDelayCounter(&scroll_delay);
+ ResetDelayCounter(&label_delay);
if (leveldir_current->name)
{
DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
}
- game_status = last_game_status; /* restore current game status */
-
return;
}
- /* scroll preview level, if needed */
+ // scroll preview level, if needed
if (preview.anim_mode != ANIM_NONE &&
(level_xsize > preview.xsize || level_ysize > preview.ysize) &&
- DelayReached(&scroll_delay, scroll_delay_value))
+ DelayReached(&scroll_delay))
{
switch (scroll_direction)
{
break;
}
- DrawPreviewLevelPlayfieldExt(from_x, from_y);
+ DrawPreviewLevelPlayfield(from_x, from_y);
}
- /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
- /* redraw micro level label, if needed */
+ // !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!!
+ // redraw micro level label, if needed
if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
!strEqual(level.author, ANONYMOUS_NAME) &&
!strEqual(level.author, leveldir_current->name) &&
- DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
+ DelayReached(&label_delay))
{
int max_label_counter = 23;
label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
- DrawPreviewLevelLabelExt(label_state);
+ DrawPreviewLevelLabel(label_state);
}
-
- game_status = last_game_status; /* restore current game status */
}
-void DrawPreviewLevelInitial()
+void DrawPreviewPlayers(void)
{
- DrawPreviewLevelExt(TRUE);
-}
+ if (game_status != GAME_MODE_MAIN)
+ return;
-void DrawPreviewLevelAnimation()
-{
- DrawPreviewLevelExt(FALSE);
-}
+ // do not draw preview players if level preview redefined, but players aren't
+ if (preview.redefined && !menu.main.preview_players.redefined)
+ return;
-inline static void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
- int graphic, int sync_frame,
- int mask_mode)
-{
- int frame = getGraphicAnimationFrame(graphic, sync_frame);
+ boolean player_found[MAX_PLAYERS];
+ int num_players = 0;
+ int i, x, y;
- if (mask_mode == USE_MASKING)
- DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
- else
- DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
-}
+ for (i = 0; i < MAX_PLAYERS; i++)
+ player_found[i] = FALSE;
-void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
- int graphic, int sync_frame, int mask_mode)
-{
- int frame = getGraphicAnimationFrame(graphic, sync_frame);
+ // check which players can be found in the level (simple approach)
+ for (x = 0; x < lev_fieldx; x++)
+ {
+ for (y = 0; y < lev_fieldy; y++)
+ {
+ int element = level.field[x][y];
- if (mask_mode == USE_MASKING)
- DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
- else
- DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
-}
+ if (IS_PLAYER_ELEMENT(element))
+ {
+ int player_nr = GET_PLAYER_NR(element);
-inline static void DrawGraphicAnimation(int x, int y, int graphic)
-{
- int lx = LEVELX(x), ly = LEVELY(y);
+ player_nr = MIN(MAX(0, player_nr), MAX_PLAYERS - 1);
- if (!IN_SCR_FIELD(x, y))
+ if (!player_found[player_nr])
+ num_players++;
+
+ player_found[player_nr] = TRUE;
+ }
+ }
+ }
+
+ struct TextPosInfo *pos = &menu.main.preview_players;
+ int tile_size = pos->tile_size;
+ int border_size = pos->border_size;
+ int player_xoffset_raw = (pos->vertical ? 0 : tile_size + border_size);
+ int player_yoffset_raw = (pos->vertical ? tile_size + border_size : 0);
+ int player_xoffset = (pos->xoffset != -1 ? pos->xoffset : player_xoffset_raw);
+ int player_yoffset = (pos->yoffset != -1 ? pos->yoffset : player_yoffset_raw);
+ int max_players_width = (MAX_PLAYERS - 1) * player_xoffset + tile_size;
+ int max_players_height = (MAX_PLAYERS - 1) * player_yoffset + tile_size;
+ int all_players_width = (num_players - 1) * player_xoffset + tile_size;
+ int all_players_height = (num_players - 1) * player_yoffset + tile_size;
+ int max_xpos = SX + ALIGNED_XPOS(pos->x, max_players_width, pos->align);
+ int max_ypos = SY + ALIGNED_YPOS(pos->y, max_players_height, pos->valign);
+ int xpos = SX + ALIGNED_XPOS(pos->x, all_players_width, pos->align);
+ int ypos = SY + ALIGNED_YPOS(pos->y, all_players_height, pos->valign);
+
+ // clear area in which the players will be drawn
+ ClearRectangleOnBackground(drawto, max_xpos, max_ypos,
+ max_players_width, max_players_height);
+
+ if (!network.enabled && !setup.team_mode)
return;
- DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
- graphic, GfxFrame[lx][ly], NO_MASKING);
+ // only draw players if level is suited for team mode
+ if (num_players < 2)
+ return;
- MarkTileDirty(x, y);
-}
+ // draw all players that were found in the level
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (player_found[i])
+ {
+ int graphic = el2img(EL_PLAYER_1 + i);
-void DrawFixedGraphicAnimation(int x, int y, int graphic)
-{
- int lx = LEVELX(x), ly = LEVELY(y);
+ DrawSizedGraphicThruMaskExt(drawto, xpos, ypos, graphic, 0, tile_size);
- if (!IN_SCR_FIELD(x, y))
- return;
+ xpos += player_xoffset;
+ ypos += player_yoffset;
+ }
+ }
+}
- DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
- graphic, GfxFrame[lx][ly], NO_MASKING);
- MarkTileDirty(x, y);
+void DrawPreviewLevelInitial(void)
+{
+ DrawPreviewLevelExt(TRUE);
+ DrawPreviewPlayers();
}
-void DrawLevelGraphicAnimation(int x, int y, int graphic)
+void DrawPreviewLevelAnimation(void)
{
- DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
+ DrawPreviewLevelExt(FALSE);
}
-void DrawLevelElementAnimation(int x, int y, int element)
+static void DrawNetworkPlayer(int x, int y, int player_nr, int tile_size,
+ int border_size, int font_nr)
{
- int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
+ int graphic = el2img(EL_PLAYER_1 + player_nr);
+ int font_height = getFontHeight(font_nr);
+ int player_height = MAX(tile_size, font_height);
+ int xoffset_text = tile_size + border_size;
+ int yoffset_text = (player_height - font_height) / 2;
+ int yoffset_graphic = (player_height - tile_size) / 2;
+ char *player_name = getNetworkPlayerName(player_nr + 1);
- DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
+ DrawSizedGraphicThruMaskExt(drawto, x, y + yoffset_graphic, graphic, 0,
+ tile_size);
+ DrawText(x + xoffset_text, y + yoffset_text, player_name, font_nr);
}
-void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
+static void DrawNetworkPlayersExt(boolean force)
{
- int sx = SCREENX(x), sy = SCREENY(y);
+ if (game_status != GAME_MODE_MAIN)
+ return;
- if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
+ if (!network.connected && !force)
return;
- if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
+ // do not draw network players if level preview redefined, but players aren't
+ if (preview.redefined && !menu.main.network_players.redefined)
return;
- DrawGraphicAnimation(sx, sy, graphic);
+ int num_players = 0;
+ int i;
-#if 1
- if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
+ for (i = 0; i < MAX_PLAYERS; i++)
+ if (stored_player[i].connected_network)
+ num_players++;
+
+ struct TextPosInfo *pos = &menu.main.network_players;
+ int tile_size = pos->tile_size;
+ int border_size = pos->border_size;
+ int xoffset_text = tile_size + border_size;
+ int font_nr = pos->font;
+ int font_width = getFontWidth(font_nr);
+ int font_height = getFontHeight(font_nr);
+ int player_height = MAX(tile_size, font_height);
+ int player_yoffset = player_height + border_size;
+ int max_players_width = xoffset_text + MAX_PLAYER_NAME_LEN * font_width;
+ int max_players_height = MAX_PLAYERS * player_yoffset - border_size;
+ int all_players_height = num_players * player_yoffset - border_size;
+ int max_xpos = SX + ALIGNED_XPOS(pos->x, max_players_width, pos->align);
+ int max_ypos = SY + ALIGNED_YPOS(pos->y, max_players_height, pos->valign);
+ int ypos = SY + ALIGNED_YPOS(pos->y, all_players_height, pos->valign);
+
+ ClearRectangleOnBackground(drawto, max_xpos, max_ypos,
+ max_players_width, max_players_height);
+
+ // first draw local network player ...
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (stored_player[i].connected_network &&
+ stored_player[i].connected_locally)
+ {
+ char *player_name = getNetworkPlayerName(i + 1);
+ int player_width = xoffset_text + getTextWidth(player_name, font_nr);
+ int xpos = SX + ALIGNED_XPOS(pos->x, player_width, pos->align);
+
+ DrawNetworkPlayer(xpos, ypos, i, tile_size, border_size, font_nr);
+
+ ypos += player_yoffset;
+ }
+ }
+
+ // ... then draw all other network players
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ if (stored_player[i].connected_network &&
+ !stored_player[i].connected_locally)
+ {
+ char *player_name = getNetworkPlayerName(i + 1);
+ int player_width = xoffset_text + getTextWidth(player_name, font_nr);
+ int xpos = SX + ALIGNED_XPOS(pos->x, player_width, pos->align);
+
+ DrawNetworkPlayer(xpos, ypos, i, tile_size, border_size, font_nr);
+
+ ypos += player_yoffset;
+ }
+ }
+}
+
+void DrawNetworkPlayers(void)
+{
+ DrawNetworkPlayersExt(FALSE);
+}
+
+void ClearNetworkPlayers(void)
+{
+ DrawNetworkPlayersExt(TRUE);
+}
+
+static void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
+ int graphic, int lx, int ly,
+ int mask_mode)
+{
+ int frame = getGraphicAnimationFrameXY(graphic, lx, ly);
+
+ if (mask_mode == USE_MASKING)
+ DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
+ else
+ DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
+}
+
+void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
+ int graphic, int sync_frame, int mask_mode)
+{
+ int frame = getGraphicAnimationFrame(graphic, sync_frame);
+
+ if (mask_mode == USE_MASKING)
+ DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
+ else
+ DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
+}
+
+void DrawSizedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
+ int graphic, int sync_frame, int tilesize,
+ int mask_mode)
+{
+ int frame = getGraphicAnimationFrame(graphic, sync_frame);
+
+ if (mask_mode == USE_MASKING)
+ DrawSizedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame, tilesize);
+ else
+ DrawSizedGraphicExt(dst_bitmap, x, y, graphic, frame, tilesize);
+}
+
+static void DrawGraphicAnimation(int x, int y, int graphic)
+{
+ int lx = LEVELX(x), ly = LEVELY(y);
+ int mask_mode = NO_MASKING;
+
+ if (!IN_SCR_FIELD(x, y))
+ return;
+
+ if (game.use_masked_elements)
+ {
+ if (Tile[lx][ly] != EL_EMPTY)
+ {
+ DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+ mask_mode = USE_MASKING;
+ }
+ }
+
+ DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
+ graphic, lx, ly, mask_mode);
+
+ MarkTileDirty(x, y);
+}
+
+void DrawFixedGraphicAnimation(int x, int y, int graphic)
+{
+ int lx = LEVELX(x), ly = LEVELY(y);
+ int mask_mode = NO_MASKING;
+
+ if (!IN_SCR_FIELD(x, y))
+ return;
+
+ if (game.use_masked_elements)
+ {
+ if (Tile[lx][ly] != EL_EMPTY)
+ {
+ DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+ mask_mode = USE_MASKING;
+ }
+ }
+
+ DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
+ graphic, lx, ly, mask_mode);
+
+ MarkTileDirty(x, y);
+}
+
+void DrawLevelGraphicAnimation(int x, int y, int graphic)
+{
+ DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
+}
+
+void DrawLevelElementAnimation(int x, int y, int element)
+{
+ int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
+
+ DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
+}
+
+void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
+{
+ int sx = SCREENX(x), sy = SCREENY(y);
+
+ if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
+ return;
+
+ if (Tile[x][y] == EL_EMPTY)
+ graphic = el2img(GfxElementEmpty[x][y]);
+
+ if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
+ return;
+
+ if (ANIM_MODE(graphic) & (ANIM_TILED | ANIM_RANDOM_STATIC))
+ return;
+
+ DrawGraphicAnimation(sx, sy, graphic);
+
+#if 1
+ if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
DrawLevelFieldCrumbled(x, y);
#else
- if (GFX_CRUMBLED(Feld[x][y]))
+ if (GFX_CRUMBLED(Tile[x][y]))
DrawLevelFieldCrumbled(x, y);
#endif
}
{
if (player->use_murphy)
{
- /* this works only because currently only one player can be "murphy" ... */
+ // this works only because currently only one player can be "murphy" ...
static int last_horizontal_dir = MV_LEFT;
int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
last_horizontal_dir = move_dir;
- if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
+ if (graphic == IMG_SP_MURPHY) // undefined => use special graphic
{
int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
return graphic;
}
else
- return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
+ return el_act_dir2img(player->artwork_element, player->GfxAction, move_dir);
}
static boolean equalGraphics(int graphic1, int graphic2)
g1->anim_mode == g2->anim_mode);
}
-void DrawAllPlayers()
+#define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
+
+enum
{
- int i;
+ DRAW_PLAYER_STAGE_INIT = 0,
+ DRAW_PLAYER_STAGE_LAST_FIELD,
+ DRAW_PLAYER_STAGE_FIELD_UNDER_PLAYER,
+#if DRAW_PLAYER_OVER_PUSHED_ELEMENT
+ DRAW_PLAYER_STAGE_ELEMENT_PUSHED,
+ DRAW_PLAYER_STAGE_PLAYER,
+#else
+ DRAW_PLAYER_STAGE_PLAYER,
+ DRAW_PLAYER_STAGE_ELEMENT_PUSHED,
+#endif
+ DRAW_PLAYER_STAGE_ELEMENT_OVER_PLAYER,
+ DRAW_PLAYER_STAGE_FIELD_OVER_PLAYER,
- for (i = 0; i < MAX_PLAYERS; i++)
- if (stored_player[i].active)
- DrawPlayer(&stored_player[i]);
-}
+ NUM_DRAW_PLAYER_STAGES
+};
-void DrawPlayerField(int x, int y)
+static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage)
{
- if (!IS_PLAYER(x, y))
+ static int static_last_player_graphic[MAX_PLAYERS];
+ static int static_last_player_frame[MAX_PLAYERS];
+ static boolean static_player_is_opaque[MAX_PLAYERS];
+ static boolean draw_player[MAX_PLAYERS];
+ int pnr = player->index_nr;
+
+ if (drawing_stage == DRAW_PLAYER_STAGE_INIT)
+ {
+ static_last_player_graphic[pnr] = getPlayerGraphic(player, player->MovDir);
+ static_last_player_frame[pnr] = player->Frame;
+ static_player_is_opaque[pnr] = FALSE;
+
+ draw_player[pnr] = TRUE;
+ }
+
+ if (!draw_player[pnr])
return;
- DrawPlayer(PLAYERINFO(x, y));
-}
+#if DEBUG
+ if (!IN_LEV_FIELD(player->jx, player->jy))
+ {
+ Debug("draw:DrawPlayerExt", "x = %d, y = %d", player->jx, player->jy);
+ Debug("draw:DrawPlayerExt", "This should never happen!");
-#define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
+ draw_player[pnr] = FALSE;
+
+ return;
+ }
+#endif
+
+ int last_player_graphic = static_last_player_graphic[pnr];
+ int last_player_frame = static_last_player_frame[pnr];
+ boolean player_is_opaque = static_player_is_opaque[pnr];
-void DrawPlayer(struct PlayerInfo *player)
-{
int jx = player->jx;
int jy = player->jy;
- int move_dir = player->MovDir;
+ int move_dir = (player->is_waiting ? player->dir_waiting : player->MovDir);
int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
int last_jx = (player->is_moving ? jx - dx : jx);
int last_jy = (player->is_moving ? jy - dy : jy);
int next_jx = jx + dx;
int next_jy = jy + dy;
- boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
- boolean player_is_opaque = FALSE;
- int sx = SCREENX(jx), sy = SCREENY(jy);
- int sxx = 0, syy = 0;
- int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
- int graphic;
- int action = ACTION_DEFAULT;
- int last_player_graphic = getPlayerGraphic(player, move_dir);
- int last_player_frame = player->Frame;
- int frame = 0;
+ boolean player_is_moving = (player->MovPos != 0 ? TRUE : FALSE);
+ int sx = SCREENX(jx);
+ int sy = SCREENY(jy);
+ int sxx = (move_dir == MV_LEFT || move_dir == MV_RIGHT ? player->GfxPos : 0);
+ int syy = (move_dir == MV_UP || move_dir == MV_DOWN ? player->GfxPos : 0);
+ int element = Tile[jx][jy];
+ int last_element = Tile[last_jx][last_jy];
+ int action = (player->is_pushing ? ACTION_PUSHING :
+ player->is_digging ? ACTION_DIGGING :
+ player->is_collecting ? ACTION_COLLECTING :
+ player->is_moving ? ACTION_MOVING :
+ player->is_snapping ? ACTION_SNAPPING :
+ player->is_dropping ? ACTION_DROPPING :
+ player->is_waiting ? player->action_waiting :
+ ACTION_DEFAULT);
+
+ if (drawing_stage == DRAW_PLAYER_STAGE_INIT)
+ {
+ // ------------------------------------------------------------------------
+ // initialize drawing the player
+ // ------------------------------------------------------------------------
- /* GfxElement[][] is set to the element the player is digging or collecting;
- remove also for off-screen player if the player is not moving anymore */
- if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
- GfxElement[jx][jy] = EL_UNDEFINED;
+ draw_player[pnr] = FALSE;
- if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
- return;
+ // GfxElement[][] is set to the element the player is digging or collecting;
+ // remove also for off-screen player if the player is not moving anymore
+ if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
+ GfxElement[jx][jy] = EL_UNDEFINED;
-#if DEBUG
- if (!IN_LEV_FIELD(jx, jy))
- {
- printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
- printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
- printf("DrawPlayerField(): This should never happen!\n");
- return;
- }
-#endif
+ if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
+ return;
- if (element == EL_EXPLOSION)
- return;
+ if (element == EL_EXPLOSION)
+ return;
- action = (player->is_pushing ? ACTION_PUSHING :
- player->is_digging ? ACTION_DIGGING :
- player->is_collecting ? ACTION_COLLECTING :
- player->is_moving ? ACTION_MOVING :
- player->is_snapping ? ACTION_SNAPPING :
- player->is_dropping ? ACTION_DROPPING :
- player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
+ InitPlayerGfxAnimation(player, action, move_dir);
- if (player->is_waiting)
- move_dir = player->dir_waiting;
+ draw_player[pnr] = TRUE;
+ }
+ else if (drawing_stage == DRAW_PLAYER_STAGE_LAST_FIELD)
+ {
+ // ------------------------------------------------------------------------
+ // draw things in the field the player is leaving, if needed
+ // ------------------------------------------------------------------------
- InitPlayerGfxAnimation(player, action, move_dir);
+ if (!IN_SCR_FIELD(sx, sy))
+ draw_player[pnr] = FALSE;
- /* ----------------------------------------------------------------------- */
- /* draw things in the field the player is leaving, if needed */
- /* ----------------------------------------------------------------------- */
+ if (!player->is_moving)
+ return;
- if (player->is_moving)
- {
if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
{
DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
last_element == EL_EM_DYNAMITE_ACTIVE ||
last_element == EL_SP_DISK_RED_ACTIVE)
DrawDynamite(last_jx, last_jy);
-#if 0
- /* !!! this is not enough to prevent flickering of players which are
- moving next to each others without a free tile between them -- this
- can only be solved by drawing all players layer by layer (first the
- background, then the foreground etc.) !!! => TODO */
- else if (!IS_PLAYER(last_jx, last_jy))
- DrawLevelField(last_jx, last_jy);
-#else
else
DrawLevelField(last_jx, last_jy);
-#endif
-
- if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
- DrawLevelElement(next_jx, next_jy, EL_EMPTY);
}
+ else if (drawing_stage == DRAW_PLAYER_STAGE_FIELD_UNDER_PLAYER)
+ {
+ // ------------------------------------------------------------------------
+ // draw things behind the player, if needed
+ // ------------------------------------------------------------------------
- if (!IN_SCR_FIELD(sx, sy))
- return;
+ if (Back[jx][jy])
+ {
+ DrawLevelElement(jx, jy, Back[jx][jy]);
+
+ return;
+ }
- /* ----------------------------------------------------------------------- */
- /* draw things behind the player, if needed */
- /* ----------------------------------------------------------------------- */
+ if (IS_ACTIVE_BOMB(element))
+ {
+ DrawLevelElement(jx, jy, EL_EMPTY);
+
+ return;
+ }
- if (Back[jx][jy])
- DrawLevelElement(jx, jy, Back[jx][jy]);
- else if (IS_ACTIVE_BOMB(element))
- DrawLevelElement(jx, jy, EL_EMPTY);
- else
- {
if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
{
int old_element = GfxElement[jx][jy];
if (GFX_CRUMBLED(old_element))
DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
else
- DrawGraphic(sx, sy, old_graphic, frame);
+ DrawScreenGraphic(sx, sy, old_graphic, frame);
if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
- player_is_opaque = TRUE;
+ static_player_is_opaque[pnr] = TRUE;
}
else
{
GfxElement[jx][jy] = EL_UNDEFINED;
- /* make sure that pushed elements are drawn with correct frame rate */
- graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
+ // make sure that pushed elements are drawn with correct frame rate
+ int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
GfxFrame[jx][jy] = player->StepFrame;
DrawLevelField(jx, jy);
}
}
-
-#if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
- /* ----------------------------------------------------------------------- */
- /* draw player himself */
- /* ----------------------------------------------------------------------- */
-
- graphic = getPlayerGraphic(player, move_dir);
-
- /* in the case of changed player action or direction, prevent the current
- animation frame from being restarted for identical animations */
- if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
- player->Frame = last_player_frame;
-
- frame = getGraphicAnimationFrame(graphic, player->Frame);
-
- if (player->GfxPos)
- {
- if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
- sxx = player->GfxPos;
- else
- syy = player->GfxPos;
- }
-
- if (player_is_opaque)
- DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
- else
- DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
-
- if (SHIELD_ON(player))
+ else if (drawing_stage == DRAW_PLAYER_STAGE_ELEMENT_PUSHED)
{
- int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
- IMG_SHIELD_NORMAL_ACTIVE);
- int frame = getGraphicAnimationFrame(graphic, -1);
-
- DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
- }
-#endif
+ // ------------------------------------------------------------------------
+ // draw things the player is pushing, if needed
+ // ------------------------------------------------------------------------
-#if DRAW_PLAYER_OVER_PUSHED_ELEMENT
- if (player->GfxPos)
- {
- if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
- sxx = player->GfxPos;
- else
- syy = player->GfxPos;
- }
-#endif
+ if (!player->is_pushing || !player->is_moving)
+ return;
- /* ----------------------------------------------------------------------- */
- /* draw things the player is pushing, if needed */
- /* ----------------------------------------------------------------------- */
+ if (Tile[next_jx][next_jy] == EL_EXPLOSION)
+ return;
- if (player->is_pushing && player->is_moving)
- {
- int px = SCREENX(jx), py = SCREENY(jy);
- int pxx = (TILEX - ABS(sxx)) * dx;
- int pyy = (TILEY - ABS(syy)) * dy;
int gfx_frame = GfxFrame[jx][jy];
- int graphic;
- int sync_frame;
- int frame;
-
- if (!IS_MOVING(jx, jy)) /* push movement already finished */
+ if (!IS_MOVING(jx, jy)) // push movement already finished
{
- element = Feld[next_jx][next_jy];
+ element = Tile[next_jx][next_jy];
gfx_frame = GfxFrame[next_jx][next_jy];
}
- graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
-
- sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
- frame = getGraphicAnimationFrame(graphic, sync_frame);
+ int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
+ int sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
+ int frame = getGraphicAnimationFrame(graphic, sync_frame);
- /* draw background element under pushed element (like the Sokoban field) */
+ // draw background element under pushed element (like the Sokoban field)
if (game.use_masked_pushing && IS_MOVING(jx, jy))
{
- /* this allows transparent pushing animation over non-black background */
+ // this allows transparent pushing animation over non-black background
if (Back[jx][jy])
DrawLevelElement(jx, jy, Back[jx][jy]);
else
DrawLevelElement(jx, jy, EL_EMPTY);
-
- if (Back[next_jx][next_jy])
- DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
- else
- DrawLevelElement(next_jx, next_jy, EL_EMPTY);
}
- else if (Back[next_jx][next_jy])
+
+ if (Back[next_jx][next_jy])
DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
+ else
+ DrawLevelElement(next_jx, next_jy, EL_EMPTY);
+
+ int px = SCREENX(jx), py = SCREENY(jy);
+ int pxx = (TILEX - ABS(sxx)) * dx;
+ int pyy = (TILEY - ABS(syy)) * dy;
#if 1
- /* do not draw (EM style) pushing animation when pushing is finished */
- /* (two-tile animations usually do not contain start and end frame) */
+ // do not draw (EM style) pushing animation when pushing is finished
+ // (two-tile animations usually do not contain start and end frame)
if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
- DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
+ DrawLevelElement(next_jx, next_jy, Tile[next_jx][next_jy]);
else
DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
#else
- /* masked drawing is needed for EMC style (double) movement graphics */
- /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
+ // masked drawing is needed for EMC style (double) movement graphics
+ // !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!!
DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
#endif
}
+ else if (drawing_stage == DRAW_PLAYER_STAGE_PLAYER)
+ {
+ // ------------------------------------------------------------------------
+ // draw player himself
+ // ------------------------------------------------------------------------
-#if DRAW_PLAYER_OVER_PUSHED_ELEMENT
- /* ----------------------------------------------------------------------- */
- /* draw player himself */
- /* ----------------------------------------------------------------------- */
-
- graphic = getPlayerGraphic(player, move_dir);
+ int graphic = getPlayerGraphic(player, move_dir);
- /* in the case of changed player action or direction, prevent the current
- animation frame from being restarted for identical animations */
- if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
- player->Frame = last_player_frame;
+ // in the case of changed player action or direction, prevent the current
+ // animation frame from being restarted for identical animations
+ if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
+ player->Frame = last_player_frame;
- frame = getGraphicAnimationFrame(graphic, player->Frame);
+ int frame = getGraphicAnimationFrame(graphic, player->Frame);
- if (player->GfxPos)
- {
- if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
- sxx = player->GfxPos;
+ if (player_is_opaque)
+ DrawGraphicShifted(sx,sy, sxx,syy, graphic, frame, NO_CUTTING,NO_MASKING);
else
- syy = player->GfxPos;
- }
-
- if (player_is_opaque)
- DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
- else
- DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+ DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
- if (SHIELD_ON(player))
- {
- int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
- IMG_SHIELD_NORMAL_ACTIVE);
- int frame = getGraphicAnimationFrame(graphic, -1);
+ if (SHIELD_ON(player))
+ {
+ graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
+ IMG_SHIELD_NORMAL_ACTIVE);
+ frame = getGraphicAnimationFrame(graphic, -1);
- DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+ DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
+ }
}
-#endif
-
- /* ----------------------------------------------------------------------- */
- /* draw things in front of player (active dynamite or dynabombs) */
- /* ----------------------------------------------------------------------- */
-
- if (IS_ACTIVE_BOMB(element))
+ else if (drawing_stage == DRAW_PLAYER_STAGE_ELEMENT_OVER_PLAYER)
{
- graphic = el2img(element);
- frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
+ // ------------------------------------------------------------------------
+ // draw things in front of player (active dynamite or dynabombs)
+ // ------------------------------------------------------------------------
- if (game.emulation == EMU_SUPAPLEX)
- DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
- else
- DrawGraphicThruMask(sx, sy, graphic, frame);
- }
+ if (IS_ACTIVE_BOMB(element))
+ {
+ int graphic = el2img(element);
+ int frame = getGraphicAnimationFrameXY(graphic, jx, jy);
- if (player_is_moving && last_element == EL_EXPLOSION)
- {
- int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
- GfxElement[last_jx][last_jy] : EL_EMPTY);
- int graphic = el_act2img(element, ACTION_EXPLODING);
- int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
- int phase = ExplodePhase[last_jx][last_jy] - 1;
- int frame = getGraphicAnimationFrame(graphic, phase - delay);
+ if (game.emulation == EMU_SUPAPLEX)
+ DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
+ else
+ DrawGraphicThruMask(sx, sy, graphic, frame);
+ }
- if (phase >= delay)
- DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
+ if (player_is_moving && last_element == EL_EXPLOSION)
+ {
+ int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
+ GfxElement[last_jx][last_jy] : EL_EMPTY);
+ int graphic = el_act2img(element, ACTION_EXPLODING);
+ int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
+ int phase = ExplodePhase[last_jx][last_jy] - 1;
+ int frame = getGraphicAnimationFrame(graphic, phase - delay);
+
+ if (phase >= delay)
+ DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
+ }
}
-
- /* ----------------------------------------------------------------------- */
- /* draw elements the player is just walking/passing through/under */
- /* ----------------------------------------------------------------------- */
-
- if (player_is_moving)
+ else if (drawing_stage == DRAW_PLAYER_STAGE_FIELD_OVER_PLAYER)
{
- /* handle the field the player is leaving ... */
- if (IS_ACCESSIBLE_INSIDE(last_element))
- DrawLevelField(last_jx, last_jy);
- else if (IS_ACCESSIBLE_UNDER(last_element))
- DrawLevelFieldThruMask(last_jx, last_jy);
- }
+ // ------------------------------------------------------------------------
+ // draw elements the player is just walking/passing through/under
+ // ------------------------------------------------------------------------
- /* do not redraw accessible elements if the player is just pushing them */
- if (!player_is_moving || !player->is_pushing)
- {
- /* ... and the field the player is entering */
- if (IS_ACCESSIBLE_INSIDE(element))
- DrawLevelField(jx, jy);
- else if (IS_ACCESSIBLE_UNDER(element))
- DrawLevelFieldThruMask(jx, jy);
+ if (player_is_moving)
+ {
+ // handle the field the player is leaving ...
+ if (IS_ACCESSIBLE_INSIDE(last_element))
+ DrawLevelField(last_jx, last_jy);
+ else if (IS_ACCESSIBLE_UNDER(last_element))
+ DrawLevelFieldThruMask(last_jx, last_jy);
+ }
+
+ // do not redraw accessible elements if the player is just pushing them
+ if (!player_is_moving || !player->is_pushing)
+ {
+ // ... and the field the player is entering
+ if (IS_ACCESSIBLE_INSIDE(element))
+ DrawLevelField(jx, jy);
+ else if (IS_ACCESSIBLE_UNDER(element))
+ DrawLevelFieldThruMask(jx, jy);
+ }
+
+ MarkTileDirty(sx, sy);
}
+}
+
+void DrawPlayer(struct PlayerInfo *player)
+{
+ int i;
+
+ for (i = 0; i < NUM_DRAW_PLAYER_STAGES; i++)
+ DrawPlayerExt(player, i);
+}
+
+void DrawAllPlayers(void)
+{
+ int i, j;
- MarkTileDirty(sx, sy);
+ for (i = 0; i < NUM_DRAW_PLAYER_STAGES; i++)
+ for (j = 0; j < MAX_PLAYERS; j++)
+ if (stored_player[j].active)
+ DrawPlayerExt(&stored_player[j], i);
+}
+
+void DrawPlayerField(int x, int y)
+{
+ if (!IS_PLAYER(x, y))
+ return;
+
+ DrawPlayer(PLAYERINFO(x, y));
}
-/* ------------------------------------------------------------------------- */
+// ----------------------------------------------------------------------------
-void WaitForEventToContinue()
+void WaitForEventToContinue(void)
{
+ boolean first_wait = TRUE;
boolean still_wait = TRUE;
- /* simulate releasing mouse button over last gadget, if still pressed */
+ if (program.headless)
+ return;
+
+ // simulate releasing mouse button over last gadget, if still pressed
if (button_status)
HandleGadgets(-1, -1, 0);
button_status = MB_RELEASED;
ClearEventQueue();
+ ClearPlayerAction();
while (still_wait)
{
- if (PendingEvent())
- {
- Event event;
-
- NextEvent(&event);
+ Event event;
+ if (NextValidEvent(&event))
+ {
switch (event.type)
{
case EVENT_BUTTONPRESS:
- case EVENT_KEYPRESS:
- still_wait = FALSE;
+ case EVENT_FINGERPRESS:
+ first_wait = FALSE;
+ break;
+
+ case EVENT_BUTTONRELEASE:
+ case EVENT_FINGERRELEASE:
+ still_wait = first_wait;
break;
- case EVENT_KEYRELEASE:
- ClearPlayerAction();
+ case EVENT_KEYPRESS:
+ case SDL_CONTROLLERBUTTONDOWN:
+ case SDL_JOYBUTTONDOWN:
+ still_wait = FALSE;
break;
default:
still_wait = FALSE;
}
- DoAnimation();
-
- /* don't eat all CPU time */
- Delay(10);
+ if (!PendingEvent())
+ BackToFront();
}
}
-#define MAX_REQUEST_LINES 13
-#define MAX_REQUEST_LINE_FONT1_LEN 7
-#define MAX_REQUEST_LINE_FONT2_LEN 10
-
-static int RequestHandleEvents(unsigned int req_state)
+static int RequestHandleEvents(unsigned int req_state, int draw_buffer_game)
{
- boolean level_solved = (game_status == GAME_MODE_PLAYING &&
- local_player->LevelSolved_GameEnd);
+ boolean game_ended = (game_status == GAME_MODE_PLAYING && checkGameEnded());
+ int draw_buffer_last = GetDrawtoField();
int width = request.width;
int height = request.height;
int sx, sy;
while (result < 0)
{
- if (level_solved)
+ if (game_ended)
{
- SetDrawtoField(DRAW_FIELDBUFFER);
+ SetDrawtoField(draw_buffer_game);
HandleGameActions();
- SetDrawtoField(DRAW_BACKBUFFER);
-
- if (global.use_envelope_request)
- {
- /* copy current state of request area to middle of playfield area */
- BlitBitmap(bitmap_db_cross, drawto, sx, sy, width, height, sx, sy);
- }
+ SetDrawtoField(DRAW_TO_BACKBUFFER);
}
if (PendingEvent())
case EVENT_BUTTONRELEASE:
case EVENT_MOTIONNOTIFY:
{
+ DrawBuffer *drawto_last = drawto;
int mx, my;
if (event.type == EVENT_MOTIONNOTIFY)
button_status = MB_RELEASED;
}
- /* this sets 'request_gadget_id' */
+ if (global.use_envelope_request)
+ {
+ // draw changed button states to temporary bitmap
+ drawto = bitmap_db_store_1;
+ }
+
+ // this sets 'request_gadget_id'
HandleGadgets(mx, my, button_status);
+ if (global.use_envelope_request)
+ {
+ // restore pointer to drawing buffer
+ drawto = drawto_last;
+
+ // prepare complete envelope request from temporary bitmap
+ PrepareEnvelopeRequestToScreen(bitmap_db_store_1, sx, sy,
+ width, height);
+ }
+
switch (request_gadget_id)
{
case TOOL_CTRL_ID_YES:
+ case TOOL_CTRL_ID_TOUCH_YES:
result = TRUE;
break;
case TOOL_CTRL_ID_NO:
+ case TOOL_CTRL_ID_TOUCH_NO:
result = FALSE;
break;
case TOOL_CTRL_ID_CONFIRM:
+ case TOOL_CTRL_ID_TOUCH_CONFIRM:
result = TRUE | FALSE;
break;
break;
}
+ // only needed to handle clickable pointer animations here
+ HandleGlobalAnimClicks(mx, my, button_status, FALSE);
+
break;
}
+ case SDL_WINDOWEVENT:
+ HandleWindowEvent((WindowEvent *) &event);
+ break;
+
+ case SDL_APP_WILLENTERBACKGROUND:
+ case SDL_APP_DIDENTERBACKGROUND:
+ case SDL_APP_WILLENTERFOREGROUND:
+ case SDL_APP_DIDENTERFOREGROUND:
+ HandlePauseResumeEvent((PauseResumeEvent *) &event);
+ break;
+
case EVENT_KEYPRESS:
- switch (GetEventKey((KeyEvent *)&event, TRUE))
+ {
+ Key key = GetEventKey((KeyEvent *)&event);
+
+ switch (key)
{
case KSYM_space:
if (req_state & REQ_CONFIRM)
break;
case KSYM_Return:
-#if defined(TARGET_SDL2)
+ case KSYM_y:
+ case KSYM_Y:
+ case KSYM_Select:
case KSYM_Menu:
+#if defined(KSYM_Rewind)
+ case KSYM_Rewind: // for Amazon Fire TV remote
#endif
result = 1;
break;
case KSYM_Escape:
-#if defined(TARGET_SDL2)
+ case KSYM_n:
+ case KSYM_N:
case KSYM_Back:
+#if defined(KSYM_FastForward)
+ case KSYM_FastForward: // for Amazon Fire TV remote
#endif
result = 0;
break;
default:
+ HandleKeysDebug(key, KEY_PRESSED);
break;
}
if (req_state & REQ_PLAYER)
- result = 0;
+ {
+ int old_player_nr = setup.network_player_nr;
+
+ if (result != -1)
+ result = old_player_nr + 1;
+
+ switch (key)
+ {
+ case KSYM_space:
+ result = old_player_nr + 1;
+ break;
+
+ case KSYM_Up:
+ case KSYM_1:
+ result = 1;
+ break;
+
+ case KSYM_Right:
+ case KSYM_2:
+ result = 2;
+ break;
+
+ case KSYM_Down:
+ case KSYM_3:
+ result = 3;
+ break;
+
+ case KSYM_Left:
+ case KSYM_4:
+ result = 4;
+ break;
+
+ default:
+ break;
+ }
+ }
+
break;
+ }
+ case EVENT_FINGERRELEASE:
case EVENT_KEYRELEASE:
ClearPlayerAction();
break;
+ case SDL_CONTROLLERBUTTONDOWN:
+ switch (event.cbutton.button)
+ {
+ case SDL_CONTROLLER_BUTTON_A:
+ case SDL_CONTROLLER_BUTTON_X:
+ case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
+ case SDL_CONTROLLER_BUTTON_LEFTSTICK:
+ result = 1;
+ break;
+
+ case SDL_CONTROLLER_BUTTON_B:
+ case SDL_CONTROLLER_BUTTON_Y:
+ case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
+ case SDL_CONTROLLER_BUTTON_RIGHTSTICK:
+ case SDL_CONTROLLER_BUTTON_BACK:
+ result = 0;
+ break;
+ }
+
+ if (req_state & REQ_PLAYER)
+ {
+ int old_player_nr = setup.network_player_nr;
+
+ if (result != -1)
+ result = old_player_nr + 1;
+
+ switch (event.cbutton.button)
+ {
+ case SDL_CONTROLLER_BUTTON_DPAD_UP:
+ case SDL_CONTROLLER_BUTTON_Y:
+ result = 1;
+ break;
+
+ case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
+ case SDL_CONTROLLER_BUTTON_B:
+ result = 2;
+ break;
+
+ case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
+ case SDL_CONTROLLER_BUTTON_A:
+ result = 3;
+ break;
+
+ case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
+ case SDL_CONTROLLER_BUTTON_X:
+ result = 4;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ break;
+
+ case SDL_CONTROLLERBUTTONUP:
+ HandleJoystickEvent(&event);
+ ClearPlayerAction();
+ break;
+
default:
HandleOtherEvents(&event);
break;
else if (joy & JOY_BUTTON_2)
result = 0;
}
-
- if (level_solved)
+ else if (AnyJoystick())
{
- if (global.use_envelope_request)
+ int joy = AnyJoystick();
+
+ if (req_state & REQ_PLAYER)
{
- /* copy back current state of pressed buttons inside request area */
- BlitBitmap(drawto, bitmap_db_cross, sx, sy, width, height, sx, sy);
+ if (joy & JOY_UP)
+ result = 1;
+ else if (joy & JOY_RIGHT)
+ result = 2;
+ else if (joy & JOY_DOWN)
+ result = 3;
+ else if (joy & JOY_LEFT)
+ result = 4;
}
}
- else
- {
- DoAnimation();
-
- if (!PendingEvent()) /* delay only if no pending events */
- Delay(10);
- }
BackToFront();
}
+ SetDrawtoField(draw_buffer_last);
+
return result;
}
-static boolean RequestDoor(char *text, unsigned int req_state)
+static void DoRequestBefore(void)
{
- unsigned int old_door_state;
- int last_game_status = game_status; /* save current game status */
- int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
- int font_nr = FONT_TEXT_2;
- char *text_ptr;
- int result;
- int ty;
+ boolean game_ended = (game_status == GAME_MODE_PLAYING && checkGameEnded());
- if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
- {
- max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
- font_nr = FONT_TEXT_1;
- }
+ // when showing request dialog after game ended, deactivate game panel
+ if (game_ended)
+ game.panel.active = FALSE;
if (game_status == GAME_MODE_PLAYING)
BlitScreenToBitmap(backbuffer);
- /* disable deactivated drawing when quick-loading level tape recording */
+ // disable deactivated drawing when quick-loading level tape recording
if (tape.playing && tape.deactivate_display)
TapeDeactivateDisplayOff(TRUE);
SetMouseCursor(CURSOR_DEFAULT);
-#if defined(NETWORK_AVALIABLE)
- /* pause network game while waiting for request to answer */
- if (options.network &&
+ // pause network game while waiting for request to answer
+ if (network.enabled &&
game_status == GAME_MODE_PLAYING &&
- req_state & REQUEST_WAIT_FOR_INPUT)
+ !game.all_players_gone)
SendToServer_PausePlaying();
-#endif
- old_door_state = GetDoorState();
-
- /* simulate releasing mouse button over last gadget, if still pressed */
+ // simulate releasing mouse button over last gadget, if still pressed
if (button_status)
HandleGadgets(-1, -1, 0);
UnmapAllGadgets();
+}
- /* draw released gadget before proceeding */
- // BackToFront();
+static void DoRequestAfter(void)
+{
+ RemapAllGadgets();
- if (old_door_state & DOOR_OPEN_1)
+ if (game_status == GAME_MODE_PLAYING)
{
- CloseDoor(DOOR_CLOSE_1);
+ SetPanelBackground();
+ SetDrawBackgroundMask(REDRAW_DOOR_1);
+ }
+ else
+ {
+ SetDrawBackgroundMask(REDRAW_FIELD);
+ }
- /* save old door content */
- BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
- 0 * DXSIZE, 0, DXSIZE, DYSIZE, 1 * DXSIZE, 0);
+ // continue network game after request
+ if (network.enabled &&
+ game_status == GAME_MODE_PLAYING &&
+ !game.all_players_gone)
+ SendToServer_ContinuePlaying();
+
+ // restore deactivated drawing when quick-loading level tape recording
+ if (tape.playing && tape.deactivate_display)
+ TapeDeactivateDisplayOn();
+}
+
+static void setRequestDoorTextProperties(char *text,
+ int text_spacing,
+ int line_spacing,
+ int *set_font_nr,
+ int *set_max_lines,
+ int *set_max_line_length)
+{
+ struct RectWithBorder *vp_door_1 = &viewport.door_1[game_status];
+ struct TextPosInfo *pos = &request.button.confirm;
+ int button_ypos = pos->y;
+ int font_nr = FONT_TEXT_2;
+ int font_width = getFontWidth(font_nr);
+ int font_height = getFontHeight(font_nr);
+ int line_height = font_height + line_spacing;
+ int max_text_width = vp_door_1->width;
+ int max_text_height = button_ypos - 2 * text_spacing;
+ int max_line_length = max_text_width / font_width;
+ int max_lines = max_text_height / line_height;
+
+ if (maxWordLengthInRequestString(text) > max_line_length)
+ {
+ font_nr = FONT_TEXT_1;
+ font_width = getFontWidth(font_nr);
+ max_line_length = max_text_width / font_width;
}
- SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
- SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
+ *set_font_nr = font_nr;
+ *set_max_lines = max_lines;
+ *set_max_line_length = max_line_length;
+}
- /* clear door drawing field */
- DrawBackground(DX, DY, DXSIZE, DYSIZE);
+static void DrawRequestDoorText(char *text)
+{
+ char *text_ptr = text;
+ int text_spacing = 8;
+ int line_spacing = 2;
+ int max_request_lines;
+ int max_request_line_len;
+ int font_nr;
+ int ty;
- /* force DOOR font inside door area */
- game_status = GAME_MODE_PSEUDO_DOOR;
+ // force DOOR font inside door area
+ SetFontStatus(GAME_MODE_PSEUDO_DOOR);
- /* write text for request */
- for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
+ setRequestDoorTextProperties(text, text_spacing, line_spacing, &font_nr,
+ &max_request_lines, &max_request_line_len);
+
+ for (text_ptr = text, ty = 0; ty < max_request_lines; ty++)
{
char text_line[max_request_line_len + 1];
int tx, tl, tc = 0;
for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
{
tc = *(text_ptr + tx);
- // if (!tc || tc == ' ')
if (!tc || tc == ' ' || tc == '?' || tc == '!')
break;
}
text_line[tl] = 0;
DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
- DY + 8 + ty * (getFontHeight(font_nr) + 2),
+ DY + text_spacing + ty * (getFontHeight(font_nr) + line_spacing),
text_line, font_nr);
text_ptr += tl + (tc == ' ' ? 1 : 0);
- // text_ptr += tl + (tc == ' ' || tc == '?' || tc == '!' ? 1 : 0);
}
- game_status = last_game_status; /* restore current game status */
+ ResetFontStatus();
+}
- if (req_state & REQ_ASK)
- {
- MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
- MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
- }
- else if (req_state & REQ_CONFIRM)
- {
- MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
- }
- else if (req_state & REQ_PLAYER)
+static int RequestDoor(char *text, unsigned int req_state)
+{
+ unsigned int old_door_state = GetDoorState();
+ int draw_buffer_last = GetDrawtoField();
+ int result;
+
+ if (old_door_state & DOOR_OPEN_1)
{
- MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
- MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
- MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
- MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
+ CloseDoor(DOOR_CLOSE_1);
+
+ // save old door content
+ BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
+ 0, 0, DXSIZE, DYSIZE, DXSIZE, 0);
}
- /* copy request gadgets to door backbuffer */
- BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
+ SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
+ SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
- OpenDoor(DOOR_OPEN_1);
+ // clear door drawing field
+ DrawBackground(DX, DY, DXSIZE, DYSIZE);
- if (!(req_state & REQUEST_WAIT_FOR_INPUT))
- {
- if (game_status == GAME_MODE_PLAYING)
- {
- SetPanelBackground();
- SetDrawBackgroundMask(REDRAW_DOOR_1);
- }
- else
- {
- SetDrawBackgroundMask(REDRAW_FIELD);
- }
+ // write text for request
+ DrawRequestDoorText(text);
- return FALSE;
- }
+ MapToolButtons(req_state);
- if (game_status != GAME_MODE_MAIN)
- InitAnimation();
+ // copy request gadgets to door backbuffer
+ BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
- SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
+ OpenDoor(DOOR_OPEN_1);
// ---------- handle request buttons ----------
- result = RequestHandleEvents(req_state);
-
- if (game_status != GAME_MODE_MAIN)
- StopAnimation();
+ result = RequestHandleEvents(req_state, draw_buffer_last);
UnmapToolButtons();
OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
}
- RemapAllGadgets();
-
- if (game_status == GAME_MODE_PLAYING)
- {
- SetPanelBackground();
- SetDrawBackgroundMask(REDRAW_DOOR_1);
- }
- else
- {
- SetDrawBackgroundMask(REDRAW_FIELD);
- }
-
-#if defined(NETWORK_AVALIABLE)
- /* continue network game after request */
- if (options.network &&
- game_status == GAME_MODE_PLAYING &&
- req_state & REQUEST_WAIT_FOR_INPUT)
- SendToServer_ContinuePlaying();
-#endif
-
- /* restore deactivated drawing when quick-loading level tape recording */
- if (tape.playing && tape.deactivate_display)
- TapeDeactivateDisplayOn();
-
return result;
}
-static boolean RequestEnvelope(char *text, unsigned int req_state)
+static int RequestEnvelope(char *text, unsigned int req_state)
{
+ int draw_buffer_last = GetDrawtoField();
int result;
- if (game_status == GAME_MODE_PLAYING)
- BlitScreenToBitmap(backbuffer);
+ DrawEnvelopeRequest(text, req_state);
+ ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
- /* disable deactivated drawing when quick-loading level tape recording */
- if (tape.playing && tape.deactivate_display)
- TapeDeactivateDisplayOff(TRUE);
+ // ---------- handle request buttons ----------
+ result = RequestHandleEvents(req_state, draw_buffer_last);
- SetMouseCursor(CURSOR_DEFAULT);
+ UnmapToolButtons();
-#if defined(NETWORK_AVALIABLE)
- /* pause network game while waiting for request to answer */
- if (options.network &&
- game_status == GAME_MODE_PLAYING &&
- req_state & REQUEST_WAIT_FOR_INPUT)
- SendToServer_PausePlaying();
-#endif
+ ShowEnvelopeRequest(text, req_state, ACTION_CLOSING);
- /* simulate releasing mouse button over last gadget, if still pressed */
- if (button_status)
- HandleGadgets(-1, -1, 0);
+ return result;
+}
- UnmapAllGadgets();
+int Request(char *text, unsigned int req_state)
+{
+ boolean overlay_enabled = GetOverlayEnabled();
+ int result;
- // (replace with setting corresponding request background)
- // SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
- // SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
+ game.request_active = TRUE;
- /* clear door drawing field */
- // DrawBackground(DX, DY, DXSIZE, DYSIZE);
+ SetOverlayEnabled(FALSE);
- ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
+ DoRequestBefore();
- if (!(req_state & REQUEST_WAIT_FOR_INPUT))
- {
- if (game_status == GAME_MODE_PLAYING)
- {
- SetPanelBackground();
- SetDrawBackgroundMask(REDRAW_DOOR_1);
- }
- else
- {
- SetDrawBackgroundMask(REDRAW_FIELD);
- }
+ if (global.use_envelope_request)
+ result = RequestEnvelope(text, req_state);
+ else
+ result = RequestDoor(text, req_state);
- return FALSE;
- }
+ DoRequestAfter();
- SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
+ SetOverlayEnabled(overlay_enabled);
- // ---------- handle request buttons ----------
- result = RequestHandleEvents(req_state);
+ game.request_active = FALSE;
- if (game_status != GAME_MODE_MAIN)
- StopAnimation();
+ return result;
+}
- UnmapToolButtons();
+static int compareDoorPartOrderInfo(const void *object1, const void *object2)
+{
+ const struct DoorPartOrderInfo *dpo1 = (struct DoorPartOrderInfo *)object1;
+ const struct DoorPartOrderInfo *dpo2 = (struct DoorPartOrderInfo *)object2;
+ int compare_result;
- ShowEnvelopeRequest(text, req_state, ACTION_CLOSING);
+ if (dpo1->sort_priority != dpo2->sort_priority)
+ compare_result = dpo1->sort_priority - dpo2->sort_priority;
+ else
+ compare_result = dpo1->nr - dpo2->nr;
- RemapAllGadgets();
+ return compare_result;
+}
- if (game_status == GAME_MODE_PLAYING)
- {
- SetPanelBackground();
- SetDrawBackgroundMask(REDRAW_DOOR_1);
- }
- else
- {
- SetDrawBackgroundMask(REDRAW_FIELD);
- }
-
-#if defined(NETWORK_AVALIABLE)
- /* continue network game after request */
- if (options.network &&
- game_status == GAME_MODE_PLAYING &&
- req_state & REQUEST_WAIT_FOR_INPUT)
- SendToServer_ContinuePlaying();
-#endif
-
- /* restore deactivated drawing when quick-loading level tape recording */
- if (tape.playing && tape.deactivate_display)
- TapeDeactivateDisplayOn();
-
- return result;
-}
-
-boolean Request(char *text, unsigned int req_state)
-{
- if (global.use_envelope_request)
- return RequestEnvelope(text, req_state);
- else
- return RequestDoor(text, req_state);
-}
-
-static int compareDoorPartOrderInfo(const void *object1, const void *object2)
-{
- const struct DoorPartOrderInfo *dpo1 = (struct DoorPartOrderInfo *)object1;
- const struct DoorPartOrderInfo *dpo2 = (struct DoorPartOrderInfo *)object2;
- int compare_result;
-
- if (dpo1->sort_priority != dpo2->sort_priority)
- compare_result = dpo1->sort_priority - dpo2->sort_priority;
- else
- compare_result = dpo1->nr - dpo2->nr;
-
- return compare_result;
-}
-
-void InitGraphicCompatibilityInfo_Doors()
+void InitGraphicCompatibilityInfo_Doors(void)
{
struct
{
}
doors[] =
{
- { DOOR_1, IMG_DOOR_1_GFX_PART_1, IMG_DOOR_1_GFX_PART_8, &door_1 },
- { DOOR_2, IMG_DOOR_2_GFX_PART_1, IMG_DOOR_2_GFX_PART_8, &door_2 },
+ { DOOR_1, IMG_GFX_DOOR_1_PART_1, IMG_GFX_DOOR_1_PART_8, &door_1 },
+ { DOOR_2, IMG_GFX_DOOR_2_PART_1, IMG_GFX_DOOR_2_PART_8, &door_2 },
{ -1, -1, -1, NULL }
};
struct Rect *door_rect = &door_rect_list[door_index];
boolean door_gfx_redefined = FALSE;
- /* check if any door part graphic definitions have been redefined */
+ // check if any door part graphic definitions have been redefined
for (j = 0; door_part_controls[j].door_token != -1; j++)
{
door_gfx_redefined = TRUE;
}
- /* check for old-style door graphic/animation modifications */
+ // check for old-style door graphic/animation modifications
if (!door_gfx_redefined)
{
struct GraphicInfo *g_part_2 = &graphic_info[part_2];
int num_door_steps, num_panel_steps;
- /* remove door part graphics other than the two default wings */
+ // remove door part graphics other than the two default wings
for (j = 0; door_part_controls[j].door_token != -1; j++)
{
g->bitmap = NULL;
}
- /* set graphics and screen positions of the default wings */
+ // set graphics and screen positions of the default wings
g_part_1->width = door_rect->width;
g_part_1->height = door_rect->height;
door->part_2.y += door_rect->height - door->height;
}
- /* set animation delays for the default wings and panels */
+ // set animation delays for the default wings and panels
door->part_1.step_delay = door->step_delay;
door->part_2.step_delay = door->step_delay;
door->panel.step_delay = door->step_delay;
- /* set animation draw order for the default wings */
+ // set animation draw order for the default wings
- door->part_1.sort_priority = 2; /* draw left wing over ... */
- door->part_2.sort_priority = 1; /* ... right wing */
+ door->part_1.sort_priority = 2; // draw left wing over ...
+ door->part_2.sort_priority = 1; // ... right wing
- /* set animation draw offset for the default wings */
+ // set animation draw offset for the default wings
if (door->anim_mode & ANIM_HORIZONTAL)
{
num_door_steps = g_part_1->height / door->step_offset;
}
- /* set animation draw offset for the default panels */
+ // set animation draw offset for the default panels
if (door->step_offset > 1)
{
}
}
-void InitDoors()
+void InitDoors(void)
{
int i;
struct DoorPartControlInfo *dpc = &door_part_controls[i];
struct DoorPartOrderInfo *dpo = &door_part_order[i];
- /* initialize "start_step_opening" and "start_step_closing", if needed */
+ // initialize "start_step_opening" and "start_step_closing", if needed
if (dpc->pos->start_step_opening == 0 &&
dpc->pos->start_step_closing == 0)
{
dpc->pos->start_step_closing = dpc->pos->start_step;
}
- /* fill structure for door part draw order (sorted below) */
+ // fill structure for door part draw order (sorted below)
dpo->nr = i;
dpo->sort_priority = dpc->pos->sort_priority;
}
- /* sort door part controls according to sort_priority and graphic number */
+ // sort door part controls according to sort_priority and graphic number
qsort(door_part_order, MAX_DOOR_PARTS,
sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo);
}
return MoveDoor(door_state);
}
-unsigned int GetDoorState()
+unsigned int GetDoorState(void)
{
return MoveDoor(DOOR_GET_STATE);
}
return MoveDoor(door_state | DOOR_SET_STATE);
}
-int euclid(int a, int b)
+static int euclid(int a, int b)
{
return (b ? euclid(b, a % b) : a);
}
{ DX, DY, DXSIZE, DYSIZE },
{ VX, VY, VXSIZE, VYSIZE }
};
- static int door1 = DOOR_OPEN_1;
+ static int door1 = DOOR_CLOSE_1;
static int door2 = DOOR_CLOSE_2;
- unsigned int door_delay = 0;
- unsigned int door_delay_value;
+ DelayCounter door_delay = { 0 };
int i;
if (door_state == DOOR_GET_STATE)
door_state &= ~DOOR_CLOSE_ALL;
}
- if (game_status == GAME_MODE_EDITOR)
+ if (game_status == GAME_MODE_EDITOR && !(door_state & DOOR_FORCE_ANIM))
door_state |= DOOR_NO_DELAY;
if (door_state & DOOR_ACTION)
{
+ boolean game_ended = (game_status == GAME_MODE_PLAYING && checkGameEnded());
boolean door_panel_drawn[NUM_DOORS];
boolean panel_has_doors[NUM_DOORS];
boolean door_part_skip[MAX_DOOR_PARTS];
int num_move_steps = 0; // number of animation steps for all doors
int max_move_delay_doors_only = 0; // delay for doors only (no panel)
int num_move_steps_doors_only = 0; // steps for doors only (no panel)
- int current_move_delay = 0;
int start = 0;
int k;
num_move_steps = max_move_delay / max_step_delay;
num_move_steps_doors_only = max_move_delay_doors_only / max_step_delay;
- door_delay_value = max_step_delay;
+ door_delay.value = max_step_delay;
if ((door_state & DOOR_NO_DELAY) || setup.quick_doors)
{
}
else
{
- /* opening door sound has priority over simultaneously closing door */
+ // opening door sound has priority over simultaneously closing door
if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
+ {
PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
+
+ if (door_state & DOOR_OPEN_1)
+ PlayMenuSoundStereo(SND_DOOR_1_OPENING, SOUND_MIDDLE);
+ if (door_state & DOOR_OPEN_2)
+ PlayMenuSoundStereo(SND_DOOR_2_OPENING, SOUND_MIDDLE);
+ }
else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
+ {
PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
+
+ if (door_state & DOOR_CLOSE_1)
+ PlayMenuSoundStereo(SND_DOOR_1_CLOSING, SOUND_MIDDLE);
+ if (door_state & DOOR_CLOSE_2)
+ PlayMenuSoundStereo(SND_DOOR_2_CLOSING, SOUND_MIDDLE);
+ }
}
for (k = start; k < num_move_steps; k++)
{
int k2_door = (door_opening ? k : num_move_steps_doors_only - k - 1);
int kk_door = MAX(0, k2_door);
- int sync_frame = kk_door * door_delay_value;
+ int sync_frame = kk_door * door_delay.value;
int frame = getGraphicAnimationFrame(dpc->graphic, sync_frame);
- getGraphicSource(dpc->graphic, frame, &bitmap, &g_src_x, &g_src_y);
+ getFixedGraphicSource(dpc->graphic, frame, &bitmap,
+ &g_src_x, &g_src_y);
}
// draw door panel
if (width > door_rect->width)
width = door_rect->width;
- // printf("::: k == %d [%d] \n", k, start_step);
+ // Debug("tools:MoveDoor", "k == %d [%d]", k, start_step);
}
if (pos->step_yoffset < 0) // door part on bottom side
if (!(door_state & DOOR_NO_DELAY))
{
- BackToFront();
+ if (game_ended)
+ HandleGameActions();
- if (game_status == GAME_MODE_MAIN)
- DoAnimation();
+ BackToFront();
- SkipUntilDelayReached(&door_delay, door_delay_value, &k, last_frame);
+ SkipUntilDelayReached(&door_delay, &k, last_frame);
- current_move_delay += max_step_delay;
+ // prevent OS (Windows) from complaining about program not responding
+ CheckQuitEvent();
}
if (door_part_done_all)
break;
}
+
+ if (!(door_state & DOOR_NO_DELAY))
+ {
+ // wait for specified door action post delay
+ if (door_state & DOOR_ACTION_1 && door_state & DOOR_ACTION_2)
+ door_delay.value = MAX(door_1.post_delay, door_2.post_delay);
+ else if (door_state & DOOR_ACTION_1)
+ door_delay.value = door_1.post_delay;
+ else if (door_state & DOOR_ACTION_2)
+ door_delay.value = door_2.post_delay;
+
+ while (!DelayReached(&door_delay))
+ {
+ if (game_ended)
+ HandleGameActions();
+
+ BackToFront();
+ }
+ }
}
if (door_state & DOOR_ACTION_1)
if (door_state & DOOR_ACTION_2)
door2 = door_state & DOOR_ACTION_2;
+ // draw masked border over door area
+ DrawMaskedBorder(REDRAW_DOOR_1);
+ DrawMaskedBorder(REDRAW_DOOR_2);
+
+ ClearAutoRepeatKeyEvents();
+
return (door1 | door2);
}
-static boolean useSpecialEditorDoor()
+static boolean useSpecialEditorDoor(void)
{
int graphic = IMG_GLOBAL_BORDER_EDITOR;
boolean redefined = getImageListEntryFromImageID(graphic)->redefined;
return TRUE;
}
-void DrawSpecialEditorDoor()
+void DrawSpecialEditorDoor(void)
{
struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
int top_border_width = gfx1->width;
if (!useSpecialEditorDoor())
return;
- /* draw bigger level editor toolbox window */
+ // draw bigger level editor toolbox window
BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
top_border_width, top_border_height, ex, ey - top_border_height);
BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
redraw_mask |= REDRAW_ALL;
}
-void UndrawSpecialEditorDoor()
+void UndrawSpecialEditorDoor(void)
{
struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
int top_border_width = gfx1->width;
if (!useSpecialEditorDoor())
return;
- /* draw normal tape recorder window */
+ // draw normal tape recorder window
if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
{
BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
}
-/* ---------- new tool button stuff ---------------------------------------- */
+// ---------- new tool button stuff -------------------------------------------
static struct
{
int graphic;
struct TextPosInfo *pos;
int gadget_id;
+ boolean is_touch_button;
char *infotext;
} toolbutton_info[NUM_TOOL_BUTTONS] =
{
{
- IMG_REQUEST_BUTTON_GFX_YES, &request.button.yes,
- TOOL_CTRL_ID_YES, "yes"
+ IMG_GFX_REQUEST_BUTTON_YES, &request.button.yes,
+ TOOL_CTRL_ID_YES, FALSE, "yes"
+ },
+ {
+ IMG_GFX_REQUEST_BUTTON_NO, &request.button.no,
+ TOOL_CTRL_ID_NO, FALSE, "no"
+ },
+ {
+ IMG_GFX_REQUEST_BUTTON_CONFIRM, &request.button.confirm,
+ TOOL_CTRL_ID_CONFIRM, FALSE, "confirm"
+ },
+ {
+ IMG_GFX_REQUEST_BUTTON_PLAYER_1, &request.button.player_1,
+ TOOL_CTRL_ID_PLAYER_1, FALSE, "player 1"
},
{
- IMG_REQUEST_BUTTON_GFX_NO, &request.button.no,
- TOOL_CTRL_ID_NO, "no"
+ IMG_GFX_REQUEST_BUTTON_PLAYER_2, &request.button.player_2,
+ TOOL_CTRL_ID_PLAYER_2, FALSE, "player 2"
},
{
- IMG_REQUEST_BUTTON_GFX_CONFIRM, &request.button.confirm,
- TOOL_CTRL_ID_CONFIRM, "confirm"
+ IMG_GFX_REQUEST_BUTTON_PLAYER_3, &request.button.player_3,
+ TOOL_CTRL_ID_PLAYER_3, FALSE, "player 3"
},
{
- IMG_REQUEST_BUTTON_GFX_PLAYER_1, &request.button.player_1,
- TOOL_CTRL_ID_PLAYER_1, "player 1"
+ IMG_GFX_REQUEST_BUTTON_PLAYER_4, &request.button.player_4,
+ TOOL_CTRL_ID_PLAYER_4, FALSE, "player 4"
},
{
- IMG_REQUEST_BUTTON_GFX_PLAYER_2, &request.button.player_2,
- TOOL_CTRL_ID_PLAYER_2, "player 2"
+ IMG_GFX_REQUEST_BUTTON_TOUCH_YES, &request.button.touch_yes,
+ TOOL_CTRL_ID_TOUCH_YES, TRUE, "yes"
},
{
- IMG_REQUEST_BUTTON_GFX_PLAYER_3, &request.button.player_3,
- TOOL_CTRL_ID_PLAYER_3, "player 3"
+ IMG_GFX_REQUEST_BUTTON_TOUCH_NO, &request.button.touch_no,
+ TOOL_CTRL_ID_TOUCH_NO, TRUE, "no"
},
{
- IMG_REQUEST_BUTTON_GFX_PLAYER_4, &request.button.player_4,
- TOOL_CTRL_ID_PLAYER_4, "player 4"
+ IMG_GFX_REQUEST_BUTTON_TOUCH_CONFIRM, &request.button.touch_confirm,
+ TOOL_CTRL_ID_TOUCH_CONFIRM, TRUE, "confirm"
}
};
-void CreateToolButtons()
+void CreateToolButtons(void)
{
int i;
for (i = 0; i < NUM_TOOL_BUTTONS; i++)
{
- struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
+ int graphic = toolbutton_info[i].graphic;
+ struct GraphicInfo *gfx = &graphic_info[graphic];
struct TextPosInfo *pos = toolbutton_info[i].pos;
struct GadgetInfo *gi;
Bitmap *deco_bitmap = None;
int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
unsigned int event_mask = GD_EVENT_RELEASED;
- int dx = DX;
- int dy = DY;
+ boolean is_touch_button = toolbutton_info[i].is_touch_button;
+ int base_x = (is_touch_button ? 0 : DX);
+ int base_y = (is_touch_button ? 0 : DY);
int gd_x = gfx->src_x;
int gd_y = gfx->src_y;
int gd_xp = gfx->src_x + gfx->pressed_xoffset;
int gd_yp = gfx->src_y + gfx->pressed_yoffset;
+ int x = pos->x;
+ int y = pos->y;
int id = i;
- if (global.use_envelope_request)
- setRequestPosition(&dx, &dy, TRUE);
+ // do not use touch buttons if overlay touch buttons are disabled
+ if (is_touch_button && !setup.touch.overlay_buttons)
+ continue;
+
+ if (global.use_envelope_request && !is_touch_button)
+ {
+ setRequestPosition(&base_x, &base_y, TRUE);
+
+ // check if request buttons are outside of envelope and fix, if needed
+ if (x < 0 || x + gfx->width > request.width ||
+ y < 0 || y + gfx->height > request.height)
+ {
+ if (id == TOOL_CTRL_ID_YES)
+ {
+ x = 0;
+ y = request.height - 2 * request.border_size - gfx->height;
+ }
+ else if (id == TOOL_CTRL_ID_NO)
+ {
+ x = request.width - 2 * request.border_size - gfx->width;
+ y = request.height - 2 * request.border_size - gfx->height;
+ }
+ else if (id == TOOL_CTRL_ID_CONFIRM)
+ {
+ x = (request.width - 2 * request.border_size - gfx->width) / 2;
+ y = request.height - 2 * request.border_size - gfx->height;
+ }
+ else if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
+ {
+ int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
+
+ x = (request.width - 2 * request.border_size - gfx->width) / 2;
+ y = request.height - 2 * request.border_size - gfx->height * 2;
+
+ x += (player_nr == 3 ? -1 : player_nr == 1 ? +1 : 0) * gfx->width;
+ y += (player_nr == 0 ? -1 : player_nr == 2 ? +1 : 0) * gfx->height;
+ }
+ }
+ }
- if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
+ if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4 &&
+ pos->draw_player)
{
int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
}
gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_IMAGE_ID, graphic,
GDI_INFO_TEXT, toolbutton_info[i].infotext,
- GDI_X, dx + GDI_ACTIVE_POS(pos->x),
- GDI_Y, dy + GDI_ACTIVE_POS(pos->y),
+ GDI_X, base_x + x,
+ GDI_Y, base_y + y,
GDI_WIDTH, gfx->width,
GDI_HEIGHT, gfx->height,
GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
GDI_DECORATION_SIZE, pos->size, pos->size,
GDI_DECORATION_SHIFTING, 1, 1,
GDI_DIRECT_DRAW, FALSE,
+ GDI_OVERLAY_TOUCH_BUTTON, is_touch_button,
GDI_EVENT_MASK, event_mask,
GDI_CALLBACK_ACTION, HandleToolButtons,
GDI_END);
if (gi == NULL)
- Error(ERR_EXIT, "cannot create gadget");
+ Fail("cannot create gadget");
tool_gadget[id] = gi;
}
}
-void FreeToolButtons()
+void FreeToolButtons(void)
{
int i;
FreeGadget(tool_gadget[i]);
}
-static void UnmapToolButtons()
+static void MapToolButtons(unsigned int req_state)
+{
+ if (req_state & REQ_ASK)
+ {
+ MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
+ MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
+ MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_YES]);
+ MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_NO]);
+ }
+ else if (req_state & REQ_CONFIRM)
+ {
+ MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
+ MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_CONFIRM]);
+ }
+ else if (req_state & REQ_PLAYER)
+ {
+ MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
+ MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
+ MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
+ MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
+ }
+}
+
+static void UnmapToolButtons(void)
{
int i;
request_gadget_id = gi->custom_id;
}
-static struct Mapping_EM_to_RND_object
+static struct Mapping_BD_to_RND_object
{
- int element_em;
- boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
- boolean is_backside; /* backside of moving element */
+ int element_bd;
+ boolean is_rnd_to_bd_mapping; // unique mapping BD <-> RND
int element_rnd;
int action;
int direction;
}
-em_object_mapping_list[] =
+bd_object_mapping_list[] =
{
+ // additional RND style elements mapped to BD style elements must be listed first
+
{
- Xblank, TRUE, FALSE,
- EL_EMPTY, -1, -1
+ O_DIRT, TRUE,
+ EL_SAND, -1, -1
},
{
- Yacid_splash_eB, FALSE, FALSE,
- EL_ACID_SPLASH_RIGHT, -1, -1
+ O_STONE, TRUE,
+ EL_BD_ROCK, -1, -1
},
{
- Yacid_splash_wB, FALSE, FALSE,
- EL_ACID_SPLASH_LEFT, -1, -1
+ O_BRICK, TRUE,
+ EL_BD_WALL, -1, -1
},
-
-#ifdef EM_ENGINE_BAD_ROLL
{
- Xstone_force_e, FALSE, FALSE,
- EL_ROCK, -1, MV_BIT_RIGHT
+ O_STEEL, TRUE,
+ EL_STEELWALL, -1, -1
},
{
- Xstone_force_w, FALSE, FALSE,
- EL_ROCK, -1, MV_BIT_LEFT
+ O_DIAMOND, TRUE,
+ EL_BD_DIAMOND, -1, -1
},
{
- Xnut_force_e, FALSE, FALSE,
- EL_NUT, -1, MV_BIT_RIGHT
+ O_INBOX, TRUE,
+ EL_PLAYER_1, -1, -1
},
{
- Xnut_force_w, FALSE, FALSE,
- EL_NUT, -1, MV_BIT_LEFT
+ O_INBOX, TRUE,
+ EL_PLAYER_2, -1, -1
},
{
- Xspring_force_e, FALSE, FALSE,
- EL_SPRING, -1, MV_BIT_RIGHT
+ O_INBOX, TRUE,
+ EL_PLAYER_3, -1, -1
},
{
- Xspring_force_w, FALSE, FALSE,
- EL_SPRING, -1, MV_BIT_LEFT
+ O_INBOX, TRUE,
+ EL_PLAYER_4, -1, -1
},
{
- Xemerald_force_e, FALSE, FALSE,
- EL_EMERALD, -1, MV_BIT_RIGHT
+ O_PRE_OUTBOX, TRUE,
+ EL_EXIT_CLOSED, -1, -1
},
+
+ // BD style elements with their corresponding RND style elements
+
{
- Xemerald_force_w, FALSE, FALSE,
- EL_EMERALD, -1, MV_BIT_LEFT
+ O_SPACE, TRUE,
+ EL_EMPTY, -1, -1
},
{
- Xdiamond_force_e, FALSE, FALSE,
- EL_DIAMOND, -1, MV_BIT_RIGHT
+ O_DIRT, TRUE,
+ EL_BD_SAND, -1, -1
},
{
- Xdiamond_force_w, FALSE, FALSE,
- EL_DIAMOND, -1, MV_BIT_LEFT
+ O_DIRT_SLOPED_UP_RIGHT, TRUE,
+ EL_BD_SAND_SLOPED_UP_RIGHT, -1, -1
},
{
- Xbomb_force_e, FALSE, FALSE,
- EL_BOMB, -1, MV_BIT_RIGHT
+ O_DIRT_SLOPED_UP_LEFT, TRUE,
+ EL_BD_SAND_SLOPED_UP_LEFT, -1, -1
},
{
- Xbomb_force_w, FALSE, FALSE,
- EL_BOMB, -1, MV_BIT_LEFT
+ O_DIRT_SLOPED_DOWN_LEFT, TRUE,
+ EL_BD_SAND_SLOPED_DOWN_LEFT, -1, -1
},
-#endif /* EM_ENGINE_BAD_ROLL */
-
{
- Xstone, TRUE, FALSE,
- EL_ROCK, -1, -1
+ O_DIRT_SLOPED_DOWN_RIGHT, TRUE,
+ EL_BD_SAND_SLOPED_DOWN_RIGHT, -1, -1
},
{
- Xstone_pause, FALSE, FALSE,
- EL_ROCK, -1, -1
+ O_DIRT_BALL, TRUE,
+ EL_BD_SAND_BALL, -1, -1
},
{
- Xstone_fall, FALSE, FALSE,
- EL_ROCK, -1, -1
+ O_DIRT_BALL_F, FALSE,
+ EL_BD_SAND_BALL, ACTION_FALLING, -1
},
{
- Ystone_s, FALSE, FALSE,
- EL_ROCK, ACTION_FALLING, -1
+ O_DIRT_LOOSE, TRUE,
+ EL_BD_SAND_LOOSE, -1, -1
},
{
- Ystone_sB, FALSE, TRUE,
- EL_ROCK, ACTION_FALLING, -1
+ O_DIRT_LOOSE_F, FALSE,
+ EL_BD_SAND_LOOSE, ACTION_FALLING, -1
},
{
- Ystone_e, FALSE, FALSE,
- EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
+ O_DIRT2, TRUE,
+ EL_BD_SAND_2, -1, -1
},
{
- Ystone_eB, FALSE, TRUE,
- EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
+ O_BRICK, TRUE,
+ EL_BD_WALL, -1, -1
},
{
- Ystone_w, FALSE, FALSE,
- EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
+ O_BRICK_SLOPED_UP_RIGHT, TRUE,
+ EL_BD_WALL_SLOPED_UP_RIGHT, -1, -1
},
{
- Ystone_wB, FALSE, TRUE,
- EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
+ O_BRICK_SLOPED_UP_LEFT, TRUE,
+ EL_BD_WALL_SLOPED_UP_LEFT, -1, -1
},
{
- Xnut, TRUE, FALSE,
- EL_NUT, -1, -1
+ O_BRICK_SLOPED_DOWN_LEFT, TRUE,
+ EL_BD_WALL_SLOPED_DOWN_LEFT, -1, -1
},
{
- Xnut_pause, FALSE, FALSE,
- EL_NUT, -1, -1
+ O_BRICK_SLOPED_DOWN_RIGHT, TRUE,
+ EL_BD_WALL_SLOPED_DOWN_RIGHT, -1, -1
},
{
- Xnut_fall, FALSE, FALSE,
- EL_NUT, -1, -1
+ O_BRICK_NON_SLOPED, TRUE,
+ EL_BD_WALL_NON_SLOPED, -1, -1
},
{
- Ynut_s, FALSE, FALSE,
- EL_NUT, ACTION_FALLING, -1
+ O_MAGIC_WALL, TRUE,
+ EL_BD_MAGIC_WALL, ACTION_ACTIVE, -1
},
{
- Ynut_sB, FALSE, TRUE,
- EL_NUT, ACTION_FALLING, -1
+ O_PRE_OUTBOX, TRUE,
+ EL_BD_EXIT_CLOSED, -1, -1
},
{
- Ynut_e, FALSE, FALSE,
- EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
+ O_OUTBOX, TRUE,
+ EL_BD_EXIT_OPEN, -1, -1
},
{
- Ynut_eB, FALSE, TRUE,
- EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
+ O_PRE_INVIS_OUTBOX, TRUE,
+ EL_BD_INVISIBLE_EXIT_CLOSED, -1, -1
},
{
- Ynut_w, FALSE, FALSE,
- EL_NUT, ACTION_MOVING, MV_BIT_LEFT
+ O_INVIS_OUTBOX, TRUE,
+ EL_BD_INVISIBLE_EXIT_OPEN, -1, -1
},
{
- Ynut_wB, FALSE, TRUE,
- EL_NUT, ACTION_MOVING, MV_BIT_LEFT
+ O_STEEL, TRUE,
+ EL_BD_STEELWALL, -1, -1
},
{
- Xbug_n, TRUE, FALSE,
- EL_BUG_UP, -1, -1
+ O_STEEL_SLOPED_UP_RIGHT, TRUE,
+ EL_BD_STEELWALL_SLOPED_UP_RIGHT, -1, -1
},
{
- Xbug_e, TRUE, FALSE,
- EL_BUG_RIGHT, -1, -1
+ O_STEEL_SLOPED_UP_LEFT, TRUE,
+ EL_BD_STEELWALL_SLOPED_UP_LEFT, -1, -1
},
{
- Xbug_s, TRUE, FALSE,
- EL_BUG_DOWN, -1, -1
+ O_STEEL_SLOPED_DOWN_LEFT, TRUE,
+ EL_BD_STEELWALL_SLOPED_DOWN_LEFT, -1, -1
},
{
- Xbug_w, TRUE, FALSE,
- EL_BUG_LEFT, -1, -1
+ O_STEEL_SLOPED_DOWN_RIGHT, TRUE,
+ EL_BD_STEELWALL_SLOPED_DOWN_RIGHT, -1, -1
},
{
- Xbug_gon, FALSE, FALSE,
- EL_BUG_UP, -1, -1
+ O_STEEL_EXPLODABLE, TRUE,
+ EL_BD_STEELWALL_EXPLODABLE, -1, -1
},
{
- Xbug_goe, FALSE, FALSE,
- EL_BUG_RIGHT, -1, -1
+ O_STEEL_EATABLE, TRUE,
+ EL_BD_STEELWALL_DIGGABLE, -1, -1
},
{
- Xbug_gos, FALSE, FALSE,
- EL_BUG_DOWN, -1, -1
+ O_BRICK_EATABLE, TRUE,
+ EL_BD_WALL_DIGGABLE, -1, -1
},
{
- Xbug_gow, FALSE, FALSE,
- EL_BUG_LEFT, -1, -1
+ O_STONE, TRUE,
+ EL_BD_ROCK, -1, -1
},
{
- Ybug_n, FALSE, FALSE,
- EL_BUG, ACTION_MOVING, MV_BIT_UP
+ O_STONE_F, FALSE,
+ EL_BD_ROCK, ACTION_FALLING, -1
},
{
- Ybug_nB, FALSE, TRUE,
- EL_BUG, ACTION_MOVING, MV_BIT_UP
+ O_FLYING_STONE, TRUE,
+ EL_BD_FLYING_ROCK, -1, -1
},
{
- Ybug_e, FALSE, FALSE,
- EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
+ O_FLYING_STONE_F, FALSE,
+ EL_BD_FLYING_ROCK, ACTION_FALLING, -1
},
{
- Ybug_eB, FALSE, TRUE,
- EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
+ O_MEGA_STONE, TRUE,
+ EL_BD_MEGA_ROCK, -1, -1
},
{
- Ybug_s, FALSE, FALSE,
- EL_BUG, ACTION_MOVING, MV_BIT_DOWN
+ O_MEGA_STONE_F, FALSE,
+ EL_BD_MEGA_ROCK, ACTION_FALLING, -1
},
{
- Ybug_sB, FALSE, TRUE,
- EL_BUG, ACTION_MOVING, MV_BIT_DOWN
+ O_DIAMOND, TRUE,
+ EL_BD_DIAMOND, -1, -1
},
{
- Ybug_w, FALSE, FALSE,
- EL_BUG, ACTION_MOVING, MV_BIT_LEFT
+ O_DIAMOND_F, FALSE,
+ EL_BD_DIAMOND, ACTION_FALLING, -1
},
{
- Ybug_wB, FALSE, TRUE,
- EL_BUG, ACTION_MOVING, MV_BIT_LEFT
+ O_FLYING_DIAMOND, TRUE,
+ EL_BD_FLYING_DIAMOND, -1, -1
},
{
- Ybug_w_n, FALSE, FALSE,
- EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
+ O_FLYING_DIAMOND_F, FALSE,
+ EL_BD_FLYING_DIAMOND, ACTION_FALLING, -1
},
{
- Ybug_n_e, FALSE, FALSE,
- EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
+ O_NUT, TRUE,
+ EL_BD_NUT, -1, -1
},
{
- Ybug_e_s, FALSE, FALSE,
- EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
+ O_NUT_F, FALSE,
+ EL_BD_NUT, ACTION_FALLING, -1
},
{
- Ybug_s_w, FALSE, FALSE,
- EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
+ O_BLADDER_SPENDER, TRUE,
+ EL_BD_BLADDER_SPENDER, -1, -1
},
{
- Ybug_e_n, FALSE, FALSE,
- EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
+ O_INBOX, TRUE,
+ EL_BD_INBOX, -1, -1
},
{
- Ybug_s_e, FALSE, FALSE,
- EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
+ O_H_EXPANDING_WALL, TRUE,
+ EL_BD_EXPANDABLE_WALL_HORIZONTAL, -1, -1
},
{
- Ybug_w_s, FALSE, FALSE,
- EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
+ O_V_EXPANDING_WALL, TRUE,
+ EL_BD_EXPANDABLE_WALL_VERTICAL, -1, -1
},
{
- Ybug_n_w, FALSE, FALSE,
- EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
+ O_EXPANDING_WALL, TRUE,
+ EL_BD_EXPANDABLE_WALL_ANY, -1, -1
},
{
- Ybug_stone, FALSE, FALSE,
- EL_BUG, ACTION_SMASHED_BY_ROCK, -1
+ O_H_EXPANDING_STEEL_WALL, TRUE,
+ EL_BD_EXPANDABLE_STEELWALL_HORIZONTAL, -1, -1
},
{
- Ybug_spring, FALSE, FALSE,
- EL_BUG, ACTION_SMASHED_BY_SPRING, -1
+ O_V_EXPANDING_STEEL_WALL, TRUE,
+ EL_BD_EXPANDABLE_STEELWALL_VERTICAL, -1, -1
},
{
- Xtank_n, TRUE, FALSE,
- EL_SPACESHIP_UP, -1, -1
+ O_EXPANDING_STEEL_WALL, TRUE,
+ EL_BD_EXPANDABLE_STEELWALL_ANY, -1, -1
},
{
- Xtank_e, TRUE, FALSE,
- EL_SPACESHIP_RIGHT, -1, -1
+ O_EXPANDING_WALL_SWITCH, TRUE,
+ EL_BD_EXPANDABLE_WALL_SWITCH_HORIZONTAL, -1, -1
},
{
- Xtank_s, TRUE, FALSE,
- EL_SPACESHIP_DOWN, -1, -1
+ O_CREATURE_SWITCH, TRUE,
+ EL_BD_CREATURE_SWITCH, -1, -1
},
{
- Xtank_w, TRUE, FALSE,
- EL_SPACESHIP_LEFT, -1, -1
+ O_BITER_SWITCH, TRUE,
+ EL_BD_BITER_SWITCH_1, -1, -1
},
{
- Xtank_gon, FALSE, FALSE,
- EL_SPACESHIP_UP, -1, -1
+ O_REPLICATOR_SWITCH, TRUE,
+ EL_BD_REPLICATOR_SWITCH, -1, -1
},
{
- Xtank_goe, FALSE, FALSE,
- EL_SPACESHIP_RIGHT, -1, -1
+ O_CONVEYOR_SWITCH, TRUE,
+ EL_BD_CONVEYOR_SWITCH, -1, -1
},
{
- Xtank_gos, FALSE, FALSE,
- EL_SPACESHIP_DOWN, -1, -1
+ O_CONVEYOR_DIR_SWITCH, TRUE,
+ EL_BD_CONVEYOR_DIR_SWITCH_RIGHT, -1, -1
},
{
- Xtank_gow, FALSE, FALSE,
- EL_SPACESHIP_LEFT, -1, -1
+ O_ACID, TRUE,
+ EL_BD_ACID, -1, -1
},
{
- Ytank_n, FALSE, FALSE,
- EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
+ O_FALLING_WALL, TRUE,
+ EL_BD_FALLING_WALL, -1, -1
},
{
- Ytank_nB, FALSE, TRUE,
- EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
+ O_FALLING_WALL_F, FALSE,
+ EL_BD_FALLING_WALL, ACTION_FALLING, -1
},
{
- Ytank_e, FALSE, FALSE,
- EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
+ O_BOX, TRUE,
+ EL_BD_BOX, -1, -1
},
{
- Ytank_eB, FALSE, TRUE,
- EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
+ O_TIME_PENALTY, TRUE,
+ EL_BD_TIME_PENALTY, -1, -1
},
{
- Ytank_s, FALSE, FALSE,
- EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
+ O_GRAVESTONE, TRUE,
+ EL_BD_GRAVESTONE, -1, -1
},
{
- Ytank_sB, FALSE, TRUE,
- EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
+ O_STONE_GLUED, TRUE,
+ EL_BD_ROCK_GLUED, -1, -1
},
{
- Ytank_w, FALSE, FALSE,
- EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
+ O_DIAMOND_GLUED, TRUE,
+ EL_BD_DIAMOND_GLUED, -1, -1
},
{
- Ytank_wB, FALSE, TRUE,
- EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
+ O_DIAMOND_KEY, TRUE,
+ EL_BD_DIAMOND_KEY, -1, -1
},
{
- Ytank_w_n, FALSE, FALSE,
- EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
+ O_TRAPPED_DIAMOND, TRUE,
+ EL_BD_TRAPPED_DIAMOND, -1, -1
},
{
- Ytank_n_e, FALSE, FALSE,
- EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
+ O_CLOCK, TRUE,
+ EL_BD_CLOCK, -1, -1
},
{
- Ytank_e_s, FALSE, FALSE,
- EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
+ O_DIRT_GLUED, TRUE,
+ EL_BD_SAND_GLUED, -1, -1
},
{
- Ytank_s_w, FALSE, FALSE,
- EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
+ O_KEY_1, TRUE,
+ EL_BD_KEY_1, -1, -1
},
{
- Ytank_e_n, FALSE, FALSE,
- EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
+ O_KEY_2, TRUE,
+ EL_BD_KEY_2, -1, -1
},
{
- Ytank_s_e, FALSE, FALSE,
- EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
+ O_KEY_3, TRUE,
+ EL_BD_KEY_3, -1, -1
},
{
- Ytank_w_s, FALSE, FALSE,
- EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
+ O_DOOR_1, TRUE,
+ EL_BD_GATE_1, -1, -1
},
{
- Ytank_n_w, FALSE, FALSE,
- EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
+ O_DOOR_2, TRUE,
+ EL_BD_GATE_2, -1, -1
},
{
- Ytank_stone, FALSE, FALSE,
- EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
+ O_DOOR_3, TRUE,
+ EL_BD_GATE_3, -1, -1
},
{
- Ytank_spring, FALSE, FALSE,
- EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
+ O_POT, TRUE,
+ EL_BD_POT, -1, -1
},
{
- Xandroid, TRUE, FALSE,
- EL_EMC_ANDROID, ACTION_ACTIVE, -1
+ O_GRAVITY_SWITCH, TRUE,
+ EL_BD_GRAVITY_SWITCH, -1, -1
},
{
- Xandroid_1_n, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
+ O_PNEUMATIC_HAMMER, TRUE,
+ EL_BD_PNEUMATIC_HAMMER, -1, -1
},
{
- Xandroid_2_n, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
+ O_TELEPORTER, TRUE,
+ EL_BD_TELEPORTER, -1, -1
},
{
- Xandroid_1_e, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
+ O_SKELETON, TRUE,
+ EL_BD_SKELETON, -1, -1
},
{
- Xandroid_2_e, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
+ O_WATER, TRUE,
+ EL_BD_WATER, -1, -1
},
{
- Xandroid_1_w, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
+ O_WATER_1, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Xandroid_2_w, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
+ O_WATER_2, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Xandroid_1_s, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
+ O_WATER_3, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Xandroid_2_s, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
+ O_WATER_4, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Yandroid_n, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
+ O_WATER_5, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Yandroid_nB, FALSE, TRUE,
- EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
+ O_WATER_6, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Yandroid_ne, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
+ O_WATER_7, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Yandroid_neB, FALSE, TRUE,
- EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
+ O_WATER_8, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Yandroid_e, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
+ O_WATER_9, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Yandroid_eB, FALSE, TRUE,
- EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
+ O_WATER_10, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Yandroid_se, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
+ O_WATER_11, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Yandroid_seB, FALSE, TRUE,
- EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
+ O_WATER_12, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Yandroid_s, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
+ O_WATER_13, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Yandroid_sB, FALSE, TRUE,
- EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
+ O_WATER_14, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Yandroid_sw, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
+ O_WATER_15, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Yandroid_swB, FALSE, TRUE,
- EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
+ O_WATER_16, FALSE,
+ EL_BD_WATER, -1, -1
},
{
- Yandroid_w, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
+ O_COW_1, TRUE,
+ EL_BD_COW_LEFT, -1, -1
},
{
- Yandroid_wB, FALSE, TRUE,
- EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
+ O_COW_2, TRUE,
+ EL_BD_COW_UP, -1, -1
},
{
- Yandroid_nw, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
+ O_COW_3, TRUE,
+ EL_BD_COW_RIGHT, -1, -1
},
{
- Yandroid_nwB, FALSE, TRUE,
- EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
+ O_COW_4, TRUE,
+ EL_BD_COW_DOWN, -1, -1
},
{
- Xspring, TRUE, FALSE,
- EL_SPRING, -1, -1
+ O_COW_ENCLOSED_1, FALSE,
+ EL_BD_COW_DOWN, -1, -1
},
{
- Xspring_pause, FALSE, FALSE,
- EL_SPRING, -1, -1
+ O_COW_ENCLOSED_2, FALSE,
+ EL_BD_COW_DOWN, -1, -1
},
{
- Xspring_e, FALSE, FALSE,
- EL_SPRING, -1, -1
+ O_COW_ENCLOSED_3, FALSE,
+ EL_BD_COW_DOWN, -1, -1
},
{
- Xspring_w, FALSE, FALSE,
- EL_SPRING, -1, -1
+ O_COW_ENCLOSED_4, FALSE,
+ EL_BD_COW_DOWN, -1, -1
},
{
- Xspring_fall, FALSE, FALSE,
- EL_SPRING, -1, -1
+ O_COW_ENCLOSED_5, FALSE,
+ EL_BD_COW_DOWN, -1, -1
},
{
- Yspring_s, FALSE, FALSE,
- EL_SPRING, ACTION_FALLING, -1
+ O_COW_ENCLOSED_6, FALSE,
+ EL_BD_COW_DOWN, -1, -1
},
{
- Yspring_sB, FALSE, TRUE,
- EL_SPRING, ACTION_FALLING, -1
+ O_COW_ENCLOSED_7, FALSE,
+ EL_BD_COW_DOWN, -1, -1
},
{
- Yspring_e, FALSE, FALSE,
- EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
+ O_WALLED_DIAMOND, TRUE,
+ EL_BD_WALL_DIAMOND, -1, -1
},
{
- Yspring_eB, FALSE, TRUE,
- EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
+ O_WALLED_KEY_1, TRUE,
+ EL_BD_WALL_KEY_1, -1, -1
},
{
- Yspring_w, FALSE, FALSE,
- EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
+ O_WALLED_KEY_2, TRUE,
+ EL_BD_WALL_KEY_2, -1, -1
},
{
- Yspring_wB, FALSE, TRUE,
- EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
+ O_WALLED_KEY_3, TRUE,
+ EL_BD_WALL_KEY_3, -1, -1
},
{
- Yspring_kill_e, FALSE, FALSE,
- EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
+ O_AMOEBA, TRUE,
+ EL_BD_AMOEBA, -1, -1
},
{
- Yspring_kill_eB, FALSE, TRUE,
- EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
+ O_AMOEBA_2, TRUE,
+ EL_BD_AMOEBA_2, -1, -1
},
{
- Yspring_kill_w, FALSE, FALSE,
- EL_SPRING, ACTION_EATING, MV_BIT_LEFT
+ O_REPLICATOR, TRUE,
+ EL_BD_REPLICATOR, -1, -1
},
{
- Yspring_kill_wB, FALSE, TRUE,
- EL_SPRING, ACTION_EATING, MV_BIT_LEFT
+ O_CONVEYOR_LEFT, TRUE,
+ EL_BD_CONVEYOR_LEFT, -1, -1
},
{
- Xeater_n, TRUE, FALSE,
- EL_YAMYAM_UP, -1, -1
+ O_CONVEYOR_RIGHT, TRUE,
+ EL_BD_CONVEYOR_RIGHT, -1, -1
},
{
- Xeater_e, TRUE, FALSE,
- EL_YAMYAM_RIGHT, -1, -1
+ O_LAVA, TRUE,
+ EL_BD_LAVA, -1, -1
},
{
- Xeater_w, TRUE, FALSE,
- EL_YAMYAM_LEFT, -1, -1
+ O_SWEET, TRUE,
+ EL_BD_SWEET, -1, -1
},
{
- Xeater_s, TRUE, FALSE,
- EL_YAMYAM_DOWN, -1, -1
+ O_VOODOO, TRUE,
+ EL_BD_VOODOO_DOLL, -1, -1
},
{
- Yeater_n, FALSE, FALSE,
- EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
+ O_SLIME, TRUE,
+ EL_BD_SLIME, -1, -1
},
{
- Yeater_nB, FALSE, TRUE,
- EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
+ O_BLADDER, TRUE,
+ EL_BD_BLADDER, -1, -1
},
{
- Yeater_e, FALSE, FALSE,
- EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
+ O_BLADDER_1, FALSE,
+ EL_BD_BLADDER, -1, -1
},
{
- Yeater_eB, FALSE, TRUE,
- EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
+ O_BLADDER_2, FALSE,
+ EL_BD_BLADDER, -1, -1
},
{
- Yeater_s, FALSE, FALSE,
- EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
+ O_BLADDER_3, FALSE,
+ EL_BD_BLADDER, -1, -1
},
{
- Yeater_sB, FALSE, TRUE,
- EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
+ O_BLADDER_4, FALSE,
+ EL_BD_BLADDER, -1, -1
},
{
- Yeater_w, FALSE, FALSE,
- EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
+ O_BLADDER_5, FALSE,
+ EL_BD_BLADDER, -1, -1
},
{
- Yeater_wB, FALSE, TRUE,
- EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
+ O_BLADDER_6, FALSE,
+ EL_BD_BLADDER, -1, -1
},
{
- Yeater_stone, FALSE, FALSE,
- EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
+ O_BLADDER_7, FALSE,
+ EL_BD_BLADDER, -1, -1
},
{
- Yeater_spring, FALSE, FALSE,
- EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
+ O_BLADDER_8, FALSE,
+ EL_BD_BLADDER, -1, -1
},
{
- Xalien, TRUE, FALSE,
- EL_ROBOT, -1, -1
+ O_WAITING_STONE, TRUE,
+ EL_BD_WAITING_ROCK, -1, -1
},
{
- Xalien_pause, FALSE, FALSE,
- EL_ROBOT, -1, -1
+ O_CHASING_STONE, TRUE,
+ EL_BD_CHASING_ROCK, -1, -1
},
{
- Yalien_n, FALSE, FALSE,
- EL_ROBOT, ACTION_MOVING, MV_BIT_UP
+ O_GHOST, TRUE,
+ EL_BD_GHOST, -1, -1
},
{
- Yalien_nB, FALSE, TRUE,
- EL_ROBOT, ACTION_MOVING, MV_BIT_UP
+ O_FIREFLY_1, TRUE,
+ EL_BD_FIREFLY_LEFT, -1, -1
},
{
- Yalien_e, FALSE, FALSE,
- EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
+ O_FIREFLY_2, TRUE,
+ EL_BD_FIREFLY_UP, -1, -1
},
{
- Yalien_eB, FALSE, TRUE,
- EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
+ O_FIREFLY_3, TRUE,
+ EL_BD_FIREFLY_RIGHT, -1, -1
},
{
- Yalien_s, FALSE, FALSE,
- EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
+ O_FIREFLY_4, TRUE,
+ EL_BD_FIREFLY_DOWN, -1, -1
},
{
- Yalien_sB, FALSE, TRUE,
- EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
+ O_ALT_FIREFLY_1, TRUE,
+ EL_BD_FIREFLY_2_LEFT, -1, -1
},
{
- Yalien_w, FALSE, FALSE,
- EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
+ O_ALT_FIREFLY_2, TRUE,
+ EL_BD_FIREFLY_2_UP, -1, -1
},
{
- Yalien_wB, FALSE, TRUE,
- EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
+ O_ALT_FIREFLY_3, TRUE,
+ EL_BD_FIREFLY_2_RIGHT, -1, -1
},
{
- Yalien_stone, FALSE, FALSE,
- EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
+ O_ALT_FIREFLY_4, TRUE,
+ EL_BD_FIREFLY_2_DOWN, -1, -1
},
{
- Yalien_spring, FALSE, FALSE,
- EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
+ O_BUTTER_1, TRUE,
+ EL_BD_BUTTERFLY_LEFT, -1, -1
},
{
- Xemerald, TRUE, FALSE,
- EL_EMERALD, -1, -1
+ O_BUTTER_2, TRUE,
+ EL_BD_BUTTERFLY_UP, -1, -1
},
{
- Xemerald_pause, FALSE, FALSE,
- EL_EMERALD, -1, -1
+ O_BUTTER_3, TRUE,
+ EL_BD_BUTTERFLY_RIGHT, -1, -1
},
{
- Xemerald_fall, FALSE, FALSE,
- EL_EMERALD, -1, -1
+ O_BUTTER_4, TRUE,
+ EL_BD_BUTTERFLY_DOWN, -1, -1
},
{
- Xemerald_shine, FALSE, FALSE,
- EL_EMERALD, ACTION_TWINKLING, -1
+ O_ALT_BUTTER_1, TRUE,
+ EL_BD_BUTTERFLY_2_LEFT, -1, -1
},
{
- Yemerald_s, FALSE, FALSE,
- EL_EMERALD, ACTION_FALLING, -1
+ O_ALT_BUTTER_2, TRUE,
+ EL_BD_BUTTERFLY_2_UP, -1, -1
},
{
- Yemerald_sB, FALSE, TRUE,
- EL_EMERALD, ACTION_FALLING, -1
+ O_ALT_BUTTER_3, TRUE,
+ EL_BD_BUTTERFLY_2_RIGHT, -1, -1
},
{
- Yemerald_e, FALSE, FALSE,
- EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
+ O_ALT_BUTTER_4, TRUE,
+ EL_BD_BUTTERFLY_2_DOWN, -1, -1
},
{
- Yemerald_eB, FALSE, TRUE,
- EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
+ O_STONEFLY_1, TRUE,
+ EL_BD_STONEFLY_LEFT, -1, -1
},
{
- Yemerald_w, FALSE, FALSE,
- EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
+ O_STONEFLY_2, TRUE,
+ EL_BD_STONEFLY_UP, -1, -1
},
{
- Yemerald_wB, FALSE, TRUE,
- EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
+ O_STONEFLY_3, TRUE,
+ EL_BD_STONEFLY_RIGHT, -1, -1
},
{
- Yemerald_eat, FALSE, FALSE,
- EL_EMERALD, ACTION_COLLECTING, -1
+ O_STONEFLY_4, TRUE,
+ EL_BD_STONEFLY_DOWN, -1, -1
},
{
- Yemerald_stone, FALSE, FALSE,
- EL_NUT, ACTION_BREAKING, -1
+ O_BITER_1, TRUE,
+ EL_BD_BITER_UP, -1, -1
},
{
- Xdiamond, TRUE, FALSE,
- EL_DIAMOND, -1, -1
+ O_BITER_2, TRUE,
+ EL_BD_BITER_RIGHT, -1, -1
},
{
- Xdiamond_pause, FALSE, FALSE,
- EL_DIAMOND, -1, -1
+ O_BITER_3, TRUE,
+ EL_BD_BITER_DOWN, -1, -1
},
{
- Xdiamond_fall, FALSE, FALSE,
- EL_DIAMOND, -1, -1
+ O_BITER_4, TRUE,
+ EL_BD_BITER_LEFT, -1, -1
},
{
- Xdiamond_shine, FALSE, FALSE,
- EL_DIAMOND, ACTION_TWINKLING, -1
+ O_DRAGONFLY_1, TRUE,
+ EL_BD_DRAGONFLY_LEFT, -1, -1
},
{
- Ydiamond_s, FALSE, FALSE,
- EL_DIAMOND, ACTION_FALLING, -1
+ O_DRAGONFLY_2, TRUE,
+ EL_BD_DRAGONFLY_UP, -1, -1
},
{
- Ydiamond_sB, FALSE, TRUE,
- EL_DIAMOND, ACTION_FALLING, -1
+ O_DRAGONFLY_3, TRUE,
+ EL_BD_DRAGONFLY_RIGHT, -1, -1
},
{
- Ydiamond_e, FALSE, FALSE,
- EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
+ O_DRAGONFLY_4, TRUE,
+ EL_BD_DRAGONFLY_DOWN, -1, -1
},
{
- Ydiamond_eB, FALSE, TRUE,
- EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
+ O_PRE_PL_1, FALSE,
+ EL_BD_PLAYER, ACTION_GROWING, -1
},
{
- Ydiamond_w, FALSE, FALSE,
- EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
+ O_PRE_PL_2, FALSE,
+ EL_BD_PLAYER, ACTION_GROWING, -1
},
{
- Ydiamond_wB, FALSE, TRUE,
- EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
+ O_PRE_PL_3, FALSE,
+ EL_BD_PLAYER, ACTION_GROWING, -1
},
{
- Ydiamond_eat, FALSE, FALSE,
- EL_DIAMOND, ACTION_COLLECTING, -1
+ O_PLAYER, TRUE,
+ EL_BD_PLAYER, -1, -1
},
{
- Ydiamond_stone, FALSE, FALSE,
- EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
+ O_PLAYER_BOMB, TRUE,
+ EL_BD_PLAYER_WITH_BOMB, -1, -1
},
{
- Xdrip_fall, TRUE, FALSE,
- EL_AMOEBA_DROP, -1, -1
+ O_PLAYER_GLUED, TRUE,
+ EL_BD_PLAYER_GLUED, -1, -1
},
{
- Xdrip_stretch, FALSE, FALSE,
- EL_AMOEBA_DROP, ACTION_FALLING, -1
+ O_PLAYER_STIRRING, TRUE,
+ EL_BD_PLAYER_STIRRING, -1, -1
},
{
- Xdrip_stretchB, FALSE, TRUE,
- EL_AMOEBA_DROP, ACTION_FALLING, -1
+ O_BOMB, TRUE,
+ EL_BD_BOMB, -1, -1
},
{
- Xdrip_eat, FALSE, FALSE,
- EL_AMOEBA_DROP, ACTION_GROWING, -1
+ O_BOMB_TICK_1, FALSE,
+ EL_BD_BOMB, ACTION_ACTIVE, -1
},
{
- Ydrip_s1, FALSE, FALSE,
- EL_AMOEBA_DROP, ACTION_FALLING, -1
+ O_BOMB_TICK_2, FALSE,
+ EL_BD_BOMB, ACTION_ACTIVE, -1
},
{
- Ydrip_s1B, FALSE, TRUE,
- EL_AMOEBA_DROP, ACTION_FALLING, -1
+ O_BOMB_TICK_3, FALSE,
+ EL_BD_BOMB, ACTION_ACTIVE, -1
},
{
- Ydrip_s2, FALSE, FALSE,
- EL_AMOEBA_DROP, ACTION_FALLING, -1
+ O_BOMB_TICK_4, FALSE,
+ EL_BD_BOMB, ACTION_ACTIVE, -1
},
{
- Ydrip_s2B, FALSE, TRUE,
- EL_AMOEBA_DROP, ACTION_FALLING, -1
+ O_BOMB_TICK_5, FALSE,
+ EL_BD_BOMB, ACTION_ACTIVE, -1
},
{
- Xbomb, TRUE, FALSE,
- EL_BOMB, -1, -1
+ O_BOMB_TICK_6, FALSE,
+ EL_BD_BOMB, ACTION_ACTIVE, -1
},
{
- Xbomb_pause, FALSE, FALSE,
- EL_BOMB, -1, -1
+ O_BOMB_TICK_7, FALSE,
+ EL_BD_BOMB, ACTION_ACTIVE, -1
},
{
- Xbomb_fall, FALSE, FALSE,
- EL_BOMB, -1, -1
+ O_NITRO_PACK, TRUE,
+ EL_BD_NITRO_PACK, -1, -1
},
{
- Ybomb_s, FALSE, FALSE,
- EL_BOMB, ACTION_FALLING, -1
+ O_NITRO_PACK_F, FALSE,
+ EL_BD_NITRO_PACK, ACTION_FALLING, -1
},
{
- Ybomb_sB, FALSE, TRUE,
- EL_BOMB, ACTION_FALLING, -1
+ O_NITRO_PACK_EXPLODE, FALSE,
+ EL_BD_NITRO_PACK, ACTION_EXPLODING, -1
},
{
- Ybomb_e, FALSE, FALSE,
- EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
+ O_PRE_CLOCK_1, FALSE,
+ EL_BD_CLOCK, ACTION_GROWING, -1
},
{
- Ybomb_eB, FALSE, TRUE,
- EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
+ O_PRE_CLOCK_2, FALSE,
+ EL_BD_CLOCK, ACTION_GROWING, -1
},
{
- Ybomb_w, FALSE, FALSE,
- EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
+ O_PRE_CLOCK_3, FALSE,
+ EL_BD_CLOCK, ACTION_GROWING, -1
},
{
- Ybomb_wB, FALSE, TRUE,
- EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
+ O_PRE_CLOCK_4, FALSE,
+ EL_BD_CLOCK, ACTION_GROWING, -1
},
{
- Ybomb_eat, FALSE, FALSE,
- EL_BOMB, ACTION_ACTIVATING, -1
+ O_PRE_DIA_1, FALSE,
+ EL_BD_DIAMOND, ACTION_GROWING, -1
},
{
- Xballoon, TRUE, FALSE,
- EL_BALLOON, -1, -1
+ O_PRE_DIA_2, FALSE,
+ EL_BD_DIAMOND, ACTION_GROWING, -1
},
{
- Yballoon_n, FALSE, FALSE,
- EL_BALLOON, ACTION_MOVING, MV_BIT_UP
+ O_PRE_DIA_3, FALSE,
+ EL_BD_DIAMOND, ACTION_GROWING, -1
},
{
- Yballoon_nB, FALSE, TRUE,
- EL_BALLOON, ACTION_MOVING, MV_BIT_UP
+ O_PRE_DIA_4, FALSE,
+ EL_BD_DIAMOND, ACTION_GROWING, -1
},
{
- Yballoon_e, FALSE, FALSE,
- EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
+ O_PRE_DIA_5, FALSE,
+ EL_BD_DIAMOND, ACTION_GROWING, -1
},
{
- Yballoon_eB, FALSE, TRUE,
- EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
+ O_EXPLODE_1, FALSE,
+ EL_DEFAULT, ACTION_EXPLODING, -1
},
{
- Yballoon_s, FALSE, FALSE,
- EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
+ O_EXPLODE_2, FALSE,
+ EL_DEFAULT, ACTION_EXPLODING, -1
},
{
- Yballoon_sB, FALSE, TRUE,
- EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
+ O_EXPLODE_3, FALSE,
+ EL_DEFAULT, ACTION_EXPLODING, -1
},
{
- Yballoon_w, FALSE, FALSE,
- EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
+ O_EXPLODE_4, FALSE,
+ EL_DEFAULT, ACTION_EXPLODING, -1
},
{
- Yballoon_wB, FALSE, TRUE,
- EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
+ O_EXPLODE_5, FALSE,
+ EL_DEFAULT, ACTION_EXPLODING, -1
},
{
- Xgrass, TRUE, FALSE,
- EL_EMC_GRASS, -1, -1
+ O_PRE_STONE_1, FALSE,
+ EL_BD_ROCK, ACTION_GROWING, -1
},
{
- Ygrass_nB, FALSE, FALSE,
- EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
+ O_PRE_STONE_2, FALSE,
+ EL_BD_ROCK, ACTION_GROWING, -1
},
{
- Ygrass_eB, FALSE, FALSE,
- EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
+ O_PRE_STONE_3, FALSE,
+ EL_BD_ROCK, ACTION_GROWING, -1
},
{
- Ygrass_sB, FALSE, FALSE,
- EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
+ O_PRE_STONE_4, FALSE,
+ EL_BD_ROCK, ACTION_GROWING, -1
},
{
- Ygrass_wB, FALSE, FALSE,
- EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
+ O_PRE_STEEL_1, FALSE,
+ EL_BD_STEELWALL, ACTION_GROWING, -1
},
{
- Xdirt, TRUE, FALSE,
- EL_SAND, -1, -1
+ O_PRE_STEEL_2, FALSE,
+ EL_BD_STEELWALL, ACTION_GROWING, -1
},
{
- Ydirt_nB, FALSE, FALSE,
- EL_SAND, ACTION_DIGGING, MV_BIT_UP
+ O_PRE_STEEL_3, FALSE,
+ EL_BD_STEELWALL, ACTION_GROWING, -1
},
{
- Ydirt_eB, FALSE, FALSE,
- EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
+ O_PRE_STEEL_4, FALSE,
+ EL_BD_STEELWALL, ACTION_GROWING, -1
},
{
- Ydirt_sB, FALSE, FALSE,
- EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
+ O_GHOST_EXPL_1, FALSE,
+ EL_BD_GHOST, ACTION_EXPLODING, -1
},
{
- Ydirt_wB, FALSE, FALSE,
- EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
+ O_GHOST_EXPL_2, FALSE,
+ EL_BD_GHOST, ACTION_EXPLODING, -1
},
{
- Xacid_ne, TRUE, FALSE,
- EL_ACID_POOL_TOPRIGHT, -1, -1
+ O_GHOST_EXPL_3, FALSE,
+ EL_BD_GHOST, ACTION_EXPLODING, -1
},
{
- Xacid_se, TRUE, FALSE,
- EL_ACID_POOL_BOTTOMRIGHT, -1, -1
+ O_GHOST_EXPL_4, FALSE,
+ EL_BD_GHOST, ACTION_EXPLODING, -1
},
{
- Xacid_s, TRUE, FALSE,
- EL_ACID_POOL_BOTTOM, -1, -1
+ O_BOMB_EXPL_1, FALSE,
+ EL_BD_BOMB, ACTION_EXPLODING, -1
},
{
- Xacid_sw, TRUE, FALSE,
- EL_ACID_POOL_BOTTOMLEFT, -1, -1
+ O_BOMB_EXPL_2, FALSE,
+ EL_BD_BOMB, ACTION_EXPLODING, -1
},
{
- Xacid_nw, TRUE, FALSE,
- EL_ACID_POOL_TOPLEFT, -1, -1
+ O_BOMB_EXPL_3, FALSE,
+ EL_BD_BOMB, ACTION_EXPLODING, -1
},
{
- Xacid_1, TRUE, FALSE,
- EL_ACID, -1, -1
+ O_BOMB_EXPL_4, FALSE,
+ EL_BD_BOMB, ACTION_EXPLODING, -1
},
{
- Xacid_2, FALSE, FALSE,
- EL_ACID, -1, -1
+ O_NITRO_EXPL_1, FALSE,
+ EL_BD_NITRO_PACK, ACTION_EXPLODING, -1
},
{
- Xacid_3, FALSE, FALSE,
- EL_ACID, -1, -1
+ O_NITRO_EXPL_2, FALSE,
+ EL_BD_NITRO_PACK, ACTION_EXPLODING, -1
},
{
- Xacid_4, FALSE, FALSE,
- EL_ACID, -1, -1
+ O_NITRO_EXPL_3, FALSE,
+ EL_BD_NITRO_PACK, ACTION_EXPLODING, -1
},
{
- Xacid_5, FALSE, FALSE,
- EL_ACID, -1, -1
+ O_NITRO_EXPL_4, FALSE,
+ EL_BD_NITRO_PACK, ACTION_EXPLODING, -1
},
{
- Xacid_6, FALSE, FALSE,
- EL_ACID, -1, -1
+ O_AMOEBA_2_EXPL_1, FALSE,
+ EL_BD_AMOEBA_2, ACTION_EXPLODING, -1
},
{
- Xacid_7, FALSE, FALSE,
- EL_ACID, -1, -1
+ O_AMOEBA_2_EXPL_2, FALSE,
+ EL_BD_AMOEBA_2, ACTION_EXPLODING, -1
},
{
- Xacid_8, FALSE, FALSE,
- EL_ACID, -1, -1
+ O_AMOEBA_2_EXPL_3, FALSE,
+ EL_BD_AMOEBA_2, ACTION_EXPLODING, -1
},
{
- Xball_1, TRUE, FALSE,
- EL_EMC_MAGIC_BALL, -1, -1
+ O_AMOEBA_2_EXPL_4, FALSE,
+ EL_BD_AMOEBA_2, ACTION_EXPLODING, -1
},
{
- Xball_1B, FALSE, FALSE,
- EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
+ O_NUT_EXPL_1, FALSE,
+ EL_BD_NUT, ACTION_BREAKING, -1
},
{
- Xball_2, FALSE, FALSE,
- EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
+ O_NUT_EXPL_2, FALSE,
+ EL_BD_NUT, ACTION_BREAKING, -1
},
{
- Xball_2B, FALSE, FALSE,
- EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
+ O_NUT_EXPL_3, FALSE,
+ EL_BD_NUT, ACTION_BREAKING, -1
},
{
- Yball_eat, FALSE, FALSE,
- EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
+ O_NUT_EXPL_4, FALSE,
+ EL_BD_NUT, ACTION_BREAKING, -1
+ },
+ {
+ O_PLAYER_PNEUMATIC_LEFT, FALSE,
+ EL_BD_PLAYER, ACTION_HITTING, MV_BIT_LEFT
+ },
+ {
+ O_PLAYER_PNEUMATIC_RIGHT, FALSE,
+ EL_BD_PLAYER, ACTION_HITTING, MV_BIT_RIGHT
+ },
+ {
+ O_PNEUMATIC_ACTIVE_LEFT, TRUE,
+ EL_BD_PNEUMATIC_HAMMER, ACTION_HITTING, MV_BIT_LEFT
+ },
+ {
+ O_PNEUMATIC_ACTIVE_RIGHT, TRUE,
+ EL_BD_PNEUMATIC_HAMMER, ACTION_HITTING, MV_BIT_RIGHT
+ },
+
+ // helper (runtime) elements
+
+ {
+ O_FAKE_BONUS, FALSE,
+ EL_BD_FAKE_BONUS, -1, -1
+ },
+ {
+ O_INBOX_CLOSED, FALSE,
+ EL_BD_INBOX, -1, -1
+ },
+ {
+ O_INBOX_OPEN, FALSE,
+ EL_BD_INBOX, ACTION_OPENING, -1
+ },
+ {
+ O_OUTBOX_CLOSED, FALSE,
+ EL_BD_EXIT_CLOSED, -1, -1
+ },
+ {
+ O_OUTBOX_OPEN, FALSE,
+ EL_BD_EXIT_OPEN, -1, -1
+ },
+ {
+ O_COVERED, FALSE,
+ EL_BD_COVERED, -1, -1
+ },
+ {
+ O_PLAYER_LEFT, FALSE,
+ EL_BD_PLAYER, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ O_PLAYER_RIGHT, FALSE,
+ EL_BD_PLAYER, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ O_PLAYER_BLINK, FALSE,
+ EL_BD_PLAYER, ACTION_BORING_1, -1
+ },
+ {
+ O_PLAYER_TAP, FALSE,
+ EL_BD_PLAYER, ACTION_BORING_2, -1
+ },
+ {
+ O_PLAYER_TAP_BLINK, FALSE,
+ EL_BD_PLAYER, ACTION_BORING_3, -1
+ },
+ {
+ O_CREATURE_SWITCH_ON, FALSE,
+ EL_BD_CREATURE_SWITCH_ACTIVE, -1, -1
+ },
+ {
+ O_EXPANDING_WALL_SWITCH_HORIZ, FALSE,
+ EL_BD_EXPANDABLE_WALL_SWITCH_HORIZONTAL, -1, -1
+ },
+ {
+ O_EXPANDING_WALL_SWITCH_VERT, FALSE,
+ EL_BD_EXPANDABLE_WALL_SWITCH_VERTICAL, -1, -1
+ },
+ {
+ O_GRAVITY_SWITCH_ACTIVE, FALSE,
+ EL_BD_GRAVITY_SWITCH_ACTIVE, -1, -1
+ },
+ {
+ O_REPLICATOR_SWITCH_OFF, FALSE,
+ EL_BD_REPLICATOR_SWITCH, -1, -1
+ },
+ {
+ O_REPLICATOR_SWITCH_ON, FALSE,
+ EL_BD_REPLICATOR_SWITCH_ACTIVE, -1, -1
+ },
+ {
+ O_CONVEYOR_DIR_NORMAL, FALSE,
+ EL_BD_CONVEYOR_DIR_SWITCH_RIGHT, -1, -1
+ },
+ {
+ O_CONVEYOR_DIR_CHANGED, FALSE,
+ EL_BD_CONVEYOR_DIR_SWITCH_LEFT, -1, -1
+ },
+ {
+ O_CONVEYOR_SWITCH_OFF, FALSE,
+ EL_BD_CONVEYOR_SWITCH, -1, -1
+ },
+ {
+ O_CONVEYOR_SWITCH_ON, FALSE,
+ EL_BD_CONVEYOR_SWITCH_ACTIVE, -1, -1
+ },
+ {
+ O_MAGIC_WALL_ACTIVE, FALSE,
+ EL_BD_MAGIC_WALL_ACTIVE, -1, -1
+ },
+ {
+ O_REPLICATOR_ACTIVE, FALSE,
+ EL_BD_REPLICATOR_ACTIVE, -1, -1
+ },
+ {
+ O_CONVEYOR_LEFT_ACTIVE, FALSE,
+ EL_BD_CONVEYOR_LEFT_ACTIVE, -1, -1
+ },
+ {
+ O_CONVEYOR_RIGHT_ACTIVE, FALSE,
+ EL_BD_CONVEYOR_RIGHT_ACTIVE, -1, -1
+ },
+ {
+ O_BITER_SWITCH_1, FALSE,
+ EL_BD_BITER_SWITCH_1, -1, -1
+ },
+ {
+ O_BITER_SWITCH_2, FALSE,
+ EL_BD_BITER_SWITCH_2, -1, -1
+ },
+ {
+ O_BITER_SWITCH_3, FALSE,
+ EL_BD_BITER_SWITCH_3, -1, -1
+ },
+ {
+ O_BITER_SWITCH_4, FALSE,
+ EL_BD_BITER_SWITCH_4, -1, -1
+ },
+
+ {
+ -1, FALSE,
+ -1, -1, -1
+ }
+};
+
+int map_element_RND_to_BD(int element_rnd)
+{
+ static unsigned short mapping_RND_to_BD[NUM_FILE_ELEMENTS];
+ static boolean mapping_initialized = FALSE;
+
+ if (!mapping_initialized)
+ {
+ int i;
+
+ // return "O_UNKNOWN" for all undefined elements in mapping array
+ for (i = 0; i < NUM_FILE_ELEMENTS; i++)
+ mapping_RND_to_BD[i] = O_UNKNOWN;
+
+ for (i = 0; bd_object_mapping_list[i].element_bd != -1; i++)
+ if (bd_object_mapping_list[i].is_rnd_to_bd_mapping)
+ mapping_RND_to_BD[bd_object_mapping_list[i].element_rnd] =
+ bd_object_mapping_list[i].element_bd;
+
+ mapping_initialized = TRUE;
+ }
+
+ if (element_rnd < 0 || element_rnd >= NUM_FILE_ELEMENTS)
+ {
+ Warn("invalid RND element %d", element_rnd);
+
+ return O_UNKNOWN;
+ }
+
+ return mapping_RND_to_BD[element_rnd];
+}
+
+int map_element_BD_to_RND(int element_bd)
+{
+ static unsigned short mapping_BD_to_RND[O_MAX_ALL];
+ static boolean mapping_initialized = FALSE;
+
+ if (!mapping_initialized)
+ {
+ int i;
+
+ // return "EL_UNKNOWN" for all undefined elements in mapping array
+ for (i = 0; i < O_MAX_ALL; i++)
+ mapping_BD_to_RND[i] = EL_UNKNOWN;
+
+ for (i = 0; bd_object_mapping_list[i].element_bd != -1; i++)
+ mapping_BD_to_RND[bd_object_mapping_list[i].element_bd] =
+ bd_object_mapping_list[i].element_rnd;
+
+ mapping_initialized = TRUE;
+ }
+
+ if (element_bd < 0 || element_bd >= O_MAX_ALL)
+ {
+ Warn("invalid BD element %d", element_bd);
+
+ return EL_UNKNOWN;
+ }
+
+ return mapping_BD_to_RND[element_bd];
+}
+
+static struct Mapping_EM_to_RND_object
+{
+ int element_em;
+ boolean is_rnd_to_em_mapping; // unique mapping EM <-> RND
+ boolean is_backside; // backside of moving element
+
+ int element_rnd;
+ int action;
+ int direction;
+}
+em_object_mapping_list[GAME_TILE_MAX + 1] =
+{
+ {
+ Zborder, FALSE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+ {
+ Zplayer, FALSE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+
+ {
+ Zbug, FALSE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+ {
+ Ztank, FALSE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+ {
+ Zeater, FALSE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+ {
+ Zdynamite, FALSE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+ {
+ Zboom, FALSE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+
+ {
+ Xchain, FALSE, FALSE,
+ EL_DEFAULT, ACTION_EXPLODING, -1
+ },
+ {
+ Xboom_bug, FALSE, FALSE,
+ EL_BUG, ACTION_EXPLODING, -1
+ },
+ {
+ Xboom_tank, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_EXPLODING, -1
+ },
+ {
+ Xboom_android, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_OTHER, -1
+ },
+ {
+ Xboom_1, FALSE, FALSE,
+ EL_DEFAULT, ACTION_EXPLODING, -1
+ },
+ {
+ Xboom_2, FALSE, FALSE,
+ EL_DEFAULT, ACTION_EXPLODING, -1
+ },
+
+ {
+ Xblank, TRUE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+
+ {
+ Xsplash_e, FALSE, FALSE,
+ EL_ACID_SPLASH_RIGHT, -1, -1
+ },
+ {
+ Xsplash_w, FALSE, FALSE,
+ EL_ACID_SPLASH_LEFT, -1, -1
+ },
+
+ {
+ Xplant, TRUE, FALSE,
+ EL_EMC_PLANT, -1, -1
+ },
+ {
+ Yplant, FALSE, FALSE,
+ EL_EMC_PLANT, -1, -1
+ },
+
+ {
+ Xacid_1, TRUE, FALSE,
+ EL_ACID, -1, -1
+ },
+ {
+ Xacid_2, FALSE, FALSE,
+ EL_ACID, -1, -1
+ },
+ {
+ Xacid_3, FALSE, FALSE,
+ EL_ACID, -1, -1
+ },
+ {
+ Xacid_4, FALSE, FALSE,
+ EL_ACID, -1, -1
+ },
+ {
+ Xacid_5, FALSE, FALSE,
+ EL_ACID, -1, -1
+ },
+ {
+ Xacid_6, FALSE, FALSE,
+ EL_ACID, -1, -1
+ },
+ {
+ Xacid_7, FALSE, FALSE,
+ EL_ACID, -1, -1
+ },
+ {
+ Xacid_8, FALSE, FALSE,
+ EL_ACID, -1, -1
+ },
+
+ {
+ Xfake_acid_1, TRUE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_2, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_3, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_4, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_5, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_6, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_7, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_8, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+
+ {
+ Xfake_acid_1_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_2_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_3_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_4_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_5_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_6_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_7_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_8_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+
+ {
+ Xgrass, TRUE, FALSE,
+ EL_EMC_GRASS, -1, -1
+ },
+ {
+ Ygrass_nB, FALSE, FALSE,
+ EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
+ },
+ {
+ Ygrass_eB, FALSE, FALSE,
+ EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
+ },
+ {
+ Ygrass_sB, FALSE, FALSE,
+ EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
+ },
+ {
+ Ygrass_wB, FALSE, FALSE,
+ EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
+ },
+
+ {
+ Xdirt, TRUE, FALSE,
+ EL_SAND, -1, -1
+ },
+ {
+ Ydirt_nB, FALSE, FALSE,
+ EL_SAND, ACTION_DIGGING, MV_BIT_UP
+ },
+ {
+ Ydirt_eB, FALSE, FALSE,
+ EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
+ },
+ {
+ Ydirt_sB, FALSE, FALSE,
+ EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
+ },
+ {
+ Ydirt_wB, FALSE, FALSE,
+ EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
+ },
+
+ {
+ Xandroid, TRUE, FALSE,
+ EL_EMC_ANDROID, ACTION_ACTIVE, -1
+ },
+ {
+ Xandroid_1_n, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
+ },
+ {
+ Xandroid_2_n, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
+ },
+ {
+ Xandroid_1_e, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
+ },
+ {
+ Xandroid_2_e, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
+ },
+ {
+ Xandroid_1_w, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
+ },
+ {
+ Xandroid_2_w, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
+ },
+ {
+ Xandroid_1_s, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
+ },
+ {
+ Xandroid_2_s, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
+ },
+ {
+ Yandroid_n, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
+ },
+ {
+ Yandroid_nB, FALSE, TRUE,
+ EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
+ },
+ {
+ Yandroid_ne, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
+ },
+ {
+ Yandroid_neB, FALSE, TRUE,
+ EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
+ },
+ {
+ Yandroid_e, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Yandroid_eB, FALSE, TRUE,
+ EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Yandroid_se, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
+ },
+ {
+ Yandroid_seB, FALSE, TRUE,
+ EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
+ },
+ {
+ Yandroid_s, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
+ },
+ {
+ Yandroid_sB, FALSE, TRUE,
+ EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
+ },
+ {
+ Yandroid_sw, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
+ },
+ {
+ Yandroid_swB, FALSE, TRUE,
+ EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
+ },
+ {
+ Yandroid_w, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Yandroid_wB, FALSE, TRUE,
+ EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Yandroid_nw, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
+ },
+ {
+ Yandroid_nwB, FALSE, TRUE,
+ EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
+ },
+
+ {
+ Xeater_n, TRUE, FALSE,
+ EL_YAMYAM_UP, -1, -1
+ },
+ {
+ Xeater_e, TRUE, FALSE,
+ EL_YAMYAM_RIGHT, -1, -1
+ },
+ {
+ Xeater_w, TRUE, FALSE,
+ EL_YAMYAM_LEFT, -1, -1
+ },
+ {
+ Xeater_s, TRUE, FALSE,
+ EL_YAMYAM_DOWN, -1, -1
+ },
+ {
+ Yeater_n, FALSE, FALSE,
+ EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
+ },
+ {
+ Yeater_nB, FALSE, TRUE,
+ EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
+ },
+ {
+ Yeater_e, FALSE, FALSE,
+ EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Yeater_eB, FALSE, TRUE,
+ EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Yeater_s, FALSE, FALSE,
+ EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
+ },
+ {
+ Yeater_sB, FALSE, TRUE,
+ EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
+ },
+ {
+ Yeater_w, FALSE, FALSE,
+ EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Yeater_wB, FALSE, TRUE,
+ EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Yeater_stone, FALSE, FALSE,
+ EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
+ },
+ {
+ Yeater_spring, FALSE, FALSE,
+ EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
+ },
+
+ {
+ Xalien, TRUE, FALSE,
+ EL_ROBOT, -1, -1
+ },
+ {
+ Xalien_pause, FALSE, FALSE,
+ EL_ROBOT, -1, -1
+ },
+ {
+ Yalien_n, FALSE, FALSE,
+ EL_ROBOT, ACTION_MOVING, MV_BIT_UP
+ },
+ {
+ Yalien_nB, FALSE, TRUE,
+ EL_ROBOT, ACTION_MOVING, MV_BIT_UP
+ },
+ {
+ Yalien_e, FALSE, FALSE,
+ EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Yalien_eB, FALSE, TRUE,
+ EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Yalien_s, FALSE, FALSE,
+ EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
+ },
+ {
+ Yalien_sB, FALSE, TRUE,
+ EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
+ },
+ {
+ Yalien_w, FALSE, FALSE,
+ EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Yalien_wB, FALSE, TRUE,
+ EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Yalien_stone, FALSE, FALSE,
+ EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
+ },
+ {
+ Yalien_spring, FALSE, FALSE,
+ EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
+ },
+
+ {
+ Xbug_1_n, TRUE, FALSE,
+ EL_BUG_UP, -1, -1
+ },
+ {
+ Xbug_1_e, TRUE, FALSE,
+ EL_BUG_RIGHT, -1, -1
+ },
+ {
+ Xbug_1_s, TRUE, FALSE,
+ EL_BUG_DOWN, -1, -1
+ },
+ {
+ Xbug_1_w, TRUE, FALSE,
+ EL_BUG_LEFT, -1, -1
+ },
+ {
+ Xbug_2_n, FALSE, FALSE,
+ EL_BUG_UP, -1, -1
+ },
+ {
+ Xbug_2_e, FALSE, FALSE,
+ EL_BUG_RIGHT, -1, -1
+ },
+ {
+ Xbug_2_s, FALSE, FALSE,
+ EL_BUG_DOWN, -1, -1
+ },
+ {
+ Xbug_2_w, FALSE, FALSE,
+ EL_BUG_LEFT, -1, -1
+ },
+ {
+ Ybug_n, FALSE, FALSE,
+ EL_BUG, ACTION_MOVING, MV_BIT_UP
+ },
+ {
+ Ybug_nB, FALSE, TRUE,
+ EL_BUG, ACTION_MOVING, MV_BIT_UP
+ },
+ {
+ Ybug_e, FALSE, FALSE,
+ EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Ybug_eB, FALSE, TRUE,
+ EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Ybug_s, FALSE, FALSE,
+ EL_BUG, ACTION_MOVING, MV_BIT_DOWN
+ },
+ {
+ Ybug_sB, FALSE, TRUE,
+ EL_BUG, ACTION_MOVING, MV_BIT_DOWN
+ },
+ {
+ Ybug_w, FALSE, FALSE,
+ EL_BUG, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Ybug_wB, FALSE, TRUE,
+ EL_BUG, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Ybug_w_n, FALSE, FALSE,
+ EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
+ },
+ {
+ Ybug_n_e, FALSE, FALSE,
+ EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
+ },
+ {
+ Ybug_e_s, FALSE, FALSE,
+ EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
+ },
+ {
+ Ybug_s_w, FALSE, FALSE,
+ EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
+ },
+ {
+ Ybug_e_n, FALSE, FALSE,
+ EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
+ },
+ {
+ Ybug_s_e, FALSE, FALSE,
+ EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
+ },
+ {
+ Ybug_w_s, FALSE, FALSE,
+ EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
+ },
+ {
+ Ybug_n_w, FALSE, FALSE,
+ EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
+ },
+ {
+ Ybug_stone, FALSE, FALSE,
+ EL_BUG, ACTION_SMASHED_BY_ROCK, -1
+ },
+ {
+ Ybug_spring, FALSE, FALSE,
+ EL_BUG, ACTION_SMASHED_BY_SPRING, -1
+ },
+
+ {
+ Xtank_1_n, TRUE, FALSE,
+ EL_SPACESHIP_UP, -1, -1
+ },
+ {
+ Xtank_1_e, TRUE, FALSE,
+ EL_SPACESHIP_RIGHT, -1, -1
+ },
+ {
+ Xtank_1_s, TRUE, FALSE,
+ EL_SPACESHIP_DOWN, -1, -1
+ },
+ {
+ Xtank_1_w, TRUE, FALSE,
+ EL_SPACESHIP_LEFT, -1, -1
+ },
+ {
+ Xtank_2_n, FALSE, FALSE,
+ EL_SPACESHIP_UP, -1, -1
+ },
+ {
+ Xtank_2_e, FALSE, FALSE,
+ EL_SPACESHIP_RIGHT, -1, -1
+ },
+ {
+ Xtank_2_s, FALSE, FALSE,
+ EL_SPACESHIP_DOWN, -1, -1
+ },
+ {
+ Xtank_2_w, FALSE, FALSE,
+ EL_SPACESHIP_LEFT, -1, -1
+ },
+ {
+ Ytank_n, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
+ },
+ {
+ Ytank_nB, FALSE, TRUE,
+ EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
+ },
+ {
+ Ytank_e, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Ytank_eB, FALSE, TRUE,
+ EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Ytank_s, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
+ },
+ {
+ Ytank_sB, FALSE, TRUE,
+ EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
+ },
+ {
+ Ytank_w, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Ytank_wB, FALSE, TRUE,
+ EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Ytank_w_n, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
+ },
+ {
+ Ytank_n_e, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
+ },
+ {
+ Ytank_e_s, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
+ },
+ {
+ Ytank_s_w, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
+ },
+ {
+ Ytank_e_n, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
+ },
+ {
+ Ytank_s_e, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
+ },
+ {
+ Ytank_w_s, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
+ },
+ {
+ Ytank_n_w, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
+ },
+ {
+ Ytank_stone, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
+ },
+ {
+ Ytank_spring, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
+ },
+
+ {
+ Xemerald, TRUE, FALSE,
+ EL_EMERALD, -1, -1
+ },
+ {
+ Xemerald_pause, FALSE, FALSE,
+ EL_EMERALD, -1, -1
+ },
+ {
+ Xemerald_fall, FALSE, FALSE,
+ EL_EMERALD, -1, -1
+ },
+ {
+ Xemerald_shine, FALSE, FALSE,
+ EL_EMERALD, ACTION_TWINKLING, -1
+ },
+ {
+ Yemerald_s, FALSE, FALSE,
+ EL_EMERALD, ACTION_FALLING, -1
+ },
+ {
+ Yemerald_sB, FALSE, TRUE,
+ EL_EMERALD, ACTION_FALLING, -1
+ },
+ {
+ Yemerald_e, FALSE, FALSE,
+ EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Yemerald_eB, FALSE, TRUE,
+ EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Yemerald_w, FALSE, FALSE,
+ EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Yemerald_wB, FALSE, TRUE,
+ EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Yemerald_blank, FALSE, FALSE,
+ EL_EMERALD, ACTION_COLLECTING, -1
+ },
+
+ {
+ Xdiamond, TRUE, FALSE,
+ EL_DIAMOND, -1, -1
+ },
+ {
+ Xdiamond_pause, FALSE, FALSE,
+ EL_DIAMOND, -1, -1
+ },
+ {
+ Xdiamond_fall, FALSE, FALSE,
+ EL_DIAMOND, -1, -1
+ },
+ {
+ Xdiamond_shine, FALSE, FALSE,
+ EL_DIAMOND, ACTION_TWINKLING, -1
+ },
+ {
+ Ydiamond_s, FALSE, FALSE,
+ EL_DIAMOND, ACTION_FALLING, -1
+ },
+ {
+ Ydiamond_sB, FALSE, TRUE,
+ EL_DIAMOND, ACTION_FALLING, -1
+ },
+ {
+ Ydiamond_e, FALSE, FALSE,
+ EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Ydiamond_eB, FALSE, TRUE,
+ EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Ydiamond_w, FALSE, FALSE,
+ EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Ydiamond_wB, FALSE, TRUE,
+ EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Ydiamond_blank, FALSE, FALSE,
+ EL_DIAMOND, ACTION_COLLECTING, -1
+ },
+ {
+ Ydiamond_stone, FALSE, FALSE,
+ EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
+ },
+
+ {
+ Xstone, TRUE, FALSE,
+ EL_ROCK, -1, -1
+ },
+ {
+ Xstone_pause, FALSE, FALSE,
+ EL_ROCK, -1, -1
+ },
+ {
+ Xstone_fall, FALSE, FALSE,
+ EL_ROCK, -1, -1
+ },
+ {
+ Ystone_s, FALSE, FALSE,
+ EL_ROCK, ACTION_FALLING, -1
+ },
+ {
+ Ystone_sB, FALSE, TRUE,
+ EL_ROCK, ACTION_FALLING, -1
+ },
+ {
+ Ystone_e, FALSE, FALSE,
+ EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Ystone_eB, FALSE, TRUE,
+ EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Ystone_w, FALSE, FALSE,
+ EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Ystone_wB, FALSE, TRUE,
+ EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
+ },
+
+ {
+ Xbomb, TRUE, FALSE,
+ EL_BOMB, -1, -1
+ },
+ {
+ Xbomb_pause, FALSE, FALSE,
+ EL_BOMB, -1, -1
+ },
+ {
+ Xbomb_fall, FALSE, FALSE,
+ EL_BOMB, -1, -1
+ },
+ {
+ Ybomb_s, FALSE, FALSE,
+ EL_BOMB, ACTION_FALLING, -1
+ },
+ {
+ Ybomb_sB, FALSE, TRUE,
+ EL_BOMB, ACTION_FALLING, -1
+ },
+ {
+ Ybomb_e, FALSE, FALSE,
+ EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
},
{
- Ykey_1_eat, FALSE, FALSE,
- EL_EM_KEY_1, ACTION_COLLECTING, -1
+ Ybomb_eB, FALSE, TRUE,
+ EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
},
{
- Ykey_2_eat, FALSE, FALSE,
- EL_EM_KEY_2, ACTION_COLLECTING, -1
+ Ybomb_w, FALSE, FALSE,
+ EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Ybomb_wB, FALSE, TRUE,
+ EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Ybomb_blank, FALSE, FALSE,
+ EL_BOMB, ACTION_ACTIVATING, -1
+ },
+
+ {
+ Xnut, TRUE, FALSE,
+ EL_NUT, -1, -1
+ },
+ {
+ Xnut_pause, FALSE, FALSE,
+ EL_NUT, -1, -1
+ },
+ {
+ Xnut_fall, FALSE, FALSE,
+ EL_NUT, -1, -1
+ },
+ {
+ Ynut_s, FALSE, FALSE,
+ EL_NUT, ACTION_FALLING, -1
+ },
+ {
+ Ynut_sB, FALSE, TRUE,
+ EL_NUT, ACTION_FALLING, -1
+ },
+ {
+ Ynut_e, FALSE, FALSE,
+ EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Ynut_eB, FALSE, TRUE,
+ EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Ynut_w, FALSE, FALSE,
+ EL_NUT, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Ynut_wB, FALSE, TRUE,
+ EL_NUT, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Ynut_stone, FALSE, FALSE,
+ EL_NUT, ACTION_BREAKING, -1
+ },
+
+ {
+ Xspring, TRUE, FALSE,
+ EL_SPRING, -1, -1
+ },
+ {
+ Xspring_pause, FALSE, FALSE,
+ EL_SPRING, -1, -1
+ },
+ {
+ Xspring_e, TRUE, FALSE,
+ EL_SPRING_RIGHT, -1, -1
+ },
+ {
+ Xspring_w, TRUE, FALSE,
+ EL_SPRING_LEFT, -1, -1
+ },
+ {
+ Xspring_fall, FALSE, FALSE,
+ EL_SPRING, -1, -1
+ },
+ {
+ Yspring_s, FALSE, FALSE,
+ EL_SPRING, ACTION_FALLING, -1
+ },
+ {
+ Yspring_sB, FALSE, TRUE,
+ EL_SPRING, ACTION_FALLING, -1
+ },
+ {
+ Yspring_e, FALSE, FALSE,
+ EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Yspring_eB, FALSE, TRUE,
+ EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
+ },
+ {
+ Yspring_w, FALSE, FALSE,
+ EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Yspring_wB, FALSE, TRUE,
+ EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
+ },
+ {
+ Yspring_alien_e, FALSE, FALSE,
+ EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
+ },
+ {
+ Yspring_alien_eB, FALSE, TRUE,
+ EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
+ },
+ {
+ Yspring_alien_w, FALSE, FALSE,
+ EL_SPRING, ACTION_EATING, MV_BIT_LEFT
+ },
+ {
+ Yspring_alien_wB, FALSE, TRUE,
+ EL_SPRING, ACTION_EATING, MV_BIT_LEFT
+ },
+
+ {
+ Xpush_emerald_e, FALSE, FALSE,
+ EL_EMERALD, -1, MV_BIT_RIGHT
+ },
+ {
+ Xpush_emerald_w, FALSE, FALSE,
+ EL_EMERALD, -1, MV_BIT_LEFT
+ },
+ {
+ Xpush_diamond_e, FALSE, FALSE,
+ EL_DIAMOND, -1, MV_BIT_RIGHT
+ },
+ {
+ Xpush_diamond_w, FALSE, FALSE,
+ EL_DIAMOND, -1, MV_BIT_LEFT
+ },
+ {
+ Xpush_stone_e, FALSE, FALSE,
+ EL_ROCK, -1, MV_BIT_RIGHT
+ },
+ {
+ Xpush_stone_w, FALSE, FALSE,
+ EL_ROCK, -1, MV_BIT_LEFT
+ },
+ {
+ Xpush_bomb_e, FALSE, FALSE,
+ EL_BOMB, -1, MV_BIT_RIGHT
+ },
+ {
+ Xpush_bomb_w, FALSE, FALSE,
+ EL_BOMB, -1, MV_BIT_LEFT
+ },
+ {
+ Xpush_nut_e, FALSE, FALSE,
+ EL_NUT, -1, MV_BIT_RIGHT
+ },
+ {
+ Xpush_nut_w, FALSE, FALSE,
+ EL_NUT, -1, MV_BIT_LEFT
+ },
+ {
+ Xpush_spring_e, FALSE, FALSE,
+ EL_SPRING_RIGHT, -1, MV_BIT_RIGHT
+ },
+ {
+ Xpush_spring_w, FALSE, FALSE,
+ EL_SPRING_LEFT, -1, MV_BIT_LEFT
+ },
+
+ {
+ Xdynamite, TRUE, FALSE,
+ EL_EM_DYNAMITE, -1, -1
+ },
+ {
+ Ydynamite_blank, FALSE, FALSE,
+ EL_EM_DYNAMITE, ACTION_COLLECTING, -1
+ },
+ {
+ Xdynamite_1, TRUE, FALSE,
+ EL_EM_DYNAMITE_ACTIVE, -1, -1
+ },
+ {
+ Xdynamite_2, FALSE, FALSE,
+ EL_EM_DYNAMITE_ACTIVE, -1, -1
+ },
+ {
+ Xdynamite_3, FALSE, FALSE,
+ EL_EM_DYNAMITE_ACTIVE, -1, -1
+ },
+ {
+ Xdynamite_4, FALSE, FALSE,
+ EL_EM_DYNAMITE_ACTIVE, -1, -1
+ },
+
+ {
+ Xkey_1, TRUE, FALSE,
+ EL_EM_KEY_1, -1, -1
+ },
+ {
+ Xkey_2, TRUE, FALSE,
+ EL_EM_KEY_2, -1, -1
+ },
+ {
+ Xkey_3, TRUE, FALSE,
+ EL_EM_KEY_3, -1, -1
+ },
+ {
+ Xkey_4, TRUE, FALSE,
+ EL_EM_KEY_4, -1, -1
+ },
+ {
+ Xkey_5, TRUE, FALSE,
+ EL_EMC_KEY_5, -1, -1
+ },
+ {
+ Xkey_6, TRUE, FALSE,
+ EL_EMC_KEY_6, -1, -1
+ },
+ {
+ Xkey_7, TRUE, FALSE,
+ EL_EMC_KEY_7, -1, -1
+ },
+ {
+ Xkey_8, TRUE, FALSE,
+ EL_EMC_KEY_8, -1, -1
+ },
+
+ {
+ Xdoor_1, TRUE, FALSE,
+ EL_EM_GATE_1, -1, -1
+ },
+ {
+ Xdoor_2, TRUE, FALSE,
+ EL_EM_GATE_2, -1, -1
+ },
+ {
+ Xdoor_3, TRUE, FALSE,
+ EL_EM_GATE_3, -1, -1
+ },
+ {
+ Xdoor_4, TRUE, FALSE,
+ EL_EM_GATE_4, -1, -1
+ },
+ {
+ Xdoor_5, TRUE, FALSE,
+ EL_EMC_GATE_5, -1, -1
+ },
+ {
+ Xdoor_6, TRUE, FALSE,
+ EL_EMC_GATE_6, -1, -1
+ },
+ {
+ Xdoor_7, TRUE, FALSE,
+ EL_EMC_GATE_7, -1, -1
+ },
+ {
+ Xdoor_8, TRUE, FALSE,
+ EL_EMC_GATE_8, -1, -1
+ },
+
+ {
+ Xfake_door_1, TRUE, FALSE,
+ EL_EM_GATE_1_GRAY, -1, -1
+ },
+ {
+ Xfake_door_2, TRUE, FALSE,
+ EL_EM_GATE_2_GRAY, -1, -1
+ },
+ {
+ Xfake_door_3, TRUE, FALSE,
+ EL_EM_GATE_3_GRAY, -1, -1
+ },
+ {
+ Xfake_door_4, TRUE, FALSE,
+ EL_EM_GATE_4_GRAY, -1, -1
+ },
+ {
+ Xfake_door_5, TRUE, FALSE,
+ EL_EMC_GATE_5_GRAY, -1, -1
+ },
+ {
+ Xfake_door_6, TRUE, FALSE,
+ EL_EMC_GATE_6_GRAY, -1, -1
},
{
- Ykey_3_eat, FALSE, FALSE,
- EL_EM_KEY_3, ACTION_COLLECTING, -1
+ Xfake_door_7, TRUE, FALSE,
+ EL_EMC_GATE_7_GRAY, -1, -1
},
{
- Ykey_4_eat, FALSE, FALSE,
- EL_EM_KEY_4, ACTION_COLLECTING, -1
+ Xfake_door_8, TRUE, FALSE,
+ EL_EMC_GATE_8_GRAY, -1, -1
},
+
{
- Ykey_5_eat, FALSE, FALSE,
- EL_EMC_KEY_5, ACTION_COLLECTING, -1
+ Xballoon, TRUE, FALSE,
+ EL_BALLOON, -1, -1
},
{
- Ykey_6_eat, FALSE, FALSE,
- EL_EMC_KEY_6, ACTION_COLLECTING, -1
+ Yballoon_n, FALSE, FALSE,
+ EL_BALLOON, ACTION_MOVING, MV_BIT_UP
},
{
- Ykey_7_eat, FALSE, FALSE,
- EL_EMC_KEY_7, ACTION_COLLECTING, -1
+ Yballoon_nB, FALSE, TRUE,
+ EL_BALLOON, ACTION_MOVING, MV_BIT_UP
},
{
- Ykey_8_eat, FALSE, FALSE,
- EL_EMC_KEY_8, ACTION_COLLECTING, -1
+ Yballoon_e, FALSE, FALSE,
+ EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
},
{
- Ylenses_eat, FALSE, FALSE,
- EL_EMC_LENSES, ACTION_COLLECTING, -1
+ Yballoon_eB, FALSE, TRUE,
+ EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
},
{
- Ymagnify_eat, FALSE, FALSE,
- EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
+ Yballoon_s, FALSE, FALSE,
+ EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
},
{
- Ygrass_eat, FALSE, FALSE,
- EL_EMC_GRASS, ACTION_SNAPPING, -1
+ Yballoon_sB, FALSE, TRUE,
+ EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
},
{
- Ydirt_eat, FALSE, FALSE,
- EL_SAND, ACTION_SNAPPING, -1
+ Yballoon_w, FALSE, FALSE,
+ EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
},
{
- Xgrow_ns, TRUE, FALSE,
- EL_EXPANDABLE_WALL_VERTICAL, -1, -1
+ Yballoon_wB, FALSE, TRUE,
+ EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
},
+
{
- Ygrow_ns_eat, FALSE, FALSE,
- EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
+ Xball_1, TRUE, FALSE,
+ EL_EMC_MAGIC_BALL, -1, -1
},
{
- Xgrow_ew, TRUE, FALSE,
- EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
+ Yball_1, FALSE, FALSE,
+ EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
},
{
- Ygrow_ew_eat, FALSE, FALSE,
- EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
+ Xball_2, FALSE, FALSE,
+ EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
},
{
- Xwonderwall, TRUE, FALSE,
- EL_MAGIC_WALL, -1, -1
+ Yball_2, FALSE, FALSE,
+ EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
},
{
- XwonderwallB, FALSE, FALSE,
- EL_MAGIC_WALL, ACTION_ACTIVE, -1
+ Yball_blank, FALSE, FALSE,
+ EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
},
+
{
Xamoeba_1, TRUE, FALSE,
EL_AMOEBA_DRY, ACTION_OTHER, -1
Xamoeba_8, FALSE, FALSE,
EL_AMOEBA_WET, ACTION_OTHER, -1
},
+
{
- Xdoor_1, TRUE, FALSE,
- EL_EM_GATE_1, -1, -1
- },
- {
- Xdoor_2, TRUE, FALSE,
- EL_EM_GATE_2, -1, -1
- },
- {
- Xdoor_3, TRUE, FALSE,
- EL_EM_GATE_3, -1, -1
- },
- {
- Xdoor_4, TRUE, FALSE,
- EL_EM_GATE_4, -1, -1
- },
- {
- Xdoor_5, TRUE, FALSE,
- EL_EMC_GATE_5, -1, -1
- },
- {
- Xdoor_6, TRUE, FALSE,
- EL_EMC_GATE_6, -1, -1
- },
- {
- Xdoor_7, TRUE, FALSE,
- EL_EMC_GATE_7, -1, -1
- },
- {
- Xdoor_8, TRUE, FALSE,
- EL_EMC_GATE_8, -1, -1
- },
- {
- Xkey_1, TRUE, FALSE,
- EL_EM_KEY_1, -1, -1
- },
- {
- Xkey_2, TRUE, FALSE,
- EL_EM_KEY_2, -1, -1
+ Xdrip, TRUE, FALSE,
+ EL_AMOEBA_DROP, ACTION_GROWING, -1
},
{
- Xkey_3, TRUE, FALSE,
- EL_EM_KEY_3, -1, -1
+ Xdrip_fall, FALSE, FALSE,
+ EL_AMOEBA_DROP, -1, -1
},
{
- Xkey_4, TRUE, FALSE,
- EL_EM_KEY_4, -1, -1
+ Xdrip_stretch, FALSE, FALSE,
+ EL_AMOEBA_DROP, ACTION_FALLING, -1
},
{
- Xkey_5, TRUE, FALSE,
- EL_EMC_KEY_5, -1, -1
+ Xdrip_stretchB, FALSE, TRUE,
+ EL_AMOEBA_DROP, ACTION_FALLING, -1
},
{
- Xkey_6, TRUE, FALSE,
- EL_EMC_KEY_6, -1, -1
+ Ydrip_1_s, FALSE, FALSE,
+ EL_AMOEBA_DROP, ACTION_FALLING, -1
},
{
- Xkey_7, TRUE, FALSE,
- EL_EMC_KEY_7, -1, -1
+ Ydrip_1_sB, FALSE, TRUE,
+ EL_AMOEBA_DROP, ACTION_FALLING, -1
},
{
- Xkey_8, TRUE, FALSE,
- EL_EMC_KEY_8, -1, -1
+ Ydrip_2_s, FALSE, FALSE,
+ EL_AMOEBA_DROP, ACTION_FALLING, -1
},
{
- Xwind_n, TRUE, FALSE,
- EL_BALLOON_SWITCH_UP, -1, -1
+ Ydrip_2_sB, FALSE, TRUE,
+ EL_AMOEBA_DROP, ACTION_FALLING, -1
},
+
{
- Xwind_e, TRUE, FALSE,
- EL_BALLOON_SWITCH_RIGHT, -1, -1
+ Xwonderwall, TRUE, FALSE,
+ EL_MAGIC_WALL, -1, -1
},
{
- Xwind_s, TRUE, FALSE,
- EL_BALLOON_SWITCH_DOWN, -1, -1
+ Ywonderwall, FALSE, FALSE,
+ EL_MAGIC_WALL, ACTION_ACTIVE, -1
},
+
{
- Xwind_w, TRUE, FALSE,
- EL_BALLOON_SWITCH_LEFT, -1, -1
+ Xwheel, TRUE, FALSE,
+ EL_ROBOT_WHEEL, -1, -1
},
{
- Xwind_nesw, TRUE, FALSE,
- EL_BALLOON_SWITCH_ANY, -1, -1
+ Ywheel, FALSE, FALSE,
+ EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
},
+
{
- Xwind_stop, TRUE, FALSE,
- EL_BALLOON_SWITCH_NONE, -1, -1
+ Xswitch, TRUE, FALSE,
+ EL_EMC_MAGIC_BALL_SWITCH, -1, -1
},
{
- Xexit, TRUE, FALSE,
- EL_EM_EXIT_CLOSED, -1, -1
+ Yswitch, FALSE, FALSE,
+ EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
},
+
{
- Xexit_1, TRUE, FALSE,
- EL_EM_EXIT_OPEN, -1, -1
+ Xbumper, TRUE, FALSE,
+ EL_EMC_SPRING_BUMPER, -1, -1
},
{
- Xexit_2, FALSE, FALSE,
- EL_EM_EXIT_OPEN, -1, -1
+ Ybumper, FALSE, FALSE,
+ EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
},
+
{
- Xexit_3, FALSE, FALSE,
- EL_EM_EXIT_OPEN, -1, -1
+ Xacid_nw, TRUE, FALSE,
+ EL_ACID_POOL_TOPLEFT, -1, -1
},
{
- Xdynamite, TRUE, FALSE,
- EL_EM_DYNAMITE, -1, -1
+ Xacid_ne, TRUE, FALSE,
+ EL_ACID_POOL_TOPRIGHT, -1, -1
},
{
- Ydynamite_eat, FALSE, FALSE,
- EL_EM_DYNAMITE, ACTION_COLLECTING, -1
+ Xacid_sw, TRUE, FALSE,
+ EL_ACID_POOL_BOTTOMLEFT, -1, -1
},
{
- Xdynamite_1, TRUE, FALSE,
- EL_EM_DYNAMITE_ACTIVE, -1, -1
+ Xacid_s, TRUE, FALSE,
+ EL_ACID_POOL_BOTTOM, -1, -1
},
{
- Xdynamite_2, FALSE, FALSE,
- EL_EM_DYNAMITE_ACTIVE, -1, -1
+ Xacid_se, TRUE, FALSE,
+ EL_ACID_POOL_BOTTOMRIGHT, -1, -1
},
+
{
- Xdynamite_3, FALSE, FALSE,
- EL_EM_DYNAMITE_ACTIVE, -1, -1
+ Xfake_blank, TRUE, FALSE,
+ EL_INVISIBLE_WALL, -1, -1
},
{
- Xdynamite_4, FALSE, FALSE,
- EL_EM_DYNAMITE_ACTIVE, -1, -1
+ Yfake_blank, FALSE, FALSE,
+ EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
},
+
{
- Xbumper, TRUE, FALSE,
- EL_EMC_SPRING_BUMPER, -1, -1
+ Xfake_grass, TRUE, FALSE,
+ EL_EMC_FAKE_GRASS, -1, -1
},
{
- XbumperB, FALSE, FALSE,
- EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
+ Yfake_grass, FALSE, FALSE,
+ EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
},
+
{
- Xwheel, TRUE, FALSE,
- EL_ROBOT_WHEEL, -1, -1
+ Xfake_amoeba, TRUE, FALSE,
+ EL_EMC_DRIPPER, -1, -1
},
{
- XwheelB, FALSE, FALSE,
- EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
+ Yfake_amoeba, FALSE, FALSE,
+ EL_EMC_DRIPPER, ACTION_ACTIVE, -1
},
+
{
- Xswitch, TRUE, FALSE,
- EL_EMC_MAGIC_BALL_SWITCH, -1, -1
+ Xlenses, TRUE, FALSE,
+ EL_EMC_LENSES, -1, -1
},
+
{
- XswitchB, FALSE, FALSE,
- EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
+ Xmagnify, TRUE, FALSE,
+ EL_EMC_MAGNIFIER, -1, -1
},
+
{
Xsand, TRUE, FALSE,
EL_QUICKSAND_EMPTY, -1, -1
Xsand_stonein_4, FALSE, TRUE,
EL_ROCK, ACTION_FILLING, -1
},
- {
- Xsand_stonesand_1, FALSE, FALSE,
- EL_QUICKSAND_EMPTYING, -1, -1
- },
- {
- Xsand_stonesand_2, FALSE, FALSE,
- EL_QUICKSAND_EMPTYING, -1, -1
- },
- {
- Xsand_stonesand_3, FALSE, FALSE,
- EL_QUICKSAND_EMPTYING, -1, -1
- },
- {
- Xsand_stonesand_4, FALSE, FALSE,
- EL_QUICKSAND_EMPTYING, -1, -1
- },
- {
- Xsand_stonesand_quickout_1, FALSE, FALSE,
- EL_QUICKSAND_EMPTYING, -1, -1
- },
- {
- Xsand_stonesand_quickout_2, FALSE, FALSE,
- EL_QUICKSAND_EMPTYING, -1, -1
- },
- {
- Xsand_stoneout_1, FALSE, FALSE,
- EL_ROCK, ACTION_EMPTYING, -1
- },
- {
- Xsand_stoneout_2, FALSE, FALSE,
- EL_ROCK, ACTION_EMPTYING, -1
- },
{
Xsand_sandstone_1, FALSE, FALSE,
EL_QUICKSAND_FILLING, -1, -1
Xsand_sandstone_3, FALSE, FALSE,
EL_QUICKSAND_FILLING, -1, -1
},
- {
- Xsand_sandstone_4, FALSE, FALSE,
- EL_QUICKSAND_FILLING, -1, -1
- },
- {
- Xplant, TRUE, FALSE,
- EL_EMC_PLANT, -1, -1
- },
- {
- Yplant, FALSE, FALSE,
- EL_EMC_PLANT, -1, -1
- },
- {
- Xlenses, TRUE, FALSE,
- EL_EMC_LENSES, -1, -1
- },
- {
- Xmagnify, TRUE, FALSE,
- EL_EMC_MAGNIFIER, -1, -1
- },
- {
- Xdripper, TRUE, FALSE,
- EL_EMC_DRIPPER, -1, -1
- },
- {
- XdripperB, FALSE, FALSE,
- EL_EMC_DRIPPER, ACTION_ACTIVE, -1
- },
- {
- Xfake_blank, TRUE, FALSE,
- EL_INVISIBLE_WALL, -1, -1
+ {
+ Xsand_sandstone_4, FALSE, FALSE,
+ EL_QUICKSAND_FILLING, -1, -1
},
{
- Xfake_blankB, FALSE, FALSE,
- EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
+ Xsand_stonesand_1, FALSE, FALSE,
+ EL_QUICKSAND_EMPTYING, -1, -1
},
{
- Xfake_grass, TRUE, FALSE,
- EL_EMC_FAKE_GRASS, -1, -1
+ Xsand_stonesand_2, FALSE, FALSE,
+ EL_QUICKSAND_EMPTYING, -1, -1
},
{
- Xfake_grassB, FALSE, FALSE,
- EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
+ Xsand_stonesand_3, FALSE, FALSE,
+ EL_QUICKSAND_EMPTYING, -1, -1
},
{
- Xfake_door_1, TRUE, FALSE,
- EL_EM_GATE_1_GRAY, -1, -1
+ Xsand_stonesand_4, FALSE, FALSE,
+ EL_QUICKSAND_EMPTYING, -1, -1
},
{
- Xfake_door_2, TRUE, FALSE,
- EL_EM_GATE_2_GRAY, -1, -1
+ Xsand_stoneout_1, FALSE, FALSE,
+ EL_ROCK, ACTION_EMPTYING, -1
},
{
- Xfake_door_3, TRUE, FALSE,
- EL_EM_GATE_3_GRAY, -1, -1
+ Xsand_stoneout_2, FALSE, FALSE,
+ EL_ROCK, ACTION_EMPTYING, -1
},
{
- Xfake_door_4, TRUE, FALSE,
- EL_EM_GATE_4_GRAY, -1, -1
+ Xsand_stonesand_quickout_1, FALSE, FALSE,
+ EL_QUICKSAND_EMPTYING, -1, -1
},
{
- Xfake_door_5, TRUE, FALSE,
- EL_EMC_GATE_5_GRAY, -1, -1
+ Xsand_stonesand_quickout_2, FALSE, FALSE,
+ EL_QUICKSAND_EMPTYING, -1, -1
},
+
{
- Xfake_door_6, TRUE, FALSE,
- EL_EMC_GATE_6_GRAY, -1, -1
+ Xslide_ns, TRUE, FALSE,
+ EL_EXPANDABLE_WALL_VERTICAL, -1, -1
},
{
- Xfake_door_7, TRUE, FALSE,
- EL_EMC_GATE_7_GRAY, -1, -1
+ Yslide_ns_blank, FALSE, FALSE,
+ EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
},
{
- Xfake_door_8, TRUE, FALSE,
- EL_EMC_GATE_8_GRAY, -1, -1
+ Xslide_ew, TRUE, FALSE,
+ EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
},
{
- Xfake_acid_1, TRUE, FALSE,
- EL_EMC_FAKE_ACID, -1, -1
+ Yslide_ew_blank, FALSE, FALSE,
+ EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
},
+
{
- Xfake_acid_2, FALSE, FALSE,
- EL_EMC_FAKE_ACID, -1, -1
+ Xwind_n, TRUE, FALSE,
+ EL_BALLOON_SWITCH_UP, -1, -1
},
{
- Xfake_acid_3, FALSE, FALSE,
- EL_EMC_FAKE_ACID, -1, -1
+ Xwind_e, TRUE, FALSE,
+ EL_BALLOON_SWITCH_RIGHT, -1, -1
},
{
- Xfake_acid_4, FALSE, FALSE,
- EL_EMC_FAKE_ACID, -1, -1
+ Xwind_s, TRUE, FALSE,
+ EL_BALLOON_SWITCH_DOWN, -1, -1
},
{
- Xfake_acid_5, FALSE, FALSE,
- EL_EMC_FAKE_ACID, -1, -1
+ Xwind_w, TRUE, FALSE,
+ EL_BALLOON_SWITCH_LEFT, -1, -1
},
{
- Xfake_acid_6, FALSE, FALSE,
- EL_EMC_FAKE_ACID, -1, -1
+ Xwind_any, TRUE, FALSE,
+ EL_BALLOON_SWITCH_ANY, -1, -1
},
{
- Xfake_acid_7, FALSE, FALSE,
- EL_EMC_FAKE_ACID, -1, -1
+ Xwind_stop, TRUE, FALSE,
+ EL_BALLOON_SWITCH_NONE, -1, -1
},
+
{
- Xfake_acid_8, FALSE, FALSE,
- EL_EMC_FAKE_ACID, -1, -1
+ Xexit, TRUE, FALSE,
+ EL_EM_EXIT_CLOSED, -1, -1
},
{
- Xsteel_1, TRUE, FALSE,
- EL_STEELWALL, -1, -1
+ Xexit_1, TRUE, FALSE,
+ EL_EM_EXIT_OPEN, -1, -1
},
{
- Xsteel_2, TRUE, FALSE,
- EL_EMC_STEELWALL_2, -1, -1
+ Xexit_2, FALSE, FALSE,
+ EL_EM_EXIT_OPEN, -1, -1
},
{
- Xsteel_3, TRUE, FALSE,
- EL_EMC_STEELWALL_3, -1, -1
+ Xexit_3, FALSE, FALSE,
+ EL_EM_EXIT_OPEN, -1, -1
},
+
{
- Xsteel_4, TRUE, FALSE,
- EL_EMC_STEELWALL_4, -1, -1
+ Xpause, FALSE, FALSE,
+ EL_EMPTY, -1, -1
},
+
{
Xwall_1, TRUE, FALSE,
EL_WALL, -1, -1
Xwall_4, TRUE, FALSE,
EL_EMC_WALL_16, -1, -1
},
+
{
- Xround_wall_1, TRUE, FALSE,
+ Xroundwall_1, TRUE, FALSE,
EL_WALL_SLIPPERY, -1, -1
},
{
- Xround_wall_2, TRUE, FALSE,
+ Xroundwall_2, TRUE, FALSE,
EL_EMC_WALL_SLIPPERY_2, -1, -1
},
{
- Xround_wall_3, TRUE, FALSE,
+ Xroundwall_3, TRUE, FALSE,
EL_EMC_WALL_SLIPPERY_3, -1, -1
},
{
- Xround_wall_4, TRUE, FALSE,
+ Xroundwall_4, TRUE, FALSE,
EL_EMC_WALL_SLIPPERY_4, -1, -1
},
+
+ {
+ Xsteel_1, TRUE, FALSE,
+ EL_STEELWALL, -1, -1
+ },
+ {
+ Xsteel_2, TRUE, FALSE,
+ EL_EMC_STEELWALL_2, -1, -1
+ },
+ {
+ Xsteel_3, TRUE, FALSE,
+ EL_EMC_STEELWALL_3, -1, -1
+ },
+ {
+ Xsteel_4, TRUE, FALSE,
+ EL_EMC_STEELWALL_4, -1, -1
+ },
+
{
Xdecor_1, TRUE, FALSE,
EL_EMC_WALL_8, -1, -1
Xdecor_12, TRUE, FALSE,
EL_EMC_WALL_12, -1, -1
},
+
{
Xalpha_0, TRUE, FALSE,
EL_CHAR('0'), -1, -1
EL_CHAR('!'), -1, -1
},
{
- Xalpha_quote, TRUE, FALSE,
- EL_CHAR('"'), -1, -1
+ Xalpha_apost, TRUE, FALSE,
+ EL_CHAR('\''), -1, -1
},
{
Xalpha_comma, TRUE, FALSE,
},
{
- Xboom_bug, FALSE, FALSE,
- EL_BUG, ACTION_EXPLODING, -1
+ Ykey_1_blank, FALSE, FALSE,
+ EL_EM_KEY_1, ACTION_COLLECTING, -1
},
{
- Xboom_bomb, FALSE, FALSE,
- EL_BOMB, ACTION_EXPLODING, -1
+ Ykey_2_blank, FALSE, FALSE,
+ EL_EM_KEY_2, ACTION_COLLECTING, -1
},
{
- Xboom_android, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_OTHER, -1
+ Ykey_3_blank, FALSE, FALSE,
+ EL_EM_KEY_3, ACTION_COLLECTING, -1
},
{
- Xboom_1, FALSE, FALSE,
- EL_DEFAULT, ACTION_EXPLODING, -1
+ Ykey_4_blank, FALSE, FALSE,
+ EL_EM_KEY_4, ACTION_COLLECTING, -1
},
{
- Xboom_2, FALSE, FALSE,
- EL_DEFAULT, ACTION_EXPLODING, -1
+ Ykey_5_blank, FALSE, FALSE,
+ EL_EMC_KEY_5, ACTION_COLLECTING, -1
},
{
- Znormal, FALSE, FALSE,
- EL_EMPTY, -1, -1
+ Ykey_6_blank, FALSE, FALSE,
+ EL_EMC_KEY_6, ACTION_COLLECTING, -1
},
{
- Zdynamite, FALSE, FALSE,
- EL_EMPTY, -1, -1
+ Ykey_7_blank, FALSE, FALSE,
+ EL_EMC_KEY_7, ACTION_COLLECTING, -1
},
{
- Zplayer, FALSE, FALSE,
- EL_EMPTY, -1, -1
+ Ykey_8_blank, FALSE, FALSE,
+ EL_EMC_KEY_8, ACTION_COLLECTING, -1
},
{
- ZBORDER, FALSE, FALSE,
- EL_EMPTY, -1, -1
+ Ylenses_blank, FALSE, FALSE,
+ EL_EMC_LENSES, ACTION_COLLECTING, -1
+ },
+ {
+ Ymagnify_blank, FALSE, FALSE,
+ EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
+ },
+ {
+ Ygrass_blank, FALSE, FALSE,
+ EL_EMC_GRASS, ACTION_SNAPPING, -1
+ },
+ {
+ Ydirt_blank, FALSE, FALSE,
+ EL_SAND, ACTION_SNAPPING, -1
},
{
int action;
int direction;
}
-em_player_mapping_list[] =
+em_player_mapping_list[MAX_PLAYERS * PLY_MAX + 1] =
{
{
- SPR_walk + 0, 0,
+ PLY_walk_n, 0,
EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
},
{
- SPR_walk + 1, 0,
+ PLY_walk_e, 0,
EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
},
{
- SPR_walk + 2, 0,
+ PLY_walk_s, 0,
EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
},
{
- SPR_walk + 3, 0,
+ PLY_walk_w, 0,
EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
},
{
- SPR_push + 0, 0,
+ PLY_push_n, 0,
EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
},
{
- SPR_push + 1, 0,
+ PLY_push_e, 0,
EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
},
{
- SPR_push + 2, 0,
+ PLY_push_s, 0,
EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
},
{
- SPR_push + 3, 0,
+ PLY_push_w, 0,
EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
},
{
- SPR_spray + 0, 0,
+ PLY_shoot_n, 0,
EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
},
{
- SPR_spray + 1, 0,
+ PLY_shoot_e, 0,
EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
},
{
- SPR_spray + 2, 0,
+ PLY_shoot_s, 0,
EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
},
{
- SPR_spray + 3, 0,
+ PLY_shoot_w, 0,
EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
},
{
- SPR_walk + 0, 1,
+ PLY_walk_n, 1,
EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
},
{
- SPR_walk + 1, 1,
+ PLY_walk_e, 1,
EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
},
{
- SPR_walk + 2, 1,
+ PLY_walk_s, 1,
EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
},
{
- SPR_walk + 3, 1,
+ PLY_walk_w, 1,
EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
},
{
- SPR_push + 0, 1,
+ PLY_push_n, 1,
EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
},
{
- SPR_push + 1, 1,
+ PLY_push_e, 1,
EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
},
{
- SPR_push + 2, 1,
+ PLY_push_s, 1,
EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
},
{
- SPR_push + 3, 1,
+ PLY_push_w, 1,
EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
},
{
- SPR_spray + 0, 1,
+ PLY_shoot_n, 1,
EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
},
{
- SPR_spray + 1, 1,
+ PLY_shoot_e, 1,
EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
},
{
- SPR_spray + 2, 1,
+ PLY_shoot_s, 1,
EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
},
{
- SPR_spray + 3, 1,
+ PLY_shoot_w, 1,
EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
},
{
- SPR_still, 0,
+ PLY_still, 0,
EL_PLAYER_1, ACTION_DEFAULT, -1,
},
{
- SPR_still, 1,
+ PLY_still, 1,
EL_PLAYER_2, ACTION_DEFAULT, -1,
},
{
- SPR_walk + 0, 2,
+ PLY_walk_n, 2,
EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
},
{
- SPR_walk + 1, 2,
+ PLY_walk_e, 2,
EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
},
{
- SPR_walk + 2, 2,
+ PLY_walk_s, 2,
EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
},
{
- SPR_walk + 3, 2,
+ PLY_walk_w, 2,
EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
},
{
- SPR_push + 0, 2,
+ PLY_push_n, 2,
EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
},
{
- SPR_push + 1, 2,
+ PLY_push_e, 2,
EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
},
{
- SPR_push + 2, 2,
+ PLY_push_s, 2,
EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
},
{
- SPR_push + 3, 2,
+ PLY_push_w, 2,
EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
},
{
- SPR_spray + 0, 2,
+ PLY_shoot_n, 2,
EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
},
{
- SPR_spray + 1, 2,
+ PLY_shoot_e, 2,
EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
},
{
- SPR_spray + 2, 2,
+ PLY_shoot_s, 2,
EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
},
{
- SPR_spray + 3, 2,
+ PLY_shoot_w, 2,
EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
},
{
- SPR_walk + 0, 3,
+ PLY_walk_n, 3,
EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
},
{
- SPR_walk + 1, 3,
+ PLY_walk_e, 3,
EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
},
{
- SPR_walk + 2, 3,
+ PLY_walk_s, 3,
EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
},
{
- SPR_walk + 3, 3,
+ PLY_walk_w, 3,
EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
},
{
- SPR_push + 0, 3,
+ PLY_push_n, 3,
EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
},
{
- SPR_push + 1, 3,
+ PLY_push_e, 3,
EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
},
{
- SPR_push + 2, 3,
+ PLY_push_s, 3,
EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
},
{
- SPR_push + 3, 3,
+ PLY_push_w, 3,
EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
},
{
- SPR_spray + 0, 3,
+ PLY_shoot_n, 3,
EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
},
{
- SPR_spray + 1, 3,
+ PLY_shoot_e, 3,
EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
},
{
- SPR_spray + 2, 3,
+ PLY_shoot_s, 3,
EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
},
{
- SPR_spray + 3, 3,
+ PLY_shoot_w, 3,
EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
},
{
- SPR_still, 2,
+ PLY_still, 2,
EL_PLAYER_3, ACTION_DEFAULT, -1,
},
{
- SPR_still, 3,
+ PLY_still, 3,
EL_PLAYER_4, ACTION_DEFAULT, -1,
},
}
};
-int map_element_RND_to_EM(int element_rnd)
+int map_element_RND_to_EM_cave(int element_rnd)
{
static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
static boolean mapping_initialized = FALSE;
{
int i;
- /* return "Xalpha_quest" for all undefined elements in mapping array */
+ // return "Xalpha_quest" for all undefined elements in mapping array
for (i = 0; i < NUM_FILE_ELEMENTS; i++)
mapping_RND_to_EM[i] = Xalpha_quest;
mapping_initialized = TRUE;
}
- if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
- return mapping_RND_to_EM[element_rnd];
+ if (element_rnd < 0 || element_rnd >= NUM_FILE_ELEMENTS)
+ {
+ Warn("invalid RND level element %d", element_rnd);
+
+ return EL_UNKNOWN;
+ }
+
+ return map_em_element_X_to_C(mapping_RND_to_EM[element_rnd]);
+}
+
+int map_element_EM_to_RND_cave(int element_em_cave)
+{
+ static unsigned short mapping_EM_to_RND[GAME_TILE_MAX];
+ static boolean mapping_initialized = FALSE;
+
+ if (!mapping_initialized)
+ {
+ int i;
+
+ // return "EL_UNKNOWN" for all undefined elements in mapping array
+ for (i = 0; i < GAME_TILE_MAX; i++)
+ mapping_EM_to_RND[i] = EL_UNKNOWN;
+
+ for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
+ mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
+ em_object_mapping_list[i].element_rnd;
+
+ mapping_initialized = TRUE;
+ }
+
+ if (element_em_cave < 0 || element_em_cave >= CAVE_TILE_MAX)
+ {
+ Warn("invalid EM cave element %d", element_em_cave);
- Error(ERR_WARN, "invalid RND level element %d", element_rnd);
+ return EL_UNKNOWN;
+ }
- return EL_UNKNOWN;
+ return mapping_EM_to_RND[map_em_element_C_to_X(element_em_cave)];
}
-int map_element_EM_to_RND(int element_em)
+int map_element_EM_to_RND_game(int element_em_game)
{
- static unsigned short mapping_EM_to_RND[TILE_MAX];
+ static unsigned short mapping_EM_to_RND[GAME_TILE_MAX];
static boolean mapping_initialized = FALSE;
if (!mapping_initialized)
{
int i;
- /* return "EL_UNKNOWN" for all undefined elements in mapping array */
- for (i = 0; i < TILE_MAX; i++)
+ // return "EL_UNKNOWN" for all undefined elements in mapping array
+ for (i = 0; i < GAME_TILE_MAX; i++)
mapping_EM_to_RND[i] = EL_UNKNOWN;
for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
mapping_initialized = TRUE;
}
- if (element_em >= 0 && element_em < TILE_MAX)
- return mapping_EM_to_RND[element_em];
+ if (element_em_game < 0 || element_em_game >= GAME_TILE_MAX)
+ {
+ Warn("invalid EM game element %d", element_em_game);
- Error(ERR_WARN, "invalid EM level element %d", element_em);
+ return EL_UNKNOWN;
+ }
- return EL_UNKNOWN;
+ return mapping_EM_to_RND[element_em_game];
}
void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
{
struct LevelInfo_EM *level_em = level->native_em_level;
- struct LEVEL *lev = level_em->lev;
+ struct CAVE *cav = level_em->cav;
int i, j;
- for (i = 0; i < TILE_MAX; i++)
- lev->android_array[i] = Xblank;
+ for (i = 0; i < GAME_TILE_MAX; i++)
+ cav->android_array[i] = Cblank;
for (i = 0; i < level->num_android_clone_elements; i++)
{
int element_rnd = level->android_clone_element[i];
- int element_em = map_element_RND_to_EM(element_rnd);
+ int element_em_cave = map_element_RND_to_EM_cave(element_rnd);
for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
if (em_object_mapping_list[j].element_rnd == element_rnd)
- lev->android_array[em_object_mapping_list[j].element_em] = element_em;
+ cav->android_array[em_object_mapping_list[j].element_em] =
+ element_em_cave;
}
}
void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
{
struct LevelInfo_EM *level_em = level->native_em_level;
- struct LEVEL *lev = level_em->lev;
+ struct CAVE *cav = level_em->cav;
int i, j;
level->num_android_clone_elements = 0;
- for (i = 0; i < TILE_MAX; i++)
+ for (i = 0; i < GAME_TILE_MAX; i++)
{
- int element_em = lev->android_array[i];
+ int element_em_cave = cav->android_array[i];
int element_rnd;
boolean element_found = FALSE;
- if (element_em == Xblank)
+ if (element_em_cave == Cblank)
continue;
- element_rnd = map_element_EM_to_RND(element_em);
+ element_rnd = map_element_EM_to_RND_cave(element_em_cave);
for (j = 0; j < level->num_android_clone_elements; j++)
if (level->android_clone_element[j] == element_rnd)
int map_element_RND_to_SP(int element_rnd)
{
- int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
+ int element_sp = 0x20; // map unknown elements to yellow "hardware"
if (element_rnd >= EL_SP_START &&
element_rnd <= EL_SP_END)
}
}
+int map_element_RND_to_MM(int element_rnd)
+{
+ return (element_rnd >= EL_MM_START_1 &&
+ element_rnd <= EL_MM_END_1 ?
+ EL_MM_START_1_NATIVE + element_rnd - EL_MM_START_1 :
+
+ element_rnd >= EL_MM_START_2 &&
+ element_rnd <= EL_MM_END_2 ?
+ EL_MM_START_2_NATIVE + element_rnd - EL_MM_START_2 :
+
+ element_rnd >= EL_MM_START_3 &&
+ element_rnd <= EL_MM_END_3 ?
+ EL_MM_START_3_NATIVE + element_rnd - EL_MM_START_3 :
+
+ element_rnd >= EL_CHAR_START &&
+ element_rnd <= EL_CHAR_END ?
+ EL_MM_CHAR_START_NATIVE + element_rnd - EL_CHAR_START :
+
+ element_rnd >= EL_MM_RUNTIME_START &&
+ element_rnd <= EL_MM_RUNTIME_END ?
+ EL_MM_RUNTIME_START_NATIVE + element_rnd - EL_MM_RUNTIME_START :
+
+ EL_MM_EMPTY_NATIVE);
+}
+
+int map_element_MM_to_RND(int element_mm)
+{
+ return (element_mm == EL_MM_EMPTY_NATIVE ||
+ element_mm == EL_DF_EMPTY_NATIVE ?
+ EL_EMPTY :
+
+ element_mm >= EL_MM_START_1_NATIVE &&
+ element_mm <= EL_MM_END_1_NATIVE ?
+ EL_MM_START_1 + element_mm - EL_MM_START_1_NATIVE :
+
+ element_mm >= EL_MM_START_2_NATIVE &&
+ element_mm <= EL_MM_END_2_NATIVE ?
+ EL_MM_START_2 + element_mm - EL_MM_START_2_NATIVE :
+
+ element_mm >= EL_MM_START_3_NATIVE &&
+ element_mm <= EL_MM_END_3_NATIVE ?
+ EL_MM_START_3 + element_mm - EL_MM_START_3_NATIVE :
+
+ element_mm >= EL_MM_CHAR_START_NATIVE &&
+ element_mm <= EL_MM_CHAR_END_NATIVE ?
+ EL_CHAR_START + element_mm - EL_MM_CHAR_START_NATIVE :
+
+ element_mm >= EL_MM_RUNTIME_START_NATIVE &&
+ element_mm <= EL_MM_RUNTIME_END_NATIVE ?
+ EL_MM_RUNTIME_START + element_mm - EL_MM_RUNTIME_START_NATIVE :
+
+ EL_EMPTY);
+}
+
+int map_action_MM_to_RND(int action_mm)
+{
+ // all MM actions are defined to exactly match their RND counterparts
+ return action_mm;
+}
+
+int map_sound_MM_to_RND(int sound_mm)
+{
+ switch (sound_mm)
+ {
+ case SND_MM_GAME_LEVELTIME_CHARGING:
+ return SND_GAME_LEVELTIME_CHARGING;
+
+ case SND_MM_GAME_HEALTH_CHARGING:
+ return SND_GAME_HEALTH_CHARGING;
+
+ default:
+ return SND_UNDEFINED;
+ }
+}
+
+int map_mm_wall_element(int element)
+{
+ return (element >= EL_MM_STEEL_WALL_START &&
+ element <= EL_MM_STEEL_WALL_END ?
+ EL_MM_STEEL_WALL :
+
+ element >= EL_MM_WOODEN_WALL_START &&
+ element <= EL_MM_WOODEN_WALL_END ?
+ EL_MM_WOODEN_WALL :
+
+ element >= EL_MM_ICE_WALL_START &&
+ element <= EL_MM_ICE_WALL_END ?
+ EL_MM_ICE_WALL :
+
+ element >= EL_MM_AMOEBA_WALL_START &&
+ element <= EL_MM_AMOEBA_WALL_END ?
+ EL_MM_AMOEBA_WALL :
+
+ element >= EL_DF_STEEL_WALL_START &&
+ element <= EL_DF_STEEL_WALL_END ?
+ EL_DF_STEEL_WALL :
+
+ element >= EL_DF_WOODEN_WALL_START &&
+ element <= EL_DF_WOODEN_WALL_END ?
+ EL_DF_WOODEN_WALL :
+
+ element);
+}
+
+int map_mm_wall_element_editor(int element)
+{
+ switch (element)
+ {
+ case EL_MM_STEEL_WALL: return EL_MM_STEEL_WALL_START;
+ case EL_MM_WOODEN_WALL: return EL_MM_WOODEN_WALL_START;
+ case EL_MM_ICE_WALL: return EL_MM_ICE_WALL_START;
+ case EL_MM_AMOEBA_WALL: return EL_MM_AMOEBA_WALL_START;
+ case EL_DF_STEEL_WALL: return EL_DF_STEEL_WALL_START;
+ case EL_DF_WOODEN_WALL: return EL_DF_WOODEN_WALL_START;
+
+ default: return element;
+ }
+}
+
int get_next_element(int element)
{
switch (element)
}
}
+int el2img_mm(int element_mm)
+{
+ return el2img(map_element_MM_to_RND(element_mm));
+}
+
+int el_act2img_mm(int element_mm, int action)
+{
+ return el_act2img(map_element_MM_to_RND(element_mm), action);
+}
+
int el_act_dir2img(int element, int action, int direction)
{
element = GFX_ELEMENT(element);
- direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
+ direction = MV_DIR_TO_BIT(direction); // default: MV_NONE => MV_DOWN
- /* direction_graphic[][] == graphic[] for undefined direction graphics */
+ // direction_graphic[][] == graphic[] for undefined direction graphics
return element_info[element].direction_graphic[action][direction];
}
static int el_act_dir2crm(int element, int action, int direction)
{
element = GFX_ELEMENT(element);
- direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
+ direction = MV_DIR_TO_BIT(direction); // default: MV_NONE => MV_DOWN
- /* direction_graphic[][] == graphic[] for undefined direction graphics */
+ // direction_graphic[][] == graphic[] for undefined direction graphics
return element_info[element].direction_crumbled[action][direction];
}
return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
}
-boolean getTeamMode_EM()
+boolean swapTiles_EM(boolean is_pre_emc_cave)
{
- return game.team_mode;
+ return is_pre_emc_cave && leveldir_current->use_emc_tiles;
}
-int getGameFrameDelay_EM(int native_em_game_frame_delay)
+boolean getTeamMode_EM(void)
{
- int game_frame_delay_value;
-
- game_frame_delay_value =
- (tape.playing && tape.fast_forward ? FfwdFrameDelay :
- GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
- GameFrameDelay);
-
- if (tape.playing && tape.warp_forward && !tape.pausing)
- game_frame_delay_value = 0;
+ return game.team_mode || network_playing;
+}
- return game_frame_delay_value;
+boolean isActivePlayer_EM(int player_nr)
+{
+ return stored_player[player_nr].active;
}
unsigned int InitRND(int seed)
{
- if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
+ if (level.game_engine_type == GAME_ENGINE_TYPE_BD)
+ return InitEngineRandom_BD(seed);
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
return InitEngineRandom_EM(seed);
else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
return InitEngineRandom_SP(seed);
+ else if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+ return InitEngineRandom_MM(seed);
else
return InitEngineRandom_RND(seed);
}
-static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
-static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
+static struct Mapping_BD_to_RND_object bd_object_mapping[O_MAX_ALL];
+static struct Mapping_EM_to_RND_object em_object_mapping[GAME_TILE_MAX];
+static struct Mapping_EM_to_RND_player em_player_mapping[MAX_PLAYERS][PLY_MAX];
-inline static int get_effective_element_EM(int tile, int frame_em)
+static int get_effective_element_EM(int tile, int frame_em)
{
- int element = object_mapping[tile].element_rnd;
- int action = object_mapping[tile].action;
- boolean is_backside = object_mapping[tile].is_backside;
+ int element = em_object_mapping[tile].element_rnd;
+ int action = em_object_mapping[tile].action;
+ boolean is_backside = em_object_mapping[tile].is_backside;
boolean action_removing = (action == ACTION_DIGGING ||
action == ACTION_SNAPPING ||
action == ACTION_COLLECTING);
{
switch (tile)
{
- case Yacid_splash_eB:
- case Yacid_splash_wB:
+ case Xsplash_e:
+ case Xsplash_w:
return (frame_em > 5 ? EL_EMPTY : element);
default:
return element;
}
}
- else /* frame_em == 7 */
+ else // frame_em == 7
{
switch (tile)
{
- case Yacid_splash_eB:
- case Yacid_splash_wB:
+ case Xsplash_e:
+ case Xsplash_w:
return EL_EMPTY;
- case Yemerald_stone:
+ case Ynut_stone:
return EL_EMERALD;
case Ydiamond_stone:
case Xdrip_stretch:
case Xdrip_stretchB:
- case Ydrip_s1:
- case Ydrip_s1B:
- case Xball_1B:
+ case Ydrip_1_s:
+ case Ydrip_1_sB:
+ case Yball_1:
case Xball_2:
- case Xball_2B:
- case Yball_eat:
- case Ykey_1_eat:
- case Ykey_2_eat:
- case Ykey_3_eat:
- case Ykey_4_eat:
- case Ykey_5_eat:
- case Ykey_6_eat:
- case Ykey_7_eat:
- case Ykey_8_eat:
- case Ylenses_eat:
- case Ymagnify_eat:
- case Ygrass_eat:
- case Ydirt_eat:
+ case Yball_2:
+ case Yball_blank:
+ case Ykey_1_blank:
+ case Ykey_2_blank:
+ case Ykey_3_blank:
+ case Ykey_4_blank:
+ case Ykey_5_blank:
+ case Ykey_6_blank:
+ case Ykey_7_blank:
+ case Ykey_8_blank:
+ case Ylenses_blank:
+ case Ymagnify_blank:
+ case Ygrass_blank:
+ case Ydirt_blank:
case Xsand_stonein_1:
case Xsand_stonein_2:
case Xsand_stonein_3:
}
}
-inline static boolean check_linear_animation_EM(int tile)
+static boolean check_linear_animation_EM(int tile)
{
switch (tile)
{
case Ytank_s_e:
case Ytank_w_s:
case Ytank_n_w:
- case Yacid_splash_eB:
- case Yacid_splash_wB:
- case Yemerald_stone:
+ case Xsplash_e:
+ case Xsplash_w:
+ case Ynut_stone:
return TRUE;
}
return FALSE;
}
-inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
- boolean has_crumbled_graphics,
- int crumbled, int sync_frame)
+static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
+ boolean has_crumbled_graphics,
+ int crumbled, int sync_frame)
{
- /* if element can be crumbled, but certain action graphics are just empty
- space (like instantly snapping sand to empty space in 1 frame), do not
- treat these empty space graphics as crumbled graphics in EMC engine */
+ // if element can be crumbled, but certain action graphics are just empty
+ // space (like instantly snapping sand to empty space in 1 frame), do not
+ // treat these empty space graphics as crumbled graphics in EMC engine
if (crumbled == IMG_EMPTY_SPACE)
has_crumbled_graphics = FALSE;
&g_em->crumbled_src_x, &g_em->crumbled_src_y);
g_em->crumbled_border_size = graphic_info[crumbled].border_size;
+ g_em->crumbled_tile_size = graphic_info[crumbled].tile_size;
g_em->has_crumbled_graphics = TRUE;
}
g_em->crumbled_src_x = 0;
g_em->crumbled_src_y = 0;
g_em->crumbled_border_size = 0;
+ g_em->crumbled_tile_size = 0;
g_em->has_crumbled_graphics = FALSE;
}
}
+#if 0
void ResetGfxAnimation_EM(int x, int y, int tile)
{
GfxFrame[x][y] = 0;
}
+#endif
void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
int tile, int frame_em, int x, int y)
{
- int action = object_mapping[tile].action;
- int direction = object_mapping[tile].direction;
+ int action = em_object_mapping[tile].action;
+ int direction = em_object_mapping[tile].direction;
int effective_element = get_effective_element_EM(tile, frame_em);
int graphic = (direction == MV_NONE ?
el_act2img(effective_element, action) :
action == ACTION_FILLING ||
action == ACTION_EMPTYING);
- /* special case: graphic uses "2nd movement tile" and has defined
- 7 frames for movement animation (or less) => use default graphic
- for last (8th) frame which ends the movement animation */
+ // special case: graphic uses "2nd movement tile" and has defined
+ // 7 frames for movement animation (or less) => use default graphic
+ // for last (8th) frame which ends the movement animation
if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
{
- action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
+ action = ACTION_DEFAULT; // (keep action_* unchanged for now)
graphic = (direction == MV_NONE ?
el_act2img(effective_element, action) :
el_act_dir2img(effective_element, action, direction));
}
else if (action_moving)
{
- boolean is_backside = object_mapping[tile].is_backside;
+ boolean is_backside = em_object_mapping[tile].is_backside;
if (is_backside)
{
- int direction = object_mapping[tile].direction;
+ int direction = em_object_mapping[tile].direction;
int move_dir = (action_falling ? MV_DOWN : direction);
GfxFrame[x][y]++;
#if 1
- /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
+ // !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!!
if (g->double_movement && frame_em == 0)
GfxFrame[x][y] = 0;
#endif
{
GfxFrame[x][y]++;
- /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
+ // special case: animation for Xsand_stonesand_quickout_1/2 twice as fast
if (tile == Xsand_stonesand_quickout_1 ||
tile == Xsand_stonesand_quickout_2)
GfxFrame[x][y]++;
if (graphic_info[graphic].anim_global_sync)
sync_frame = FrameCounter;
+ else if (graphic_info[graphic].anim_global_anim_sync)
+ sync_frame = getGlobalAnimSyncFrame();
else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
sync_frame = GfxFrame[x][y];
else
- sync_frame = 0; /* playfield border (pseudo steel) */
+ sync_frame = 0; // playfield border (pseudo steel)
SetRandomAnimationValue(x, y);
void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
int tile, int frame_em, int x, int y)
{
- int action = object_mapping[tile].action;
- int direction = object_mapping[tile].direction;
- boolean is_backside = object_mapping[tile].is_backside;
+ int action = em_object_mapping[tile].action;
+ int direction = em_object_mapping[tile].direction;
+ boolean is_backside = em_object_mapping[tile].is_backside;
int effective_element = get_effective_element_EM(tile, frame_em);
int effective_action = action;
int graphic = (direction == MV_NONE ?
struct GraphicInfo *g = &graphic_info[graphic];
int sync_frame;
- /* special case: graphic uses "2nd movement tile" and has defined
- 7 frames for movement animation (or less) => use default graphic
- for last (8th) frame which ends the movement animation */
+ // special case: graphic uses "2nd movement tile" and has defined
+ // 7 frames for movement animation (or less) => use default graphic
+ // for last (8th) frame which ends the movement animation
if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
{
effective_action = ACTION_DEFAULT;
if (graphic_info[graphic].anim_global_sync)
sync_frame = FrameCounter;
+ else if (graphic_info[graphic].anim_global_anim_sync)
+ sync_frame = getGlobalAnimSyncFrame();
else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
sync_frame = GfxFrame[x][y];
else
- sync_frame = 0; /* playfield border (pseudo steel) */
+ sync_frame = 0; // playfield border (pseudo steel)
SetRandomAnimationValue(x, y);
getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
g->double_movement && is_backside);
- /* (updating the "crumbled" graphic definitions is probably not really needed,
- as animations for crumbled graphics can't be longer than one EMC cycle) */
+ // (updating the "crumbled" graphic definitions is probably not really needed,
+ // as animations for crumbled graphics can't be longer than one EMC cycle)
set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
sync_frame);
}
void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
int player_nr, int anim, int frame_em)
{
- int element = player_mapping[player_nr][anim].element_rnd;
- int action = player_mapping[player_nr][anim].action;
- int direction = player_mapping[player_nr][anim].direction;
+ int element = em_player_mapping[player_nr][anim].element_rnd;
+ int action = em_player_mapping[player_nr][anim].action;
+ int direction = em_player_mapping[player_nr][anim].direction;
int graphic = (direction == MV_NONE ?
el_act2img(element, action) :
el_act_dir2img(element, action, direction));
&g_em->src_x, &g_em->src_y, FALSE);
}
-void InitGraphicInfo_EM(void)
+#define BD_GFX_RANGE(a, n, i) ((i) >= (a) && (i) < (a) + (n))
+#define BD_GFX_FRAME(b, i) (((i) - (b)) * 8)
+
+void InitGraphicInfo_BD(void)
{
- int i, j, p;
+ int i, j;
-#if DEBUG_EM_GFX
- int num_em_gfx_errors = 0;
+ // always start with reliable default values
+ for (i = 0; i < O_MAX_ALL; i++)
+ {
+ bd_object_mapping[i].element_rnd = EL_UNKNOWN;
+ bd_object_mapping[i].action = ACTION_DEFAULT;
+ bd_object_mapping[i].direction = MV_NONE;
+ }
- if (graphic_info_em_object[0][0].bitmap == NULL)
+ for (i = 0; bd_object_mapping_list[i].element_bd != -1; i++)
{
- /* EM graphics not yet initialized in em_open_all() */
+ int e = bd_object_mapping_list[i].element_bd;
- return;
+ bd_object_mapping[e].element_rnd = bd_object_mapping_list[i].element_rnd;
+
+ if (bd_object_mapping_list[i].action != -1)
+ bd_object_mapping[e].action = bd_object_mapping_list[i].action;
+
+ if (bd_object_mapping_list[i].direction != -1)
+ bd_object_mapping[e].direction =
+ MV_DIR_FROM_BIT(bd_object_mapping_list[i].direction);
}
- printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
-#endif
+ for (i = 0; i < O_MAX_ALL; i++)
+ {
+ int element = bd_object_mapping[i].element_rnd;
+ int action = bd_object_mapping[i].action;
+ int direction = bd_object_mapping[i].direction;
+
+ for (j = 0; j < 8; j++)
+ {
+ int effective_element = element;
+ int effective_action = action;
+ int graphic = (el_act_dir2img(effective_element, effective_action,
+ direction));
+ struct GraphicInfo *g = &graphic_info[graphic];
+ struct GraphicInfo_BD *g_bd = &graphic_info_bd_object[i][j];
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+ int sync_frame = (BD_GFX_RANGE(O_PRE_PL_1, 3, i) ? BD_GFX_FRAME(O_PRE_PL_1, i) :
+ BD_GFX_RANGE(O_PRE_DIA_1, 5, i) ? BD_GFX_FRAME(O_PRE_DIA_1, i) :
+ BD_GFX_RANGE(O_PRE_STONE_1, 4, i) ? BD_GFX_FRAME(O_PRE_STONE_1, i) :
+ BD_GFX_RANGE(O_PRE_STEEL_1, 4, i) ? BD_GFX_FRAME(O_PRE_STEEL_1, i) :
+ BD_GFX_RANGE(O_BOMB_TICK_1, 7, i) ? BD_GFX_FRAME(O_BOMB_TICK_1, i) :
+ BD_GFX_RANGE(O_BOMB_EXPL_1, 4, i) ? BD_GFX_FRAME(O_BOMB_EXPL_1, i) :
+ BD_GFX_RANGE(O_NUT_EXPL_1, 4, i) ? BD_GFX_FRAME(O_NUT_EXPL_1, i) :
+ BD_GFX_RANGE(O_GHOST_EXPL_1, 4, i) ? BD_GFX_FRAME(O_GHOST_EXPL_1, i) :
+ BD_GFX_RANGE(O_EXPLODE_1, 5, i) ? BD_GFX_FRAME(O_EXPLODE_1, i) :
+ BD_GFX_RANGE(O_PRE_CLOCK_1, 4, i) ? BD_GFX_FRAME(O_PRE_CLOCK_1, i) :
+ BD_GFX_RANGE(O_NITRO_EXPL_1, 4, i) ? BD_GFX_FRAME(O_NITRO_EXPL_1, i) :
+ BD_GFX_RANGE(O_AMOEBA_2_EXPL_1, 4, i) ? BD_GFX_FRAME(O_AMOEBA_2_EXPL_1, i):
+ i == O_INBOX_OPEN || i == O_OUTBOX_OPEN ? j :
+ j * 2);
+ int frame = getAnimationFrame(g->anim_frames,
+ g->anim_delay,
+ g->anim_mode,
+ g->anim_start_frame,
+ sync_frame);
+
+ getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
+
+ g_bd->bitmap = src_bitmap;
+ g_bd->src_x = src_x;
+ g_bd->src_y = src_y;
+ g_bd->width = TILEX;
+ g_bd->height = TILEY;
+ }
+ }
+}
+
+void InitGraphicInfo_EM(void)
+{
+ int i, j, p;
- /* always start with reliable default values */
- for (i = 0; i < TILE_MAX; i++)
+ // always start with reliable default values
+ for (i = 0; i < GAME_TILE_MAX; i++)
{
- object_mapping[i].element_rnd = EL_UNKNOWN;
- object_mapping[i].is_backside = FALSE;
- object_mapping[i].action = ACTION_DEFAULT;
- object_mapping[i].direction = MV_NONE;
+ em_object_mapping[i].element_rnd = EL_UNKNOWN;
+ em_object_mapping[i].is_backside = FALSE;
+ em_object_mapping[i].action = ACTION_DEFAULT;
+ em_object_mapping[i].direction = MV_NONE;
}
- /* always start with reliable default values */
+ // always start with reliable default values
for (p = 0; p < MAX_PLAYERS; p++)
{
- for (i = 0; i < SPR_MAX; i++)
+ for (i = 0; i < PLY_MAX; i++)
{
- player_mapping[p][i].element_rnd = EL_UNKNOWN;
- player_mapping[p][i].action = ACTION_DEFAULT;
- player_mapping[p][i].direction = MV_NONE;
+ em_player_mapping[p][i].element_rnd = EL_UNKNOWN;
+ em_player_mapping[p][i].action = ACTION_DEFAULT;
+ em_player_mapping[p][i].direction = MV_NONE;
}
}
{
int e = em_object_mapping_list[i].element_em;
- object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
- object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
+ em_object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
+ em_object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
if (em_object_mapping_list[i].action != -1)
- object_mapping[e].action = em_object_mapping_list[i].action;
+ em_object_mapping[e].action = em_object_mapping_list[i].action;
if (em_object_mapping_list[i].direction != -1)
- object_mapping[e].direction =
+ em_object_mapping[e].direction =
MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
}
int a = em_player_mapping_list[i].action_em;
int p = em_player_mapping_list[i].player_nr;
- player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
+ em_player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
if (em_player_mapping_list[i].action != -1)
- player_mapping[p][a].action = em_player_mapping_list[i].action;
+ em_player_mapping[p][a].action = em_player_mapping_list[i].action;
if (em_player_mapping_list[i].direction != -1)
- player_mapping[p][a].direction =
+ em_player_mapping[p][a].direction =
MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
}
- for (i = 0; i < TILE_MAX; i++)
+ for (i = 0; i < GAME_TILE_MAX; i++)
{
- int element = object_mapping[i].element_rnd;
- int action = object_mapping[i].action;
- int direction = object_mapping[i].direction;
- boolean is_backside = object_mapping[i].is_backside;
+ int element = em_object_mapping[i].element_rnd;
+ int action = em_object_mapping[i].action;
+ int direction = em_object_mapping[i].direction;
+ boolean is_backside = em_object_mapping[i].is_backside;
boolean action_exploding = ((action == ACTION_EXPLODING ||
action == ACTION_SMASHED_BY_ROCK ||
action == ACTION_SMASHED_BY_SPRING) &&
int effective_action = (j < 7 ? action :
i == Xdrip_stretch ? action :
i == Xdrip_stretchB ? action :
- i == Ydrip_s1 ? action :
- i == Ydrip_s1B ? action :
- i == Xball_1B ? action :
+ i == Ydrip_1_s ? action :
+ i == Ydrip_1_sB ? action :
+ i == Yball_1 ? action :
i == Xball_2 ? action :
- i == Xball_2B ? action :
- i == Yball_eat ? action :
- i == Ykey_1_eat ? action :
- i == Ykey_2_eat ? action :
- i == Ykey_3_eat ? action :
- i == Ykey_4_eat ? action :
- i == Ykey_5_eat ? action :
- i == Ykey_6_eat ? action :
- i == Ykey_7_eat ? action :
- i == Ykey_8_eat ? action :
- i == Ylenses_eat ? action :
- i == Ymagnify_eat ? action :
- i == Ygrass_eat ? action :
- i == Ydirt_eat ? action :
+ i == Yball_2 ? action :
+ i == Yball_blank ? action :
+ i == Ykey_1_blank ? action :
+ i == Ykey_2_blank ? action :
+ i == Ykey_3_blank ? action :
+ i == Ykey_4_blank ? action :
+ i == Ykey_5_blank ? action :
+ i == Ykey_6_blank ? action :
+ i == Ykey_7_blank ? action :
+ i == Ykey_8_blank ? action :
+ i == Ylenses_blank ? action :
+ i == Ymagnify_blank ? action :
+ i == Ygrass_blank ? action :
+ i == Ydirt_blank ? action :
i == Xsand_stonein_1 ? action :
i == Xsand_stonein_2 ? action :
i == Xsand_stonein_3 ? action :
boolean has_action_graphics = (graphic != base_graphic);
boolean has_crumbled_graphics = (base_crumbled != base_graphic);
struct GraphicInfo *g = &graphic_info[graphic];
- struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
+ struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][j];
Bitmap *src_bitmap;
int src_x, src_y;
- /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
+ // ensure to get symmetric 3-frame, 2-delay animations as used in EM
boolean special_animation = (action != ACTION_DEFAULT &&
g->anim_frames == 3 &&
g->anim_delay == 2 &&
g->anim_mode & ANIM_LINEAR);
int sync_frame = (i == Xdrip_stretch ? 7 :
i == Xdrip_stretchB ? 7 :
- i == Ydrip_s2 ? j + 8 :
- i == Ydrip_s2B ? j + 8 :
+ i == Ydrip_2_s ? j + 8 :
+ i == Ydrip_2_sB ? j + 8 :
i == Xacid_1 ? 0 :
i == Xacid_2 ? 10 :
i == Xacid_3 ? 20 :
i == Xfake_acid_6 ? 50 :
i == Xfake_acid_7 ? 60 :
i == Xfake_acid_8 ? 70 :
+ i == Xfake_acid_1_player ? 0 :
+ i == Xfake_acid_2_player ? 10 :
+ i == Xfake_acid_3_player ? 20 :
+ i == Xfake_acid_4_player ? 30 :
+ i == Xfake_acid_5_player ? 40 :
+ i == Xfake_acid_6_player ? 50 :
+ i == Xfake_acid_7_player ? 60 :
+ i == Xfake_acid_8_player ? 70 :
i == Xball_2 ? 7 :
- i == Xball_2B ? j + 8 :
- i == Yball_eat ? j + 1 :
- i == Ykey_1_eat ? j + 1 :
- i == Ykey_2_eat ? j + 1 :
- i == Ykey_3_eat ? j + 1 :
- i == Ykey_4_eat ? j + 1 :
- i == Ykey_5_eat ? j + 1 :
- i == Ykey_6_eat ? j + 1 :
- i == Ykey_7_eat ? j + 1 :
- i == Ykey_8_eat ? j + 1 :
- i == Ylenses_eat ? j + 1 :
- i == Ymagnify_eat ? j + 1 :
- i == Ygrass_eat ? j + 1 :
- i == Ydirt_eat ? j + 1 :
+ i == Yball_2 ? j + 8 :
+ i == Yball_blank ? j + 1 :
+ i == Ykey_1_blank ? j + 1 :
+ i == Ykey_2_blank ? j + 1 :
+ i == Ykey_3_blank ? j + 1 :
+ i == Ykey_4_blank ? j + 1 :
+ i == Ykey_5_blank ? j + 1 :
+ i == Ykey_6_blank ? j + 1 :
+ i == Ykey_7_blank ? j + 1 :
+ i == Ykey_8_blank ? j + 1 :
+ i == Ylenses_blank ? j + 1 :
+ i == Ymagnify_blank ? j + 1 :
+ i == Ygrass_blank ? j + 1 :
+ i == Ydirt_blank ? j + 1 :
i == Xamoeba_1 ? 0 :
i == Xamoeba_2 ? 1 :
i == Xamoeba_3 ? 2 :
i == Xboom_bug && j == 5 ? 2 :
i == Xboom_bug && j == 6 ? 2 :
i == Xboom_bug && j == 7 ? 0 :
- i == Xboom_bomb && j == 1 ? 2 :
- i == Xboom_bomb && j == 2 ? 2 :
- i == Xboom_bomb && j == 3 ? 4 :
- i == Xboom_bomb && j == 4 ? 4 :
- i == Xboom_bomb && j == 5 ? 2 :
- i == Xboom_bomb && j == 6 ? 2 :
- i == Xboom_bomb && j == 7 ? 0 :
+ i == Xboom_tank && j == 1 ? 2 :
+ i == Xboom_tank && j == 2 ? 2 :
+ i == Xboom_tank && j == 3 ? 4 :
+ i == Xboom_tank && j == 4 ? 4 :
+ i == Xboom_tank && j == 5 ? 2 :
+ i == Xboom_tank && j == 6 ? 2 :
+ i == Xboom_tank && j == 7 ? 0 :
i == Xboom_android && j == 7 ? 6 :
i == Xboom_1 && j == 1 ? 2 :
i == Xboom_1 && j == 2 ? 2 :
special_animation && j == 4 ? 3 :
effective_action != action ? 0 :
j);
-
-#if DEBUG_EM_GFX
- Bitmap *debug_bitmap = g_em->bitmap;
- int debug_src_x = g_em->src_x;
- int debug_src_y = g_em->src_y;
-#endif
-
int frame = getAnimationFrame(g->anim_frames,
g->anim_delay,
g->anim_mode,
effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
- int num_steps = (i == Ydrip_s1 ? 16 :
- i == Ydrip_s1B ? 16 :
- i == Ydrip_s2 ? 16 :
- i == Ydrip_s2B ? 16 :
+ int num_steps = (i == Ydrip_1_s ? 16 :
+ i == Ydrip_1_sB ? 16 :
+ i == Ydrip_2_s ? 16 :
+ i == Ydrip_2_sB ? 16 :
i == Xsand_stonein_1 ? 32 :
i == Xsand_stonein_2 ? 32 :
i == Xsand_stonein_3 ? 32 :
i == Xsand_stoneout_2 ? 16 : 8);
int cx = ABS(dx) * (TILEX / num_steps);
int cy = ABS(dy) * (TILEY / num_steps);
- int step_frame = (i == Ydrip_s2 ? j + 8 :
- i == Ydrip_s2B ? j + 8 :
+ int step_frame = (i == Ydrip_2_s ? j + 8 :
+ i == Ydrip_2_sB ? j + 8 :
i == Xsand_stonein_2 ? j + 8 :
i == Xsand_stonein_3 ? j + 16 :
i == Xsand_stonein_4 ? j + 24 :
i == Xsand_stoneout_2 ? j + 8 : j) + 1;
int step = (is_backside ? step_frame : num_steps - step_frame);
- if (is_backside) /* tile where movement starts */
+ if (is_backside) // tile where movement starts
{
if (dx < 0 || dy < 0)
{
g_em->dst_offset_y = cy * step;
}
}
- else /* tile where movement ends */
+ else // tile where movement ends
{
if (dx < 0 || dy < 0)
{
g_em->height = TILEY - cy * step;
}
- /* create unique graphic identifier to decide if tile must be redrawn */
+ // create unique graphic identifier to decide if tile must be redrawn
/* bit 31 - 16 (16 bit): EM style graphic
bit 15 - 12 ( 4 bit): EM style frame
bit 11 - 6 ( 6 bit): graphic width
bit 5 - 0 ( 6 bit): graphic height */
g_em->unique_identifier =
(graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
-
-#if DEBUG_EM_GFX
-
- /* skip check for EMC elements not contained in original EMC artwork */
- if (element == EL_EMC_FAKE_ACID)
- continue;
-
- if (g_em->bitmap != debug_bitmap ||
- g_em->src_x != debug_src_x ||
- g_em->src_y != debug_src_y ||
- g_em->src_offset_x != 0 ||
- g_em->src_offset_y != 0 ||
- g_em->dst_offset_x != 0 ||
- g_em->dst_offset_y != 0 ||
- g_em->width != TILEX ||
- g_em->height != TILEY)
- {
- static int last_i = -1;
-
- if (i != last_i)
- {
- printf("\n");
- last_i = i;
- }
-
- printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
- i, element, element_info[element].token_name,
- element_action_info[effective_action].suffix, direction);
-
- if (element != effective_element)
- printf(" [%d ('%s')]",
- effective_element,
- element_info[effective_element].token_name);
-
- printf("\n");
-
- if (g_em->bitmap != debug_bitmap)
- printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
- j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
-
- if (g_em->src_x != debug_src_x ||
- g_em->src_y != debug_src_y)
- printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
- j, (is_backside ? 'B' : 'F'),
- g_em->src_x, g_em->src_y,
- g_em->src_x / 32, g_em->src_y / 32,
- debug_src_x, debug_src_y,
- debug_src_x / 32, debug_src_y / 32);
-
- if (g_em->src_offset_x != 0 ||
- g_em->src_offset_y != 0 ||
- g_em->dst_offset_x != 0 ||
- g_em->dst_offset_y != 0)
- printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
- j, is_backside,
- g_em->src_offset_x, g_em->src_offset_y,
- g_em->dst_offset_x, g_em->dst_offset_y);
-
- if (g_em->width != TILEX ||
- g_em->height != TILEY)
- printf(" %d (%d): size %d,%d should be %d,%d\n",
- j, is_backside,
- g_em->width, g_em->height, TILEX, TILEY);
-
- num_em_gfx_errors++;
- }
-#endif
-
}
}
- for (i = 0; i < TILE_MAX; i++)
+ for (i = 0; i < GAME_TILE_MAX; i++)
{
for (j = 0; j < 8; j++)
{
- int element = object_mapping[i].element_rnd;
- int action = object_mapping[i].action;
- int direction = object_mapping[i].direction;
- boolean is_backside = object_mapping[i].is_backside;
+ int element = em_object_mapping[i].element_rnd;
+ int action = em_object_mapping[i].action;
+ int direction = em_object_mapping[i].direction;
+ boolean is_backside = em_object_mapping[i].is_backside;
int graphic_action = el_act_dir2img(element, action, direction);
int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
Xspring);
- /* no separate animation for "smashed by rock" -- use rock instead */
- struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
- struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
+ // no separate animation for "smashed by rock" -- use rock instead
+ struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][j];
+ struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][j];
g_em->bitmap = g_xx->bitmap;
g_em->src_x = g_xx->src_x;
for (p = 0; p < MAX_PLAYERS; p++)
{
- for (i = 0; i < SPR_MAX; i++)
+ for (i = 0; i < PLY_MAX; i++)
{
- int element = player_mapping[p][i].element_rnd;
- int action = player_mapping[p][i].action;
- int direction = player_mapping[p][i].direction;
+ int element = em_player_mapping[p][i].element_rnd;
+ int action = em_player_mapping[p][i].action;
+ int direction = em_player_mapping[p][i].direction;
for (j = 0; j < 8; j++)
{
el_act_dir2img(effective_element, effective_action,
direction));
struct GraphicInfo *g = &graphic_info[graphic];
- struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
+ struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][j];
Bitmap *src_bitmap;
int src_x, src_y;
int sync_frame = j;
-
-#if DEBUG_EM_GFX
- Bitmap *debug_bitmap = g_em->bitmap;
- int debug_src_x = g_em->src_x;
- int debug_src_y = g_em->src_y;
-#endif
-
int frame = getAnimationFrame(g->anim_frames,
g->anim_delay,
g->anim_mode,
g_em->dst_offset_y = 0;
g_em->width = TILEX;
g_em->height = TILEY;
-
-#if DEBUG_EM_GFX
-
- /* skip check for EMC elements not contained in original EMC artwork */
- if (element == EL_PLAYER_3 ||
- element == EL_PLAYER_4)
- continue;
-
- if (g_em->bitmap != debug_bitmap ||
- g_em->src_x != debug_src_x ||
- g_em->src_y != debug_src_y)
- {
- static int last_i = -1;
-
- if (i != last_i)
- {
- printf("\n");
- last_i = i;
- }
-
- printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
- p, i, element, element_info[element].token_name,
- element_action_info[effective_action].suffix, direction);
-
- if (element != effective_element)
- printf(" [%d ('%s')]",
- effective_element,
- element_info[effective_element].token_name);
-
- printf("\n");
-
- if (g_em->bitmap != debug_bitmap)
- printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
- j, (int)(g_em->bitmap), (int)(debug_bitmap));
-
- if (g_em->src_x != debug_src_x ||
- g_em->src_y != debug_src_y)
- printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
- j,
- g_em->src_x, g_em->src_y,
- g_em->src_x / 32, g_em->src_y / 32,
- debug_src_x, debug_src_y,
- debug_src_x / 32, debug_src_y / 32);
-
- num_em_gfx_errors++;
- }
-#endif
-
}
}
}
-
-#if DEBUG_EM_GFX
- printf("\n");
- printf("::: [%d errors found]\n", num_em_gfx_errors);
-
- exit(0);
-#endif
}
-void CheckSaveEngineSnapshot_EM(byte action[MAX_PLAYERS], int frame,
- boolean any_player_moving,
- boolean any_player_snapping,
- boolean any_player_dropping)
+static void CheckSaveEngineSnapshot_EM(int frame,
+ boolean any_player_moving,
+ boolean any_player_snapping,
+ boolean any_player_dropping)
{
- static boolean player_was_waiting = TRUE;
-
- if (frame == 0 && !any_player_dropping)
+ if (frame == 7 && !any_player_dropping)
{
- if (!player_was_waiting)
+ if (!local_player->was_waiting)
{
- if (!SaveEngineSnapshotToList())
+ if (!CheckSaveEngineSnapshotToList())
return;
- player_was_waiting = TRUE;
+ local_player->was_waiting = TRUE;
}
}
else if (any_player_moving || any_player_snapping || any_player_dropping)
{
- player_was_waiting = FALSE;
+ local_player->was_waiting = FALSE;
}
}
-void CheckSaveEngineSnapshot_SP(boolean murphy_is_waiting,
- boolean murphy_is_dropping)
+static void CheckSaveEngineSnapshot_SP(boolean murphy_is_waiting,
+ boolean murphy_is_dropping)
{
- static boolean player_was_waiting = TRUE;
-
if (murphy_is_waiting)
{
- if (!player_was_waiting)
+ if (!local_player->was_waiting)
{
- if (!SaveEngineSnapshotToList())
+ if (!CheckSaveEngineSnapshotToList())
return;
- player_was_waiting = TRUE;
+ local_player->was_waiting = TRUE;
}
}
else
{
- player_was_waiting = FALSE;
+ local_player->was_waiting = FALSE;
+ }
+}
+
+static void CheckSaveEngineSnapshot_MM(boolean element_clicked,
+ boolean button_released)
+{
+ if (button_released)
+ {
+ if (game.snapshot.mode == SNAPSHOT_MODE_EVERY_MOVE)
+ CheckSaveEngineSnapshotToList();
+ }
+ else if (element_clicked)
+ {
+ if (game.snapshot.mode != SNAPSHOT_MODE_EVERY_MOVE)
+ CheckSaveEngineSnapshotToList();
+
+ game.snapshot.changed_action = TRUE;
}
}
-void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
- boolean any_player_moving,
- boolean any_player_snapping,
- boolean any_player_dropping)
+boolean CheckSingleStepMode_EM(int frame,
+ boolean any_player_moving,
+ boolean any_player_snapping,
+ boolean any_player_dropping)
{
if (tape.single_step && tape.recording && !tape.pausing)
- if (frame == 0 && !any_player_dropping)
+ if (frame == 7 && !any_player_dropping && FrameCounter > 6)
TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
- CheckSaveEngineSnapshot_EM(action, frame, any_player_moving,
+ CheckSaveEngineSnapshot_EM(frame, any_player_moving,
any_player_snapping, any_player_dropping);
+
+ return tape.pausing;
}
void CheckSingleStepMode_SP(boolean murphy_is_waiting,
boolean murphy_is_dropping)
{
+ boolean murphy_starts_dropping = FALSE;
+ int i;
+
+ for (i = 0; i < MAX_PLAYERS; i++)
+ if (stored_player[i].force_dropping)
+ murphy_starts_dropping = TRUE;
+
if (tape.single_step && tape.recording && !tape.pausing)
- if (murphy_is_waiting)
+ if (murphy_is_waiting && !murphy_starts_dropping)
TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
CheckSaveEngineSnapshot_SP(murphy_is_waiting, murphy_is_dropping);
}
+void CheckSingleStepMode_MM(boolean element_clicked,
+ boolean button_released)
+{
+ if (tape.single_step && tape.recording && !tape.pausing)
+ if (button_released)
+ TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
+
+ CheckSaveEngineSnapshot_MM(element_clicked, button_released);
+}
+
void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
- int graphic, int sync_frame, int x, int y)
+ int graphic, int sync_frame)
{
int frame = getGraphicAnimationFrame(graphic, sync_frame);
return graphic_info[graphic].anim_delay;
}
+boolean getGraphicInfo_NewFrame(int x, int y, int graphic)
+{
+ if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
+ return FALSE;
+
+ if (ANIM_MODE(graphic) & (ANIM_TILED | ANIM_RANDOM_STATIC))
+ return FALSE;
+
+ return TRUE;
+}
+
void PlayMenuSoundExt(int sound)
{
if (sound == SND_UNDEFINED)
PlaySound(sound);
}
-void PlayMenuSound()
+void PlayMenuSound(void)
{
PlayMenuSoundExt(menu.sound[game_status]);
}
PlaySoundLoop(sound);
}
-void PlayMenuSoundIfLoop()
+void PlayMenuSoundIfLoop(void)
{
PlayMenuSoundIfLoopExt(menu.sound[game_status]);
}
if (!setup.sound_music)
return;
- PlayMusic(music);
+ if (IS_LOOP_MUSIC(music))
+ PlayMusicLoop(music);
+ else
+ PlayMusic(music);
+}
+
+void PlayMenuMusic(void)
+{
+ char *curr_music = getCurrentlyPlayingMusicFilename();
+ char *next_music = getMusicInfoEntryFilename(menu.music[game_status]);
+
+ if (!strEqual(curr_music, next_music))
+ PlayMenuMusicExt(menu.music[game_status]);
+}
+
+void PlayMenuSoundsAndMusic(void)
+{
+ PlayMenuSound();
+ PlayMenuMusic();
+}
+
+static void FadeMenuSounds(void)
+{
+ FadeSounds();
+}
+
+static void FadeMenuMusic(void)
+{
+ char *curr_music = getCurrentlyPlayingMusicFilename();
+ char *next_music = getMusicInfoEntryFilename(menu.music[game_status]);
+
+ if (!strEqual(curr_music, next_music))
+ FadeMusic();
}
-void PlayMenuMusic()
+void FadeMenuSoundsAndMusic(void)
{
- PlayMenuMusicExt(menu.music[game_status]);
+ FadeMenuSounds();
+ FadeMenuMusic();
}
-void PlaySoundActivating()
+void PlaySoundActivating(void)
{
#if 0
PlaySound(SND_MENU_ITEM_ACTIVATING);
#endif
}
-void PlaySoundSelecting()
+void PlaySoundSelecting(void)
{
#if 0
PlaySound(SND_MENU_ITEM_SELECTING);
#endif
}
-void ToggleFullscreenOrChangeWindowScalingIfNeeded()
+void ToggleFullscreenIfNeeded(void)
{
- boolean change_fullscreen = (setup.fullscreen !=
- video.fullscreen_enabled);
- boolean change_fullscreen_mode = (video.fullscreen_enabled &&
- !strEqual(setup.fullscreen_mode,
- video.fullscreen_mode_current));
- boolean change_window_scaling_percent = (!video.fullscreen_enabled &&
- setup.window_scaling_percent !=
- video.window_scaling_percent);
-
- if (change_window_scaling_percent && video.fullscreen_enabled)
+ // if setup and video fullscreen state are already matching, nothing do do
+ if (setup.fullscreen == video.fullscreen_enabled ||
+ !video.fullscreen_available)
return;
- if (!change_window_scaling_percent && !video.fullscreen_available)
- return;
+ SDLSetWindowFullscreen(setup.fullscreen);
-#if defined(TARGET_SDL2)
- if (change_window_scaling_percent)
- {
- SDLSetWindowScaling(setup.window_scaling_percent);
+ // set setup value according to successfully changed fullscreen mode
+ setup.fullscreen = video.fullscreen_enabled;
+}
+void ChangeWindowScalingIfNeeded(void)
+{
+ // if setup and video window scaling are already matching, nothing do do
+ if (setup.window_scaling_percent == video.window_scaling_percent ||
+ video.fullscreen_enabled)
return;
- }
- else if (change_fullscreen)
- {
- SDLSetWindowFullscreen(setup.fullscreen);
- /* set setup value according to successfully changed fullscreen mode */
- setup.fullscreen = video.fullscreen_enabled;
+ SDLSetWindowScaling(setup.window_scaling_percent);
+
+ // set setup value according to successfully changed window scaling
+ setup.window_scaling_percent = video.window_scaling_percent;
+}
+void ChangeVsyncModeIfNeeded(void)
+{
+ int setup_vsync_mode = VSYNC_MODE_STR_TO_INT(setup.vsync_mode);
+ int video_vsync_mode = video.vsync_mode;
+
+ // if setup and video vsync mode are already matching, nothing do do
+ if (setup_vsync_mode == video_vsync_mode)
return;
- }
-#endif
- if (change_fullscreen ||
- change_fullscreen_mode ||
- change_window_scaling_percent)
+ // if renderer is using OpenGL, vsync mode can directly be changed
+ SDLSetScreenVsyncMode(setup.vsync_mode);
+
+ // if vsync mode unchanged, try re-creating renderer to set vsync mode
+ if (video.vsync_mode == video_vsync_mode)
{
Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
- /* save backbuffer content which gets lost when toggling fullscreen mode */
+ // save backbuffer content which gets lost when re-creating screen
BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
- if (change_fullscreen_mode)
- {
- /* keep fullscreen, but change fullscreen mode (screen resolution) */
- video.fullscreen_enabled = FALSE; /* force new fullscreen mode */
- }
+ // force re-creating screen and renderer to set new vsync mode
+ video.fullscreen_enabled = !setup.fullscreen;
- if (change_window_scaling_percent)
- {
- /* keep window mode, but change window scaling */
- video.fullscreen_enabled = TRUE; /* force new window scaling */
- }
+ // when creating new renderer, destroy textures linked to old renderer
+ FreeAllImageTextures(); // needs old renderer to free the textures
- /* toggle fullscreen */
+ // re-create screen and renderer (including change of vsync mode)
ChangeVideoModeIfNeeded(setup.fullscreen);
- /* set setup value according to successfully changed fullscreen mode */
+ // set setup value according to successfully changed fullscreen mode
setup.fullscreen = video.fullscreen_enabled;
- /* restore backbuffer content from temporary backbuffer backup bitmap */
+ // restore backbuffer content from temporary backbuffer backup bitmap
BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
-
FreeBitmap(tmp_backbuffer);
- /* update visible window/screen */
+ // update visible window/screen
BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+ // when changing vsync mode, re-create textures for new renderer
+ InitImageTextures();
}
+
+ // set setup value according to successfully changed vsync mode
+ setup.vsync_mode = VSYNC_MODE_INT_TO_STR(video.vsync_mode);
}
-void JoinRectangles(int *x, int *y, int *width, int *height,
- int x2, int y2, int width2, int height2)
+static void JoinRectangles(int *x, int *y, int *width, int *height,
+ int x2, int y2, int width2, int height2)
{
// do not join with "off-screen" rectangle
if (x2 == -1 || y2 == -1)
*height = MAX(*height, height2);
}
-void ChangeViewportPropertiesIfNeeded()
+void SetAnimStatus(int anim_status_new)
+{
+ if (anim_status_new == GAME_MODE_MAIN)
+ anim_status_new = GAME_MODE_PSEUDO_MAINONLY;
+ else if (anim_status_new == GAME_MODE_NAMES)
+ anim_status_new = GAME_MODE_PSEUDO_NAMESONLY;
+ else if (anim_status_new == GAME_MODE_SCORES)
+ anim_status_new = GAME_MODE_PSEUDO_SCORESOLD;
+
+ global.anim_status_next = anim_status_new;
+
+ // directly set screen modes that are entered without fading
+ if ((global.anim_status == GAME_MODE_PSEUDO_MAINONLY &&
+ global.anim_status_next == GAME_MODE_PSEUDO_TYPENAME) ||
+ (global.anim_status == GAME_MODE_PSEUDO_TYPENAME &&
+ global.anim_status_next == GAME_MODE_PSEUDO_MAINONLY) ||
+ (global.anim_status == GAME_MODE_PSEUDO_NAMESONLY &&
+ global.anim_status_next == GAME_MODE_PSEUDO_TYPENAMES) ||
+ (global.anim_status == GAME_MODE_PSEUDO_TYPENAMES &&
+ global.anim_status_next == GAME_MODE_PSEUDO_NAMESONLY))
+ global.anim_status = global.anim_status_next;
+}
+
+void SetGameStatus(int game_status_new)
+{
+ if (game_status_new != game_status)
+ game_status_last_screen = game_status;
+
+ game_status = game_status_new;
+
+ SetAnimStatus(game_status_new);
+}
+
+void SetFontStatus(int game_status_new)
+{
+ static int last_game_status = -1;
+
+ if (game_status_new != -1)
+ {
+ // set game status for font use after storing last game status
+ last_game_status = game_status;
+ game_status = game_status_new;
+ }
+ else
+ {
+ // reset game status after font use from last stored game status
+ game_status = last_game_status;
+ }
+}
+
+void ResetFontStatus(void)
+{
+ SetFontStatus(-1);
+}
+
+void SetLevelSetInfo(char *identifier, int level_nr)
+{
+ setString(&levelset.identifier, identifier);
+
+ levelset.level_nr = level_nr;
+}
+
+boolean CheckIfAllViewportsHaveChanged(void)
+{
+ // if game status has not changed, viewports have not changed either
+ if (game_status == game_status_last)
+ return FALSE;
+
+ // check if all viewports have changed with current game status
+
+ struct RectWithBorder *vp_playfield = &viewport.playfield[game_status];
+ struct RectWithBorder *vp_door_1 = &viewport.door_1[game_status];
+ struct RectWithBorder *vp_door_2 = &viewport.door_2[game_status];
+ int new_real_sx = vp_playfield->x;
+ int new_real_sy = vp_playfield->y;
+ int new_full_sxsize = vp_playfield->width;
+ int new_full_sysize = vp_playfield->height;
+ int new_dx = vp_door_1->x;
+ int new_dy = vp_door_1->y;
+ int new_dxsize = vp_door_1->width;
+ int new_dysize = vp_door_1->height;
+ int new_vx = vp_door_2->x;
+ int new_vy = vp_door_2->y;
+ int new_vxsize = vp_door_2->width;
+ int new_vysize = vp_door_2->height;
+
+ boolean playfield_viewport_has_changed =
+ (new_real_sx != REAL_SX ||
+ new_real_sy != REAL_SY ||
+ new_full_sxsize != FULL_SXSIZE ||
+ new_full_sysize != FULL_SYSIZE);
+
+ boolean door_1_viewport_has_changed =
+ (new_dx != DX ||
+ new_dy != DY ||
+ new_dxsize != DXSIZE ||
+ new_dysize != DYSIZE);
+
+ boolean door_2_viewport_has_changed =
+ (new_vx != VX ||
+ new_vy != VY ||
+ new_vxsize != VXSIZE ||
+ new_vysize != VYSIZE ||
+ game_status_last == GAME_MODE_EDITOR);
+
+ return (playfield_viewport_has_changed &&
+ door_1_viewport_has_changed &&
+ door_2_viewport_has_changed);
+}
+
+boolean CheckFadeAll(void)
+{
+ return (CheckIfGlobalBorderHasChanged() ||
+ CheckIfAllViewportsHaveChanged());
+}
+
+void ChangeViewportPropertiesIfNeeded(void)
{
- int gfx_game_mode = game_status;
- int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
- game_status);
+ boolean use_mini_tilesize = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?
+ FALSE : setup.small_game_graphics);
+ int gfx_game_mode = getGlobalGameStatus(game_status);
+ int gfx_game_mode2 = (gfx_game_mode == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
+ gfx_game_mode);
+ struct RectWithBorder *vp_window = &viewport.window[gfx_game_mode];
struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
- struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
- struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode2];
- struct RectWithBorder *vp_door_3 = &viewport.door_2[GAME_MODE_EDITOR];
- int border_size = vp_playfield->border_size;
- int new_sx = vp_playfield->x + border_size;
- int new_sy = vp_playfield->y + border_size;
- int new_sxsize = vp_playfield->width - 2 * border_size;
- int new_sysize = vp_playfield->height - 2 * border_size;
+ struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
+ struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode2];
+ struct RectWithBorder *vp_door_3 = &viewport.door_2[GAME_MODE_EDITOR];
+ int new_win_xsize = vp_window->width;
+ int new_win_ysize = vp_window->height;
+ int border_left = vp_playfield->border_left;
+ int border_right = vp_playfield->border_right;
+ int border_top = vp_playfield->border_top;
+ int border_bottom = vp_playfield->border_bottom;
+ int new_sx = vp_playfield->x + border_left;
+ int new_sy = vp_playfield->y + border_top;
+ int new_sxsize = vp_playfield->width - border_left - border_right;
+ int new_sysize = vp_playfield->height - border_top - border_bottom;
int new_real_sx = vp_playfield->x;
int new_real_sy = vp_playfield->y;
int new_full_sxsize = vp_playfield->width;
int new_ey = vp_door_3->y;
int new_exsize = vp_door_3->width;
int new_eysize = vp_door_3->height;
- int new_tilesize_var =
- (setup.small_game_graphics ? MINI_TILESIZE : game.tile_size);
-
+ int new_tilesize_var = (use_mini_tilesize ? MINI_TILESIZE : game.tile_size);
int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
int new_scr_fieldx = new_sxsize / tilesize;
int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
boolean init_gfx_buffers = FALSE;
boolean init_video_buffer = FALSE;
- boolean init_gadgets_and_toons = FALSE;
+ boolean init_gadgets_and_anims = FALSE;
+ boolean init_bd_graphics = FALSE;
boolean init_em_graphics = FALSE;
- if (viewport.window.width != WIN_XSIZE ||
- viewport.window.height != WIN_YSIZE)
+ if (new_win_xsize != WIN_XSIZE ||
+ new_win_ysize != WIN_YSIZE)
{
- WIN_XSIZE = viewport.window.width;
- WIN_YSIZE = viewport.window.height;
+ WIN_XSIZE = new_win_xsize;
+ WIN_YSIZE = new_win_ysize;
init_video_buffer = TRUE;
init_gfx_buffers = TRUE;
+ init_gadgets_and_anims = TRUE;
- // printf("::: video: init_video_buffer, init_gfx_buffers\n");
+ // Debug("tools:viewport", "video: init_video_buffer, init_gfx_buffers");
}
if (new_scr_fieldx != SCR_FIELDX ||
new_scr_fieldy != SCR_FIELDY)
{
- /* this always toggles between MAIN and GAME when using small tile size */
+ // this always toggles between MAIN and GAME when using small tile size
SCR_FIELDX = new_scr_fieldx;
SCR_FIELDY = new_scr_fieldy;
- // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
+ // Debug("tools:viewport", "new_scr_fieldx != SCR_FIELDX ...");
}
if (new_sx != SX ||
}
// add current and new door 2 area if position or size has changed
- if (new_dx != VX || new_dy != VY ||
- new_dxsize != VXSIZE || new_dysize != VYSIZE)
+ if (new_vx != VX || new_vy != VY ||
+ new_vxsize != VXSIZE || new_vysize != VYSIZE)
{
JoinRectangles(&FADE_SX, &FADE_SY, &FADE_SXSIZE, &FADE_SYSIZE,
VX, VY, VXSIZE, VYSIZE);
if (new_tilesize_var != TILESIZE_VAR)
{
- // printf("::: new_tilesize_var != TILESIZE_VAR\n");
+ // Debug("tools:viewport", "new_tilesize_var != TILESIZE_VAR");
// changing tile size invalidates scroll values of engine snapshots
FreeEngineSnapshotSingle();
- // changing tile size requires update of graphic mapping for EM engine
+ // changing tile size requires update of graphic mapping for BD/EM engine
+ init_bd_graphics = TRUE;
init_em_graphics = TRUE;
}
TILESIZE_VAR = new_tilesize_var;
init_gfx_buffers = TRUE;
- init_gadgets_and_toons = TRUE;
+ init_gadgets_and_anims = TRUE;
- // printf("::: viewports: init_gfx_buffers\n");
- // printf("::: viewports: init_gadgets_and_toons\n");
+ // Debug("tools:viewport", "viewports: init_gfx_buffers");
+ // Debug("tools:viewport", "viewports: init_gadgets_and_anims");
}
if (init_gfx_buffers)
{
- // printf("::: init_gfx_buffers\n");
+ // Debug("tools:viewport", "init_gfx_buffers");
SCR_FIELDX = new_scr_fieldx_buffers;
SCR_FIELDY = new_scr_fieldy_buffers;
if (init_video_buffer)
{
- // printf("::: init_video_buffer\n");
+ // Debug("tools:viewport", "init_video_buffer");
+
+ FreeAllImageTextures(); // needs old renderer to free the textures
InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
+ InitImageTextures();
}
- if (init_gadgets_and_toons)
+ if (init_gadgets_and_anims)
{
- // printf("::: init_gadgets_and_toons\n");
+ // Debug("tools:viewport", "init_gadgets_and_anims");
InitGadgets();
- InitToons();
+ InitGlobalAnimations();
+ }
+
+ if (init_bd_graphics)
+ {
+ InitGraphicInfo_BD();
}
if (init_em_graphics)
{
- InitGraphicInfo_EM();
+ InitGraphicInfo_EM();
+ }
+}
+
+void OpenURL(char *url)
+{
+#if SDL_VERSION_ATLEAST(2,0,14)
+ SDL_OpenURL(url);
+#else
+ Warn("SDL_OpenURL(\"%s\") not supported by SDL %d.%d.%d!",
+ url, SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL);
+ Warn("Please upgrade to at least SDL 2.0.14 for URL support!");
+#endif
+}
+
+void OpenURLFromHash(SetupFileHash *hash, int hash_key)
+{
+ OpenURL(getHashEntry(hash, int2str(hash_key, 0)));
+}
+
+
+// ============================================================================
+// tests
+// ============================================================================
+
+#if defined(PLATFORM_WINDOWS)
+/* FILETIME of Jan 1 1970 00:00:00. */
+static const unsigned __int64 epoch = ((unsigned __int64) 116444736000000000ULL);
+
+/*
+ * timezone information is stored outside the kernel so tzp isn't used anymore.
+ *
+ * Note: this function is not for Win32 high precision timing purpose. See
+ * elapsed_time().
+ */
+static int gettimeofday_windows(struct timeval * tp, struct timezone * tzp)
+{
+ FILETIME file_time;
+ SYSTEMTIME system_time;
+ ULARGE_INTEGER ularge;
+
+ GetSystemTime(&system_time);
+ SystemTimeToFileTime(&system_time, &file_time);
+ ularge.LowPart = file_time.dwLowDateTime;
+ ularge.HighPart = file_time.dwHighDateTime;
+
+ tp->tv_sec = (long) ((ularge.QuadPart - epoch) / 10000000L);
+ tp->tv_usec = (long) (system_time.wMilliseconds * 1000);
+
+ return 0;
+}
+#endif
+
+static char *test_init_uuid_random_function_simple(void)
+{
+ static char seed_text[100];
+ unsigned int seed = InitSimpleRandom(NEW_RANDOMIZE);
+
+ sprintf(seed_text, "%d", seed);
+
+ return seed_text;
+}
+
+static char *test_init_uuid_random_function_better(void)
+{
+ static char seed_text[100];
+ struct timeval current_time;
+
+ gettimeofday(¤t_time, NULL);
+
+ prng_seed_bytes(¤t_time, sizeof(current_time));
+
+ sprintf(seed_text, "%ld.%ld",
+ (long)current_time.tv_sec,
+ (long)current_time.tv_usec);
+
+ return seed_text;
+}
+
+#if defined(PLATFORM_WINDOWS)
+static char *test_init_uuid_random_function_better_windows(void)
+{
+ static char seed_text[100];
+ struct timeval current_time;
+
+ gettimeofday_windows(¤t_time, NULL);
+
+ prng_seed_bytes(¤t_time, sizeof(current_time));
+
+ sprintf(seed_text, "%ld.%ld",
+ (long)current_time.tv_sec,
+ (long)current_time.tv_usec);
+
+ return seed_text;
+}
+#endif
+
+static unsigned int test_uuid_random_function_simple(int max)
+{
+ return GetSimpleRandom(max);
+}
+
+static unsigned int test_uuid_random_function_better(int max)
+{
+ return (max > 0 ? prng_get_uint() % max : 0);
+}
+
+#if defined(PLATFORM_WINDOWS)
+#define NUM_UUID_TESTS 3
+#else
+#define NUM_UUID_TESTS 2
+#endif
+
+static void TestGeneratingUUIDs_RunTest(int nr, int always_seed, int num_uuids)
+{
+ struct hashtable *hash_seeds =
+ create_hashtable(16, 0.75, get_hash_from_key, hash_keys_are_equal);
+ struct hashtable *hash_uuids =
+ create_hashtable(16, 0.75, get_hash_from_key, hash_keys_are_equal);
+ static char message[100];
+ int i;
+
+ char *random_name = (nr == 0 ? "simple" : "better");
+ char *random_type = (always_seed ? "always" : "only once");
+ char *(*init_random_function)(void) =
+ (nr == 0 ?
+ test_init_uuid_random_function_simple :
+ test_init_uuid_random_function_better);
+ unsigned int (*random_function)(int) =
+ (nr == 0 ?
+ test_uuid_random_function_simple :
+ test_uuid_random_function_better);
+ int xpos = 40;
+
+#if defined(PLATFORM_WINDOWS)
+ if (nr == 2)
+ {
+ random_name = "windows";
+ init_random_function = test_init_uuid_random_function_better_windows;
+ }
+#endif
+
+ ClearField();
+
+ DrawTextF(xpos, 40, FC_GREEN, "Test: Generating UUIDs");
+ DrawTextF(xpos, 80, FC_YELLOW, "Test %d.%d:", nr + 1, always_seed + 1);
+
+ DrawTextF(xpos, 100, FC_YELLOW, "Random Generator Name: %s", random_name);
+ DrawTextF(xpos, 120, FC_YELLOW, "Seeding Random Generator: %s", random_type);
+ DrawTextF(xpos, 140, FC_YELLOW, "Number of UUIDs generated: %d", num_uuids);
+
+ DrawTextF(xpos, 180, FC_GREEN, "Please wait ...");
+
+ BackToFront();
+
+ // always initialize random number generator at least once
+ init_random_function();
+
+ unsigned int time_start = SDL_GetTicks();
+
+ for (i = 0; i < num_uuids; i++)
+ {
+ if (always_seed)
+ {
+ char *seed = getStringCopy(init_random_function());
+
+ hashtable_remove(hash_seeds, seed);
+ hashtable_insert(hash_seeds, seed, "1");
+ }
+
+ char *uuid = getStringCopy(getUUIDExt(random_function));
+
+ hashtable_remove(hash_uuids, uuid);
+ hashtable_insert(hash_uuids, uuid, "1");
}
+
+ int num_unique_seeds = hashtable_count(hash_seeds);
+ int num_unique_uuids = hashtable_count(hash_uuids);
+
+ unsigned int time_needed = SDL_GetTicks() - time_start;
+
+ DrawTextF(xpos, 220, FC_YELLOW, "Time needed: %d ms", time_needed);
+
+ DrawTextF(xpos, 240, FC_YELLOW, "Number of unique UUIDs: %d", num_unique_uuids);
+
+ if (always_seed)
+ DrawTextF(xpos, 260, FC_YELLOW, "Number of unique seeds: %d", num_unique_seeds);
+
+ if (nr == NUM_UUID_TESTS - 1 && always_seed)
+ DrawTextF(xpos, 300, FC_GREEN, "All tests done!");
+ else
+ DrawTextF(xpos, 300, FC_GREEN, "Confirm dialog for next test ...");
+
+ sprintf(message, "Test %d.%d finished!", nr + 1, always_seed + 1);
+
+ Request(message, REQ_CONFIRM);
+
+ hashtable_destroy(hash_seeds, 0);
+ hashtable_destroy(hash_uuids, 0);
+}
+
+void TestGeneratingUUIDs(void)
+{
+ int num_uuids = 1000000;
+ int i, j;
+
+ for (i = 0; i < NUM_UUID_TESTS; i++)
+ for (j = 0; j < 2; j++)
+ TestGeneratingUUIDs_RunTest(i, j, num_uuids);
+
+ CloseAllAndExit(0);
}