X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ftools.c;h=c859e633975d4e6819e78a298c16ba0db0d3e134;hb=refs%2Fheads%2Fmaster-next-major-release;hp=c1b367a600776bad7a9a9bd163ef8de58e6d74fb;hpb=7b969bbc735e5a6754610952d1f815c5d3886611;p=rocksndiamonds.git diff --git a/src/tools.c b/src/tools.c index c1b367a6..d56532d1 100644 --- a/src/tools.c +++ b/src/tools.c @@ -500,7 +500,9 @@ 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); @@ -646,9 +648,11 @@ void DrawMaskedBorderToTarget(int draw_target) } } -void DrawTileCursor(int draw_target) +void DrawTileCursor(int draw_target, int drawing_stage) { - DrawTileCursor_MM(draw_target, game_status == GAME_MODE_PLAYING); + 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) @@ -666,7 +670,9 @@ void BlitScreenToBitmap_RND(Bitmap *target_bitmap) 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); @@ -1024,6 +1030,10 @@ void FadeOut(int fade_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); @@ -1515,6 +1525,11 @@ 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 @@ -2803,12 +2818,14 @@ static void DrawSizedElementExt(int x, int y, int element, int tilesize, } else { - int graphic = el2edimg(element); + int graphic, frame; + + el2edimg_with_frame(element, &graphic, &frame); if (masked) - DrawSizedGraphicThruMask(x, y, graphic, 0, tilesize); + DrawSizedGraphicThruMask(x, y, graphic, frame, tilesize); else - DrawSizedGraphic(x, y, graphic, 0, tilesize); + DrawSizedGraphic(x, y, graphic, frame, tilesize); } } @@ -3054,6 +3071,8 @@ static void PrepareEnvelopeRequestToScreen(Bitmap *bitmap, int sx, int sy, SDLFreeBitmapTextures(request.bitmap); SDLCreateBitmapTextures(request.bitmap); + ResetBitmapAlpha(request.bitmap); + // set envelope request run-time values request.sx = sx; request.sy = sy; @@ -3067,7 +3086,11 @@ void DrawEnvelopeRequestToScreen(int drawing_target) game.request_active && drawing_target == DRAW_TO_SCREEN) { - if (graphic_info[IMG_BACKGROUND_REQUEST].draw_masked) + 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 @@ -3143,9 +3166,8 @@ static void setRequestPosition(int *x, int *y, boolean add_border_size) setRequestPositionExt(x, y, request.width, request.height, add_border_size); } -static void DrawEnvelopeRequest(char *text, unsigned int req_state) +static void DrawEnvelopeRequestText(int sx, int sy, char *text) { - DrawBuffer *drawto_last = drawto; char *text_final = text; char *text_door_style = NULL; int graphic = IMG_BACKGROUND_REQUEST; @@ -3162,15 +3184,11 @@ static void DrawEnvelopeRequest(char *text, unsigned int req_state) 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 x, y; + + // force DOOR font inside door area + SetFontStatus(GAME_MODE_PSEUDO_DOOR); if (request.centered) sx_offset = (request.width - text_width) / 2; @@ -3179,6 +3197,13 @@ static void DrawEnvelopeRequest(char *text, unsigned int req_state) { 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; @@ -3202,6 +3227,28 @@ static void DrawEnvelopeRequest(char *text, unsigned int req_state) 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); // draw complete envelope request to temporary bitmap @@ -3215,14 +3262,8 @@ static void DrawEnvelopeRequest(char *text, unsigned int req_state) x, y, x_steps, y_steps, tile_size, tile_size); - // force DOOR font inside door area - SetFontStatus(GAME_MODE_PSEUDO_DOOR); - - 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); - - ResetFontStatus(); + // write text for request + DrawEnvelopeRequestText(sx, sy, text); MapToolButtons(req_state); @@ -3231,9 +3272,6 @@ static void DrawEnvelopeRequest(char *text, unsigned int req_state) // prepare complete envelope request from temporary bitmap PrepareEnvelopeRequestToScreen(bitmap_db_store_1, sx, sy, width, height); - - if (text_door_style) - free(text_door_style); } static void AnimateEnvelopeRequest(int anim_mode, int action) @@ -3360,6 +3398,14 @@ static void ShowEnvelopeRequest(char *text, unsigned int req_state, int action) game.envelope_active = FALSE; } +static Bitmap *GetPreviewTileBitmap(Bitmap *bitmap) +{ + if (level.game_engine_type == GAME_ENGINE_TYPE_BD) + return GetPreviewTileBitmap_BD(bitmap); + + return bitmap; +} + static void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize) { if (IS_MM_WALL(element)) @@ -3373,6 +3419,10 @@ static void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize) int graphic = el2preimg(element); getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y); + + // for BD style levels, maybe use bitmap with level-specific colors + src_bitmap = GetPreviewTileBitmap(src_bitmap); + BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x, dst_y); } @@ -3417,11 +3467,27 @@ void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y) redraw_mask |= REDRAW_FIELD; } +static int getPreviewLevelWidth(void) +{ + if (level.game_engine_type == GAME_ENGINE_TYPE_BD) + return (level.native_bd_level->cave->x2 - level.native_bd_level->cave->x1 + 1); + + return lev_fieldx; +} + +static int getPreviewLevelHeight(void) +{ + if (level.game_engine_type == GAME_ENGINE_TYPE_BD) + return (level.native_bd_level->cave->y2 - level.native_bd_level->cave->y1 + 1); + + return lev_fieldy; +} + 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); - int level_ysize = lev_fieldy + (show_level_border ? 2 : 0); + int level_xsize = getPreviewLevelWidth() + (show_level_border ? 2 : 0); + int level_ysize = getPreviewLevelHeight() + (show_level_border ? 2 : 0); int tile_size = preview.tile_size; int preview_width = preview.xsize * tile_size; int preview_height = preview.ysize * tile_size; @@ -3779,8 +3845,35 @@ void DrawPreviewPlayers(void) } } +static void PreparePreviewTileBitmap(void) +{ + // check if special preview bitmap with level-specific colors should be created + if (level.game_engine_type != GAME_ENGINE_TYPE_BD) + return; + + // use original sized bitmap (else reduced color palette is lost by downscaling) + int original_tilesize = MAX(MINI_TILESIZE, preview.tile_size); + int scale_down_factor = original_tilesize / preview.tile_size; + Bitmap *src_bitmap; + int src_x, src_y; + int element_template = EL_BDX_GAME_GRAPHICS_COLOR_TEMPLATE; + int graphic_template = el2preimg(element_template); + int element_default = EL_BDX_ROCK; + int graphic_default = el2preimg(element_default); + + // create special preview bitmap and scale it down to preview tile size + getSizedGraphicSource(graphic_template, 0, original_tilesize, &src_bitmap, &src_x, &src_y); + PreparePreviewTileBitmap_BD(src_bitmap, scale_down_factor); + + // force using special preview bitmap to replace original preview bitmap + getSizedGraphicSource(graphic_default, 0, preview.tile_size, &src_bitmap, &src_x, &src_y); + SetPreviewTileBitmapReference_BD(src_bitmap); +} + void DrawPreviewLevelInitial(void) { + PreparePreviewTileBitmap(); // only needed for native BD style levels + DrawPreviewLevelExt(TRUE); DrawPreviewPlayers(); } @@ -4475,10 +4568,6 @@ void WaitForEventToContinue(void) } } -#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, int draw_buffer_game) { boolean game_ended = (game_status == GAME_MODE_PLAYING && checkGameEnded()); @@ -4589,11 +4678,12 @@ static int RequestHandleEvents(unsigned int req_state, int draw_buffer_game) break; default: - // only check clickable animations if no request gadget clicked - HandleGlobalAnimClicks(mx, my, button_status, FALSE); break; } + // only needed to handle clickable pointer animations here + HandleGlobalAnimClicks(mx, my, button_status, FALSE); + break; } @@ -4793,6 +4883,12 @@ static int RequestHandleEvents(unsigned int req_state, int draw_buffer_game) static void DoRequestBefore(void) { + boolean game_ended = (game_status == GAME_MODE_PLAYING && checkGameEnded()); + + // 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); @@ -4840,23 +4936,54 @@ static void DoRequestAfter(void) 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; + } + + *set_font_nr = font_nr; + *set_max_lines = max_lines; + *set_max_line_length = max_line_length; +} + static void DrawRequestDoorText(char *text) { char *text_ptr = text; - int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN; - int font_nr = FONT_TEXT_2; + 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 SetFontStatus(GAME_MODE_PSEUDO_DOOR); - if (maxWordLengthInRequestString(text) > MAX_REQUEST_LINE_FONT1_LEN) - { - max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN; - font_nr = FONT_TEXT_1; - } + 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++) + for (text_ptr = text, ty = 0; ty < max_request_lines; ty++) { char text_line[max_request_line_len + 1]; int tx, tl, tc = 0; @@ -4885,7 +5012,7 @@ static void DrawRequestDoorText(char *text) 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); @@ -4896,12 +5023,10 @@ static void DrawRequestDoorText(char *text) static int RequestDoor(char *text, unsigned int req_state) { - int draw_buffer_last = GetDrawtoField(); unsigned int old_door_state = GetDoorState(); + int draw_buffer_last = GetDrawtoField(); int result; - DoRequestBefore(); - if (old_door_state & DOOR_OPEN_1) { CloseDoor(DOOR_CLOSE_1); @@ -4941,8 +5066,6 @@ static int RequestDoor(char *text, unsigned int req_state) OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK); } - DoRequestAfter(); - return result; } @@ -4951,8 +5074,6 @@ static int RequestEnvelope(char *text, unsigned int req_state) int draw_buffer_last = GetDrawtoField(); int result; - DoRequestBefore(); - DrawEnvelopeRequest(text, req_state); ShowEnvelopeRequest(text, req_state, ACTION_OPENING); @@ -4963,30 +5084,27 @@ static int RequestEnvelope(char *text, unsigned int req_state) ShowEnvelopeRequest(text, req_state, ACTION_CLOSING); - DoRequestAfter(); - return result; } int Request(char *text, unsigned int req_state) { - boolean game_ended = (game_status == GAME_MODE_PLAYING && checkGameEnded()); boolean overlay_enabled = GetOverlayEnabled(); int result; - // when showing request dialog after game ended, deactivate game panel - if (game_ended) - game.panel.active = FALSE; - game.request_active = TRUE; SetOverlayEnabled(FALSE); + DoRequestBefore(); + if (global.use_envelope_request) result = RequestEnvelope(text, req_state); else result = RequestDoor(text, req_state); + DoRequestAfter(); + SetOverlayEnabled(overlay_enabled); game.request_active = FALSE; @@ -5399,6 +5517,10 @@ unsigned int MoveDoor(unsigned int door_state) } } + SetDoorBackgroundImage(IMG_BACKGROUND_DOOR); + + game.any_door_active = TRUE; + for (k = start; k < num_move_steps; k++) { int last_frame = num_move_steps - 1; // last frame of this "for" loop @@ -5464,8 +5586,8 @@ unsigned int MoveDoor(unsigned int door_state) if (!door_panel_drawn[door_index]) { - ClearRectangle(drawto, door_rect->x, door_rect->y, - door_rect->width, door_rect->height); + ClearRectangleOnBackground(drawto, door_rect->x, door_rect->y, + door_rect->width, door_rect->height); door_panel_drawn[door_index] = TRUE; } @@ -5593,6 +5715,8 @@ unsigned int MoveDoor(unsigned int door_state) BackToFront(); } } + + game.any_door_active = FALSE; } if (door_state & DOOR_ACTION_1) @@ -5890,185 +6014,1897 @@ static void HandleToolButtons(struct GadgetInfo *gi) request_gadget_id = gi->custom_id; } -static struct Mapping_EM_to_RND_object +static int getEngineElement_Ext(int element, int game_engine_type, boolean is_drawing_element) { - int element_em; - boolean is_rnd_to_em_mapping; // unique mapping EM <-> RND - boolean is_backside; // backside of moving element + int el_empty; + int el_player; + int el_sand; + int el_wall; + int el_steelwall; + int el_exit_closed; + + if (game_engine_type == -1) + game_engine_type = level.game_engine_type; + + if (level.game_engine_type == GAME_ENGINE_TYPE_BD) + { + el_empty = EL_EMPTY; + el_player = EL_BDX_PLAYER; + el_sand = EL_BDX_SAND_1; + el_wall = EL_BDX_WALL; + el_steelwall = EL_BDX_STEELWALL; + el_exit_closed = EL_BDX_EXIT_CLOSED; + } + else if (level.game_engine_type == GAME_ENGINE_TYPE_EM) + { + el_empty = EL_EMPTY; + el_player = EL_PLAYER_1; + el_sand = EL_SAND; + el_wall = EL_WALL; + el_steelwall = EL_STEELWALL; + el_exit_closed = EL_EM_EXIT_CLOSED; + } + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + { + el_empty = EL_EMPTY; + el_player = EL_SP_MURPHY; + el_sand = EL_SP_BASE; + el_wall = EL_SP_CHIP_SINGLE; + el_steelwall = EL_SP_HARDWARE_GRAY; + el_exit_closed = EL_SP_EXIT_CLOSED; + } + else if (level.game_engine_type == GAME_ENGINE_TYPE_MM) + { + el_empty = EL_EMPTY; + el_player = EL_MM_MCDUFFIN_DOWN; + el_sand = EL_EMPTY; + el_wall = EL_MM_WOODEN_WALL; + el_steelwall = EL_MM_STEEL_WALL; + el_exit_closed = EL_MM_EXIT_CLOSED; + + if (is_drawing_element) + { + el_wall = EL_MM_MIRROR_START; + el_sand = EL_MM_WOODEN_WALL; + } + } + else + { + el_empty = EL_EMPTY; + el_player = EL_PLAYER_1; + el_sand = EL_SAND; + el_wall = EL_WALL; + el_steelwall = EL_STEELWALL; + el_exit_closed = EL_EXIT_CLOSED; + } + + return (element == EL_EMPTY ? el_empty : + element == EL_PLAYER_1 ? el_player : + element == EL_SAND ? el_sand : + element == EL_WALL ? el_wall : + element == EL_STEELWALL ? el_steelwall : + element == EL_EXIT_CLOSED ? el_exit_closed : EL_EMPTY); +} + +int getEngineElement(int element) +{ + return getEngineElement_Ext(element, -1, FALSE); +} + +int getDrawingElement(int element) +{ + return getEngineElement_Ext(element, -1, TRUE); +} + +static struct Mapping_BD_to_RND_object +{ + int element_bd; + boolean is_rnd_to_bd_mapping; // unique mapping BD <-> RND int element_rnd; int action; int direction; } -em_object_mapping_list[GAME_TILE_MAX + 1] = +bd_object_mapping_list[] = { + // additional RND style elements mapped to BD style elements (must be listed first) + { - Zborder, FALSE, FALSE, - EL_EMPTY, -1, -1 + O_DIRT, TRUE, + EL_SAND, -1, -1 }, { - Zplayer, FALSE, FALSE, - EL_EMPTY, -1, -1 + O_STONE, TRUE, + EL_BD_ROCK, -1, -1 }, - { - Zbug, FALSE, FALSE, - EL_EMPTY, -1, -1 + O_BRICK, TRUE, + EL_BD_WALL, -1, -1 }, { - Ztank, FALSE, FALSE, - EL_EMPTY, -1, -1 + O_STEEL, TRUE, + EL_STEELWALL, -1, -1 }, { - Zeater, FALSE, FALSE, - EL_EMPTY, -1, -1 + O_DIAMOND, TRUE, + EL_BD_DIAMOND, -1, -1 }, { - Zdynamite, FALSE, FALSE, - EL_EMPTY, -1, -1 + O_INBOX, TRUE, + EL_PLAYER_1, -1, -1 }, { - Zboom, FALSE, FALSE, - EL_EMPTY, -1, -1 + O_INBOX, TRUE, + EL_PLAYER_2, -1, -1 }, - { - Xchain, FALSE, FALSE, - EL_DEFAULT, ACTION_EXPLODING, -1 + O_INBOX, TRUE, + EL_PLAYER_3, -1, -1 }, { - Xboom_bug, FALSE, FALSE, - EL_BUG, ACTION_EXPLODING, -1 + O_INBOX, TRUE, + EL_PLAYER_4, -1, -1 }, { - Xboom_tank, FALSE, FALSE, - EL_SPACESHIP, ACTION_EXPLODING, -1 + O_PRE_OUTBOX, TRUE, + EL_EXIT_CLOSED, -1, -1 }, + + // BD style elements with their corresponding RND style elements + { - Xboom_android, FALSE, FALSE, - EL_EMC_ANDROID, ACTION_OTHER, -1 + O_SPACE, TRUE, + EL_EMPTY, -1, -1 }, { - Xboom_1, FALSE, FALSE, - EL_DEFAULT, ACTION_EXPLODING, -1 + O_DIRT, TRUE, + EL_BDX_SAND_1, -1, -1 }, { - Xboom_2, FALSE, FALSE, - EL_DEFAULT, ACTION_EXPLODING, -1 + O_DIRT_SLOPED_UP_RIGHT, TRUE, + EL_BDX_SAND_SLOPED_UP_RIGHT, -1, -1 }, - { - Xblank, TRUE, FALSE, - EL_EMPTY, -1, -1 + O_DIRT_SLOPED_UP_LEFT, TRUE, + EL_BDX_SAND_SLOPED_UP_LEFT, -1, -1 }, - { - Xsplash_e, FALSE, FALSE, - EL_ACID_SPLASH_RIGHT, -1, -1 + O_DIRT_SLOPED_DOWN_LEFT, TRUE, + EL_BDX_SAND_SLOPED_DOWN_LEFT, -1, -1 }, { - Xsplash_w, FALSE, FALSE, - EL_ACID_SPLASH_LEFT, -1, -1 + O_DIRT_SLOPED_DOWN_RIGHT, TRUE, + EL_BDX_SAND_SLOPED_DOWN_RIGHT, -1, -1 }, - { - Xplant, TRUE, FALSE, - EL_EMC_PLANT, -1, -1 + O_DIRT_BALL, TRUE, + EL_BDX_SAND_BALL, -1, -1 }, { - Yplant, FALSE, FALSE, - EL_EMC_PLANT, -1, -1 + O_DIRT_BALL_F, TRUE, + EL_BDX_SAND_BALL_FALLING, -1, -1 }, - { - Xacid_1, TRUE, FALSE, - EL_ACID, -1, -1 + O_DIRT_BALL_F, FALSE, + EL_BDX_SAND_BALL, ACTION_FALLING, -1 }, { - Xacid_2, FALSE, FALSE, - EL_ACID, -1, -1 + O_DIRT_LOOSE, TRUE, + EL_BDX_SAND_LOOSE, -1, -1 }, { - Xacid_3, FALSE, FALSE, - EL_ACID, -1, -1 + O_DIRT_LOOSE_F, TRUE, + EL_BDX_SAND_LOOSE_FALLING, -1, -1 }, { - Xacid_4, FALSE, FALSE, - EL_ACID, -1, -1 + O_DIRT_LOOSE_F, FALSE, + EL_BDX_SAND_LOOSE, ACTION_FALLING, -1 }, { - Xacid_5, FALSE, FALSE, - EL_ACID, -1, -1 + O_DIRT2, TRUE, + EL_BDX_SAND_2, -1, -1 }, { - Xacid_6, FALSE, FALSE, - EL_ACID, -1, -1 + O_BRICK, TRUE, + EL_BDX_WALL, -1, -1 }, { - Xacid_7, FALSE, FALSE, - EL_ACID, -1, -1 + O_BRICK_SLOPED_UP_RIGHT, TRUE, + EL_BDX_WALL_SLOPED_UP_RIGHT, -1, -1 }, { - Xacid_8, FALSE, FALSE, - EL_ACID, -1, -1 + O_BRICK_SLOPED_UP_LEFT, TRUE, + EL_BDX_WALL_SLOPED_UP_LEFT, -1, -1 }, - { - Xfake_acid_1, TRUE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + O_BRICK_SLOPED_DOWN_LEFT, TRUE, + EL_BDX_WALL_SLOPED_DOWN_LEFT, -1, -1 }, { - Xfake_acid_2, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + O_BRICK_SLOPED_DOWN_RIGHT, TRUE, + EL_BDX_WALL_SLOPED_DOWN_RIGHT, -1, -1 }, { - Xfake_acid_3, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + O_BRICK_NON_SLOPED, TRUE, + EL_BDX_WALL_NON_SLOPED, -1, -1 }, { - Xfake_acid_4, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + O_MAGIC_WALL, TRUE, + EL_BDX_MAGIC_WALL, ACTION_ACTIVE, -1 }, { - Xfake_acid_5, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + O_PRE_OUTBOX, TRUE, + EL_BDX_EXIT_CLOSED, -1, -1 }, { - Xfake_acid_6, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + O_OUTBOX, TRUE, + EL_BDX_EXIT_OPEN, -1, -1 }, { - Xfake_acid_7, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + O_PRE_INVIS_OUTBOX, TRUE, + EL_BDX_INVISIBLE_EXIT_CLOSED, -1, -1 }, { - Xfake_acid_8, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + O_INVIS_OUTBOX, TRUE, + EL_BDX_INVISIBLE_EXIT_OPEN, -1, -1 }, - { - Xfake_acid_1_player, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + O_STEEL, TRUE, + EL_BDX_STEELWALL, -1, -1 }, { - Xfake_acid_2_player, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + O_STEEL_SLOPED_UP_RIGHT, TRUE, + EL_BDX_STEELWALL_SLOPED_UP_RIGHT, -1, -1 }, { - Xfake_acid_3_player, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + O_STEEL_SLOPED_UP_LEFT, TRUE, + EL_BDX_STEELWALL_SLOPED_UP_LEFT, -1, -1 }, { - Xfake_acid_4_player, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + O_STEEL_SLOPED_DOWN_LEFT, TRUE, + EL_BDX_STEELWALL_SLOPED_DOWN_LEFT, -1, -1 }, { - Xfake_acid_5_player, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + O_STEEL_SLOPED_DOWN_RIGHT, TRUE, + EL_BDX_STEELWALL_SLOPED_DOWN_RIGHT, -1, -1 }, { - Xfake_acid_6_player, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + O_STEEL_EXPLODABLE, TRUE, + EL_BDX_STEELWALL_EXPLODABLE, -1, -1 + }, + { + O_STEEL_EATABLE, TRUE, + EL_BDX_STEELWALL_DIGGABLE, -1, -1 + }, + { + O_BRICK_EATABLE, TRUE, + EL_BDX_WALL_DIGGABLE, -1, -1 + }, + { + O_STONE, TRUE, + EL_BDX_ROCK, -1, -1 + }, + { + O_STONE_F, TRUE, + EL_BDX_ROCK_FALLING, -1, -1 + }, + { + O_STONE_F, FALSE, + EL_BDX_ROCK, ACTION_FALLING, -1 + }, + { + O_FLYING_STONE, TRUE, + EL_BDX_FLYING_ROCK, -1, -1 + }, + { + O_FLYING_STONE_F, TRUE, + EL_BDX_FLYING_ROCK_FLYING, -1, -1 + }, + { + O_FLYING_STONE_F, FALSE, + EL_BDX_FLYING_ROCK, ACTION_FLYING, -1 + }, + { + O_MEGA_STONE, TRUE, + EL_BDX_MEGA_ROCK, -1, -1 + }, + { + O_MEGA_STONE_F, TRUE, + EL_BDX_MEGA_ROCK_FALLING, -1, -1 + }, + { + O_MEGA_STONE_F, FALSE, + EL_BDX_MEGA_ROCK, ACTION_FALLING, -1 + }, + { + O_DIAMOND, TRUE, + EL_BDX_DIAMOND, -1, -1 + }, + { + O_DIAMOND_F, TRUE, + EL_BDX_DIAMOND_FALLING, -1, -1 + }, + { + O_DIAMOND_F, FALSE, + EL_BDX_DIAMOND, ACTION_FALLING, -1 + }, + { + O_FLYING_DIAMOND, TRUE, + EL_BDX_FLYING_DIAMOND, -1, -1 + }, + { + O_FLYING_DIAMOND_F, TRUE, + EL_BDX_FLYING_DIAMOND_FLYING, -1, -1 + }, + { + O_FLYING_DIAMOND_F, FALSE, + EL_BDX_FLYING_DIAMOND, ACTION_FLYING, -1 + }, + { + O_NUT, TRUE, + EL_BDX_NUT, -1, -1 + }, + { + O_NUT_F, TRUE, + EL_BDX_NUT_FALLING, -1, -1 + }, + { + O_NUT_F, FALSE, + EL_BDX_NUT, ACTION_FALLING, -1 + }, + { + O_BLADDER_SPENDER, TRUE, + EL_BDX_BLADDER_SPENDER, -1, -1 + }, + { + O_INBOX, TRUE, + EL_BDX_INBOX, -1, -1 + }, + { + O_H_EXPANDING_WALL, TRUE, + EL_BDX_EXPANDABLE_WALL_HORIZONTAL, -1, -1 + }, + { + O_V_EXPANDING_WALL, TRUE, + EL_BDX_EXPANDABLE_WALL_VERTICAL, -1, -1 + }, + { + O_EXPANDING_WALL, TRUE, + EL_BDX_EXPANDABLE_WALL_ANY, -1, -1 + }, + { + O_H_EXPANDING_STEEL_WALL, TRUE, + EL_BDX_EXPANDABLE_STEELWALL_HORIZONTAL, -1, -1 + }, + { + O_V_EXPANDING_STEEL_WALL, TRUE, + EL_BDX_EXPANDABLE_STEELWALL_VERTICAL, -1, -1 + }, + { + O_EXPANDING_STEEL_WALL, TRUE, + EL_BDX_EXPANDABLE_STEELWALL_ANY, -1, -1 + }, + { + O_EXPANDING_WALL_SWITCH, TRUE, + EL_BDX_EXPANDABLE_WALL_SWITCH, -1, -1 + }, + { + O_CREATURE_SWITCH, TRUE, + EL_BDX_CREATURE_SWITCH, -1, -1 + }, + { + O_BITER_SWITCH, TRUE, + EL_BDX_BITER_SWITCH_1, -1, -1 + }, + { + O_REPLICATOR_SWITCH, TRUE, + EL_BDX_REPLICATOR_SWITCH, -1, -1 + }, + { + O_CONVEYOR_SWITCH, TRUE, + EL_BDX_CONVEYOR_SWITCH, -1, -1 + }, + { + O_CONVEYOR_DIR_SWITCH, TRUE, + EL_BDX_CONVEYOR_DIR_SWITCH, -1, -1 + }, + { + O_ACID, TRUE, + EL_BDX_ACID, -1, -1 + }, + { + O_FALLING_WALL, TRUE, + EL_BDX_FALLING_WALL, -1, -1 + }, + { + O_FALLING_WALL_F, TRUE, + EL_BDX_FALLING_WALL_FALLING, -1, -1 + }, + { + O_FALLING_WALL_F, FALSE, + EL_BDX_FALLING_WALL, ACTION_FALLING, -1 + }, + { + O_BOX, TRUE, + EL_BDX_BOX, -1, -1 + }, + { + O_TIME_PENALTY, TRUE, + EL_BDX_TIME_PENALTY, -1, -1 + }, + { + O_GRAVESTONE, TRUE, + EL_BDX_GRAVESTONE, -1, -1 + }, + { + O_STONE_GLUED, TRUE, + EL_BDX_ROCK_GLUED, -1, -1 + }, + { + O_DIAMOND_GLUED, TRUE, + EL_BDX_DIAMOND_GLUED, -1, -1 + }, + { + O_DIAMOND_KEY, TRUE, + EL_BDX_DIAMOND_KEY, -1, -1 + }, + { + O_TRAPPED_DIAMOND, TRUE, + EL_BDX_TRAPPED_DIAMOND, -1, -1 + }, + { + O_CLOCK, TRUE, + EL_BDX_CLOCK, -1, -1 + }, + { + O_DIRT_GLUED, TRUE, + EL_BDX_SAND_GLUED, -1, -1 + }, + { + O_KEY_1, TRUE, + EL_BDX_KEY_1, -1, -1 + }, + { + O_KEY_2, TRUE, + EL_BDX_KEY_2, -1, -1 + }, + { + O_KEY_3, TRUE, + EL_BDX_KEY_3, -1, -1 + }, + { + O_DOOR_1, TRUE, + EL_BDX_GATE_1, -1, -1 + }, + { + O_DOOR_2, TRUE, + EL_BDX_GATE_2, -1, -1 + }, + { + O_DOOR_3, TRUE, + EL_BDX_GATE_3, -1, -1 + }, + { + O_POT, TRUE, + EL_BDX_POT, -1, -1 + }, + { + O_GRAVITY_SWITCH, TRUE, + EL_BDX_GRAVITY_SWITCH, -1, -1 + }, + { + O_PNEUMATIC_HAMMER, TRUE, + EL_BDX_PNEUMATIC_HAMMER, -1, -1 + }, + { + O_TELEPORTER, TRUE, + EL_BDX_TELEPORTER, -1, -1 + }, + { + O_SKELETON, TRUE, + EL_BDX_SKELETON, -1, -1 + }, + { + O_WATER, TRUE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_1, TRUE, + EL_BDX_WATER_1, -1, -1 + }, + { + O_WATER_1, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_2, TRUE, + EL_BDX_WATER_2, -1, -1 + }, + { + O_WATER_2, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_3, TRUE, + EL_BDX_WATER_3, -1, -1 + }, + { + O_WATER_3, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_4, TRUE, + EL_BDX_WATER_4, -1, -1 + }, + { + O_WATER_4, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_5, TRUE, + EL_BDX_WATER_5, -1, -1 + }, + { + O_WATER_5, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_6, TRUE, + EL_BDX_WATER_6, -1, -1 + }, + { + O_WATER_6, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_7, TRUE, + EL_BDX_WATER_7, -1, -1 + }, + { + O_WATER_7, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_8, TRUE, + EL_BDX_WATER_8, -1, -1 + }, + { + O_WATER_8, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_9, TRUE, + EL_BDX_WATER_9, -1, -1 + }, + { + O_WATER_9, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_10, TRUE, + EL_BDX_WATER_10, -1, -1 + }, + { + O_WATER_10, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_11, TRUE, + EL_BDX_WATER_11, -1, -1 + }, + { + O_WATER_11, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_12, TRUE, + EL_BDX_WATER_12, -1, -1 + }, + { + O_WATER_12, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_13, TRUE, + EL_BDX_WATER_13, -1, -1 + }, + { + O_WATER_13, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_14, TRUE, + EL_BDX_WATER_14, -1, -1 + }, + { + O_WATER_14, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_15, TRUE, + EL_BDX_WATER_15, -1, -1 + }, + { + O_WATER_15, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_WATER_16, TRUE, + EL_BDX_WATER_16, -1, -1 + }, + { + O_WATER_16, FALSE, + EL_BDX_WATER, -1, -1 + }, + { + O_COW_1, TRUE, + EL_BDX_COW_LEFT, -1, -1 + }, + { + O_COW_2, TRUE, + EL_BDX_COW_UP, -1, -1 + }, + { + O_COW_3, TRUE, + EL_BDX_COW_RIGHT, -1, -1 + }, + { + O_COW_4, TRUE, + EL_BDX_COW_DOWN, -1, -1 + }, + { + O_COW_ENCLOSED_1, TRUE, + EL_BDX_COW_ENCLOSED_1, -1, -1 + }, + { + O_COW_ENCLOSED_1, FALSE, + EL_BDX_COW_DOWN, -1, -1 + }, + { + O_COW_ENCLOSED_2, TRUE, + EL_BDX_COW_ENCLOSED_2, -1, -1 + }, + { + O_COW_ENCLOSED_2, FALSE, + EL_BDX_COW_DOWN, -1, -1 + }, + { + O_COW_ENCLOSED_3, TRUE, + EL_BDX_COW_ENCLOSED_3, -1, -1 + }, + { + O_COW_ENCLOSED_3, FALSE, + EL_BDX_COW_DOWN, -1, -1 + }, + { + O_COW_ENCLOSED_4, TRUE, + EL_BDX_COW_ENCLOSED_4, -1, -1 + }, + { + O_COW_ENCLOSED_4, FALSE, + EL_BDX_COW_DOWN, -1, -1 + }, + { + O_COW_ENCLOSED_5, TRUE, + EL_BDX_COW_ENCLOSED_5, -1, -1 + }, + { + O_COW_ENCLOSED_5, FALSE, + EL_BDX_COW_DOWN, -1, -1 + }, + { + O_COW_ENCLOSED_6, TRUE, + EL_BDX_COW_ENCLOSED_6, -1, -1 + }, + { + O_COW_ENCLOSED_6, FALSE, + EL_BDX_COW_DOWN, -1, -1 + }, + { + O_COW_ENCLOSED_7, TRUE, + EL_BDX_COW_ENCLOSED_7, -1, -1 + }, + { + O_COW_ENCLOSED_7, FALSE, + EL_BDX_COW_DOWN, -1, -1 + }, + { + O_WALLED_DIAMOND, TRUE, + EL_BDX_WALL_DIAMOND, -1, -1 + }, + { + O_WALLED_KEY_1, TRUE, + EL_BDX_WALL_KEY_1, -1, -1 + }, + { + O_WALLED_KEY_2, TRUE, + EL_BDX_WALL_KEY_2, -1, -1 + }, + { + O_WALLED_KEY_3, TRUE, + EL_BDX_WALL_KEY_3, -1, -1 + }, + { + O_AMOEBA, TRUE, + EL_BDX_AMOEBA_1, -1, -1 + }, + { + O_AMOEBA_2, TRUE, + EL_BDX_AMOEBA_2, -1, -1 + }, + { + O_REPLICATOR, TRUE, + EL_BDX_REPLICATOR, -1, -1 + }, + { + O_CONVEYOR_LEFT, TRUE, + EL_BDX_CONVEYOR_LEFT, -1, -1 + }, + { + O_CONVEYOR_RIGHT, TRUE, + EL_BDX_CONVEYOR_RIGHT, -1, -1 + }, + { + O_LAVA, TRUE, + EL_BDX_LAVA, -1, -1 + }, + { + O_SWEET, TRUE, + EL_BDX_SWEET, -1, -1 + }, + { + O_VOODOO, TRUE, + EL_BDX_VOODOO_DOLL, -1, -1 + }, + { + O_SLIME, TRUE, + EL_BDX_SLIME, -1, -1 + }, + { + O_BLADDER, TRUE, + EL_BDX_BLADDER, -1, -1 + }, + { + O_BLADDER_1, TRUE, + EL_BDX_BLADDER_1, -1, -1 + }, + { + O_BLADDER_1, FALSE, + EL_BDX_BLADDER, -1, -1 + }, + { + O_BLADDER_2, TRUE, + EL_BDX_BLADDER_2, -1, -1 + }, + { + O_BLADDER_2, FALSE, + EL_BDX_BLADDER, -1, -1 + }, + { + O_BLADDER_3, TRUE, + EL_BDX_BLADDER_3, -1, -1 + }, + { + O_BLADDER_3, FALSE, + EL_BDX_BLADDER, -1, -1 + }, + { + O_BLADDER_4, TRUE, + EL_BDX_BLADDER_4, -1, -1 + }, + { + O_BLADDER_4, FALSE, + EL_BDX_BLADDER, -1, -1 + }, + { + O_BLADDER_5, TRUE, + EL_BDX_BLADDER_5, -1, -1 + }, + { + O_BLADDER_5, FALSE, + EL_BDX_BLADDER, -1, -1 + }, + { + O_BLADDER_6, TRUE, + EL_BDX_BLADDER_6, -1, -1 + }, + { + O_BLADDER_6, FALSE, + EL_BDX_BLADDER, -1, -1 + }, + { + O_BLADDER_7, TRUE, + EL_BDX_BLADDER_7, -1, -1 + }, + { + O_BLADDER_7, FALSE, + EL_BDX_BLADDER, -1, -1 + }, + { + O_BLADDER_8, TRUE, + EL_BDX_BLADDER_8, -1, -1 + }, + { + O_BLADDER_8, FALSE, + EL_BDX_BLADDER, -1, -1 + }, + { + O_WAITING_STONE, TRUE, + EL_BDX_WAITING_ROCK, -1, -1 + }, + { + O_CHASING_STONE, TRUE, + EL_BDX_CHASING_ROCK, -1, -1 + }, + { + O_GHOST, TRUE, + EL_BDX_GHOST, -1, -1 + }, + { + O_FIREFLY_1, TRUE, + EL_BDX_FIREFLY_1_LEFT, -1, -1 + }, + { + O_FIREFLY_2, TRUE, + EL_BDX_FIREFLY_1_UP, -1, -1 + }, + { + O_FIREFLY_3, TRUE, + EL_BDX_FIREFLY_1_RIGHT, -1, -1 + }, + { + O_FIREFLY_4, TRUE, + EL_BDX_FIREFLY_1_DOWN, -1, -1 + }, + { + O_ALT_FIREFLY_1, TRUE, + EL_BDX_FIREFLY_2_LEFT, -1, -1 + }, + { + O_ALT_FIREFLY_2, TRUE, + EL_BDX_FIREFLY_2_UP, -1, -1 + }, + { + O_ALT_FIREFLY_3, TRUE, + EL_BDX_FIREFLY_2_RIGHT, -1, -1 + }, + { + O_ALT_FIREFLY_4, TRUE, + EL_BDX_FIREFLY_2_DOWN, -1, -1 + }, + { + O_BUTTER_1, TRUE, + EL_BDX_BUTTERFLY_1_LEFT, -1, -1 + }, + { + O_BUTTER_2, TRUE, + EL_BDX_BUTTERFLY_1_UP, -1, -1 + }, + { + O_BUTTER_3, TRUE, + EL_BDX_BUTTERFLY_1_RIGHT, -1, -1 + }, + { + O_BUTTER_4, TRUE, + EL_BDX_BUTTERFLY_1_DOWN, -1, -1 + }, + { + O_ALT_BUTTER_1, TRUE, + EL_BDX_BUTTERFLY_2_LEFT, -1, -1 + }, + { + O_ALT_BUTTER_2, TRUE, + EL_BDX_BUTTERFLY_2_UP, -1, -1 + }, + { + O_ALT_BUTTER_3, TRUE, + EL_BDX_BUTTERFLY_2_RIGHT, -1, -1 + }, + { + O_ALT_BUTTER_4, TRUE, + EL_BDX_BUTTERFLY_2_DOWN, -1, -1 + }, + { + O_STONEFLY_1, TRUE, + EL_BDX_STONEFLY_LEFT, -1, -1 + }, + { + O_STONEFLY_2, TRUE, + EL_BDX_STONEFLY_UP, -1, -1 + }, + { + O_STONEFLY_3, TRUE, + EL_BDX_STONEFLY_RIGHT, -1, -1 + }, + { + O_STONEFLY_4, TRUE, + EL_BDX_STONEFLY_DOWN, -1, -1 + }, + { + O_BITER_1, TRUE, + EL_BDX_BITER_UP, -1, -1 + }, + { + O_BITER_2, TRUE, + EL_BDX_BITER_RIGHT, -1, -1 + }, + { + O_BITER_3, TRUE, + EL_BDX_BITER_DOWN, -1, -1 + }, + { + O_BITER_4, TRUE, + EL_BDX_BITER_LEFT, -1, -1 + }, + { + O_DRAGONFLY_1, TRUE, + EL_BDX_DRAGONFLY_LEFT, -1, -1 + }, + { + O_DRAGONFLY_2, TRUE, + EL_BDX_DRAGONFLY_UP, -1, -1 + }, + { + O_DRAGONFLY_3, TRUE, + EL_BDX_DRAGONFLY_RIGHT, -1, -1 + }, + { + O_DRAGONFLY_4, TRUE, + EL_BDX_DRAGONFLY_DOWN, -1, -1 + }, + { + O_PRE_PL_1, TRUE, + EL_BDX_PLAYER_GROWING_1, -1, -1 + }, + { + O_PRE_PL_1, FALSE, + EL_BDX_PLAYER, ACTION_GROWING, -1 + }, + { + O_PRE_PL_2, TRUE, + EL_BDX_PLAYER_GROWING_2, -1, -1 + }, + { + O_PRE_PL_2, FALSE, + EL_BDX_PLAYER, ACTION_GROWING, -1 + }, + { + O_PRE_PL_3, TRUE, + EL_BDX_PLAYER_GROWING_3, -1, -1 + }, + { + O_PRE_PL_3, FALSE, + EL_BDX_PLAYER, ACTION_GROWING, -1 + }, + { + O_PLAYER, TRUE, + EL_BDX_PLAYER, -1, -1 + }, + { + O_PLAYER_BOMB, TRUE, + EL_BDX_PLAYER_WITH_BOMB, -1, -1 + }, + { + O_PLAYER_ROCKET_LAUNCHER, TRUE, + EL_BDX_PLAYER_WITH_ROCKET_LAUNCHER, -1, -1 + }, + { + O_PLAYER_GLUED, TRUE, + EL_BDX_PLAYER_GLUED, -1, -1 + }, + { + O_PLAYER_STIRRING, TRUE, + EL_BDX_PLAYER_STIRRING, -1, -1 + }, + { + O_ROCKET_LAUNCHER, TRUE, + EL_BDX_ROCKET_LAUNCHER, -1, -1 + }, + { + O_ROCKET_1, TRUE, + EL_BDX_ROCKET_RIGHT, -1, -1 + }, + { + O_ROCKET_2, TRUE, + EL_BDX_ROCKET_UP, -1, -1 + }, + { + O_ROCKET_3, TRUE, + EL_BDX_ROCKET_LEFT, -1, -1 + }, + { + O_ROCKET_4, TRUE, + EL_BDX_ROCKET_DOWN, -1, -1 + }, + { + O_BOMB, TRUE, + EL_BDX_BOMB, -1, -1 + }, + { + O_BOMB_TICK_1, TRUE, + EL_BDX_BOMB_TICKING_1, -1, -1 + }, + { + O_BOMB_TICK_1, FALSE, + EL_BDX_BOMB, ACTION_ACTIVE, -1 + }, + { + O_BOMB_TICK_2, TRUE, + EL_BDX_BOMB_TICKING_2, -1, -1 + }, + { + O_BOMB_TICK_2, FALSE, + EL_BDX_BOMB, ACTION_ACTIVE, -1 + }, + { + O_BOMB_TICK_3, TRUE, + EL_BDX_BOMB_TICKING_3, -1, -1 + }, + { + O_BOMB_TICK_3, FALSE, + EL_BDX_BOMB, ACTION_ACTIVE, -1 + }, + { + O_BOMB_TICK_4, TRUE, + EL_BDX_BOMB_TICKING_4, -1, -1 + }, + { + O_BOMB_TICK_4, FALSE, + EL_BDX_BOMB, ACTION_ACTIVE, -1 + }, + { + O_BOMB_TICK_5, TRUE, + EL_BDX_BOMB_TICKING_5, -1, -1 + }, + { + O_BOMB_TICK_5, FALSE, + EL_BDX_BOMB, ACTION_ACTIVE, -1 + }, + { + O_BOMB_TICK_6, TRUE, + EL_BDX_BOMB_TICKING_6, -1, -1 + }, + { + O_BOMB_TICK_6, FALSE, + EL_BDX_BOMB, ACTION_ACTIVE, -1 + }, + { + O_BOMB_TICK_7, TRUE, + EL_BDX_BOMB_TICKING_7, -1, -1 + }, + { + O_BOMB_TICK_7, FALSE, + EL_BDX_BOMB, ACTION_ACTIVE, -1 + }, + { + O_NITRO_PACK, TRUE, + EL_BDX_NITRO_PACK, -1, -1 + }, + { + O_NITRO_PACK_F, TRUE, + EL_BDX_NITRO_PACK_FALLING, -1, -1 + }, + { + O_NITRO_PACK_F, FALSE, + EL_BDX_NITRO_PACK, ACTION_FALLING, -1 + }, + { + O_PRE_CLOCK_1, TRUE, + EL_BDX_CLOCK_GROWING_1, -1, -1 + }, + { + O_PRE_CLOCK_1, FALSE, + EL_BDX_CLOCK, ACTION_GROWING, -1 + }, + { + O_PRE_CLOCK_2, TRUE, + EL_BDX_CLOCK_GROWING_2, -1, -1 + }, + { + O_PRE_CLOCK_2, FALSE, + EL_BDX_CLOCK, ACTION_GROWING, -1 + }, + { + O_PRE_CLOCK_3, TRUE, + EL_BDX_CLOCK_GROWING_3, -1, -1 + }, + { + O_PRE_CLOCK_3, FALSE, + EL_BDX_CLOCK, ACTION_GROWING, -1 + }, + { + O_PRE_CLOCK_4, TRUE, + EL_BDX_CLOCK_GROWING_4, -1, -1 + }, + { + O_PRE_CLOCK_4, FALSE, + EL_BDX_CLOCK, ACTION_GROWING, -1 + }, + { + O_PRE_DIA_1, TRUE, + EL_BDX_DIAMOND_GROWING_1, -1, -1 + }, + { + O_PRE_DIA_1, FALSE, + EL_BDX_DIAMOND, ACTION_GROWING, -1 + }, + { + O_PRE_DIA_2, TRUE, + EL_BDX_DIAMOND_GROWING_2, -1, -1 + }, + { + O_PRE_DIA_2, FALSE, + EL_BDX_DIAMOND, ACTION_GROWING, -1 + }, + { + O_PRE_DIA_3, TRUE, + EL_BDX_DIAMOND_GROWING_3, -1, -1 + }, + { + O_PRE_DIA_3, FALSE, + EL_BDX_DIAMOND, ACTION_GROWING, -1 + }, + { + O_PRE_DIA_4, TRUE, + EL_BDX_DIAMOND_GROWING_4, -1, -1 + }, + { + O_PRE_DIA_4, FALSE, + EL_BDX_DIAMOND, ACTION_GROWING, -1 + }, + { + O_PRE_DIA_5, TRUE, + EL_BDX_DIAMOND_GROWING_5, -1, -1 + }, + { + O_PRE_DIA_5, FALSE, + EL_BDX_DIAMOND, ACTION_GROWING, -1 + }, + { + O_EXPLODE_1, TRUE, + EL_BDX_EXPLODING_1, -1, -1 + }, + { + O_EXPLODE_1, FALSE, + EL_BDX_DEFAULT, ACTION_EXPLODING, -1 + }, + { + O_EXPLODE_2, TRUE, + EL_BDX_EXPLODING_2, -1, -1 + }, + { + O_EXPLODE_2, FALSE, + EL_BDX_DEFAULT, ACTION_EXPLODING, -1 + }, + { + O_EXPLODE_3, TRUE, + EL_BDX_EXPLODING_3, -1, -1 + }, + { + O_EXPLODE_3, FALSE, + EL_BDX_DEFAULT, ACTION_EXPLODING, -1 + }, + { + O_EXPLODE_4, TRUE, + EL_BDX_EXPLODING_4, -1, -1 + }, + { + O_EXPLODE_4, FALSE, + EL_BDX_DEFAULT, ACTION_EXPLODING, -1 + }, + { + O_EXPLODE_5, TRUE, + EL_BDX_EXPLODING_5, -1, -1 + }, + { + O_EXPLODE_5, FALSE, + EL_BDX_DEFAULT, ACTION_EXPLODING, -1 + }, + { + O_PRE_STONE_1, TRUE, + EL_BDX_ROCK_GROWING_1, -1, -1 + }, + { + O_PRE_STONE_1, FALSE, + EL_BDX_ROCK, ACTION_GROWING, -1 + }, + { + O_PRE_STONE_2, TRUE, + EL_BDX_ROCK_GROWING_2, -1, -1 + }, + { + O_PRE_STONE_2, FALSE, + EL_BDX_ROCK, ACTION_GROWING, -1 + }, + { + O_PRE_STONE_3, TRUE, + EL_BDX_ROCK_GROWING_3, -1, -1 + }, + { + O_PRE_STONE_3, FALSE, + EL_BDX_ROCK, ACTION_GROWING, -1 + }, + { + O_PRE_STONE_4, TRUE, + EL_BDX_ROCK_GROWING_4, -1, -1 + }, + { + O_PRE_STONE_4, FALSE, + EL_BDX_ROCK, ACTION_GROWING, -1 + }, + { + O_PRE_STEEL_1, TRUE, + EL_BDX_STEELWALL_GROWING_1, -1, -1 + }, + { + O_PRE_STEEL_1, FALSE, + EL_BDX_STEELWALL, ACTION_GROWING, -1 + }, + { + O_PRE_STEEL_2, TRUE, + EL_BDX_STEELWALL_GROWING_2, -1, -1 + }, + { + O_PRE_STEEL_2, FALSE, + EL_BDX_STEELWALL, ACTION_GROWING, -1 + }, + { + O_PRE_STEEL_3, TRUE, + EL_BDX_STEELWALL_GROWING_3, -1, -1 + }, + { + O_PRE_STEEL_3, FALSE, + EL_BDX_STEELWALL, ACTION_GROWING, -1 + }, + { + O_PRE_STEEL_4, TRUE, + EL_BDX_STEELWALL_GROWING_4, -1, -1 + }, + { + O_PRE_STEEL_4, FALSE, + EL_BDX_STEELWALL, ACTION_GROWING, -1 + }, + { + O_GHOST_EXPL_1, TRUE, + EL_BDX_GHOST_EXPLODING_1, -1, -1 + }, + { + O_GHOST_EXPL_1, FALSE, + EL_BDX_GHOST, ACTION_EXPLODING, -1 + }, + { + O_GHOST_EXPL_2, TRUE, + EL_BDX_GHOST_EXPLODING_2, -1, -1 + }, + { + O_GHOST_EXPL_2, FALSE, + EL_BDX_GHOST, ACTION_EXPLODING, -1 + }, + { + O_GHOST_EXPL_3, TRUE, + EL_BDX_GHOST_EXPLODING_3, -1, -1 + }, + { + O_GHOST_EXPL_3, FALSE, + EL_BDX_GHOST, ACTION_EXPLODING, -1 + }, + { + O_GHOST_EXPL_4, TRUE, + EL_BDX_GHOST_EXPLODING_4, -1, -1 + }, + { + O_GHOST_EXPL_4, FALSE, + EL_BDX_GHOST, ACTION_EXPLODING, -1 + }, + { + O_BOMB_EXPL_1, TRUE, + EL_BDX_BOMB_EXPLODING_1, -1, -1 + }, + { + O_BOMB_EXPL_1, FALSE, + EL_BDX_BOMB, ACTION_EXPLODING, -1 + }, + { + O_BOMB_EXPL_2, TRUE, + EL_BDX_BOMB_EXPLODING_2, -1, -1 + }, + { + O_BOMB_EXPL_2, FALSE, + EL_BDX_BOMB, ACTION_EXPLODING, -1 + }, + { + O_BOMB_EXPL_3, TRUE, + EL_BDX_BOMB_EXPLODING_3, -1, -1 + }, + { + O_BOMB_EXPL_3, FALSE, + EL_BDX_BOMB, ACTION_EXPLODING, -1 + }, + { + O_BOMB_EXPL_4, TRUE, + EL_BDX_BOMB_EXPLODING_4, -1, -1 + }, + { + O_BOMB_EXPL_4, FALSE, + EL_BDX_BOMB, ACTION_EXPLODING, -1 + }, + { + O_NITRO_EXPL_1, TRUE, + EL_BDX_NITRO_PACK_EXPLODING_1, -1, -1 + }, + { + O_NITRO_EXPL_1, FALSE, + EL_BDX_NITRO_PACK, ACTION_EXPLODING, -1 + }, + { + O_NITRO_EXPL_2, TRUE, + EL_BDX_NITRO_PACK_EXPLODING_2, -1, -1 + }, + { + O_NITRO_EXPL_2, FALSE, + EL_BDX_NITRO_PACK, ACTION_EXPLODING, -1 + }, + { + O_NITRO_EXPL_3, TRUE, + EL_BDX_NITRO_PACK_EXPLODING_3, -1, -1 + }, + { + O_NITRO_EXPL_3, FALSE, + EL_BDX_NITRO_PACK, ACTION_EXPLODING, -1 + }, + { + O_NITRO_EXPL_4, TRUE, + EL_BDX_NITRO_PACK_EXPLODING_4, -1, -1 + }, + { + O_NITRO_EXPL_4, FALSE, + EL_BDX_NITRO_PACK, ACTION_EXPLODING, -1 + }, + { + O_NITRO_PACK_EXPLODE, TRUE, + EL_BDX_NITRO_PACK_EXPLODING, -1, -1 + }, + { + O_NITRO_PACK_EXPLODE, FALSE, + EL_BDX_NITRO_PACK, ACTION_EXPLODING, -1 + }, + { + O_AMOEBA_2_EXPL_1, TRUE, + EL_BDX_AMOEBA_2_EXPLODING_1, -1, -1 + }, + { + O_AMOEBA_2_EXPL_1, FALSE, + EL_BDX_AMOEBA_2, ACTION_EXPLODING, -1 + }, + { + O_AMOEBA_2_EXPL_2, TRUE, + EL_BDX_AMOEBA_2_EXPLODING_2, -1, -1 + }, + { + O_AMOEBA_2_EXPL_2, FALSE, + EL_BDX_AMOEBA_2, ACTION_EXPLODING, -1 + }, + { + O_AMOEBA_2_EXPL_3, TRUE, + EL_BDX_AMOEBA_2_EXPLODING_3, -1, -1 + }, + { + O_AMOEBA_2_EXPL_3, FALSE, + EL_BDX_AMOEBA_2, ACTION_EXPLODING, -1 + }, + { + O_AMOEBA_2_EXPL_4, TRUE, + EL_BDX_AMOEBA_2_EXPLODING_4, -1, -1 + }, + { + O_AMOEBA_2_EXPL_4, FALSE, + EL_BDX_AMOEBA_2, ACTION_EXPLODING, -1 + }, + { + O_NUT_EXPL_1, TRUE, + EL_BDX_NUT_BREAKING_1, -1, -1 + }, + { + O_NUT_EXPL_1, FALSE, + EL_BDX_NUT, ACTION_BREAKING, -1 + }, + { + O_NUT_EXPL_2, TRUE, + EL_BDX_NUT_BREAKING_2, -1, -1 + }, + { + O_NUT_EXPL_2, FALSE, + EL_BDX_NUT, ACTION_BREAKING, -1 + }, + { + O_NUT_EXPL_3, TRUE, + EL_BDX_NUT_BREAKING_3, -1, -1 + }, + { + O_NUT_EXPL_3, FALSE, + EL_BDX_NUT, ACTION_BREAKING, -1 + }, + { + O_NUT_EXPL_4, TRUE, + EL_BDX_NUT_BREAKING_4, -1, -1 + }, + { + O_NUT_EXPL_4, FALSE, + EL_BDX_NUT, ACTION_BREAKING, -1 + }, + { + O_PLAYER_PNEUMATIC_LEFT, FALSE, + EL_BDX_PLAYER, ACTION_HITTING, MV_BIT_LEFT + }, + { + O_PLAYER_PNEUMATIC_RIGHT, FALSE, + EL_BDX_PLAYER, ACTION_HITTING, MV_BIT_RIGHT + }, + { + O_PNEUMATIC_ACTIVE_LEFT, FALSE, + EL_BDX_PNEUMATIC_HAMMER, ACTION_HITTING, MV_BIT_LEFT + }, + { + O_PNEUMATIC_ACTIVE_RIGHT, FALSE, + EL_BDX_PNEUMATIC_HAMMER, ACTION_HITTING, MV_BIT_RIGHT + }, + + // helper (runtime) elements + + { + O_FAKE_BONUS, FALSE, + EL_BDX_FAKE_BONUS, -1, -1 + }, + { + O_INBOX_CLOSED, FALSE, + EL_BDX_INBOX, -1, -1 + }, + { + O_INBOX_OPEN, FALSE, + EL_BDX_INBOX, ACTION_OPENING, -1 + }, + { + O_OUTBOX_CLOSED, FALSE, + EL_BDX_EXIT_CLOSED, -1, -1 + }, + { + O_OUTBOX_OPEN, FALSE, + EL_BDX_EXIT_OPEN, -1, -1 + }, + { + O_COVERED, FALSE, + EL_BDX_COVERED, -1, -1 + }, + { + O_PLAYER_LEFT, FALSE, + EL_BDX_PLAYER, ACTION_MOVING, MV_BIT_LEFT + }, + { + O_PLAYER_RIGHT, FALSE, + EL_BDX_PLAYER, ACTION_MOVING, MV_BIT_RIGHT + }, + { + O_PLAYER_UP, FALSE, + EL_BDX_PLAYER, ACTION_MOVING, MV_BIT_UP + }, + { + O_PLAYER_DOWN, FALSE, + EL_BDX_PLAYER, ACTION_MOVING, MV_BIT_DOWN + }, + { + O_PLAYER_BLINK, FALSE, + EL_BDX_PLAYER, ACTION_BORING_1, -1 + }, + { + O_PLAYER_TAP, FALSE, + EL_BDX_PLAYER, ACTION_BORING_2, -1 + }, + { + O_PLAYER_TAP_BLINK, FALSE, + EL_BDX_PLAYER, ACTION_BORING_3, -1 + }, + { + O_PLAYER_PUSH_LEFT, FALSE, + EL_BDX_PLAYER, ACTION_PUSHING, MV_BIT_LEFT + }, + { + O_PLAYER_PUSH_RIGHT, FALSE, + EL_BDX_PLAYER, ACTION_PUSHING, MV_BIT_RIGHT + }, + { + O_CREATURE_SWITCH_ON, FALSE, + EL_BDX_CREATURE_SWITCH_ACTIVE, -1, -1 + }, + { + O_EXPANDING_WALL_SWITCH_HORIZ, FALSE, + EL_BDX_EXPANDABLE_WALL_SWITCH, -1, -1 + }, + { + O_EXPANDING_WALL_SWITCH_VERT, FALSE, + EL_BDX_EXPANDABLE_WALL_SWITCH_ACTIVE, -1, -1 + }, + { + O_GRAVITY_SWITCH_ACTIVE, FALSE, + EL_BDX_GRAVITY_SWITCH_ACTIVE, -1, -1 + }, + { + O_REPLICATOR_SWITCH_OFF, FALSE, + EL_BDX_REPLICATOR_SWITCH, -1, -1 + }, + { + O_REPLICATOR_SWITCH_ON, FALSE, + EL_BDX_REPLICATOR_SWITCH_ACTIVE, -1, -1 + }, + { + O_CONVEYOR_DIR_NORMAL, FALSE, + EL_BDX_CONVEYOR_DIR_SWITCH, -1, -1 + }, + { + O_CONVEYOR_DIR_CHANGED, FALSE, + EL_BDX_CONVEYOR_DIR_SWITCH_ACTIVE, -1, -1 + }, + { + O_CONVEYOR_SWITCH_OFF, FALSE, + EL_BDX_CONVEYOR_SWITCH, -1, -1 + }, + { + O_CONVEYOR_SWITCH_ON, FALSE, + EL_BDX_CONVEYOR_SWITCH_ACTIVE, -1, -1 + }, + { + O_MAGIC_WALL_ACTIVE, FALSE, + EL_BDX_MAGIC_WALL_ACTIVE, -1, -1 + }, + { + O_REPLICATOR_ACTIVE, FALSE, + EL_BDX_REPLICATOR_ACTIVE, -1, -1 + }, + { + O_CONVEYOR_LEFT_ACTIVE, FALSE, + EL_BDX_CONVEYOR_LEFT_ACTIVE, -1, -1 + }, + { + O_CONVEYOR_RIGHT_ACTIVE, FALSE, + EL_BDX_CONVEYOR_RIGHT_ACTIVE, -1, -1 + }, + { + O_BITER_SWITCH_1, FALSE, + EL_BDX_BITER_SWITCH_1, -1, -1 + }, + { + O_BITER_SWITCH_2, FALSE, + EL_BDX_BITER_SWITCH_2, -1, -1 + }, + { + O_BITER_SWITCH_3, FALSE, + EL_BDX_BITER_SWITCH_3, -1, -1 + }, + { + O_BITER_SWITCH_4, FALSE, + EL_BDX_BITER_SWITCH_4, -1, -1 + }, + + { + -1, FALSE, + -1, -1, -1 + } +}; + +int map_element_RND_to_BD_cave(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_RND_to_BD_effect(int element_rnd, int action) +{ + static unsigned short mapping_RND_to_BD[NUM_FILE_ELEMENTS][NUM_ACTIONS]; + static boolean mapping_initialized = FALSE; + + if (!mapping_initialized) + { + int i, j; + + // return "O_UNKNOWN" for all undefined elements in mapping array + for (i = 0; i < NUM_FILE_ELEMENTS; i++) + for (j = 0; j < NUM_ACTIONS; j++) + mapping_RND_to_BD[i][j] = O_UNKNOWN; + + for (i = 0; bd_object_mapping_list[i].element_bd != -1; i++) + { + int element_rnd = bd_object_mapping_list[i].element_rnd; + int element_bd = bd_object_mapping_list[i].element_bd; + int action = bd_object_mapping_list[i].action; + + if (action != -1) + mapping_RND_to_BD[element_rnd][action] = element_bd; + } + + mapping_initialized = TRUE; + } + + if (element_rnd < 0 || element_rnd >= NUM_FILE_ELEMENTS) + { + Warn("invalid RND element %d", element_rnd); + + return O_UNKNOWN; + } + + if (action < 0 || action >= NUM_ACTIONS) + { + Warn("invalid action %d", action); + + return O_UNKNOWN; + } + + return mapping_RND_to_BD[element_rnd][action]; +} + +int map_element_BD_to_RND_cave(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++) + if (bd_object_mapping_list[i].is_rnd_to_bd_mapping) + 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]; +} + +int map_element_BD_to_RND_game(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, @@ -8329,6 +10165,29 @@ int el2edimg(int element) return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR]; } +int el2edimg_with_frame(int element, int *graphic, int *frame) +{ + *graphic = el2edimg(element); + *frame = 0; + + if (*graphic == IMG_UNKNOWN) + { + // no graphic defined -- if BD style, try to get runtime ("effect") element graphics + // (normal BD style elements have graphics, but runtime ("effects") elements do not) + int element_bd = map_element_RND_to_BD_cave(element); + + if (element_bd != O_UNKNOWN) + { + struct GraphicInfo_BD *g_bd = &graphic_info_bd_object[element_bd][0]; + + *graphic = g_bd->graphic; + *frame = g_bd->frame; + } + } + + return *graphic; +} + int el2preimg(int element) { element = GFX_ELEMENT(element); @@ -8486,7 +10345,9 @@ boolean isActivePlayer_EM(int player_nr) 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); @@ -8496,14 +10357,15 @@ unsigned int InitRND(int seed) return InitEngineRandom_RND(seed); } -static struct Mapping_EM_to_RND_object object_mapping[GAME_TILE_MAX]; -static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][PLY_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]; 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); @@ -8651,8 +10513,8 @@ void ResetGfxAnimation_EM(int x, int y, int tile) 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) : @@ -8691,11 +10553,11 @@ void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em, } 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]++; @@ -8750,9 +10612,9 @@ void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em, 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 ? @@ -8816,9 +10678,9 @@ void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em, 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)); @@ -8841,6 +10703,105 @@ void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em, &g_em->src_x, &g_em->src_y, FALSE); } +#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; + + if (graphic_info == NULL) // still at startup phase + return; + + // 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; + } + + for (i = 0; bd_object_mapping_list[i].element_bd != -1; i++) + { + int e = bd_object_mapping_list[i].element_bd; + + 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); + } + + 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; + + g_bd->graphic = graphic; + g_bd->frame = frame; + } + } + + // game graphics template for level-specific colors for native BD levels + int graphic = IMG_BDX_GAME_GRAPHICS_COLOR_TEMPLATE; + struct GraphicInfo_BD *g_bd = &graphic_info_bd_color_template; + Bitmap *src_bitmap; + int src_x, src_y; + + getGraphicSourceExt(graphic, 0, &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; + + g_bd->graphic = graphic; + g_bd->frame = 0; +} + void InitGraphicInfo_EM(void) { int i, j, p; @@ -8848,10 +10809,10 @@ void InitGraphicInfo_EM(void) // 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 @@ -8859,9 +10820,9 @@ void InitGraphicInfo_EM(void) { 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; } } @@ -8869,14 +10830,14 @@ void InitGraphicInfo_EM(void) { 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); } @@ -8885,22 +10846,22 @@ void InitGraphicInfo_EM(void) 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 < 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) && @@ -9172,10 +11133,10 @@ void InitGraphicInfo_EM(void) { 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); @@ -9215,9 +11176,9 @@ void InitGraphicInfo_EM(void) { 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++) { @@ -9254,6 +11215,26 @@ void InitGraphicInfo_EM(void) } } +static void CheckSaveEngineSnapshot_BD(boolean frame_max, + boolean player_moving, + boolean player_snapping) +{ + if (frame_max) + { + if (!local_player->was_waiting) + { + if (!CheckSaveEngineSnapshotToList()) + return; + + local_player->was_waiting = TRUE; + } + } + else if (player_moving || player_snapping) + { + local_player->was_waiting = FALSE; + } +} + static void CheckSaveEngineSnapshot_EM(int frame, boolean any_player_moving, boolean any_player_snapping, @@ -9311,6 +11292,19 @@ static void CheckSaveEngineSnapshot_MM(boolean element_clicked, } } +boolean CheckSingleStepMode_BD(boolean frame_max, + boolean player_moving, + boolean player_snapping) +{ + if (tape.single_step && tape.recording && !tape.pausing) + if (frame_max && FrameCounter > 6) + TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); + + CheckSaveEngineSnapshot_BD(frame_max, player_moving, player_snapping); + + return tape.pausing; +} + boolean CheckSingleStepMode_EM(int frame, boolean any_player_moving, boolean any_player_snapping, @@ -9498,6 +11492,27 @@ void PlaySoundSelecting(void) #endif } +void ToggleAudioSampleRateIfNeeded(void) +{ + int setup_audio_sample_rate = (setup.audio_sample_rate_44100 ? 44100 : 22050); + + // if setup and audio sample rate are already matching, nothing do do + if ((setup_audio_sample_rate == audio.sample_rate) || + !audio.sound_available) + return; + +#if 1 + // apparently changing the audio output sample rate does not work at runtime, + // so currently the program has to be restarted to apply the new sample rate + Request("Please restart the program to change audio sample rate!", REQ_CONFIRM); +#else + SDLReopenAudio(); + + // set setup value according to successfully changed audio sample rate + setup.audio_sample_rate_44100 = (audio.sample_rate == 44100); +#endif +} + void ToggleFullscreenIfNeeded(void) { // if setup and video fullscreen state are already matching, nothing do do @@ -9748,6 +11763,7 @@ void ChangeViewportPropertiesIfNeeded(void) boolean init_gfx_buffers = FALSE; boolean init_video_buffer = FALSE; boolean init_gadgets_and_anims = FALSE; + boolean init_bd_graphics = FALSE; boolean init_em_graphics = FALSE; if (new_win_xsize != WIN_XSIZE || @@ -9846,7 +11862,8 @@ void ChangeViewportPropertiesIfNeeded(void) // 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; } @@ -9913,6 +11930,11 @@ void ChangeViewportPropertiesIfNeeded(void) InitGlobalAnimations(); } + if (init_bd_graphics) + { + InitGraphicInfo_BD(); + } + if (init_em_graphics) { InitGraphicInfo_EM(); @@ -10030,10 +12052,10 @@ static unsigned int test_uuid_random_function_better(int max) 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); + HashTable *hash_seeds = + create_hashtable(get_hash_from_string, hash_key_strings_are_equal, free, NULL); + HashTable *hash_uuids = + create_hashtable(get_hash_from_string, hash_key_strings_are_equal, free, NULL); static char message[100]; int i; @@ -10112,8 +12134,8 @@ static void TestGeneratingUUIDs_RunTest(int nr, int always_seed, int num_uuids) Request(message, REQ_CONFIRM); - hashtable_destroy(hash_seeds, 0); - hashtable_destroy(hash_uuids, 0); + hashtable_destroy(hash_seeds); + hashtable_destroy(hash_uuids); } void TestGeneratingUUIDs(void)