1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-2006 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
16 #include "libgame/libgame.h"
28 /* select level set with EMC X11 graphics before activating EM GFX debugging */
29 #define DEBUG_EM_GFX 0
31 /* tool button identifiers */
32 #define TOOL_CTRL_ID_YES 0
33 #define TOOL_CTRL_ID_NO 1
34 #define TOOL_CTRL_ID_CONFIRM 2
35 #define TOOL_CTRL_ID_PLAYER_1 3
36 #define TOOL_CTRL_ID_PLAYER_2 4
37 #define TOOL_CTRL_ID_PLAYER_3 5
38 #define TOOL_CTRL_ID_PLAYER_4 6
40 #define NUM_TOOL_BUTTONS 7
42 /* constants for number of doors and door parts */
44 #define NUM_PANELS NUM_DOORS
45 // #define NUM_PANELS 0
46 #define MAX_PARTS_PER_DOOR 8
47 #define MAX_DOOR_PARTS (NUM_DOORS * MAX_PARTS_PER_DOOR + NUM_PANELS)
48 #define DOOR_PART_IS_PANEL(i) ((i) >= NUM_DOORS * MAX_PARTS_PER_DOOR)
51 struct DoorPartOrderInfo
57 static struct DoorPartOrderInfo door_part_order[MAX_DOOR_PARTS];
59 struct DoorPartControlInfo
63 struct DoorPartPosInfo *pos;
66 static struct DoorPartControlInfo door_part_controls[] =
70 IMG_DOOR_1_GFX_PART_1,
75 IMG_DOOR_1_GFX_PART_2,
80 IMG_DOOR_1_GFX_PART_3,
85 IMG_DOOR_1_GFX_PART_4,
90 IMG_DOOR_1_GFX_PART_5,
95 IMG_DOOR_1_GFX_PART_6,
100 IMG_DOOR_1_GFX_PART_7,
105 IMG_DOOR_1_GFX_PART_8,
111 IMG_DOOR_2_GFX_PART_1,
116 IMG_DOOR_2_GFX_PART_2,
121 IMG_DOOR_2_GFX_PART_3,
126 IMG_DOOR_2_GFX_PART_4,
131 IMG_DOOR_2_GFX_PART_5,
136 IMG_DOOR_2_GFX_PART_6,
141 IMG_DOOR_2_GFX_PART_7,
146 IMG_DOOR_2_GFX_PART_8,
152 IMG_BACKGROUND_PANEL,
169 /* forward declaration for internal use */
170 static void UnmapToolButtons();
171 static void HandleToolButtons(struct GadgetInfo *);
172 static int el_act_dir2crm(int, int, int);
173 static int el_act2crm(int, int);
175 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
176 static int request_gadget_id = -1;
178 static char *print_if_not_empty(int element)
180 static char *s = NULL;
181 char *token_name = element_info[element].token_name;
186 s = checked_malloc(strlen(token_name) + 10 + 1);
188 if (element != EL_EMPTY)
189 sprintf(s, "%d\t['%s']", element, token_name);
191 sprintf(s, "%d", element);
196 void DumpTile(int x, int y)
201 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
207 printf_line("-", 79);
208 printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
209 printf_line("-", 79);
211 if (!IN_LEV_FIELD(x, y))
213 printf("(not in level field)\n");
219 printf(" Feld: %d\t['%s']\n", Feld[x][y],
220 element_info[Feld[x][y]].token_name);
221 printf(" Back: %s\n", print_if_not_empty(Back[x][y]));
222 printf(" Store: %s\n", print_if_not_empty(Store[x][y]));
223 printf(" Store2: %s\n", print_if_not_empty(Store2[x][y]));
224 printf(" StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
225 printf(" MovPos: %d\n", MovPos[x][y]);
226 printf(" MovDir: %d\n", MovDir[x][y]);
227 printf(" MovDelay: %d\n", MovDelay[x][y]);
228 printf(" ChangeDelay: %d\n", ChangeDelay[x][y]);
229 printf(" CustomValue: %d\n", CustomValue[x][y]);
230 printf(" GfxElement: %d\n", GfxElement[x][y]);
231 printf(" GfxAction: %d\n", GfxAction[x][y]);
232 printf(" GfxFrame: %d\n", GfxFrame[x][y]);
236 void SetDrawtoField(int mode)
238 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
246 BX2 = SCR_FIELDX + 1;
247 BY2 = SCR_FIELDY + 1;
266 BX2 = SCR_FIELDX + 1;
267 BY2 = SCR_FIELDY + 1;
282 drawto_field = fieldbuffer;
284 else /* DRAW_BACKBUFFER */
290 BX2 = SCR_FIELDX - 1;
291 BY2 = SCR_FIELDY - 1;
295 drawto_field = backbuffer;
299 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
301 if (game_status == GAME_MODE_PLAYING &&
302 level.game_engine_type == GAME_ENGINE_TYPE_EM)
304 /* currently there is no partial redraw -- always redraw whole playfield */
305 RedrawPlayfield_EM(TRUE);
307 /* blit playfield from scroll buffer to normal back buffer for fading in */
308 BlitScreenToBitmap_EM(backbuffer);
310 else if (game_status == GAME_MODE_PLAYING &&
311 level.game_engine_type == GAME_ENGINE_TYPE_SP)
313 /* currently there is no partial redraw -- always redraw whole playfield */
314 RedrawPlayfield_SP(TRUE);
316 /* blit playfield from scroll buffer to normal back buffer for fading in */
317 BlitScreenToBitmap_SP(backbuffer);
319 else if (game_status == GAME_MODE_PLAYING &&
320 !game.envelope_active)
326 width = gfx.sxsize + 2 * TILEX;
327 height = gfx.sysize + 2 * TILEY;
333 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
334 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
336 for (xx = BX1; xx <= BX2; xx++)
337 for (yy = BY1; yy <= BY2; yy++)
338 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
339 DrawScreenField(xx, yy);
343 if (setup.soft_scrolling)
345 int fx = FX, fy = FY;
347 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
348 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
350 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
362 BlitBitmap(drawto, window, x, y, width, height, x, y);
365 void DrawMaskedBorder_Rect(int x, int y, int width, int height)
367 Bitmap *bitmap = graphic_info[IMG_GLOBAL_BORDER].bitmap;
369 SetClipOrigin(bitmap, bitmap->stored_clip_gc, 0, 0);
370 BlitBitmapMasked(bitmap, backbuffer, x, y, width, height, x, y);
373 void DrawMaskedBorder_FIELD()
375 if (global.border_status >= GAME_MODE_TITLE &&
376 global.border_status <= GAME_MODE_PLAYING &&
377 border.draw_masked[global.border_status])
378 DrawMaskedBorder_Rect(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
381 void DrawMaskedBorder_DOOR_1()
383 if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
384 (global.border_status != GAME_MODE_EDITOR ||
385 border.draw_masked[GFX_SPECIAL_ARG_EDITOR]))
386 DrawMaskedBorder_Rect(DX, DY, DXSIZE, DYSIZE);
389 void DrawMaskedBorder_DOOR_2()
391 if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
392 global.border_status != GAME_MODE_EDITOR)
393 DrawMaskedBorder_Rect(VX, VY, VXSIZE, VYSIZE);
396 void DrawMaskedBorder_DOOR_3()
398 /* currently not available */
401 void DrawMaskedBorder_ALL()
403 DrawMaskedBorder_FIELD();
404 DrawMaskedBorder_DOOR_1();
405 DrawMaskedBorder_DOOR_2();
406 DrawMaskedBorder_DOOR_3();
409 void DrawMaskedBorder(int redraw_mask)
411 /* never draw masked screen borders on borderless screens */
412 if (effectiveGameStatus() == GAME_MODE_LOADING ||
413 effectiveGameStatus() == GAME_MODE_TITLE)
416 /* never draw masked screen borders when displaying request outside door */
417 if (effectiveGameStatus() == GAME_MODE_PSEUDO_DOOR &&
418 global.use_envelope_request)
421 if (redraw_mask & REDRAW_ALL)
422 DrawMaskedBorder_ALL();
425 if (redraw_mask & REDRAW_FIELD)
426 DrawMaskedBorder_FIELD();
427 if (redraw_mask & REDRAW_DOOR_1)
428 DrawMaskedBorder_DOOR_1();
429 if (redraw_mask & REDRAW_DOOR_2)
430 DrawMaskedBorder_DOOR_2();
431 if (redraw_mask & REDRAW_DOOR_3)
432 DrawMaskedBorder_DOOR_3();
436 void BlitScreenToBitmap(Bitmap *target_bitmap)
438 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
439 int fx = FX, fy = FY;
440 int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
441 int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0);
444 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
445 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
446 int dx_var = dx * TILESIZE_VAR / TILESIZE;
447 int dy_var = dy * TILESIZE_VAR / TILESIZE;
450 // fx += dx * TILESIZE_VAR / TILESIZE;
451 // fy += dy * TILESIZE_VAR / TILESIZE;
453 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
454 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
457 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
458 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
460 if (EVEN(SCR_FIELDX))
462 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
463 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
465 fx += (dx_var > 0 ? TILEX_VAR : 0);
472 if (EVEN(SCR_FIELDY))
474 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
475 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
477 fy += (dy_var > 0 ? TILEY_VAR : 0);
485 printf("::: (%d, %d) [(%d / %d, %d / %d)] => %d, %d\n",
488 SBY_Upper, SBY_Lower,
493 if (full_lev_fieldx <= SCR_FIELDX)
495 // printf(":1: PLAYFIELD FITS TO SCREEN [%d, %d, %d]\n", fx, ffx, dx_var);
497 if (EVEN(SCR_FIELDX))
498 fx = 2 * TILEX_VAR - (ODD(lev_fieldx) ? TILEX_VAR / 2 : 0);
500 fx = 2 * TILEX_VAR - (EVEN(lev_fieldx) ? TILEX_VAR / 2 : 0);
502 // printf(":2: PLAYFIELD FITS TO SCREEN [%d, %d, %d]\n", fx, ffx, dx_var);
505 if (full_lev_fieldy <= SCR_FIELDY)
507 if (EVEN(SCR_FIELDY))
508 fy = 2 * TILEY_VAR - (ODD(lev_fieldy) ? TILEY_VAR / 2 : 0);
510 fy = 2 * TILEY_VAR - (EVEN(lev_fieldy) ? TILEY_VAR / 2 : 0);
514 if (border.draw_masked[GAME_MODE_PLAYING])
516 if (buffer != backbuffer)
518 /* copy playfield buffer to backbuffer to add masked border */
519 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
520 DrawMaskedBorder(REDRAW_FIELD);
523 BlitBitmap(backbuffer, target_bitmap,
524 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
529 BlitBitmap(buffer, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
536 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
539 printf("::: TILES TO REFRESH: %d\n", redraw_tiles);
540 for (x = 0; x < SCR_FIELDX; x++)
541 for (y = 0 ; y < SCR_FIELDY; y++)
542 if (redraw[redraw_x1 + x][redraw_y1 + y])
543 printf("::: - %d, %d [%s]\n",
544 LEVELX(x), LEVELY(y),
545 EL_NAME(Feld[LEVELX(x)][LEVELY(y)]));
548 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
549 redraw_mask |= REDRAW_FIELD;
552 // never redraw single tiles, always redraw the whole field
553 // (redrawing single tiles up to a certain threshold was faster on old,
554 // now legacy graphics, but slows things down on modern graphics now)
555 // UPDATE: this is now globally defined by value of REDRAWTILES_THRESHOLD
556 if (redraw_mask & REDRAW_TILES)
557 redraw_mask |= REDRAW_FIELD;
561 /* !!! TEST ONLY !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
562 /* (force full redraw) */
563 if (game_status == GAME_MODE_PLAYING)
564 redraw_mask |= REDRAW_FIELD;
567 if (redraw_mask & REDRAW_FIELD)
568 redraw_mask &= ~REDRAW_TILES;
570 if (redraw_mask == REDRAW_NONE)
575 if (redraw_mask & REDRAW_ALL)
576 printf("[REDRAW_ALL]");
577 if (redraw_mask & REDRAW_FIELD)
578 printf("[REDRAW_FIELD]");
579 if (redraw_mask & REDRAW_TILES)
580 printf("[REDRAW_TILES]");
581 if (redraw_mask & REDRAW_DOOR_1)
582 printf("[REDRAW_DOOR_1]");
583 if (redraw_mask & REDRAW_DOOR_2)
584 printf("[REDRAW_DOOR_2]");
585 if (redraw_mask & REDRAW_FROM_BACKBUFFER)
586 printf("[REDRAW_FROM_BACKBUFFER]");
587 printf(" [%d]\n", FrameCounter);
590 if (redraw_mask & REDRAW_TILES &&
591 game_status == GAME_MODE_PLAYING &&
592 border.draw_masked[GAME_MODE_PLAYING])
593 redraw_mask |= REDRAW_FIELD;
595 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
597 static boolean last_frame_skipped = FALSE;
598 boolean skip_even_when_not_scrolling = TRUE;
599 boolean just_scrolling = (ScreenMovDir != 0);
600 boolean verbose = FALSE;
602 if (global.fps_slowdown_factor > 1 &&
603 (FrameCounter % global.fps_slowdown_factor) &&
604 (just_scrolling || skip_even_when_not_scrolling))
606 redraw_mask &= ~REDRAW_MAIN;
608 last_frame_skipped = TRUE;
611 printf("FRAME SKIPPED\n");
615 if (last_frame_skipped)
616 redraw_mask |= REDRAW_FIELD;
618 last_frame_skipped = FALSE;
621 printf("frame not skipped\n");
625 /* synchronize X11 graphics at this point; if we would synchronize the
626 display immediately after the buffer switching (after the XFlush),
627 this could mean that we have to wait for the graphics to complete,
628 although we could go on doing calculations for the next frame */
632 /* never draw masked border to backbuffer when using playfield buffer */
633 if (game_status != GAME_MODE_PLAYING ||
634 redraw_mask & REDRAW_FROM_BACKBUFFER ||
635 buffer == backbuffer)
636 DrawMaskedBorder(redraw_mask);
638 DrawMaskedBorder(redraw_mask & REDRAW_DOORS);
640 if (redraw_mask & REDRAW_ALL)
642 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
644 redraw_mask = REDRAW_NONE;
647 if (redraw_mask & REDRAW_FIELD)
650 printf("::: REDRAW_FIELD\n");
653 if (game_status != GAME_MODE_PLAYING ||
654 redraw_mask & REDRAW_FROM_BACKBUFFER)
656 BlitBitmap(backbuffer, window,
657 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
662 BlitScreenToBitmap(window);
664 int fx = FX, fy = FY;
667 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
668 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
669 int dx_var = dx * TILESIZE_VAR / TILESIZE;
670 int dy_var = dy * TILESIZE_VAR / TILESIZE;
673 // fx += dx * TILESIZE_VAR / TILESIZE;
674 // fy += dy * TILESIZE_VAR / TILESIZE;
676 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
677 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
680 /* !!! THIS WORKS !!! */
682 printf("::: %d, %d\n", scroll_x, scroll_y);
684 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
685 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
687 if (EVEN(SCR_FIELDX))
689 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
690 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
692 fx += (dx > 0 ? TILEX_VAR : 0);
699 if (EVEN(SCR_FIELDY))
701 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
702 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
704 fy += (dy > 0 ? TILEY_VAR : 0);
711 if (border.draw_masked[GAME_MODE_PLAYING])
713 if (buffer != backbuffer)
715 /* copy playfield buffer to backbuffer to add masked border */
716 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
717 DrawMaskedBorder(REDRAW_FIELD);
720 BlitBitmap(backbuffer, window,
721 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
726 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
732 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
734 (setup.soft_scrolling ?
735 "setup.soft_scrolling" :
736 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
737 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
738 ABS(ScreenGfxPos) == ScrollStepSize ?
739 "ABS(ScreenGfxPos) == ScrollStepSize" :
740 "redraw_tiles > REDRAWTILES_THRESHOLD"));
745 redraw_mask &= ~REDRAW_MAIN;
748 if (redraw_mask & REDRAW_DOORS)
750 if (redraw_mask & REDRAW_DOOR_1)
751 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
753 if (redraw_mask & REDRAW_DOOR_2)
754 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
756 if (redraw_mask & REDRAW_DOOR_3)
757 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
759 redraw_mask &= ~REDRAW_DOORS;
762 if (redraw_mask & REDRAW_MICROLEVEL)
764 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
765 SX, SY + 10 * TILEY);
767 redraw_mask &= ~REDRAW_MICROLEVEL;
770 if (redraw_mask & REDRAW_TILES)
773 printf("::: REDRAW_TILES\n");
779 InitGfxClipRegion(TRUE, SX, SY, SXSIZE, SYSIZE);
782 int sx = SX; // - (EVEN(SCR_FIELDX) ? TILEX_VAR / 2 : 0);
783 int sy = SY; // + (EVEN(SCR_FIELDY) ? TILEY_VAR / 2 : 0);
786 int dx_var = dx * TILESIZE_VAR / TILESIZE;
787 int dy_var = dy * TILESIZE_VAR / TILESIZE;
789 int fx = FX, fy = FY;
791 int scr_fieldx = SCR_FIELDX + (EVEN(SCR_FIELDX) ? 2 : 0);
792 int scr_fieldy = SCR_FIELDY + (EVEN(SCR_FIELDY) ? 2 : 0);
794 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
795 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
797 if (EVEN(SCR_FIELDX))
799 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
801 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
810 fx += (dx_var > 0 ? TILEX_VAR : 0);
814 if (EVEN(SCR_FIELDY))
816 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
818 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
827 fy += (dy_var > 0 ? TILEY_VAR : 0);
832 printf("::: %d, %d, %d, %d\n", sx, sy, SCR_FIELDX, SCR_FIELDY);
835 for (x = 0; x < scr_fieldx; x++)
836 for (y = 0 ; y < scr_fieldy; y++)
837 if (redraw[redraw_x1 + x][redraw_y1 + y])
838 BlitBitmap(buffer, window,
839 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
840 TILEX_VAR, TILEY_VAR,
841 sx + x * TILEX_VAR, sy + y * TILEY_VAR);
844 InitGfxClipRegion(FALSE, -1, -1, -1, -1);
846 for (x = 0; x < SCR_FIELDX; x++)
847 for (y = 0 ; y < SCR_FIELDY; y++)
848 if (redraw[redraw_x1 + x][redraw_y1 + y])
849 BlitBitmap(buffer, window,
850 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
851 TILEX_VAR, TILEY_VAR,
852 SX + x * TILEX_VAR, SY + y * TILEY_VAR);
856 for (x = 0; x < SCR_FIELDX; x++)
857 for (y = 0 ; y < SCR_FIELDY; y++)
858 if (redraw[redraw_x1 + x][redraw_y1 + y])
859 BlitBitmap(buffer, window,
860 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
861 SX + x * TILEX, SY + y * TILEY);
865 if (redraw_mask & REDRAW_FPS) /* display frames per second */
870 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
871 if (!global.fps_slowdown)
874 sprintf(text, "%04.1f fps%s", global.frames_per_second, info1);
876 DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE);
878 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
884 for (x = 0; x < MAX_BUF_XSIZE; x++)
885 for (y = 0; y < MAX_BUF_YSIZE; y++)
888 redraw_mask = REDRAW_NONE;
891 static void FadeCrossSaveBackbuffer()
893 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
896 static void FadeExt(int fade_mask, int fade_mode, int fade_type)
898 static int fade_type_skip = FADE_TYPE_NONE;
899 void (*draw_border_function)(void) = NULL;
900 Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL);
901 int x, y, width, height;
902 int fade_delay, post_delay;
904 if (fade_type == FADE_TYPE_FADE_OUT)
906 if (fade_type_skip != FADE_TYPE_NONE)
909 printf("::: skipping %d ... [%d] (X)\n", fade_mode, fade_type_skip);
912 /* skip all fade operations until specified fade operation */
913 if (fade_type & fade_type_skip)
914 fade_type_skip = FADE_TYPE_NONE;
919 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
921 FadeCrossSaveBackbuffer();
927 redraw_mask |= fade_mask;
929 if (fade_type == FADE_TYPE_SKIP)
932 printf("::: will skip %d ... [%d]\n", fade_mode, fade_type_skip);
935 fade_type_skip = fade_mode;
941 printf("::: !!! FADING %d ... [%d] [%d]\n", fade_mode, fade_type,
946 fade_delay = fading.fade_delay;
947 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
950 if (fade_type_skip != FADE_TYPE_NONE)
953 printf("::: skipping %d ... [%d]\n", fade_mode, fade_type_skip);
956 /* skip all fade operations until specified fade operation */
957 if (fade_type & fade_type_skip)
958 fade_type_skip = FADE_TYPE_NONE;
968 if (global.autoplay_leveldir)
970 // fading.fade_mode = FADE_MODE_NONE;
977 if (fading.fade_mode == FADE_MODE_NONE)
985 /* !!! what about fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */
988 printf("::: NOW FADING %d ... [%d]\n", fade_mode, fade_type);
992 if (fade_mask == REDRAW_NONE)
993 fade_mask = REDRAW_FIELD;
996 // if (fade_mask & REDRAW_FIELD)
997 if (fade_mask == REDRAW_FIELD)
1001 width = FULL_SXSIZE;
1002 height = FULL_SYSIZE;
1005 fade_delay = fading.fade_delay;
1006 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
1009 if (border.draw_masked_when_fading)
1010 draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */
1012 DrawMaskedBorder_FIELD(); /* draw once */
1014 else /* REDRAW_ALL */
1022 fade_delay = fading.fade_delay;
1023 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
1028 if (!setup.fade_screens ||
1030 fading.fade_mode == FADE_MODE_NONE)
1032 if (!setup.fade_screens || fade_delay == 0)
1035 if (fade_mode == FADE_MODE_FADE_OUT)
1039 if (fade_mode == FADE_MODE_FADE_OUT &&
1040 fading.fade_mode != FADE_MODE_NONE)
1041 ClearRectangle(backbuffer, x, y, width, height);
1047 BlitBitmap(backbuffer, window, x, y, width, height, x, y);
1049 redraw_mask &= ~fade_mask;
1051 /* always redraw area that was explicitly marked to fade */
1052 redraw_mask |= fade_mask;
1060 BlitBitmap(backbuffer, window, x, y, width, height, x, y);
1061 redraw_mask = REDRAW_NONE;
1062 // (^^^ WRONG; should be "redraw_mask &= ~fade_mask" if done this way)
1071 FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay,
1072 draw_border_function);
1074 redraw_mask &= ~fade_mask;
1077 void FadeIn(int fade_mask)
1079 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
1080 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN);
1082 FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN);
1085 void FadeOut(int fade_mask)
1087 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
1088 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_OUT);
1090 FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT);
1092 global.border_status = game_status;
1095 static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set)
1097 static struct TitleFadingInfo fading_leave_stored;
1100 fading_leave_stored = fading_leave;
1102 fading = fading_leave_stored;
1105 void FadeSetEnterMenu()
1107 fading = menu.enter_menu;
1110 printf("::: storing enter_menu\n");
1113 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1116 void FadeSetLeaveMenu()
1118 fading = menu.leave_menu;
1121 printf("::: storing leave_menu\n");
1124 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1127 void FadeSetEnterScreen()
1129 fading = menu.enter_screen[game_status];
1132 printf("::: storing leave_screen[%d]\n", game_status);
1135 FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */
1138 void FadeSetNextScreen()
1140 fading = menu.next_screen;
1143 printf("::: storing next_screen\n");
1146 // (do not overwrite fade mode set by FadeSetEnterScreen)
1147 // FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1150 void FadeSetLeaveScreen()
1153 printf("::: recalling last stored value\n");
1156 FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */
1159 void FadeSetFromType(int type)
1161 if (type & TYPE_ENTER_SCREEN)
1162 FadeSetEnterScreen();
1163 else if (type & TYPE_ENTER)
1165 else if (type & TYPE_LEAVE)
1169 void FadeSetDisabled()
1171 static struct TitleFadingInfo fading_none = { FADE_MODE_NONE, -1, -1, -1 };
1173 fading = fading_none;
1176 void FadeSkipNextFadeIn()
1178 FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP);
1181 void FadeSkipNextFadeOut()
1183 FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
1186 void SetWindowBackgroundImageIfDefined(int graphic)
1188 if (graphic_info[graphic].bitmap)
1189 SetWindowBackgroundBitmap(graphic_info[graphic].bitmap);
1192 void SetMainBackgroundImageIfDefined(int graphic)
1194 if (graphic_info[graphic].bitmap)
1195 SetMainBackgroundBitmap(graphic_info[graphic].bitmap);
1198 void SetDoorBackgroundImageIfDefined(int graphic)
1200 if (graphic_info[graphic].bitmap)
1201 SetDoorBackgroundBitmap(graphic_info[graphic].bitmap);
1204 void SetWindowBackgroundImage(int graphic)
1206 SetWindowBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1207 graphic_info[graphic].bitmap ?
1208 graphic_info[graphic].bitmap :
1209 graphic_info[IMG_BACKGROUND].bitmap);
1212 void SetMainBackgroundImage(int graphic)
1214 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1215 graphic_info[graphic].bitmap ?
1216 graphic_info[graphic].bitmap :
1217 graphic_info[IMG_BACKGROUND].bitmap);
1220 void SetDoorBackgroundImage(int graphic)
1222 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1223 graphic_info[graphic].bitmap ?
1224 graphic_info[graphic].bitmap :
1225 graphic_info[IMG_BACKGROUND].bitmap);
1228 void SetPanelBackground()
1231 struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL];
1234 BlitBitmapTiled(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1235 gfx->width, gfx->height, 0, 0, DXSIZE, DYSIZE);
1237 /* (ClearRectangle() only needed if panel bitmap is smaller than panel) */
1238 ClearRectangle(bitmap_db_panel, DX, DY, DXSIZE, DYSIZE);
1239 BlitBitmap(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1240 MIN(gfx->width, DXSIZE), MIN(gfx->height, DYSIZE), 0, 0);
1243 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, bitmap_db_panel,
1244 DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, 0, 0);
1247 SetDoorBackgroundBitmap(bitmap_db_panel);
1250 void DrawBackground(int x, int y, int width, int height)
1252 /* !!! "drawto" might still point to playfield buffer here (see below) !!! */
1253 /* (when entering hall of fame after playing) */
1255 ClearRectangleOnBackground(drawto, x, y, width, height);
1257 ClearRectangleOnBackground(backbuffer, x, y, width, height);
1263 if (IN_GFX_FIELD_FULL(x, y))
1264 redraw_mask |= REDRAW_FIELD;
1265 else if (IN_GFX_DOOR_1(x, y))
1266 redraw_mask |= REDRAW_DOOR_1;
1267 else if (IN_GFX_DOOR_2(x, y))
1268 redraw_mask |= REDRAW_DOOR_2;
1269 else if (IN_GFX_DOOR_3(x, y))
1270 redraw_mask |= REDRAW_DOOR_3;
1272 /* (this only works for the current arrangement of playfield and panels) */
1274 redraw_mask |= REDRAW_FIELD;
1275 else if (y < gfx.vy)
1276 redraw_mask |= REDRAW_DOOR_1;
1278 redraw_mask |= REDRAW_DOOR_2;
1282 /* (this is just wrong (when drawing to one of the two door panel areas)) */
1283 redraw_mask |= REDRAW_FIELD;
1287 void DrawBackgroundForFont(int x, int y, int width, int height, int font_nr)
1289 struct FontBitmapInfo *font = getFontBitmapInfo(font_nr);
1291 if (font->bitmap == NULL)
1294 DrawBackground(x, y, width, height);
1297 void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic)
1299 struct GraphicInfo *g = &graphic_info[graphic];
1301 if (g->bitmap == NULL)
1304 DrawBackground(x, y, width, height);
1309 /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
1310 /* (when entering hall of fame after playing) */
1311 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
1313 /* !!! maybe this should be done before clearing the background !!! */
1314 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
1316 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
1317 SetDrawtoField(DRAW_BUFFERED);
1320 SetDrawtoField(DRAW_BACKBUFFER);
1323 void MarkTileDirty(int x, int y)
1325 int xx = redraw_x1 + x;
1326 int yy = redraw_y1 + y;
1328 if (!redraw[xx][yy])
1331 redraw[xx][yy] = TRUE;
1332 redraw_mask |= REDRAW_TILES;
1335 void SetBorderElement()
1339 BorderElement = EL_EMPTY;
1341 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
1343 for (x = 0; x < lev_fieldx; x++)
1345 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
1346 BorderElement = EL_STEELWALL;
1348 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
1354 void FloodFillLevel(int from_x, int from_y, int fill_element,
1355 short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
1356 int max_fieldx, int max_fieldy)
1360 static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
1361 static int safety = 0;
1363 /* check if starting field still has the desired content */
1364 if (field[from_x][from_y] == fill_element)
1369 if (safety > max_fieldx * max_fieldy)
1370 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
1372 old_element = field[from_x][from_y];
1373 field[from_x][from_y] = fill_element;
1375 for (i = 0; i < 4; i++)
1377 x = from_x + check[i][0];
1378 y = from_y + check[i][1];
1380 if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
1381 FloodFillLevel(x, y, fill_element, field, max_fieldx, max_fieldy);
1387 void SetRandomAnimationValue(int x, int y)
1389 gfx.anim_random_frame = GfxRandom[x][y];
1392 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
1394 /* animation synchronized with global frame counter, not move position */
1395 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
1396 sync_frame = FrameCounter;
1398 return getAnimationFrame(graphic_info[graphic].anim_frames,
1399 graphic_info[graphic].anim_delay,
1400 graphic_info[graphic].anim_mode,
1401 graphic_info[graphic].anim_start_frame,
1405 void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw,
1406 Bitmap **bitmap, int *x, int *y,
1407 boolean get_backside)
1411 int width_mult, width_div;
1412 int height_mult, height_div;
1416 { 15, 16, 2, 3 }, /* 1 x 1 */
1417 { 7, 8, 2, 3 }, /* 2 x 2 */
1418 { 3, 4, 2, 3 }, /* 4 x 4 */
1419 { 1, 2, 2, 3 }, /* 8 x 8 */
1420 { 0, 1, 2, 3 }, /* 16 x 16 */
1421 { 0, 1, 0, 1 }, /* 32 x 32 */
1423 struct GraphicInfo *g = &graphic_info[graphic];
1424 Bitmap *src_bitmap = g->bitmap;
1425 int tilesize = MIN(MAX(1, tilesize_raw), TILESIZE);
1426 int offset_calc_pos = log_2(tilesize);
1427 int width_mult = offset_calc[offset_calc_pos].width_mult;
1428 int width_div = offset_calc[offset_calc_pos].width_div;
1429 int height_mult = offset_calc[offset_calc_pos].height_mult;
1430 int height_div = offset_calc[offset_calc_pos].height_div;
1431 int startx = src_bitmap->width * width_mult / width_div;
1432 int starty = src_bitmap->height * height_mult / height_div;
1434 int src_x = (g->src_x + (get_backside ? g->offset2_x : 0)) *
1435 tilesize / TILESIZE;
1436 int src_y = (g->src_y + (get_backside ? g->offset2_y : 0)) *
1437 tilesize / TILESIZE;
1439 int src_x = g->src_x * tilesize / TILESIZE;
1440 int src_y = g->src_y * tilesize / TILESIZE;
1442 int width = g->width * tilesize / TILESIZE;
1443 int height = g->height * tilesize / TILESIZE;
1444 int offset_x = g->offset_x * tilesize / TILESIZE;
1445 int offset_y = g->offset_y * tilesize / TILESIZE;
1447 if (g->offset_y == 0) /* frames are ordered horizontally */
1449 int max_width = g->anim_frames_per_line * width;
1450 int pos = (src_y / height) * max_width + src_x + frame * offset_x;
1452 src_x = pos % max_width;
1453 src_y = src_y % height + pos / max_width * height;
1455 else if (g->offset_x == 0) /* frames are ordered vertically */
1457 int max_height = g->anim_frames_per_line * height;
1458 int pos = (src_x / width) * max_height + src_y + frame * offset_y;
1460 src_x = src_x % width + pos / max_height * width;
1461 src_y = pos % max_height;
1463 else /* frames are ordered diagonally */
1465 src_x = src_x + frame * offset_x;
1466 src_y = src_y + frame * offset_y;
1469 *bitmap = src_bitmap;
1470 *x = startx + src_x;
1471 *y = starty + src_y;
1474 void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1475 int *x, int *y, boolean get_backside)
1477 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y,
1481 void getSizedGraphicSource(int graphic, int frame, int tilesize_raw,
1482 Bitmap **bitmap, int *x, int *y)
1484 getSizedGraphicSourceExt(graphic, frame, tilesize_raw, bitmap, x, y, FALSE);
1487 void getFixedGraphicSource(int graphic, int frame,
1488 Bitmap **bitmap, int *x, int *y)
1490 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y, FALSE);
1493 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1496 getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
1498 struct GraphicInfo *g = &graphic_info[graphic];
1499 int mini_startx = 0;
1500 int mini_starty = g->bitmap->height * 2 / 3;
1502 *bitmap = g->bitmap;
1503 *x = mini_startx + g->src_x / 2;
1504 *y = mini_starty + g->src_y / 2;
1508 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1509 int *x, int *y, boolean get_backside)
1511 struct GraphicInfo *g = &graphic_info[graphic];
1512 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
1513 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
1516 if (TILESIZE_VAR != TILESIZE)
1517 return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
1521 *bitmap = g->bitmap;
1523 if (g->offset_y == 0) /* frames are ordered horizontally */
1525 int max_width = g->anim_frames_per_line * g->width;
1526 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
1528 *x = pos % max_width;
1529 *y = src_y % g->height + pos / max_width * g->height;
1531 else if (g->offset_x == 0) /* frames are ordered vertically */
1533 int max_height = g->anim_frames_per_line * g->height;
1534 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
1536 *x = src_x % g->width + pos / max_height * g->width;
1537 *y = pos % max_height;
1539 else /* frames are ordered diagonally */
1541 *x = src_x + frame * g->offset_x;
1542 *y = src_y + frame * g->offset_y;
1546 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
1548 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
1551 void DrawGraphic(int x, int y, int graphic, int frame)
1554 if (!IN_SCR_FIELD(x, y))
1556 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1557 printf("DrawGraphic(): This should never happen!\n");
1563 DrawGraphicExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR, graphic,
1566 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
1568 MarkTileDirty(x, y);
1571 void DrawFixedGraphic(int x, int y, int graphic, int frame)
1574 if (!IN_SCR_FIELD(x, y))
1576 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1577 printf("DrawGraphic(): This should never happen!\n");
1582 DrawFixedGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1584 MarkTileDirty(x, y);
1587 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1593 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1595 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX_VAR, TILEY_VAR, x, y);
1597 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1601 void DrawFixedGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1607 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1608 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1611 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
1614 if (!IN_SCR_FIELD(x, y))
1616 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1617 printf("DrawGraphicThruMask(): This should never happen!\n");
1623 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
1626 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1629 MarkTileDirty(x, y);
1632 void DrawFixedGraphicThruMask(int x, int y, int graphic, int frame)
1635 if (!IN_SCR_FIELD(x, y))
1637 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1638 printf("DrawGraphicThruMask(): This should never happen!\n");
1643 DrawFixedGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1645 MarkTileDirty(x, y);
1648 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
1654 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1656 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1657 dst_x - src_x, dst_y - src_y);
1659 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX_VAR, TILEY_VAR,
1662 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1666 void DrawFixedGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y,
1667 int graphic, int frame)
1672 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1674 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1675 dst_x - src_x, dst_y - src_y);
1676 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1679 void DrawSizedGraphic(int x, int y, int graphic, int frame, int tilesize)
1681 DrawSizedGraphicExt(drawto, SX + x * tilesize, SY + y * tilesize, graphic,
1683 MarkTileDirty(x / tilesize, y / tilesize);
1686 void DrawSizedGraphicExt(DrawBuffer *d, int x, int y, int graphic, int frame,
1692 getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
1693 BlitBitmap(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
1696 void DrawMiniGraphic(int x, int y, int graphic)
1698 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1699 MarkTileDirty(x / 2, y / 2);
1702 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1707 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1708 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1711 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
1712 int graphic, int frame,
1713 int cut_mode, int mask_mode)
1718 int width = TILEX, height = TILEY;
1721 if (dx || dy) /* shifted graphic */
1723 if (x < BX1) /* object enters playfield from the left */
1730 else if (x > BX2) /* object enters playfield from the right */
1736 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1742 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1744 else if (dx) /* general horizontal movement */
1745 MarkTileDirty(x + SIGN(dx), y);
1747 if (y < BY1) /* object enters playfield from the top */
1749 if (cut_mode==CUT_BELOW) /* object completely above top border */
1757 else if (y > BY2) /* object enters playfield from the bottom */
1763 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1769 else if (dy > 0 && cut_mode == CUT_ABOVE)
1771 if (y == BY2) /* object completely above bottom border */
1777 MarkTileDirty(x, y + 1);
1778 } /* object leaves playfield to the bottom */
1779 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1781 else if (dy) /* general vertical movement */
1782 MarkTileDirty(x, y + SIGN(dy));
1786 if (!IN_SCR_FIELD(x, y))
1788 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1789 printf("DrawGraphicShifted(): This should never happen!\n");
1795 width = width * TILESIZE_VAR / TILESIZE;
1796 height = height * TILESIZE_VAR / TILESIZE;
1797 cx = cx * TILESIZE_VAR / TILESIZE;
1798 cy = cy * TILESIZE_VAR / TILESIZE;
1799 dx = dx * TILESIZE_VAR / TILESIZE;
1800 dy = dy * TILESIZE_VAR / TILESIZE;
1803 if (width > 0 && height > 0)
1805 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1811 dst_x = FX + x * TILEX_VAR + dx;
1812 dst_y = FY + y * TILEY_VAR + dy;
1814 dst_x = FX + x * TILEX + dx;
1815 dst_y = FY + y * TILEY + dy;
1818 if (mask_mode == USE_MASKING)
1820 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1821 dst_x - src_x, dst_y - src_y);
1822 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1826 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1829 MarkTileDirty(x, y);
1833 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
1834 int graphic, int frame,
1835 int cut_mode, int mask_mode)
1841 int width = TILEX_VAR, height = TILEY_VAR;
1843 int width = TILEX, height = TILEY;
1847 int x2 = x + SIGN(dx);
1848 int y2 = y + SIGN(dy);
1850 /* !!! DOES NOT WORK FOR SLOW MOVEMENT !!! */
1851 int sync_frame = GfxFrame[LEVELX(x)][LEVELY(y)];
1853 /* movement with two-tile animations must be sync'ed with movement position,
1854 not with current GfxFrame (which can be higher when using slow movement) */
1855 int anim_pos = (dx ? ABS(dx) : ABS(dy));
1856 int anim_frames = graphic_info[graphic].anim_frames;
1858 /* (we also need anim_delay here for movement animations with less frames) */
1859 int anim_delay = graphic_info[graphic].anim_delay;
1860 int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
1862 int sync_frame = anim_pos * anim_frames / TILESIZE;
1865 boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */
1866 boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */
1868 /* re-calculate animation frame for two-tile movement animation */
1869 frame = getGraphicAnimationFrame(graphic, sync_frame);
1873 printf("::: %d, %d, %d => %d [%d]\n",
1874 anim_pos, anim_frames, anim_delay, sync_frame, graphic);
1876 printf("::: %d, %d => %d\n",
1877 anim_pos, anim_frames, sync_frame);
1882 printf("::: %d [%d, %d] [%d] [%d]\n", frame, sync_frame, dy,
1883 GfxFrame[LEVELX(x)][LEVELY(y)], mask_mode);
1886 /* check if movement start graphic inside screen area and should be drawn */
1887 if (draw_start_tile && IN_SCR_FIELD(x1, y1))
1889 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
1892 dst_x = FX + x1 * TILEX_VAR;
1893 dst_y = FY + y1 * TILEY_VAR;
1895 dst_x = FX + x1 * TILEX;
1896 dst_y = FY + y1 * TILEY;
1899 if (mask_mode == USE_MASKING)
1901 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1902 dst_x - src_x, dst_y - src_y);
1903 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1907 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1910 MarkTileDirty(x1, y1);
1913 /* check if movement end graphic inside screen area and should be drawn */
1914 if (draw_end_tile && IN_SCR_FIELD(x2, y2))
1916 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
1919 dst_x = FX + x2 * TILEX_VAR;
1920 dst_y = FY + y2 * TILEY_VAR;
1922 dst_x = FX + x2 * TILEX;
1923 dst_y = FY + y2 * TILEY;
1926 if (mask_mode == USE_MASKING)
1928 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1929 dst_x - src_x, dst_y - src_y);
1930 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1934 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1937 MarkTileDirty(x2, y2);
1941 static void DrawGraphicShifted(int x, int y, int dx, int dy,
1942 int graphic, int frame,
1943 int cut_mode, int mask_mode)
1947 DrawGraphic(x, y, graphic, frame);
1952 if (graphic_info[graphic].double_movement) /* EM style movement images */
1953 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1955 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1958 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1959 int frame, int cut_mode)
1961 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1964 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1965 int cut_mode, int mask_mode)
1967 int lx = LEVELX(x), ly = LEVELY(y);
1971 if (IN_LEV_FIELD(lx, ly))
1973 SetRandomAnimationValue(lx, ly);
1975 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1976 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1978 /* do not use double (EM style) movement graphic when not moving */
1979 if (graphic_info[graphic].double_movement && !dx && !dy)
1981 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
1982 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1985 else /* border element */
1987 graphic = el2img(element);
1988 frame = getGraphicAnimationFrame(graphic, -1);
1991 if (element == EL_EXPANDABLE_WALL)
1993 boolean left_stopped = FALSE, right_stopped = FALSE;
1995 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1996 left_stopped = TRUE;
1997 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1998 right_stopped = TRUE;
2000 if (left_stopped && right_stopped)
2002 else if (left_stopped)
2004 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
2005 frame = graphic_info[graphic].anim_frames - 1;
2007 else if (right_stopped)
2009 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
2010 frame = graphic_info[graphic].anim_frames - 1;
2015 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
2016 else if (mask_mode == USE_MASKING)
2017 DrawGraphicThruMask(x, y, graphic, frame);
2019 DrawGraphic(x, y, graphic, frame);
2022 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
2023 int cut_mode, int mask_mode)
2025 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2026 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
2027 cut_mode, mask_mode);
2030 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
2033 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
2036 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
2039 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
2042 void DrawLevelElementThruMask(int x, int y, int element)
2044 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
2047 void DrawLevelFieldThruMask(int x, int y)
2049 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
2052 /* !!! implementation of quicksand is totally broken !!! */
2053 #define IS_CRUMBLED_TILE(x, y, e) \
2054 (GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) || \
2055 !IS_MOVING(x, y) || \
2056 (e) == EL_QUICKSAND_EMPTYING || \
2057 (e) == EL_QUICKSAND_FAST_EMPTYING))
2059 static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
2064 int width, height, cx, cy;
2065 int sx = SCREENX(x), sy = SCREENY(y);
2066 int crumbled_border_size = graphic_info[graphic].border_size;
2069 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2071 for (i = 1; i < 4; i++)
2073 int dxx = (i & 1 ? dx : 0);
2074 int dyy = (i & 2 ? dy : 0);
2077 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2080 /* check if neighbour field is of same crumble type */
2081 boolean same = (IS_CRUMBLED_TILE(xx, yy, element) &&
2082 graphic_info[graphic].class ==
2083 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class);
2085 /* return if check prevents inner corner */
2086 if (same == (dxx == dx && dyy == dy))
2090 /* if we reach this point, we have an inner corner */
2092 getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
2095 width = crumbled_border_size * TILESIZE_VAR / TILESIZE;
2096 height = crumbled_border_size * TILESIZE_VAR / TILESIZE;
2097 cx = (dx > 0 ? TILEX - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
2098 cy = (dy > 0 ? TILEY - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
2100 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2101 width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
2103 width = crumbled_border_size;
2104 height = crumbled_border_size;
2105 cx = (dx > 0 ? TILEX - crumbled_border_size : 0);
2106 cy = (dy > 0 ? TILEY - crumbled_border_size : 0);
2108 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2109 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2113 static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
2118 int width, height, bx, by, cx, cy;
2119 int sx = SCREENX(x), sy = SCREENY(y);
2120 int crumbled_border_size = graphic_info[graphic].border_size;
2123 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
2125 /* draw simple, sloppy, non-corner-accurate crumbled border */
2128 width = (dir == 1 || dir == 2 ? crumbled_border_size : TILEX);
2129 height = (dir == 0 || dir == 3 ? crumbled_border_size : TILEY);
2130 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2131 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2133 if (dir == 1 || dir == 2) /* left or right crumbled border */
2135 width = crumbled_border_size;
2137 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2140 else /* top or bottom crumbled border */
2143 height = crumbled_border_size;
2145 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2150 BlitBitmap(src_bitmap, drawto_field,
2151 src_x + cx * TILESIZE_VAR / TILESIZE,
2152 src_y + cy * TILESIZE_VAR / TILESIZE,
2153 width * TILESIZE_VAR / TILESIZE,
2154 height * TILESIZE_VAR / TILESIZE,
2155 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
2156 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
2158 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2159 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2162 /* (remaining middle border part must be at least as big as corner part) */
2163 if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
2164 crumbled_border_size >= TILESIZE / 3)
2167 /* correct corners of crumbled border, if needed */
2170 for (i = -1; i <= 1; i+=2)
2172 int xx = x + (dir == 0 || dir == 3 ? i : 0);
2173 int yy = y + (dir == 1 || dir == 2 ? i : 0);
2174 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2177 /* check if neighbour field is of same crumble type */
2178 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2179 graphic_info[graphic].class ==
2180 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2182 /* no crumbled corner, but continued crumbled border */
2184 int c1 = (dir == 2 || dir == 3 ? TILESIZE - crumbled_border_size : 0);
2185 int c2 = (i == 1 ? TILESIZE - crumbled_border_size : 0);
2186 int b1 = (i == 1 ? crumbled_border_size :
2187 TILESIZE - 2 * crumbled_border_size);
2189 width = crumbled_border_size;
2190 height = crumbled_border_size;
2192 if (dir == 1 || dir == 2)
2208 BlitBitmap(src_bitmap, drawto_field,
2209 src_x + bx * TILESIZE_VAR / TILESIZE,
2210 src_y + by * TILESIZE_VAR / TILESIZE,
2211 width * TILESIZE_VAR / TILESIZE,
2212 height * TILESIZE_VAR / TILESIZE,
2213 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
2214 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
2216 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2217 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2222 if (dir == 1 || dir == 2) /* left or right crumbled border */
2224 for (i = -1; i <= 1; i+=2)
2228 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2231 /* check if neighbour field is of same crumble type */
2232 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2233 graphic_info[graphic].class ==
2234 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2236 /* no crumbled corner, but continued crumbled border */
2238 width = crumbled_border_size;
2239 height = crumbled_border_size;
2240 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2241 cy = (i == 1 ? TILEY - crumbled_border_size : 0);
2243 by = (i == 1 ? crumbled_border_size :
2244 TILEY - 2 * crumbled_border_size);
2246 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2247 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2251 else /* top or bottom crumbled border */
2253 for (i = -1; i <= 1; i+=2)
2257 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2260 /* check if neighbour field is of same crumble type */
2261 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2262 graphic_info[graphic].class ==
2263 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2265 /* no crumbled corner, but continued crumbled border */
2267 width = crumbled_border_size;
2268 height = crumbled_border_size;
2269 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
2270 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2271 bx = (i == 1 ? crumbled_border_size :
2272 TILEX - 2 * crumbled_border_size);
2275 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2276 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2283 static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
2285 int sx = SCREENX(x), sy = SCREENY(y);
2288 static int xy[4][2] =
2296 if (!IN_LEV_FIELD(x, y))
2299 element = TILE_GFX_ELEMENT(x, y);
2301 /* crumble field itself */
2302 if (IS_CRUMBLED_TILE(x, y, element))
2304 if (!IN_SCR_FIELD(sx, sy))
2307 for (i = 0; i < 4; i++)
2309 int xx = x + xy[i][0];
2310 int yy = y + xy[i][1];
2312 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2315 /* check if neighbour field is of same crumble type */
2317 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2318 graphic_info[graphic].class ==
2319 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2322 if (IS_CRUMBLED_TILE(xx, yy, element))
2326 DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
2329 if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
2330 graphic_info[graphic].anim_frames == 2)
2332 for (i = 0; i < 4; i++)
2334 int dx = (i & 1 ? +1 : -1);
2335 int dy = (i & 2 ? +1 : -1);
2337 DrawLevelFieldCrumbledInnerCorners(x, y, dx, dy, graphic);
2341 MarkTileDirty(sx, sy);
2343 else /* center field not crumbled -- crumble neighbour fields */
2345 for (i = 0; i < 4; i++)
2347 int xx = x + xy[i][0];
2348 int yy = y + xy[i][1];
2349 int sxx = sx + xy[i][0];
2350 int syy = sy + xy[i][1];
2352 if (!IN_LEV_FIELD(xx, yy) ||
2353 !IN_SCR_FIELD(sxx, syy))
2356 if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
2359 element = TILE_GFX_ELEMENT(xx, yy);
2361 if (!IS_CRUMBLED_TILE(xx, yy, element))
2364 graphic = el_act2crm(element, ACTION_DEFAULT);
2366 DrawLevelFieldCrumbledBorders(xx, yy, graphic, 0, 3 - i);
2368 MarkTileDirty(sxx, syy);
2373 void DrawLevelFieldCrumbled(int x, int y)
2377 if (!IN_LEV_FIELD(x, y))
2381 /* !!! CHECK THIS !!! */
2384 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2385 GFX_CRUMBLED(GfxElement[x][y]))
2388 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2389 GfxElement[x][y] != EL_UNDEFINED &&
2390 GFX_CRUMBLED(GfxElement[x][y]))
2392 DrawLevelFieldCrumbledDigging(x, y, GfxDir[x][y], GfxFrame[x][y]);
2399 graphic = el_act2crm(TILE_GFX_ELEMENT(x, y), ACTION_DEFAULT);
2401 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
2404 DrawLevelFieldCrumbledExt(x, y, graphic, 0);
2407 void DrawLevelFieldCrumbledDigging(int x, int y, int direction,
2410 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
2411 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
2412 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
2413 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
2414 int sx = SCREENX(x), sy = SCREENY(y);
2416 DrawGraphic(sx, sy, graphic1, frame1);
2417 DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
2420 void DrawLevelFieldCrumbledNeighbours(int x, int y)
2422 int sx = SCREENX(x), sy = SCREENY(y);
2423 static int xy[4][2] =
2432 for (i = 0; i < 4; i++)
2434 int xx = x + xy[i][0];
2435 int yy = y + xy[i][1];
2436 int sxx = sx + xy[i][0];
2437 int syy = sy + xy[i][1];
2439 if (!IN_LEV_FIELD(xx, yy) ||
2440 !IN_SCR_FIELD(sxx, syy) ||
2441 !GFX_CRUMBLED(Feld[xx][yy]) ||
2445 DrawLevelField(xx, yy);
2449 static int getBorderElement(int x, int y)
2453 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
2454 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
2455 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
2456 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
2457 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
2458 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
2459 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
2461 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2462 int steel_position = (x == -1 && y == -1 ? 0 :
2463 x == lev_fieldx && y == -1 ? 1 :
2464 x == -1 && y == lev_fieldy ? 2 :
2465 x == lev_fieldx && y == lev_fieldy ? 3 :
2466 x == -1 || x == lev_fieldx ? 4 :
2467 y == -1 || y == lev_fieldy ? 5 : 6);
2469 return border[steel_position][steel_type];
2472 void DrawScreenElement(int x, int y, int element)
2474 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
2475 DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
2478 void DrawLevelElement(int x, int y, int element)
2480 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2481 DrawScreenElement(SCREENX(x), SCREENY(y), element);
2484 void DrawScreenField(int x, int y)
2486 int lx = LEVELX(x), ly = LEVELY(y);
2487 int element, content;
2489 if (!IN_LEV_FIELD(lx, ly))
2491 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
2494 element = getBorderElement(lx, ly);
2496 DrawScreenElement(x, y, element);
2501 element = Feld[lx][ly];
2502 content = Store[lx][ly];
2504 if (IS_MOVING(lx, ly))
2506 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
2507 boolean cut_mode = NO_CUTTING;
2509 if (element == EL_QUICKSAND_EMPTYING ||
2510 element == EL_QUICKSAND_FAST_EMPTYING ||
2511 element == EL_MAGIC_WALL_EMPTYING ||
2512 element == EL_BD_MAGIC_WALL_EMPTYING ||
2513 element == EL_DC_MAGIC_WALL_EMPTYING ||
2514 element == EL_AMOEBA_DROPPING)
2515 cut_mode = CUT_ABOVE;
2516 else if (element == EL_QUICKSAND_FILLING ||
2517 element == EL_QUICKSAND_FAST_FILLING ||
2518 element == EL_MAGIC_WALL_FILLING ||
2519 element == EL_BD_MAGIC_WALL_FILLING ||
2520 element == EL_DC_MAGIC_WALL_FILLING)
2521 cut_mode = CUT_BELOW;
2524 if (lx == 9 && ly == 1)
2525 printf("::: %s [%d] [%d, %d] [%d]\n",
2526 EL_NAME(TILE_GFX_ELEMENT(lx, ly)),
2527 el_act2crm(TILE_GFX_ELEMENT(lx, ly), ACTION_DEFAULT),
2528 element_info[EL_QUICKSAND_EMPTYING].graphic[ACTION_DEFAULT],
2529 element_info[EL_QUICKSAND_EMPTYING].crumbled[ACTION_DEFAULT],
2530 GFX_CRUMBLED(TILE_GFX_ELEMENT(lx, ly)));
2533 if (cut_mode == CUT_ABOVE)
2535 DrawScreenElement(x, y, element);
2537 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
2540 DrawScreenElement(x, y, EL_EMPTY);
2543 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
2544 else if (cut_mode == NO_CUTTING)
2545 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
2548 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
2551 if (cut_mode == CUT_BELOW &&
2552 IN_LEV_FIELD(lx, ly + 1) && IN_SCR_FIELD(x, y + 1))
2553 DrawLevelElement(lx, ly + 1, element);
2557 if (content == EL_ACID)
2559 int dir = MovDir[lx][ly];
2560 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
2561 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
2563 DrawLevelElementThruMask(newlx, newly, EL_ACID);
2566 else if (IS_BLOCKED(lx, ly))
2571 boolean cut_mode = NO_CUTTING;
2572 int element_old, content_old;
2574 Blocked2Moving(lx, ly, &oldx, &oldy);
2577 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
2578 MovDir[oldx][oldy] == MV_RIGHT);
2580 element_old = Feld[oldx][oldy];
2581 content_old = Store[oldx][oldy];
2583 if (element_old == EL_QUICKSAND_EMPTYING ||
2584 element_old == EL_QUICKSAND_FAST_EMPTYING ||
2585 element_old == EL_MAGIC_WALL_EMPTYING ||
2586 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2587 element_old == EL_DC_MAGIC_WALL_EMPTYING ||
2588 element_old == EL_AMOEBA_DROPPING)
2589 cut_mode = CUT_ABOVE;
2591 DrawScreenElement(x, y, EL_EMPTY);
2594 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2596 else if (cut_mode == NO_CUTTING)
2597 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2600 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2603 else if (IS_DRAWABLE(element))
2604 DrawScreenElement(x, y, element);
2606 DrawScreenElement(x, y, EL_EMPTY);
2609 void DrawLevelField(int x, int y)
2611 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2612 DrawScreenField(SCREENX(x), SCREENY(y));
2613 else if (IS_MOVING(x, y))
2617 Moving2Blocked(x, y, &newx, &newy);
2618 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2619 DrawScreenField(SCREENX(newx), SCREENY(newy));
2621 else if (IS_BLOCKED(x, y))
2625 Blocked2Moving(x, y, &oldx, &oldy);
2626 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2627 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2631 void DrawMiniElement(int x, int y, int element)
2635 graphic = el2edimg(element);
2636 DrawMiniGraphic(x, y, graphic);
2639 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2641 int x = sx + scroll_x, y = sy + scroll_y;
2643 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2644 DrawMiniElement(sx, sy, EL_EMPTY);
2645 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2646 DrawMiniElement(sx, sy, Feld[x][y]);
2648 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
2651 void DrawEnvelopeBackgroundTiles(int graphic, int startx, int starty,
2652 int x, int y, int xsize, int ysize,
2653 int tile_width, int tile_height)
2657 int dst_x = startx + x * tile_width;
2658 int dst_y = starty + y * tile_height;
2659 int width = graphic_info[graphic].width;
2660 int height = graphic_info[graphic].height;
2661 int inner_width_raw = MAX(width - 2 * tile_width, tile_width);
2662 int inner_height_raw = MAX(height - 2 * tile_height, tile_height);
2663 int inner_width = inner_width_raw - (inner_width_raw % tile_width);
2664 int inner_height = inner_height_raw - (inner_height_raw % tile_height);
2665 int inner_sx = (width >= 3 * tile_width ? tile_width : 0);
2666 int inner_sy = (height >= 3 * tile_height ? tile_height : 0);
2667 boolean draw_masked = graphic_info[graphic].draw_masked;
2669 getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2671 if (src_bitmap == NULL || width < tile_width || height < tile_height)
2673 ClearRectangle(drawto, dst_x, dst_y, tile_width, tile_height);
2677 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - tile_width :
2678 inner_sx + (x - 1) * tile_width % inner_width);
2679 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - tile_height :
2680 inner_sy + (y - 1) * tile_height % inner_height);
2684 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
2685 dst_x - src_x, dst_y - src_y);
2686 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
2690 BlitBitmap(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
2694 void DrawEnvelopeBackground(int graphic, int startx, int starty,
2695 int x, int y, int xsize, int ysize, int font_nr)
2697 int font_width = getFontWidth(font_nr);
2698 int font_height = getFontHeight(font_nr);
2700 DrawEnvelopeBackgroundTiles(graphic, startx, starty, x, y, xsize, ysize,
2701 font_width, font_height);
2704 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
2706 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2707 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2708 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2709 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2710 boolean no_delay = (tape.warp_forward);
2711 unsigned int anim_delay = 0;
2712 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2713 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
2714 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2715 int font_width = getFontWidth(font_nr);
2716 int font_height = getFontHeight(font_nr);
2717 int max_xsize = level.envelope[envelope_nr].xsize;
2718 int max_ysize = level.envelope[envelope_nr].ysize;
2719 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2720 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2721 int xend = max_xsize;
2722 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2723 int xstep = (xstart < xend ? 1 : 0);
2724 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2727 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2729 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2730 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2731 int sx = SX + (SXSIZE - xsize * font_width) / 2;
2732 int sy = SY + (SYSIZE - ysize * font_height) / 2;
2735 SetDrawtoField(DRAW_BUFFERED);
2738 BlitScreenToBitmap(backbuffer);
2740 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2743 SetDrawtoField(DRAW_BACKBUFFER);
2745 for (yy = 0; yy < ysize; yy++)
2746 for (xx = 0; xx < xsize; xx++)
2747 DrawEnvelopeBackground(graphic, sx, sy, xx, yy, xsize, ysize, font_nr);
2750 DrawTextBuffer(sx + font_width, sy + font_height,
2751 level.envelope[envelope_nr].text, font_nr, max_xsize,
2752 xsize - 2, ysize - 2, 0, mask_mode,
2753 level.envelope[envelope_nr].autowrap,
2754 level.envelope[envelope_nr].centered, FALSE);
2756 DrawTextToTextArea(sx + font_width, sy + font_height,
2757 level.envelope[envelope_nr].text, font_nr, max_xsize,
2758 xsize - 2, ysize - 2, mask_mode);
2761 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2764 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2768 void ShowEnvelope(int envelope_nr)
2770 int element = EL_ENVELOPE_1 + envelope_nr;
2771 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2772 int sound_opening = element_info[element].sound[ACTION_OPENING];
2773 int sound_closing = element_info[element].sound[ACTION_CLOSING];
2774 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2775 boolean no_delay = (tape.warp_forward);
2776 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
2777 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
2778 int anim_mode = graphic_info[graphic].anim_mode;
2779 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
2780 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
2782 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
2784 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
2786 if (anim_mode == ANIM_DEFAULT)
2787 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
2789 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
2792 Delay(wait_delay_value);
2794 WaitForEventToContinue();
2796 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
2798 if (anim_mode != ANIM_NONE)
2799 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
2801 if (anim_mode == ANIM_DEFAULT)
2802 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
2804 game.envelope_active = FALSE;
2806 SetDrawtoField(DRAW_BUFFERED);
2808 redraw_mask |= REDRAW_FIELD;
2812 static void setRequestPosition(int *x, int *y, boolean add_border_size)
2814 int border_size = request.border_size;
2815 int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2);
2816 int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2);
2817 int sx = sx_center - request.width / 2;
2818 int sy = sy_center - request.height / 2;
2820 if (add_border_size)
2830 void DrawEnvelopeRequest(char *text)
2832 char *text_final = text;
2833 char *text_door_style = NULL;
2834 int graphic = IMG_BACKGROUND_REQUEST;
2835 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2836 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2837 int font_nr = FONT_REQUEST;
2838 int font_width = getFontWidth(font_nr);
2839 int font_height = getFontHeight(font_nr);
2840 int border_size = request.border_size;
2841 int line_spacing = request.line_spacing;
2842 int line_height = font_height + line_spacing;
2843 int text_width = request.width - 2 * border_size;
2844 int text_height = request.height - 2 * border_size;
2845 int line_length = text_width / font_width;
2846 int max_lines = text_height / line_height;
2847 int width = request.width;
2848 int height = request.height;
2849 int tile_size = request.step_offset;
2850 int x_steps = width / tile_size;
2851 int y_steps = height / tile_size;
2855 if (request.wrap_single_words)
2857 char *src_text_ptr, *dst_text_ptr;
2859 text_door_style = checked_malloc(2 * strlen(text) + 1);
2861 src_text_ptr = text;
2862 dst_text_ptr = text_door_style;
2864 while (*src_text_ptr)
2866 if (*src_text_ptr == ' ' ||
2867 *src_text_ptr == '?' ||
2868 *src_text_ptr == '!')
2869 *dst_text_ptr++ = '\n';
2871 if (*src_text_ptr != ' ')
2872 *dst_text_ptr++ = *src_text_ptr;
2877 *dst_text_ptr = '\0';
2879 text_final = text_door_style;
2882 setRequestPosition(&sx, &sy, FALSE);
2884 ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
2886 for (y = 0; y < y_steps; y++)
2887 for (x = 0; x < x_steps; x++)
2888 DrawEnvelopeBackgroundTiles(graphic, sx, sy,
2889 x, y, x_steps, y_steps,
2890 tile_size, tile_size);
2892 DrawTextBuffer(sx + border_size, sy + border_size, text_final, font_nr,
2893 line_length, -1, max_lines, line_spacing, mask_mode,
2894 request.autowrap, request.centered, FALSE);
2896 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2897 RedrawGadget(tool_gadget[i]);
2899 // store readily prepared envelope request for later use when animating
2900 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2904 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2905 BlitBitmap(bitmap_db_cross, backbuffer, sx, sy, width, height, sx, sy);
2907 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2912 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2914 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2920 if (text_door_style)
2921 free(text_door_style);
2926 void AnimateEnvelopeRequest(int anim_mode, int action)
2928 int graphic = IMG_BACKGROUND_REQUEST;
2929 boolean draw_masked = graphic_info[graphic].draw_masked;
2931 int delay_value_normal = request.step_delay;
2932 int delay_value_fast = delay_value_normal / 2;
2934 int delay_value_normal = GameFrameDelay;
2935 int delay_value_fast = FfwdFrameDelay;
2937 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2938 boolean no_delay = (tape.warp_forward);
2939 int delay_value = (ffwd_delay ? delay_value_fast : delay_value_normal);
2940 int anim_delay_value = (no_delay ? 0 : delay_value + 500 * 0);
2941 unsigned int anim_delay = 0;
2943 int width = request.width;
2944 int height = request.height;
2945 int tile_size = request.step_offset;
2946 int max_xsize = width / tile_size;
2947 int max_ysize = height / tile_size;
2948 int max_xsize_inner = max_xsize - 2;
2949 int max_ysize_inner = max_ysize - 2;
2951 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize_inner : 0);
2952 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize_inner : 0);
2953 int xend = max_xsize_inner;
2954 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize_inner : 0);
2955 int xstep = (xstart < xend ? 1 : 0);
2956 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2959 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2961 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2962 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2963 int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2);
2964 int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2);
2965 int src_x = sx_center - width / 2;
2966 int src_y = sy_center - height / 2;
2967 int dst_x = sx_center - xsize * tile_size / 2;
2968 int dst_y = sy_center - ysize * tile_size / 2;
2969 int xsize_size_left = (xsize - 1) * tile_size;
2970 int ysize_size_top = (ysize - 1) * tile_size;
2971 int max_xsize_pos = (max_xsize - 1) * tile_size;
2972 int max_ysize_pos = (max_ysize - 1) * tile_size;
2975 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2978 for (yy = 0; yy < 2; yy++)
2980 for (xx = 0; xx < 2; xx++)
2982 int src_xx = src_x + xx * max_xsize_pos;
2983 int src_yy = src_y + yy * max_ysize_pos;
2984 int dst_xx = dst_x + xx * xsize_size_left;
2985 int dst_yy = dst_y + yy * ysize_size_top;
2986 int xx_size = (xx ? tile_size : xsize_size_left);
2987 int yy_size = (yy ? tile_size : ysize_size_top);
2990 BlitBitmapMasked(bitmap_db_cross, backbuffer,
2991 src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
2993 BlitBitmap(bitmap_db_cross, backbuffer,
2994 src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
2998 BlitBitmap(bitmap_db_cross, backbuffer,
3000 xsize_size_left, ysize_size_top,
3002 BlitBitmap(bitmap_db_cross, backbuffer,
3003 src_x + max_xsize_pos, src_y,
3004 tile_size, ysize_size_top,
3005 dst_x + xsize_size_left, dst_y);
3006 BlitBitmap(bitmap_db_cross, backbuffer,
3007 src_x, src_y + max_ysize_pos,
3008 xsize_size_left, tile_size,
3009 dst_x, dst_y + ysize_size_top);
3010 BlitBitmap(bitmap_db_cross, backbuffer,
3011 src_x + max_xsize_pos, src_y + max_ysize_pos,
3012 tile_size, tile_size,
3013 dst_x + xsize_size_left, dst_y + ysize_size_top);
3017 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3018 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
3020 /* CHECK AGAIN (previous code reactivated) */
3021 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3031 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
3037 void AnimateEnvelopeRequest(char *text, int anim_mode, int action)
3040 int envelope_nr = 0;
3043 int graphic = IMG_BACKGROUND_REQUEST;
3045 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
3047 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
3048 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
3049 boolean ffwd_delay = (tape.playing && tape.fast_forward);
3050 boolean no_delay = (tape.warp_forward);
3051 unsigned int anim_delay = 0;
3052 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
3053 int anim_delay_value = (no_delay ? 0 : frame_delay_value + 500 * 0);
3055 int max_word_len = maxWordLengthInString(text);
3056 int font_nr = (max_word_len > 7 ? FONT_TEXT_1 : FONT_TEXT_2);
3058 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
3060 int font_width = getFontWidth(font_nr);
3061 int font_height = getFontHeight(font_nr);
3062 int line_spacing = 2 * 1;
3066 int max_xsize = DXSIZE / font_width;
3067 // int max_ysize = DYSIZE / font_height;
3068 int max_ysize = DYSIZE / (font_height + line_spacing);
3070 int max_xsize = 7; /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
3071 int max_ysize = 13; /* tools.c: MAX_REQUEST_LINES == 13 */
3075 int max_xsize = level.envelope[envelope_nr].xsize;
3076 int max_ysize = level.envelope[envelope_nr].ysize;
3078 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
3079 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
3080 int xend = max_xsize;
3081 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
3082 int xstep = (xstart < xend ? 1 : 0);
3083 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
3088 char *text_copy = getStringCopy(text);
3091 font_nr = FONT_TEXT_2;
3093 if (maxWordLengthInString(text) > 7) /* MAX_REQUEST_LINE_FONT1_LEN == 7 */
3095 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
3096 font_nr = FONT_TEXT_1;
3099 int max_word_len = 0;
3101 char *text_copy = getStringCopy(text);
3103 font_nr = FONT_TEXT_2;
3105 for (text_ptr = text; *text_ptr; text_ptr++)
3107 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
3109 if (max_word_len > 7) /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
3111 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
3112 font_nr = FONT_TEXT_1;
3121 for (text_ptr = text_copy; *text_ptr; text_ptr++)
3122 if (*text_ptr == ' ')
3127 dDX = SX + (SXSIZE - DXSIZE) / 2 - DX;
3128 dDY = SY + (SYSIZE - DYSIZE) / 2 - DY;
3130 dDX = SX + SXSIZE / 2 - max_xsize * font_width / 2 - DX;
3131 dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY;
3134 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
3136 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
3137 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
3138 int sx = SX + (SXSIZE - xsize * font_width) / 2;
3139 // int sy = SX + (SYSIZE - ysize * font_height) / 2;
3140 int sy = SY + (SYSIZE - ysize * (font_height + line_spacing)) / 2;
3144 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3146 SetDrawtoField(DRAW_BUFFERED);
3149 BlitScreenToBitmap(backbuffer);
3151 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
3154 SetDrawtoField(DRAW_BACKBUFFER);
3157 for (yy = 0; yy < ysize; yy++)
3158 for (xx = 0; xx < xsize; xx++)
3159 DrawEnvelopeBackgroundTiles(graphic, sx, sy, xx, yy, xsize, ysize,
3160 getFontWidth(font_nr),
3161 getFontHeight(font_nr) + line_spacing);
3166 DrawTextBuffer(sx + font_width, sy + font_height + 8,
3167 text_copy, font_nr, max_xsize,
3168 xsize - 2, ysize - 2, line_spacing, mask_mode,
3169 FALSE, TRUE, FALSE);
3171 DrawTextBuffer(sx + font_width, sy + font_height,
3172 level.envelope[envelope_nr].text, font_nr, max_xsize,
3173 xsize - 2, ysize - 2, 0, mask_mode,
3174 level.envelope[envelope_nr].autowrap,
3175 level.envelope[envelope_nr].centered, FALSE);
3179 DrawTextToTextArea(sx + font_width, sy + font_height,
3180 level.envelope[envelope_nr].text, font_nr, max_xsize,
3181 xsize - 2, ysize - 2, mask_mode);
3184 /* copy request gadgets to door backbuffer */
3187 if ((ysize - 2) > 13)
3188 BlitBitmap(bitmap_db_door, drawto,
3189 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3190 DOOR_GFX_PAGEY1 + 13 * font_height,
3191 (xsize - 2) * font_width,
3192 (ysize - 2 - 13) * font_height,
3194 sy + font_height * (1 + 13));
3196 if ((ysize - 2) > 13)
3197 BlitBitmap(bitmap_db_door, drawto,
3198 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3199 DOOR_GFX_PAGEY1 + 11 * (font_height + line_spacing * 0),
3200 (xsize - 2) * font_width,
3201 (ysize - 2 - 13) * (font_height + line_spacing),
3203 sy + (font_height + line_spacing) * (1 + 13));
3205 if ((ysize - 2) > 13)
3206 BlitBitmap(bitmap_db_door, drawto,
3207 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3208 DOOR_GFX_PAGEY1 + 13 * font_height,
3209 (xsize - 2) * font_width,
3210 (ysize - 2 - 13) * font_height,
3212 sy + font_height * (1 + 13));
3216 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3217 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
3219 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3229 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
3239 void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
3242 int last_game_status = game_status; /* save current game status */
3243 // int last_draw_background_mask = gfx.draw_background_mask;
3246 int graphic = IMG_BACKGROUND_REQUEST;
3247 int sound_opening = SND_REQUEST_OPENING;
3248 int sound_closing = SND_REQUEST_CLOSING;
3250 int envelope_nr = 0;
3251 int element = EL_ENVELOPE_1 + envelope_nr;
3252 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
3253 int sound_opening = element_info[element].sound[ACTION_OPENING];
3254 int sound_closing = element_info[element].sound[ACTION_CLOSING];
3257 boolean ffwd_delay = (tape.playing && tape.fast_forward);
3258 boolean no_delay = (tape.warp_forward);
3259 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
3260 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
3262 int anim_mode = graphic_info[graphic].anim_mode;
3263 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
3264 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
3266 char *text_copy = getStringCopy(text);
3269 for (text_ptr = text_copy; *text_ptr; text_ptr++)
3270 if (*text_ptr == ' ')
3275 if (game_status == GAME_MODE_PLAYING)
3277 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
3278 BlitScreenToBitmap_EM(backbuffer);
3279 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3280 BlitScreenToBitmap_SP(backbuffer);
3283 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
3287 SetDrawtoField(DRAW_BACKBUFFER);
3289 // SetDrawBackgroundMask(REDRAW_NONE);
3291 if (action == ACTION_OPENING)
3293 BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3296 if (req_state & REQ_ASK)
3298 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
3299 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
3301 else if (req_state & REQ_CONFIRM)
3303 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
3305 else if (req_state & REQ_PLAYER)
3307 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
3308 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
3309 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
3310 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
3315 DrawEnvelopeRequest(text);
3317 DrawEnvelopeRequest(text_copy);
3320 if (game_status != GAME_MODE_MAIN)
3324 /* force DOOR font inside door area */
3325 game_status = GAME_MODE_PSEUDO_DOOR;
3328 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
3330 if (action == ACTION_OPENING)
3332 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
3334 if (anim_mode == ANIM_DEFAULT)
3335 AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_OPENING);
3337 AnimateEnvelopeRequest(main_anim_mode, ACTION_OPENING);
3341 Delay(wait_delay_value);
3343 WaitForEventToContinue();
3348 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
3350 if (anim_mode != ANIM_NONE)
3351 AnimateEnvelopeRequest(main_anim_mode, ACTION_CLOSING);
3353 if (anim_mode == ANIM_DEFAULT)
3354 AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_CLOSING);
3357 game.envelope_active = FALSE;
3360 // game_status = last_game_status; /* restore current game status */
3363 /* !!! CHECK AGAIN (SEE BELOW) !!! */
3364 game_status = last_game_status; /* restore current game status */
3367 if (action == ACTION_CLOSING)
3369 if (game_status != GAME_MODE_MAIN)
3372 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3375 SetDrawtoField(DRAW_BUFFERED);
3378 // SetDrawBackgroundMask(last_draw_background_mask);
3381 redraw_mask = REDRAW_FIELD;
3382 // redraw_mask |= REDRAW_ALL;
3384 /* CHECK AGAIN (previous code reactivated) */
3385 redraw_mask |= REDRAW_FIELD;
3389 if (game_status == GAME_MODE_MAIN)
3395 /* (important: after "BackToFront()", but before "SetDrawtoField()") */
3396 game_status = last_game_status; /* restore current game status */
3400 if (action == ACTION_CLOSING &&
3401 game_status == GAME_MODE_PLAYING &&
3402 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3403 SetDrawtoField(DRAW_BUFFERED);
3405 if (game_status == GAME_MODE_PLAYING &&
3406 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3407 SetDrawtoField(DRAW_BUFFERED);
3419 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
3423 int graphic = el2preimg(element);
3425 getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
3426 BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
3434 SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
3435 SetDrawBackgroundMask(REDRAW_FIELD);
3437 SetDrawBackgroundMask(REDRAW_NONE);
3442 for (x = BX1; x <= BX2; x++)
3443 for (y = BY1; y <= BY2; y++)
3444 DrawScreenField(x, y);
3446 redraw_mask |= REDRAW_FIELD;
3449 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
3453 for (x = 0; x < size_x; x++)
3454 for (y = 0; y < size_y; y++)
3455 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
3457 redraw_mask |= REDRAW_FIELD;
3460 static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y)
3462 boolean show_level_border = (BorderElement != EL_EMPTY);
3463 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3464 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3465 int tile_size = preview.tile_size;
3466 int preview_width = preview.xsize * tile_size;
3467 int preview_height = preview.ysize * tile_size;
3468 int real_preview_xsize = MIN(level_xsize, preview.xsize);
3469 int real_preview_ysize = MIN(level_ysize, preview.ysize);
3470 int real_preview_width = real_preview_xsize * tile_size;
3471 int real_preview_height = real_preview_ysize * tile_size;
3472 int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
3473 int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
3477 if (!IN_GFX_FIELD_FULL(dst_x, dst_y + preview_height - 1))
3482 dst_x += (preview_width - real_preview_width) / 2;
3483 dst_y += (preview_height - real_preview_height) / 2;
3485 DrawBackground(dst_x, dst_y, real_preview_width, real_preview_height);
3487 DrawBackground(dst_x, dst_y, preview_width, preview_height);
3489 dst_x += (preview_width - real_preview_width) / 2;
3490 dst_y += (preview_height - real_preview_height) / 2;
3493 for (x = 0; x < real_preview_xsize; x++)
3495 for (y = 0; y < real_preview_ysize; y++)
3497 int lx = from_x + x + (show_level_border ? -1 : 0);
3498 int ly = from_y + y + (show_level_border ? -1 : 0);
3499 int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
3500 getBorderElement(lx, ly));
3502 DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size,
3503 element, tile_size);
3507 redraw_mask |= REDRAW_MICROLEVEL;
3510 #define MICROLABEL_EMPTY 0
3511 #define MICROLABEL_LEVEL_NAME 1
3512 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
3513 #define MICROLABEL_LEVEL_AUTHOR 3
3514 #define MICROLABEL_IMPORTED_FROM_HEAD 4
3515 #define MICROLABEL_IMPORTED_FROM 5
3516 #define MICROLABEL_IMPORTED_BY_HEAD 6
3517 #define MICROLABEL_IMPORTED_BY 7
3519 static int getMaxTextLength(struct TextPosInfo *pos, int font_nr)
3521 int max_text_width = SXSIZE;
3522 int font_width = getFontWidth(font_nr);
3524 if (pos->align == ALIGN_CENTER)
3525 max_text_width = (pos->x < SXSIZE / 2 ? pos->x * 2 : (SXSIZE - pos->x) * 2);
3526 else if (pos->align == ALIGN_RIGHT)
3527 max_text_width = pos->x;
3529 max_text_width = SXSIZE - pos->x;
3531 return max_text_width / font_width;
3534 static void DrawPreviewLevelLabelExt(int mode)
3536 struct TextPosInfo *pos = &menu.main.text.level_info_2;
3537 char label_text[MAX_OUTPUT_LINESIZE + 1];
3538 int max_len_label_text;
3540 int font_nr = pos->font;
3543 if (!IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
3546 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3547 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3548 mode == MICROLABEL_IMPORTED_BY_HEAD)
3549 font_nr = pos->font_alt;
3551 int font_nr = FONT_TEXT_2;
3554 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3555 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3556 mode == MICROLABEL_IMPORTED_BY_HEAD)
3557 font_nr = FONT_TEXT_3;
3561 max_len_label_text = getMaxTextLength(pos, font_nr);
3563 max_len_label_text = SXSIZE / getFontWidth(font_nr);
3567 if (pos->size != -1)
3568 max_len_label_text = pos->size;
3571 for (i = 0; i < max_len_label_text; i++)
3572 label_text[i] = ' ';
3573 label_text[max_len_label_text] = '\0';
3575 if (strlen(label_text) > 0)
3578 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3580 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3581 int lypos = MICROLABEL2_YPOS;
3583 DrawText(lxpos, lypos, label_text, font_nr);
3588 (mode == MICROLABEL_LEVEL_NAME ? level.name :
3589 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
3590 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
3591 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
3592 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
3593 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
3594 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
3595 max_len_label_text);
3596 label_text[max_len_label_text] = '\0';
3598 if (strlen(label_text) > 0)
3601 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3603 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3604 int lypos = MICROLABEL2_YPOS;
3606 DrawText(lxpos, lypos, label_text, font_nr);
3610 redraw_mask |= REDRAW_MICROLEVEL;
3613 static void DrawPreviewLevelExt(boolean restart)
3615 static unsigned int scroll_delay = 0;
3616 static unsigned int label_delay = 0;
3617 static int from_x, from_y, scroll_direction;
3618 static int label_state, label_counter;
3619 unsigned int scroll_delay_value = preview.step_delay;
3620 boolean show_level_border = (BorderElement != EL_EMPTY);
3621 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3622 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3623 int last_game_status = game_status; /* save current game status */
3626 /* force PREVIEW font on preview level */
3627 game_status = GAME_MODE_PSEUDO_PREVIEW;
3635 if (preview.anim_mode == ANIM_CENTERED)
3637 if (level_xsize > preview.xsize)
3638 from_x = (level_xsize - preview.xsize) / 2;
3639 if (level_ysize > preview.ysize)
3640 from_y = (level_ysize - preview.ysize) / 2;
3643 from_x += preview.xoffset;
3644 from_y += preview.yoffset;
3646 scroll_direction = MV_RIGHT;
3650 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3651 DrawPreviewLevelLabelExt(label_state);
3653 /* initialize delay counters */
3654 DelayReached(&scroll_delay, 0);
3655 DelayReached(&label_delay, 0);
3657 if (leveldir_current->name)
3659 struct TextPosInfo *pos = &menu.main.text.level_info_1;
3660 char label_text[MAX_OUTPUT_LINESIZE + 1];
3662 int font_nr = pos->font;
3664 int font_nr = FONT_TEXT_1;
3667 int max_len_label_text = getMaxTextLength(pos, font_nr);
3669 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
3677 if (pos->size != -1)
3678 max_len_label_text = pos->size;
3681 strncpy(label_text, leveldir_current->name, max_len_label_text);
3682 label_text[max_len_label_text] = '\0';
3685 if (IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
3686 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3688 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3689 lypos = SY + MICROLABEL1_YPOS;
3691 DrawText(lxpos, lypos, label_text, font_nr);
3695 game_status = last_game_status; /* restore current game status */
3700 /* scroll preview level, if needed */
3701 if (preview.anim_mode != ANIM_NONE &&
3702 (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
3703 DelayReached(&scroll_delay, scroll_delay_value))
3705 switch (scroll_direction)
3710 from_x -= preview.step_offset;
3711 from_x = (from_x < 0 ? 0 : from_x);
3714 scroll_direction = MV_UP;
3718 if (from_x < level_xsize - preview.xsize)
3720 from_x += preview.step_offset;
3721 from_x = (from_x > level_xsize - preview.xsize ?
3722 level_xsize - preview.xsize : from_x);
3725 scroll_direction = MV_DOWN;
3731 from_y -= preview.step_offset;
3732 from_y = (from_y < 0 ? 0 : from_y);
3735 scroll_direction = MV_RIGHT;
3739 if (from_y < level_ysize - preview.ysize)
3741 from_y += preview.step_offset;
3742 from_y = (from_y > level_ysize - preview.ysize ?
3743 level_ysize - preview.ysize : from_y);
3746 scroll_direction = MV_LEFT;
3753 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3756 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
3757 /* redraw micro level label, if needed */
3758 if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
3759 !strEqual(level.author, ANONYMOUS_NAME) &&
3760 !strEqual(level.author, leveldir_current->name) &&
3761 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
3763 int max_label_counter = 23;
3765 if (leveldir_current->imported_from != NULL &&
3766 strlen(leveldir_current->imported_from) > 0)
3767 max_label_counter += 14;
3768 if (leveldir_current->imported_by != NULL &&
3769 strlen(leveldir_current->imported_by) > 0)
3770 max_label_counter += 14;
3772 label_counter = (label_counter + 1) % max_label_counter;
3773 label_state = (label_counter >= 0 && label_counter <= 7 ?
3774 MICROLABEL_LEVEL_NAME :
3775 label_counter >= 9 && label_counter <= 12 ?
3776 MICROLABEL_LEVEL_AUTHOR_HEAD :
3777 label_counter >= 14 && label_counter <= 21 ?
3778 MICROLABEL_LEVEL_AUTHOR :
3779 label_counter >= 23 && label_counter <= 26 ?
3780 MICROLABEL_IMPORTED_FROM_HEAD :
3781 label_counter >= 28 && label_counter <= 35 ?
3782 MICROLABEL_IMPORTED_FROM :
3783 label_counter >= 37 && label_counter <= 40 ?
3784 MICROLABEL_IMPORTED_BY_HEAD :
3785 label_counter >= 42 && label_counter <= 49 ?
3786 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
3788 if (leveldir_current->imported_from == NULL &&
3789 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
3790 label_state == MICROLABEL_IMPORTED_FROM))
3791 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
3792 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
3794 DrawPreviewLevelLabelExt(label_state);
3797 game_status = last_game_status; /* restore current game status */
3800 void DrawPreviewLevelInitial()
3802 DrawPreviewLevelExt(TRUE);
3805 void DrawPreviewLevelAnimation()
3807 DrawPreviewLevelExt(FALSE);
3810 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3811 int graphic, int sync_frame, int mask_mode)
3813 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3815 if (mask_mode == USE_MASKING)
3816 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3818 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
3821 inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3822 int graphic, int sync_frame,
3825 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3827 if (mask_mode == USE_MASKING)
3828 DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3830 DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
3833 inline void DrawGraphicAnimation(int x, int y, int graphic)
3835 int lx = LEVELX(x), ly = LEVELY(y);
3837 if (!IN_SCR_FIELD(x, y))
3841 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
3842 graphic, GfxFrame[lx][ly], NO_MASKING);
3844 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3845 graphic, GfxFrame[lx][ly], NO_MASKING);
3847 MarkTileDirty(x, y);
3850 inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
3852 int lx = LEVELX(x), ly = LEVELY(y);
3854 if (!IN_SCR_FIELD(x, y))
3857 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3858 graphic, GfxFrame[lx][ly], NO_MASKING);
3859 MarkTileDirty(x, y);
3862 void DrawLevelGraphicAnimation(int x, int y, int graphic)
3864 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3867 void DrawLevelElementAnimation(int x, int y, int element)
3869 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3871 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3874 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
3876 int sx = SCREENX(x), sy = SCREENY(y);
3878 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3881 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3884 DrawGraphicAnimation(sx, sy, graphic);
3887 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
3888 DrawLevelFieldCrumbled(x, y);
3890 if (GFX_CRUMBLED(Feld[x][y]))
3891 DrawLevelFieldCrumbled(x, y);
3895 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
3897 int sx = SCREENX(x), sy = SCREENY(y);
3900 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3903 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3905 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3908 DrawGraphicAnimation(sx, sy, graphic);
3910 if (GFX_CRUMBLED(element))
3911 DrawLevelFieldCrumbled(x, y);
3914 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
3916 if (player->use_murphy)
3918 /* this works only because currently only one player can be "murphy" ... */
3919 static int last_horizontal_dir = MV_LEFT;
3920 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
3922 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3923 last_horizontal_dir = move_dir;
3925 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
3927 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
3929 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
3935 return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
3938 static boolean equalGraphics(int graphic1, int graphic2)
3940 struct GraphicInfo *g1 = &graphic_info[graphic1];
3941 struct GraphicInfo *g2 = &graphic_info[graphic2];
3943 return (g1->bitmap == g2->bitmap &&
3944 g1->src_x == g2->src_x &&
3945 g1->src_y == g2->src_y &&
3946 g1->anim_frames == g2->anim_frames &&
3947 g1->anim_delay == g2->anim_delay &&
3948 g1->anim_mode == g2->anim_mode);
3951 void DrawAllPlayers()
3955 for (i = 0; i < MAX_PLAYERS; i++)
3956 if (stored_player[i].active)
3957 DrawPlayer(&stored_player[i]);
3960 void DrawPlayerField(int x, int y)
3962 if (!IS_PLAYER(x, y))
3965 DrawPlayer(PLAYERINFO(x, y));
3968 #define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
3970 void DrawPlayer(struct PlayerInfo *player)
3972 int jx = player->jx;
3973 int jy = player->jy;
3974 int move_dir = player->MovDir;
3975 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
3976 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
3977 int last_jx = (player->is_moving ? jx - dx : jx);
3978 int last_jy = (player->is_moving ? jy - dy : jy);
3979 int next_jx = jx + dx;
3980 int next_jy = jy + dy;
3981 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
3982 boolean player_is_opaque = FALSE;
3983 int sx = SCREENX(jx), sy = SCREENY(jy);
3984 int sxx = 0, syy = 0;
3985 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
3987 int action = ACTION_DEFAULT;
3988 int last_player_graphic = getPlayerGraphic(player, move_dir);
3989 int last_player_frame = player->Frame;
3992 /* GfxElement[][] is set to the element the player is digging or collecting;
3993 remove also for off-screen player if the player is not moving anymore */
3994 if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
3995 GfxElement[jx][jy] = EL_UNDEFINED;
3997 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
4001 if (!IN_LEV_FIELD(jx, jy))
4003 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
4004 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
4005 printf("DrawPlayerField(): This should never happen!\n");
4010 if (element == EL_EXPLOSION)
4013 action = (player->is_pushing ? ACTION_PUSHING :
4014 player->is_digging ? ACTION_DIGGING :
4015 player->is_collecting ? ACTION_COLLECTING :
4016 player->is_moving ? ACTION_MOVING :
4017 player->is_snapping ? ACTION_SNAPPING :
4018 player->is_dropping ? ACTION_DROPPING :
4019 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
4021 if (player->is_waiting)
4022 move_dir = player->dir_waiting;
4024 InitPlayerGfxAnimation(player, action, move_dir);
4026 /* ----------------------------------------------------------------------- */
4027 /* draw things in the field the player is leaving, if needed */
4028 /* ----------------------------------------------------------------------- */
4030 if (player->is_moving)
4032 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
4034 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
4036 if (last_element == EL_DYNAMITE_ACTIVE ||
4037 last_element == EL_EM_DYNAMITE_ACTIVE ||
4038 last_element == EL_SP_DISK_RED_ACTIVE)
4039 DrawDynamite(last_jx, last_jy);
4041 DrawLevelFieldThruMask(last_jx, last_jy);
4043 else if (last_element == EL_DYNAMITE_ACTIVE ||
4044 last_element == EL_EM_DYNAMITE_ACTIVE ||
4045 last_element == EL_SP_DISK_RED_ACTIVE)
4046 DrawDynamite(last_jx, last_jy);
4048 /* !!! this is not enough to prevent flickering of players which are
4049 moving next to each others without a free tile between them -- this
4050 can only be solved by drawing all players layer by layer (first the
4051 background, then the foreground etc.) !!! => TODO */
4052 else if (!IS_PLAYER(last_jx, last_jy))
4053 DrawLevelField(last_jx, last_jy);
4056 DrawLevelField(last_jx, last_jy);
4059 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
4060 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4063 if (!IN_SCR_FIELD(sx, sy))
4066 /* ----------------------------------------------------------------------- */
4067 /* draw things behind the player, if needed */
4068 /* ----------------------------------------------------------------------- */
4071 DrawLevelElement(jx, jy, Back[jx][jy]);
4072 else if (IS_ACTIVE_BOMB(element))
4073 DrawLevelElement(jx, jy, EL_EMPTY);
4076 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
4078 int old_element = GfxElement[jx][jy];
4079 int old_graphic = el_act_dir2img(old_element, action, move_dir);
4080 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
4082 if (GFX_CRUMBLED(old_element))
4083 DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
4085 DrawGraphic(sx, sy, old_graphic, frame);
4087 if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
4088 player_is_opaque = TRUE;
4092 GfxElement[jx][jy] = EL_UNDEFINED;
4094 /* make sure that pushed elements are drawn with correct frame rate */
4096 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4098 if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
4099 GfxFrame[jx][jy] = player->StepFrame;
4101 if (player->is_pushing && player->is_moving)
4102 GfxFrame[jx][jy] = player->StepFrame;
4105 DrawLevelField(jx, jy);
4109 #if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
4110 /* ----------------------------------------------------------------------- */
4111 /* draw player himself */
4112 /* ----------------------------------------------------------------------- */
4114 graphic = getPlayerGraphic(player, move_dir);
4116 /* in the case of changed player action or direction, prevent the current
4117 animation frame from being restarted for identical animations */
4118 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4119 player->Frame = last_player_frame;
4121 frame = getGraphicAnimationFrame(graphic, player->Frame);
4125 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4126 sxx = player->GfxPos;
4128 syy = player->GfxPos;
4131 if (!setup.soft_scrolling && ScreenMovPos)
4134 if (player_is_opaque)
4135 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4137 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4139 if (SHIELD_ON(player))
4141 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4142 IMG_SHIELD_NORMAL_ACTIVE);
4143 int frame = getGraphicAnimationFrame(graphic, -1);
4145 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4149 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4152 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4153 sxx = player->GfxPos;
4155 syy = player->GfxPos;
4159 /* ----------------------------------------------------------------------- */
4160 /* draw things the player is pushing, if needed */
4161 /* ----------------------------------------------------------------------- */
4164 printf("::: %d, %d [%d, %d] [%d]\n",
4165 player->is_pushing, player_is_moving, player->GfxAction,
4166 player->is_moving, player_is_moving);
4170 if (player->is_pushing && player->is_moving)
4172 int px = SCREENX(jx), py = SCREENY(jy);
4173 int pxx = (TILEX - ABS(sxx)) * dx;
4174 int pyy = (TILEY - ABS(syy)) * dy;
4175 int gfx_frame = GfxFrame[jx][jy];
4181 if (!IS_MOVING(jx, jy)) /* push movement already finished */
4183 element = Feld[next_jx][next_jy];
4184 gfx_frame = GfxFrame[next_jx][next_jy];
4187 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4190 sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
4191 frame = getGraphicAnimationFrame(graphic, sync_frame);
4193 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
4196 /* draw background element under pushed element (like the Sokoban field) */
4198 if (game.use_masked_pushing && IS_MOVING(jx, jy))
4200 /* this allows transparent pushing animation over non-black background */
4203 DrawLevelElement(jx, jy, Back[jx][jy]);
4205 DrawLevelElement(jx, jy, EL_EMPTY);
4207 if (Back[next_jx][next_jy])
4208 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4210 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4212 else if (Back[next_jx][next_jy])
4213 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4215 if (Back[next_jx][next_jy])
4216 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4220 printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
4221 jx, px, player->GfxPos, player->StepFrame,
4226 GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
4230 /* do not draw (EM style) pushing animation when pushing is finished */
4231 /* (two-tile animations usually do not contain start and end frame) */
4232 if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
4233 DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
4235 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4237 /* masked drawing is needed for EMC style (double) movement graphics */
4238 /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
4239 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4244 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4245 /* ----------------------------------------------------------------------- */
4246 /* draw player himself */
4247 /* ----------------------------------------------------------------------- */
4249 graphic = getPlayerGraphic(player, move_dir);
4251 /* in the case of changed player action or direction, prevent the current
4252 animation frame from being restarted for identical animations */
4253 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4254 player->Frame = last_player_frame;
4256 frame = getGraphicAnimationFrame(graphic, player->Frame);
4260 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4261 sxx = player->GfxPos;
4263 syy = player->GfxPos;
4266 if (!setup.soft_scrolling && ScreenMovPos)
4269 if (player_is_opaque)
4270 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4272 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4274 if (SHIELD_ON(player))
4276 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4277 IMG_SHIELD_NORMAL_ACTIVE);
4278 int frame = getGraphicAnimationFrame(graphic, -1);
4280 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4284 /* ----------------------------------------------------------------------- */
4285 /* draw things in front of player (active dynamite or dynabombs) */
4286 /* ----------------------------------------------------------------------- */
4288 if (IS_ACTIVE_BOMB(element))
4290 graphic = el2img(element);
4291 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
4293 if (game.emulation == EMU_SUPAPLEX)
4294 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
4296 DrawGraphicThruMask(sx, sy, graphic, frame);
4299 if (player_is_moving && last_element == EL_EXPLOSION)
4301 int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
4302 GfxElement[last_jx][last_jy] : EL_EMPTY);
4303 int graphic = el_act2img(element, ACTION_EXPLODING);
4304 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
4305 int phase = ExplodePhase[last_jx][last_jy] - 1;
4306 int frame = getGraphicAnimationFrame(graphic, phase - delay);
4309 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
4312 /* ----------------------------------------------------------------------- */
4313 /* draw elements the player is just walking/passing through/under */
4314 /* ----------------------------------------------------------------------- */
4316 if (player_is_moving)
4318 /* handle the field the player is leaving ... */
4319 if (IS_ACCESSIBLE_INSIDE(last_element))
4320 DrawLevelField(last_jx, last_jy);
4321 else if (IS_ACCESSIBLE_UNDER(last_element))
4322 DrawLevelFieldThruMask(last_jx, last_jy);
4325 /* do not redraw accessible elements if the player is just pushing them */
4326 if (!player_is_moving || !player->is_pushing)
4328 /* ... and the field the player is entering */
4329 if (IS_ACCESSIBLE_INSIDE(element))
4330 DrawLevelField(jx, jy);
4331 else if (IS_ACCESSIBLE_UNDER(element))
4332 DrawLevelFieldThruMask(jx, jy);
4335 MarkTileDirty(sx, sy);
4338 /* ------------------------------------------------------------------------- */
4340 void WaitForEventToContinue()
4342 boolean still_wait = TRUE;
4344 /* simulate releasing mouse button over last gadget, if still pressed */
4346 HandleGadgets(-1, -1, 0);
4348 button_status = MB_RELEASED;
4364 case EVENT_BUTTONPRESS:
4365 case EVENT_KEYPRESS:
4369 case EVENT_KEYRELEASE:
4370 ClearPlayerAction();
4374 HandleOtherEvents(&event);
4378 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4385 /* don't eat all CPU time */
4390 #define MAX_REQUEST_LINES 13
4391 #define MAX_REQUEST_LINE_FONT1_LEN 7
4392 #define MAX_REQUEST_LINE_FONT2_LEN 10
4396 static int RequestHandleEvents(unsigned int req_state)
4398 int last_game_status = game_status; /* save current game status */
4402 button_status = MB_RELEASED;
4404 request_gadget_id = -1;
4417 case EVENT_BUTTONPRESS:
4418 case EVENT_BUTTONRELEASE:
4419 case EVENT_MOTIONNOTIFY:
4421 if (event.type == EVENT_MOTIONNOTIFY)
4423 if (!PointerInWindow(window))
4424 continue; /* window and pointer are on different screens */
4429 motion_status = TRUE;
4430 mx = ((MotionEvent *) &event)->x;
4431 my = ((MotionEvent *) &event)->y;
4435 motion_status = FALSE;
4436 mx = ((ButtonEvent *) &event)->x;
4437 my = ((ButtonEvent *) &event)->y;
4438 if (event.type == EVENT_BUTTONPRESS)
4439 button_status = ((ButtonEvent *) &event)->button;
4441 button_status = MB_RELEASED;
4444 /* this sets 'request_gadget_id' */
4445 HandleGadgets(mx, my, button_status);
4447 switch (request_gadget_id)
4449 case TOOL_CTRL_ID_YES:
4452 case TOOL_CTRL_ID_NO:
4455 case TOOL_CTRL_ID_CONFIRM:
4456 result = TRUE | FALSE;
4459 case TOOL_CTRL_ID_PLAYER_1:
4462 case TOOL_CTRL_ID_PLAYER_2:
4465 case TOOL_CTRL_ID_PLAYER_3:
4468 case TOOL_CTRL_ID_PLAYER_4:
4479 case EVENT_KEYPRESS:
4480 switch (GetEventKey((KeyEvent *)&event, TRUE))
4483 if (req_state & REQ_CONFIRM)
4492 #if defined(TARGET_SDL2)
4502 if (req_state & REQ_PLAYER)
4506 case EVENT_KEYRELEASE:
4507 ClearPlayerAction();
4511 HandleOtherEvents(&event);
4515 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4517 int joy = AnyJoystick();
4519 if (joy & JOY_BUTTON_1)
4521 else if (joy & JOY_BUTTON_2)
4527 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
4529 HandleGameActions();
4535 if (!PendingEvent()) /* delay only if no pending events */
4540 game_status = GAME_MODE_PSEUDO_DOOR;
4546 game_status = last_game_status; /* restore current game status */
4554 if (!PendingEvent()) /* delay only if no pending events */
4557 /* don't eat all CPU time */
4567 static boolean RequestDoor(char *text, unsigned int req_state)
4569 unsigned int old_door_state;
4570 int last_game_status = game_status; /* save current game status */
4571 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4572 int font_nr = FONT_TEXT_2;
4577 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4579 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4580 font_nr = FONT_TEXT_1;
4583 if (game_status == GAME_MODE_PLAYING)
4585 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4586 BlitScreenToBitmap_EM(backbuffer);
4587 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4588 BlitScreenToBitmap_SP(backbuffer);
4591 /* disable deactivated drawing when quick-loading level tape recording */
4592 if (tape.playing && tape.deactivate_display)
4593 TapeDeactivateDisplayOff(TRUE);
4595 SetMouseCursor(CURSOR_DEFAULT);
4597 #if defined(NETWORK_AVALIABLE)
4598 /* pause network game while waiting for request to answer */
4599 if (options.network &&
4600 game_status == GAME_MODE_PLAYING &&
4601 req_state & REQUEST_WAIT_FOR_INPUT)
4602 SendToServer_PausePlaying();
4605 old_door_state = GetDoorState();
4607 /* simulate releasing mouse button over last gadget, if still pressed */
4609 HandleGadgets(-1, -1, 0);
4613 /* draw released gadget before proceeding */
4616 if (old_door_state & DOOR_OPEN_1)
4618 CloseDoor(DOOR_CLOSE_1);
4620 /* save old door content */
4622 BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
4623 0 * DXSIZE, 0, DXSIZE, DYSIZE, 1 * DXSIZE, 0);
4625 BlitBitmap(bitmap_db_door, bitmap_db_door,
4626 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4627 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
4631 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4632 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4634 /* clear door drawing field */
4635 DrawBackground(DX, DY, DXSIZE, DYSIZE);
4637 /* force DOOR font inside door area */
4638 game_status = GAME_MODE_PSEUDO_DOOR;
4640 /* write text for request */
4641 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
4643 char text_line[max_request_line_len + 1];
4649 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
4651 tc = *(text_ptr + tx);
4652 // if (!tc || tc == ' ')
4653 if (!tc || tc == ' ' || tc == '?' || tc == '!')
4657 if ((tc == '?' || tc == '!') && tl == 0)
4667 strncpy(text_line, text_ptr, tl);
4670 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
4671 DY + 8 + ty * (getFontHeight(font_nr) + 2),
4672 text_line, font_nr);
4674 text_ptr += tl + (tc == ' ' ? 1 : 0);
4675 // text_ptr += tl + (tc == ' ' || tc == '?' || tc == '!' ? 1 : 0);
4678 game_status = last_game_status; /* restore current game status */
4680 if (req_state & REQ_ASK)
4682 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4683 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4685 else if (req_state & REQ_CONFIRM)
4687 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4689 else if (req_state & REQ_PLAYER)
4691 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4692 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4693 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4694 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4697 /* copy request gadgets to door backbuffer */
4699 BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0);
4701 BlitBitmap(drawto, bitmap_db_door,
4702 DX, DY, DXSIZE, DYSIZE,
4703 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4706 OpenDoor(DOOR_OPEN_1);
4708 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4710 if (game_status == GAME_MODE_PLAYING)
4712 SetPanelBackground();
4713 SetDrawBackgroundMask(REDRAW_DOOR_1);
4717 SetDrawBackgroundMask(REDRAW_FIELD);
4723 if (game_status != GAME_MODE_MAIN)
4726 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4728 // ---------- handle request buttons ----------
4729 result = RequestHandleEvents(req_state);
4731 if (game_status != GAME_MODE_MAIN)
4736 if (!(req_state & REQ_STAY_OPEN))
4738 CloseDoor(DOOR_CLOSE_1);
4740 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
4741 (req_state & REQ_REOPEN))
4742 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
4747 if (game_status == GAME_MODE_PLAYING)
4749 SetPanelBackground();
4750 SetDrawBackgroundMask(REDRAW_DOOR_1);
4754 SetDrawBackgroundMask(REDRAW_FIELD);
4757 #if defined(NETWORK_AVALIABLE)
4758 /* continue network game after request */
4759 if (options.network &&
4760 game_status == GAME_MODE_PLAYING &&
4761 req_state & REQUEST_WAIT_FOR_INPUT)
4762 SendToServer_ContinuePlaying();
4765 /* restore deactivated drawing when quick-loading level tape recording */
4766 if (tape.playing && tape.deactivate_display)
4767 TapeDeactivateDisplayOn();
4772 static boolean RequestEnvelope(char *text, unsigned int req_state)
4779 if (game_status == GAME_MODE_PLAYING)
4781 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4782 BlitScreenToBitmap_EM(backbuffer);
4783 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4784 BlitScreenToBitmap_SP(backbuffer);
4787 /* disable deactivated drawing when quick-loading level tape recording */
4788 if (tape.playing && tape.deactivate_display)
4789 TapeDeactivateDisplayOff(TRUE);
4791 SetMouseCursor(CURSOR_DEFAULT);
4793 #if defined(NETWORK_AVALIABLE)
4794 /* pause network game while waiting for request to answer */
4795 if (options.network &&
4796 game_status == GAME_MODE_PLAYING &&
4797 req_state & REQUEST_WAIT_FOR_INPUT)
4798 SendToServer_PausePlaying();
4801 /* simulate releasing mouse button over last gadget, if still pressed */
4803 HandleGadgets(-1, -1, 0);
4807 // (replace with setting corresponding request background)
4808 // SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4809 // SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4811 /* clear door drawing field */
4812 // DrawBackground(DX, DY, DXSIZE, DYSIZE);
4815 if (global.use_envelope_request)
4819 CreateToolButtons();
4825 if (req_state & REQ_ASK)
4827 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_YES], FALSE);
4828 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_NO], FALSE);
4830 else if (req_state & REQ_CONFIRM)
4832 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_CONFIRM], FALSE);
4834 else if (req_state & REQ_PLAYER)
4836 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_1], FALSE);
4837 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_2], FALSE);
4838 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_3], FALSE);
4839 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_4], FALSE);
4842 if (req_state & REQ_ASK)
4844 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4845 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4847 else if (req_state & REQ_CONFIRM)
4849 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4851 else if (req_state & REQ_PLAYER)
4853 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4854 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4855 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4856 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4861 ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
4864 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4866 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
4867 i == TOOL_CTRL_ID_NO)) ||
4868 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
4869 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
4870 i == TOOL_CTRL_ID_PLAYER_2 &&
4871 i == TOOL_CTRL_ID_PLAYER_3 &&
4872 i == TOOL_CTRL_ID_PLAYER_4)))
4874 int x = tool_gadget[i]->x + dDX;
4875 int y = tool_gadget[i]->y + dDY;
4877 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
4882 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4884 if (game_status == GAME_MODE_PLAYING)
4886 SetPanelBackground();
4887 SetDrawBackgroundMask(REDRAW_DOOR_1);
4891 SetDrawBackgroundMask(REDRAW_FIELD);
4898 if (game_status != GAME_MODE_MAIN)
4902 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4904 // ---------- handle request buttons ----------
4905 result = RequestHandleEvents(req_state);
4907 if (game_status != GAME_MODE_MAIN)
4912 ShowEnvelopeRequest(text, req_state, ACTION_CLOSING);
4916 if (game_status == GAME_MODE_PLAYING)
4918 SetPanelBackground();
4919 SetDrawBackgroundMask(REDRAW_DOOR_1);
4923 SetDrawBackgroundMask(REDRAW_FIELD);
4926 #if defined(NETWORK_AVALIABLE)
4927 /* continue network game after request */
4928 if (options.network &&
4929 game_status == GAME_MODE_PLAYING &&
4930 req_state & REQUEST_WAIT_FOR_INPUT)
4931 SendToServer_ContinuePlaying();
4934 /* restore deactivated drawing when quick-loading level tape recording */
4935 if (tape.playing && tape.deactivate_display)
4936 TapeDeactivateDisplayOn();
4941 boolean Request(char *text, unsigned int req_state)
4943 if (global.use_envelope_request)
4944 return RequestEnvelope(text, req_state);
4946 return RequestDoor(text, req_state);
4949 #else // =====================================================================
4951 boolean Request(char *text, unsigned int req_state)
4953 int mx, my, ty, result = -1;
4954 unsigned int old_door_state;
4955 int last_game_status = game_status; /* save current game status */
4956 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4957 int font_nr = FONT_TEXT_2;
4959 int max_word_len = 0;
4965 global.use_envelope_request = 1;
4969 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4971 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4972 font_nr = FONT_TEXT_1;
4975 for (text_ptr = text; *text_ptr; text_ptr++)
4977 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
4979 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
4981 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4983 font_nr = FONT_TEXT_1;
4985 font_nr = FONT_LEVEL_NUMBER;
4993 if (game_status == GAME_MODE_PLAYING)
4995 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4996 BlitScreenToBitmap_EM(backbuffer);
4997 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4998 BlitScreenToBitmap_SP(backbuffer);
5001 /* disable deactivated drawing when quick-loading level tape recording */
5002 if (tape.playing && tape.deactivate_display)
5003 TapeDeactivateDisplayOff(TRUE);
5005 SetMouseCursor(CURSOR_DEFAULT);
5007 #if defined(NETWORK_AVALIABLE)
5008 /* pause network game while waiting for request to answer */
5009 if (options.network &&
5010 game_status == GAME_MODE_PLAYING &&
5011 req_state & REQUEST_WAIT_FOR_INPUT)
5012 SendToServer_PausePlaying();
5015 old_door_state = GetDoorState();
5017 /* simulate releasing mouse button over last gadget, if still pressed */
5019 HandleGadgets(-1, -1, 0);
5023 /* draw released gadget before proceeding */
5027 if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request)
5029 if (old_door_state & DOOR_OPEN_1)
5033 if (!global.use_envelope_request)
5034 CloseDoor(DOOR_CLOSE_1);
5036 CloseDoor(DOOR_CLOSE_1);
5039 /* save old door content */
5040 BlitBitmap(bitmap_db_door, bitmap_db_door,
5041 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
5042 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
5046 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
5049 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
5051 /* clear door drawing field */
5052 DrawBackground(DX, DY, DXSIZE, DYSIZE);
5054 /* force DOOR font inside door area */
5055 game_status = GAME_MODE_PSEUDO_DOOR;
5057 /* write text for request */
5058 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
5060 char text_line[max_request_line_len + 1];
5066 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
5068 tc = *(text_ptr + tx);
5069 if (!tc || tc == ' ')
5080 strncpy(text_line, text_ptr, tl);
5083 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
5084 DY + 8 + ty * (getFontHeight(font_nr) + 2),
5085 text_line, font_nr);
5087 text_ptr += tl + (tc == ' ' ? 1 : 0);
5090 game_status = last_game_status; /* restore current game status */
5093 if (global.use_envelope_request)
5097 CreateToolButtons();
5101 if (req_state & REQ_ASK)
5103 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
5104 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
5106 else if (req_state & REQ_CONFIRM)
5108 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
5110 else if (req_state & REQ_PLAYER)
5112 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
5113 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
5114 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
5115 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
5118 /* copy request gadgets to door backbuffer */
5119 BlitBitmap(drawto, bitmap_db_door,
5120 DX, DY, DXSIZE, DYSIZE,
5121 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5124 if (global.use_envelope_request)
5126 ShowEnvelopeRequest(text, ACTION_OPENING);
5128 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
5130 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
5131 i == TOOL_CTRL_ID_NO)) ||
5132 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
5133 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
5134 i == TOOL_CTRL_ID_PLAYER_2 &&
5135 i == TOOL_CTRL_ID_PLAYER_3 &&
5136 i == TOOL_CTRL_ID_PLAYER_4)))
5138 int x = tool_gadget[i]->x + dDX;
5139 int y = tool_gadget[i]->y + dDY;
5141 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
5148 if (!global.use_envelope_request)
5149 OpenDoor(DOOR_OPEN_1);
5151 OpenDoor(DOOR_OPEN_1);
5154 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
5156 if (game_status == GAME_MODE_PLAYING)
5158 SetPanelBackground();
5159 SetDrawBackgroundMask(REDRAW_DOOR_1);
5163 SetDrawBackgroundMask(REDRAW_FIELD);
5170 if (game_status != GAME_MODE_MAIN && !global.use_envelope_request)
5173 if (game_status != GAME_MODE_MAIN)
5177 button_status = MB_RELEASED;
5179 request_gadget_id = -1;
5181 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
5193 case EVENT_BUTTONPRESS:
5194 case EVENT_BUTTONRELEASE:
5195 case EVENT_MOTIONNOTIFY:
5197 if (event.type == EVENT_MOTIONNOTIFY)
5199 if (!PointerInWindow(window))
5200 continue; /* window and pointer are on different screens */
5205 motion_status = TRUE;
5206 mx = ((MotionEvent *) &event)->x;
5207 my = ((MotionEvent *) &event)->y;
5211 motion_status = FALSE;
5212 mx = ((ButtonEvent *) &event)->x;
5213 my = ((ButtonEvent *) &event)->y;
5214 if (event.type == EVENT_BUTTONPRESS)
5215 button_status = ((ButtonEvent *) &event)->button;
5217 button_status = MB_RELEASED;
5220 /* this sets 'request_gadget_id' */
5221 HandleGadgets(mx, my, button_status);
5223 switch (request_gadget_id)
5225 case TOOL_CTRL_ID_YES:
5228 case TOOL_CTRL_ID_NO:
5231 case TOOL_CTRL_ID_CONFIRM:
5232 result = TRUE | FALSE;
5235 case TOOL_CTRL_ID_PLAYER_1:
5238 case TOOL_CTRL_ID_PLAYER_2:
5241 case TOOL_CTRL_ID_PLAYER_3:
5244 case TOOL_CTRL_ID_PLAYER_4:
5255 case EVENT_KEYPRESS:
5256 switch (GetEventKey((KeyEvent *)&event, TRUE))
5259 if (req_state & REQ_CONFIRM)
5268 #if defined(TARGET_SDL2)
5278 if (req_state & REQ_PLAYER)
5282 case EVENT_KEYRELEASE:
5283 ClearPlayerAction();
5287 HandleOtherEvents(&event);
5291 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
5293 int joy = AnyJoystick();
5295 if (joy & JOY_BUTTON_1)
5297 else if (joy & JOY_BUTTON_2)
5303 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
5305 HandleGameActions();
5311 if (!PendingEvent()) /* delay only if no pending events */
5316 game_status = GAME_MODE_PSEUDO_DOOR;
5322 game_status = last_game_status; /* restore current game status */
5330 if (!PendingEvent()) /* delay only if no pending events */
5333 /* don't eat all CPU time */
5340 if (game_status != GAME_MODE_MAIN)
5346 if (global.use_envelope_request)
5347 ShowEnvelopeRequest(text, ACTION_CLOSING);
5351 if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request)
5353 if (!(req_state & REQ_STAY_OPEN))
5356 CloseDoor(DOOR_CLOSE_1);
5358 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
5359 (req_state & REQ_REOPEN))
5360 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
5365 if (game_status == GAME_MODE_PLAYING)
5367 SetPanelBackground();
5368 SetDrawBackgroundMask(REDRAW_DOOR_1);
5372 SetDrawBackgroundMask(REDRAW_FIELD);
5375 #if defined(NETWORK_AVALIABLE)
5376 /* continue network game after request */
5377 if (options.network &&
5378 game_status == GAME_MODE_PLAYING &&
5379 req_state & REQUEST_WAIT_FOR_INPUT)
5380 SendToServer_ContinuePlaying();
5383 /* restore deactivated drawing when quick-loading level tape recording */
5384 if (tape.playing && tape.deactivate_display)
5385 TapeDeactivateDisplayOn();
5392 static int compareDoorPartOrderInfo(const void *object1, const void *object2)
5394 const struct DoorPartOrderInfo *dpo1 = (struct DoorPartOrderInfo *)object1;
5395 const struct DoorPartOrderInfo *dpo2 = (struct DoorPartOrderInfo *)object2;
5398 if (dpo1->sort_priority != dpo2->sort_priority)
5399 compare_result = dpo1->sort_priority - dpo2->sort_priority;
5401 compare_result = dpo1->nr - dpo2->nr;
5403 return compare_result;
5406 void InitGraphicCompatibilityInfo_Doors()
5412 struct DoorInfo *door;
5416 { DOOR_1, IMG_DOOR_1_GFX_PART_1, IMG_DOOR_1_GFX_PART_8, &door_1 },
5417 { DOOR_2, IMG_DOOR_2_GFX_PART_1, IMG_DOOR_2_GFX_PART_8, &door_2 },
5419 { -1, -1, -1, NULL }
5421 struct Rect door_rect_list[] =
5423 { DX, DY, DXSIZE, DYSIZE },
5424 { VX, VY, VXSIZE, VYSIZE }
5428 for (i = 0; doors[i].door_token != -1; i++)
5430 int door_token = doors[i].door_token;
5431 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5432 int part_1 = doors[i].part_1;
5433 int part_8 = doors[i].part_8;
5434 int part_2 = part_1 + 1;
5435 int part_3 = part_1 + 2;
5436 struct DoorInfo *door = doors[i].door;
5437 struct Rect *door_rect = &door_rect_list[door_index];
5438 boolean door_gfx_redefined = FALSE;
5440 /* check if any door part graphic definitions have been redefined */
5442 for (j = 0; door_part_controls[j].door_token != -1; j++)
5444 struct DoorPartControlInfo *dpc = &door_part_controls[j];
5445 struct FileInfo *fi = getImageListEntryFromImageID(dpc->graphic);
5447 if (dpc->door_token == door_token && fi->redefined)
5448 door_gfx_redefined = TRUE;
5451 /* check for old-style door graphic/animation modifications */
5453 if (!door_gfx_redefined)
5455 if (door->anim_mode & ANIM_STATIC_PANEL)
5457 door->panel.step_xoffset = 0;
5458 door->panel.step_yoffset = 0;
5461 if (door->anim_mode & (ANIM_HORIZONTAL | ANIM_VERTICAL))
5463 struct GraphicInfo *g_part_1 = &graphic_info[part_1];
5464 struct GraphicInfo *g_part_2 = &graphic_info[part_2];
5465 int num_door_steps, num_panel_steps;
5467 /* remove door part graphics other than the two default wings */
5469 for (j = 0; door_part_controls[j].door_token != -1; j++)
5471 struct DoorPartControlInfo *dpc = &door_part_controls[j];
5472 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5474 if (dpc->graphic >= part_3 &&
5475 dpc->graphic <= part_8)
5479 /* set graphics and screen positions of the default wings */
5481 g_part_1->width = door_rect->width;
5482 g_part_1->height = door_rect->height;
5483 g_part_2->width = door_rect->width;
5484 g_part_2->height = door_rect->height;
5485 g_part_2->src_x = door_rect->width;
5486 g_part_2->src_y = g_part_1->src_y;
5488 door->part_2.x = door->part_1.x;
5489 door->part_2.y = door->part_1.y;
5491 if (door->width != -1)
5493 g_part_1->width = door->width;
5494 g_part_2->width = door->width;
5496 // special treatment for graphics and screen position of right wing
5497 g_part_2->src_x += door_rect->width - door->width;
5498 door->part_2.x += door_rect->width - door->width;
5501 if (door->height != -1)
5503 g_part_1->height = door->height;
5504 g_part_2->height = door->height;
5506 // special treatment for graphics and screen position of bottom wing
5507 g_part_2->src_y += door_rect->height - door->height;
5508 door->part_2.y += door_rect->height - door->height;
5511 /* set animation delays for the default wings and panels */
5513 door->part_1.step_delay = door->step_delay;
5514 door->part_2.step_delay = door->step_delay;
5515 door->panel.step_delay = door->step_delay;
5517 /* set animation draw order for the default wings */
5519 door->part_1.sort_priority = 2; /* draw left wing over ... */
5520 door->part_2.sort_priority = 1; /* ... right wing */
5522 /* set animation draw offset for the default wings */
5524 if (door->anim_mode & ANIM_HORIZONTAL)
5526 door->part_1.step_xoffset = door->step_offset;
5527 door->part_1.step_yoffset = 0;
5528 door->part_2.step_xoffset = door->step_offset * -1;
5529 door->part_2.step_yoffset = 0;
5531 num_door_steps = g_part_1->width / door->step_offset;
5533 else // ANIM_VERTICAL
5535 door->part_1.step_xoffset = 0;
5536 door->part_1.step_yoffset = door->step_offset;
5537 door->part_2.step_xoffset = 0;
5538 door->part_2.step_yoffset = door->step_offset * -1;
5540 num_door_steps = g_part_1->height / door->step_offset;
5543 /* set animation draw offset for the default panels */
5545 if (door->step_offset > 1)
5547 num_panel_steps = 2 * door_rect->height / door->step_offset;
5548 door->panel.start_step = num_panel_steps - num_door_steps;
5552 num_panel_steps = door_rect->height / door->step_offset;
5553 door->panel.start_step = num_panel_steps - num_door_steps / 2;
5554 door->panel.step_delay *= 2;
5565 for (i = 0; door_part_controls[i].door_token != -1; i++)
5567 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5568 struct DoorPartOrderInfo *dpo = &door_part_order[i];
5570 /* initialize "start_step_opening" and "start_step_closing", if needed */
5571 if (dpc->pos->start_step_opening == 0 &&
5572 dpc->pos->start_step_closing == 0)
5574 // dpc->pos->start_step_opening = dpc->pos->start_step;
5575 dpc->pos->start_step_closing = dpc->pos->start_step;
5578 /* fill structure for door part draw order (sorted below) */
5580 dpo->sort_priority = dpc->pos->sort_priority;
5583 struct DoorPartPosInfo *pos = dpc->pos;
5585 printf(":0: step_xoffset == %d, step_yoffset == %d\n",
5586 pos->step_xoffset, pos->step_yoffset);
5590 /* sort door part controls according to sort_priority and graphic number */
5591 qsort(door_part_order, MAX_DOOR_PARTS,
5592 sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo);
5595 unsigned int OpenDoor(unsigned int door_state)
5597 if (door_state & DOOR_COPY_BACK)
5600 if (door_state & DOOR_OPEN_1)
5601 BlitBitmap(bitmap_db_door_1, bitmap_db_door_1,
5602 1 * DXSIZE, 0, DXSIZE, DYSIZE, 0 * DXSIZE, 0);
5604 if (door_state & DOOR_OPEN_2)
5605 BlitBitmap(bitmap_db_door_2, bitmap_db_door_2,
5606 1 * VXSIZE, 0, VXSIZE, VYSIZE, 0 * VXSIZE, 0);
5608 if (door_state & DOOR_OPEN_1)
5609 BlitBitmap(bitmap_db_door, bitmap_db_door,
5610 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
5611 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5613 if (door_state & DOOR_OPEN_2)
5614 BlitBitmap(bitmap_db_door, bitmap_db_door,
5615 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
5616 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5619 door_state &= ~DOOR_COPY_BACK;
5622 return MoveDoor(door_state);
5625 unsigned int CloseDoor(unsigned int door_state)
5627 unsigned int old_door_state = GetDoorState();
5629 if (!(door_state & DOOR_NO_COPY_BACK))
5632 if (old_door_state & DOOR_OPEN_1)
5633 BlitBitmap(backbuffer, bitmap_db_door_1,
5634 DX, DY, DXSIZE, DYSIZE, 0, 0);
5636 if (old_door_state & DOOR_OPEN_2)
5637 BlitBitmap(backbuffer, bitmap_db_door_2,
5638 VX, VY, VXSIZE, VYSIZE, 0, 0);
5640 if (old_door_state & DOOR_OPEN_1)
5641 BlitBitmap(backbuffer, bitmap_db_door,
5642 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5644 if (old_door_state & DOOR_OPEN_2)
5645 BlitBitmap(backbuffer, bitmap_db_door,
5646 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5649 door_state &= ~DOOR_NO_COPY_BACK;
5652 return MoveDoor(door_state);
5655 unsigned int GetDoorState()
5657 return MoveDoor(DOOR_GET_STATE);
5660 unsigned int SetDoorState(unsigned int door_state)
5662 return MoveDoor(door_state | DOOR_SET_STATE);
5667 // ========== TEST 1 ===========================================================
5669 int euclid(int a, int b)
5671 return (b ? euclid(b, a % b) : a);
5674 unsigned int MoveDoor(unsigned int door_state)
5677 struct XY panel_pos_list[] =
5679 { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 },
5680 { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 },
5683 struct Rect door_rect_list[] =
5685 { DX, DY, DXSIZE, DYSIZE },
5686 { VX, VY, VXSIZE, VYSIZE }
5688 static int door1 = DOOR_OPEN_1;
5689 static int door2 = DOOR_CLOSE_2;
5690 unsigned int door_delay = 0;
5691 unsigned int door_delay_value;
5695 if (door_1.width < 0 || door_1.width > DXSIZE)
5696 door_1.width = DXSIZE;
5697 if (door_1.height < 0 || door_1.height > DYSIZE)
5698 door_1.height = DYSIZE;
5699 if (door_2.width < 0 || door_2.width > VXSIZE)
5700 door_2.width = VXSIZE;
5701 if (door_2.height < 0 || door_2.height > VYSIZE)
5702 door_2.height = VYSIZE;
5705 if (door_state == DOOR_GET_STATE)
5706 return (door1 | door2);
5708 if (door_state & DOOR_SET_STATE)
5710 if (door_state & DOOR_ACTION_1)
5711 door1 = door_state & DOOR_ACTION_1;
5712 if (door_state & DOOR_ACTION_2)
5713 door2 = door_state & DOOR_ACTION_2;
5715 return (door1 | door2);
5718 if (!(door_state & DOOR_FORCE_REDRAW))
5720 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
5721 door_state &= ~DOOR_OPEN_1;
5722 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
5723 door_state &= ~DOOR_CLOSE_1;
5724 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
5725 door_state &= ~DOOR_OPEN_2;
5726 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
5727 door_state &= ~DOOR_CLOSE_2;
5731 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
5734 if (setup.quick_doors)
5736 stepsize = 20; /* must be chosen to always draw last frame */
5737 door_delay_value = 0;
5741 if (global.autoplay_leveldir)
5743 door_state |= DOOR_NO_DELAY;
5744 door_state &= ~DOOR_CLOSE_ALL;
5748 if (game_status == GAME_MODE_EDITOR)
5749 door_state |= DOOR_NO_DELAY;
5752 if (door_state & DOOR_ACTION)
5754 boolean door_panel_drawn[NUM_DOORS];
5755 boolean panel_has_doors[NUM_DOORS];
5756 boolean door_part_skip[MAX_DOOR_PARTS];
5757 boolean door_part_done[MAX_DOOR_PARTS];
5758 boolean door_part_done_all;
5759 int num_steps[MAX_DOOR_PARTS];
5760 int max_move_delay = 0; // delay for complete animations of all doors
5761 int max_step_delay = 0; // delay (ms) between two animation frames
5762 int num_move_steps = 0; // number of animation steps for all doors
5763 int current_move_delay = 0;
5766 for (i = 0; i < NUM_DOORS; i++)
5767 panel_has_doors[i] = FALSE;
5769 for (i = 0; i < MAX_DOOR_PARTS; i++)
5771 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5772 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5773 int door_token = dpc->door_token;
5775 door_part_done[i] = FALSE;
5776 door_part_skip[i] = (!(door_state & door_token) ||
5781 for (i = 0; i < MAX_DOOR_PARTS; i++)
5783 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5784 struct DoorPartPosInfo *pos = dpc->pos;
5785 int start_step = pos->start_step;
5787 printf("::: ---> %d: start_step == %d [%d]\n",
5788 i, start_step, door_part_done[i]);
5792 for (i = 0; i < MAX_DOOR_PARTS; i++)
5794 int nr = door_part_order[i].nr;
5795 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5796 struct DoorPartPosInfo *pos = dpc->pos;
5797 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5798 int door_token = dpc->door_token;
5799 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5800 boolean is_panel = DOOR_PART_IS_PANEL(nr);
5801 int step_xoffset = ABS(pos->step_xoffset);
5802 int step_yoffset = ABS(pos->step_yoffset);
5803 int step_delay = pos->step_delay;
5804 int current_door_state = door_state & door_token;
5805 boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
5806 boolean door_closing = ((current_door_state & DOOR_CLOSE) != 0);
5807 boolean part_opening = (is_panel ? door_closing : door_opening);
5808 int start_step = (part_opening ? pos->start_step_opening :
5809 pos->start_step_closing);
5810 float move_xsize = (step_xoffset ? g->width : 0);
5811 float move_ysize = (step_yoffset ? g->height : 0);
5812 int move_xsteps = (step_xoffset ? ceil(move_xsize / step_xoffset) : 0);
5813 int move_ysteps = (step_yoffset ? ceil(move_ysize / step_yoffset) : 0);
5814 int move_steps = (move_xsteps && move_ysteps ?
5815 MIN(move_xsteps, move_ysteps) :
5816 move_xsteps ? move_xsteps : move_ysteps) - start_step;
5817 int move_delay = move_steps * step_delay;
5819 if (door_part_skip[nr])
5823 panel_has_doors[door_index] = TRUE;
5825 max_move_delay = MAX(max_move_delay, move_delay);
5826 max_step_delay = (max_step_delay == 0 ? step_delay :
5827 euclid(max_step_delay, step_delay));
5828 num_steps[nr] = move_steps;
5832 printf("::: %d: move_delay == %d, start_step == %d [%d]\n",
5833 i, move_delay, start_step, door_part_order[i].nr);
5835 if (DOOR_PART_IS_PANEL(i))
5836 printf("::: %d: move_delay == %d, start_step == %d\n",
5837 i, move_delay, start_step);
5842 num_move_steps = max_move_delay / max_step_delay;
5844 door_delay_value = max_step_delay;
5847 door_delay_value *= 10;
5851 printf("::: num_move_steps == %d, max_move_delay == %d, max_step_delay == %d\n", num_move_steps, max_move_delay, max_step_delay);
5854 for (k = 0; k < num_move_steps; k++)
5856 door_part_done_all = TRUE;
5858 for (i = 0; i < NUM_DOORS; i++)
5859 door_panel_drawn[i] = FALSE;
5861 for (i = 0; i < MAX_DOOR_PARTS; i++)
5863 int nr = door_part_order[i].nr;
5864 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5865 struct DoorPartPosInfo *pos = dpc->pos;
5866 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5867 int door_token = dpc->door_token;
5868 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5869 boolean is_panel = DOOR_PART_IS_PANEL(nr);
5871 struct XY *panel_pos = &panel_pos_list[door_index];
5873 struct Rect *door_rect = &door_rect_list[door_index];
5874 Bitmap *bitmap_db_door = (door_token == DOOR_1 ? bitmap_db_door_1 :
5876 Bitmap *bitmap = (is_panel ? bitmap_db_door : g->bitmap);
5877 int current_door_state = door_state & door_token;
5878 boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
5879 boolean door_closing = !door_opening;
5880 boolean part_opening = (is_panel ? door_closing : door_opening);
5881 boolean part_closing = !part_opening;
5882 int start_step = (part_opening ? pos->start_step_opening :
5883 pos->start_step_closing);
5884 int step_delay = pos->step_delay;
5885 int step_factor = step_delay / max_step_delay;
5886 int k1 = (step_factor ? k / step_factor + 1 : k);
5887 int k2 = (part_opening ? k1 + start_step : num_steps[nr] - k1);
5888 int kk = (k2 < 0 ? 0 : k2);
5889 int src_x, src_y, src_xx, src_yy;
5890 int dst_x, dst_y, dst_xx, dst_yy;
5894 if (k == 0 && is_panel && door_token == DOOR_2)
5895 printf("::: %d, %d\n", g->width, g->height);
5899 if (DOOR_PART_IS_PANEL(nr))
5901 int start_step = pos->start_step;
5903 k2 = (door_closing ? k1 : num_steps[nr] - k1);// - start_step;
5904 kk = (k2 < 0 ? 0 : k2);
5910 if (nr != 16 && nr != 0)
5921 if (door_part_skip[nr])
5925 if (!(door_state & door_token))
5932 if (current_move_delay % step_delay)
5938 if (!door_panel_drawn[door_index])
5941 ClearRectangle(drawto, door_rect->x, door_rect->y,
5942 door_rect->width, door_rect->height);
5944 BlitBitmap(bitmap_db_door, drawto, panel_pos->x, panel_pos->y,
5945 door_rect->width, door_rect->height,
5946 door_rect->x, door_rect->y);
5949 door_panel_drawn[door_index] = TRUE;
5952 // draw opening or closing door parts
5954 if (pos->step_xoffset < 0) // door part on right side
5957 dst_xx = pos->x + ABS(kk * pos->step_xoffset);
5960 if (dst_xx + width > door_rect->width)
5961 width = door_rect->width - dst_xx;
5963 else // door part on left side
5966 dst_xx = pos->x - kk * pos->step_xoffset;
5970 src_xx = ABS(dst_xx);
5974 width = g->width - src_xx;
5976 // printf("::: k == %d [%d] \n", k, start_step);
5979 if (pos->step_yoffset < 0) // door part on bottom side
5982 dst_yy = pos->y + ABS(kk * pos->step_yoffset);
5985 if (dst_yy + height > door_rect->height)
5986 height = door_rect->height - dst_yy;
5988 else // door part on top side
5991 dst_yy = pos->y - kk * pos->step_yoffset;
5995 src_yy = ABS(dst_yy);
5999 height = g->height - src_yy;
6008 src_x = panel_pos->x + src_xx;
6009 src_y = panel_pos->y + src_yy;
6014 src_x = g->src_x + src_xx;
6015 src_y = g->src_y + src_yy;
6018 dst_x = door_rect->x + dst_xx;
6019 dst_y = door_rect->y + dst_yy;
6022 if (DOOR_PART_IS_PANEL(nr))
6024 printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
6025 width, height, g->width, g->height, src_x, src_y);
6029 if (width >= 0 && width <= g->width &&
6030 height >= 0 && height <= g->height)
6032 if (is_panel || !pos->draw_masked)
6033 BlitBitmap(bitmap, drawto, src_x, src_y, width, height,
6036 BlitBitmapMasked(bitmap, drawto, src_x, src_y, width, height,
6041 if (DOOR_PART_IS_PANEL(nr))
6043 bitmap = bitmap_db_door;
6044 src_x = panel_pos->x + src_xx;
6045 src_y = panel_pos->y + src_yy;
6047 printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
6048 width, height, g->width, g->height, src_x, src_y);
6050 if (width >= 0 && width <= g->width &&
6051 height >= 0 && height <= g->height)
6052 BlitBitmap(bitmap, drawto, src_x, src_y,
6058 redraw_mask |= REDRAW_DOOR_FROM_TOKEN(door_token);
6061 if ((part_opening && (width < 0 || height < 0)) ||
6062 (part_closing && (width >= g->width && height >= g->height)))
6063 door_part_done[nr] = TRUE;
6065 if ((door_opening && (width < 0 || height < 0)) ||
6066 (door_closing && (width >= g->width && height >= g->height)))
6067 door_part_done[nr] = TRUE;
6071 // continue door part animations, but not panel after door has closed
6072 if (!door_part_done[nr] &&
6073 !(is_panel && door_closing && panel_has_doors[door_index]))
6074 door_part_done_all = FALSE;
6076 // continue door part animations, but not panel after door has closed
6077 if (!door_part_done[nr] && !(is_panel && door_closing))
6078 door_part_done_all = FALSE;
6082 if (!door_part_done[nr])
6083 printf("::: k == %d, nr == %d\n", k, nr);
6087 if (!(door_state & DOOR_NO_DELAY))
6091 if (game_status == GAME_MODE_MAIN)
6094 WaitUntilDelayReached(&door_delay, door_delay_value);
6096 current_move_delay += max_step_delay;
6100 door_part_done_all = TRUE;
6102 for (i = 0; i < MAX_DOOR_PARTS; i++)
6103 if (!door_part_done[i] &&
6104 !(DOOR_PART_IS_PANEL(i) && door_closing))
6105 door_part_done_all = FALSE;
6108 if (door_part_done_all)
6114 if (door_state & DOOR_ACTION_1)
6115 door1 = door_state & DOOR_ACTION_1;
6116 if (door_state & DOOR_ACTION_2)
6117 door2 = door_state & DOOR_ACTION_2;
6120 printf("::: DOORS DONE %08x\n", door_state);
6122 printf("::: GO!\n");
6125 return (door1 | door2);
6130 // ========== OLD ==============================================================
6132 unsigned int MoveDoor(unsigned int door_state)
6134 static int door1 = DOOR_OPEN_1;
6135 static int door2 = DOOR_CLOSE_2;
6136 unsigned int door_delay = 0;
6137 unsigned int door_delay_value;
6141 if (door_1.width < 0 || door_1.width > DXSIZE)
6142 door_1.width = DXSIZE;
6143 if (door_1.height < 0 || door_1.height > DYSIZE)
6144 door_1.height = DYSIZE;
6145 if (door_2.width < 0 || door_2.width > VXSIZE)
6146 door_2.width = VXSIZE;
6147 if (door_2.height < 0 || door_2.height > VYSIZE)
6148 door_2.height = VYSIZE;
6151 if (door_state == DOOR_GET_STATE)
6152 return (door1 | door2);
6154 if (door_state & DOOR_SET_STATE)
6156 if (door_state & DOOR_ACTION_1)
6157 door1 = door_state & DOOR_ACTION_1;
6158 if (door_state & DOOR_ACTION_2)
6159 door2 = door_state & DOOR_ACTION_2;
6161 return (door1 | door2);
6164 if (!(door_state & DOOR_FORCE_REDRAW))
6166 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
6167 door_state &= ~DOOR_OPEN_1;
6168 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
6169 door_state &= ~DOOR_CLOSE_1;
6170 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
6171 door_state &= ~DOOR_OPEN_2;
6172 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
6173 door_state &= ~DOOR_CLOSE_2;
6176 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
6179 // door_delay_value *= 4; // !!! TEST ONLY !!!
6181 if (setup.quick_doors)
6183 stepsize = 20; /* must be chosen to always draw last frame */
6184 door_delay_value = 0;
6187 if (global.autoplay_leveldir)
6189 door_state |= DOOR_NO_DELAY;
6190 door_state &= ~DOOR_CLOSE_ALL;
6194 if (game_status == GAME_MODE_EDITOR)
6195 door_state |= DOOR_NO_DELAY;
6198 if (door_state & DOOR_ACTION)
6201 struct GraphicInfo *g1_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
6202 struct GraphicInfo *g1_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
6203 struct GraphicInfo *g2_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
6204 struct GraphicInfo *g2_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
6205 int door_1_left_width = g1_left->width;
6206 int door_1_left_height = g1_left->height;
6207 int door_1_right_width = g1_right->width;
6208 int door_1_right_height = g1_right->height;
6209 int door_2_left_width = g2_left->width;
6210 int door_2_left_height = g2_left->height;
6211 int door_2_right_width = g2_right->width;
6212 int door_2_right_height = g2_right->height;
6213 int door_1_width = MAX(door_1_left_width, door_1_right_width);
6214 int door_1_height = MAX(door_1_left_height, door_1_right_height);
6215 int door_2_width = MAX(door_2_left_width, door_2_right_width);
6216 int door_2_height = MAX(door_2_left_height, door_2_right_height);
6218 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
6219 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
6220 boolean door_1_done = (!handle_door_1);
6221 boolean door_2_done = (!handle_door_2);
6222 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
6223 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
6226 int door_size_1 = (door_1_vertical ? door_1_height : door_1_width);
6227 int door_size_2 = (door_2_vertical ? door_2_height : door_2_width);
6229 int door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
6230 int door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
6233 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
6234 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
6236 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
6237 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
6238 // int door_size = (handle_door_1 ? door_size_1 : door_size_2);
6239 int door_size = (handle_door_2 ? door_size_2 : door_size_1);
6240 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
6241 int door_skip = max_door_size - door_size;
6242 int end = door_size;
6243 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
6246 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
6248 /* opening door sound has priority over simultaneously closing door */
6249 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
6250 PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
6251 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
6252 PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
6255 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
6259 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6260 GC gc = bitmap->stored_clip_gc;
6263 if (door_state & DOOR_ACTION_1 &&
6264 x * door_1.step_offset <= door_size_1)
6266 int a = MIN(x * door_1.step_offset, end);
6267 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
6271 int i = p + door_skip;
6275 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
6276 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
6277 Bitmap *bm_left = g_left->bitmap;
6278 Bitmap *bm_right = g_right->bitmap;
6279 GC gc_left = bm_left->stored_clip_gc;
6280 GC gc_right = bm_right->stored_clip_gc;
6283 int classic_dxsize = 100;
6284 int classic_dysize = 280;
6285 boolean classic_door_1_size = (DXSIZE == classic_dxsize &&
6286 DYSIZE == classic_dysize);
6288 if (door_1.anim_mode & ANIM_STATIC_PANEL)
6290 BlitBitmap(bitmap_db_door, drawto,
6291 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
6292 DXSIZE, DYSIZE, DX, DY);
6296 BlitBitmap(bitmap_db_door, drawto,
6297 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
6298 DXSIZE, DYSIZE - p / 2, DX, DY);
6301 // printf("::: p == %d\n", p);
6302 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
6306 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
6309 int src1_x = g_right->src_x;
6310 int src1_y = g_right->src_y;
6311 int src2_x = g_left->src_x + g_left->width - i;
6312 int src2_y = g_left->src_y;
6313 int dst1_x = DX + DXSIZE - i;
6318 int height = DYSIZE;
6320 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6321 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6324 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6325 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6328 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6329 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
6330 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
6331 int dst2_x = DX, dst2_y = DY;
6332 int width = i, height = DYSIZE;
6334 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6335 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6338 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6339 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6343 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
6346 int src1_x = g_right->src_x;
6347 int src1_y = g_right->src_y;
6348 int src2_x = g_left->src_x;
6349 int src2_y = g_left->src_y + g_left->height - i;
6351 int dst1_y = DY + DYSIZE - i;
6357 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6358 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6361 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6362 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6365 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6366 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
6367 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
6368 int dst2_x = DX, dst2_y = DY;
6369 int width = DXSIZE, height = i;
6371 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6372 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6375 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6376 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6380 else if (classic_door_1_size && x <= DXSIZE) /* ANIM_DEFAULT */
6382 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
6385 int src1_x = g_right->src_x;
6386 int src1_y = g_right->src_y;
6387 int src2_x = g_left->src_x + g_left->width - i;
6388 int src2_y = g_left->src_y;
6389 int dst1_x = DX + DXSIZE - i;
6394 int height1 = 63, height2 = DYSIZE / 2 - height1;
6395 int ypos1 = 0, ypos2 = height2;
6396 int ypos3 = DYSIZE / 2, ypos4 = DYSIZE - height2;
6398 SetClipOrigin(bm_right, gc_right,
6399 dst1_x - src1_x, dst1_y - src1_y + j);
6400 BlitBitmapMasked(bm_right, drawto,
6401 src1_x, src1_y + ypos1, width, height2,
6402 dst1_x, dst1_y + ypos1 + j);
6403 BlitBitmapMasked(bm_right, drawto,
6404 src1_x, src1_y + ypos3, width, height1,
6405 dst1_x, dst1_y + ypos3 + j);
6406 SetClipOrigin(bm_left, gc_left,
6407 dst2_x - src2_x, dst2_y - src2_y - j);
6408 BlitBitmapMasked(bm_left, drawto,
6409 src2_x, src2_y + ypos1 + j, width, height2 - j,
6410 dst2_x, dst2_y + ypos1);
6411 BlitBitmapMasked(bm_left, drawto,
6412 src2_x, src2_y + ypos3, width, height1,
6413 dst2_x, dst2_y + ypos3 - j);
6415 SetClipOrigin(bm_left, gc_left,
6416 dst2_x - src2_x, dst2_y - src2_y - j);
6417 BlitBitmapMasked(bm_left, drawto,
6418 src2_x, src2_y + ypos2, width, height1,
6419 dst2_x, dst2_y + ypos2 - j);
6420 BlitBitmapMasked(bm_left, drawto,
6421 src2_x, src2_y + ypos4, width, height2,
6422 dst2_x, dst2_y + ypos4 - j);
6423 SetClipOrigin(bm_right, gc_right,
6424 dst1_x - src1_x, dst1_y - src1_y + j);
6425 BlitBitmapMasked(bm_right, drawto,
6426 src1_x, src1_y + ypos2, width, height1,
6427 dst1_x, dst1_y + ypos2 + j);
6428 BlitBitmapMasked(bm_right, drawto,
6429 src1_x, src1_y + ypos4, width, height2 - j,
6430 dst1_x, dst1_y + ypos4 + j);
6433 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6434 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
6435 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
6436 int dst2_x = DX, dst2_y = DY;
6437 int width = i, height = DYSIZE;
6438 int ypos1 = 63, ypos2 = 77, ypos3 = 140, ypos4 = 203;
6440 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6441 BlitBitmapMasked(bitmap, drawto,
6442 src1_x, src1_y, width, ypos2,
6443 dst1_x, dst1_y + j);
6444 BlitBitmapMasked(bitmap, drawto,
6445 src1_x, src1_y + ypos3, width, ypos1,
6446 dst1_x, dst1_y + ypos3 + j);
6447 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
6448 BlitBitmapMasked(bitmap, drawto,
6449 src2_x, src2_y + j, width, ypos2 - j,
6451 BlitBitmapMasked(bitmap, drawto,
6452 src2_x, src2_y + ypos3, width, ypos1,
6453 dst2_x, dst2_y + ypos3 - j);
6455 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
6456 BlitBitmapMasked(bitmap, drawto,
6457 src2_x, src2_y + ypos2, width, ypos1,
6458 dst2_x, dst2_y + ypos2 - j);
6459 BlitBitmapMasked(bitmap, drawto,
6460 src2_x, src2_y + ypos4, width, ypos2,
6461 dst2_x, dst2_y + ypos4 - j);
6462 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6463 BlitBitmapMasked(bitmap, drawto,
6464 src1_x, src1_y + ypos2, width, ypos1,
6465 dst1_x, dst1_y + ypos2 + j);
6466 BlitBitmapMasked(bitmap, drawto,
6467 src1_x, src1_y + ypos4, width, ypos2 - j,
6468 dst1_x, dst1_y + ypos4 + j);
6471 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
6472 BlitBitmapMasked(bitmap, drawto,
6473 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
6474 DX + DXSIZE - i, DY + j);
6475 BlitBitmapMasked(bitmap, drawto,
6476 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
6477 DX + DXSIZE - i, DY + 140 + j);
6478 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
6479 DY - (DOOR_GFX_PAGEY1 + j));
6480 BlitBitmapMasked(bitmap, drawto,
6481 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
6483 BlitBitmapMasked(bitmap, drawto,
6484 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
6487 BlitBitmapMasked(bitmap, drawto,
6488 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
6490 BlitBitmapMasked(bitmap, drawto,
6491 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
6493 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
6494 BlitBitmapMasked(bitmap, drawto,
6495 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
6496 DX + DXSIZE - i, DY + 77 + j);
6497 BlitBitmapMasked(bitmap, drawto,
6498 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
6499 DX + DXSIZE - i, DY + 203 + j);
6504 redraw_mask |= REDRAW_DOOR_1;
6505 door_1_done = (a == end);
6508 if (door_state & DOOR_ACTION_2 &&
6509 x * door_2.step_offset <= door_size_2)
6511 int a = MIN(x * door_2.step_offset, door_size);
6512 int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
6513 int i = p + door_skip;
6516 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
6517 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
6518 Bitmap *bm_left = g_left->bitmap;
6519 Bitmap *bm_right = g_right->bitmap;
6520 GC gc_left = bm_left->stored_clip_gc;
6521 GC gc_right = bm_right->stored_clip_gc;
6524 int classic_vxsize = 100;
6525 int classic_vysize = 100;
6526 boolean classic_door_2_size = (VXSIZE == classic_vxsize &&
6527 VYSIZE == classic_vysize);
6529 if (door_2.anim_mode & ANIM_STATIC_PANEL)
6531 BlitBitmap(bitmap_db_door, drawto,
6532 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
6533 VXSIZE, VYSIZE, VX, VY);
6535 else if (x <= VYSIZE)
6537 BlitBitmap(bitmap_db_door, drawto,
6538 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
6539 VXSIZE, VYSIZE - p / 2, VX, VY);
6541 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
6544 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
6547 int src1_x = g_right->src_x;
6548 int src1_y = g_right->src_y;
6549 int src2_x = g_left->src_x + g_left->width - i;
6550 int src2_y = g_left->src_y;
6551 int dst1_x = VX + VXSIZE - i;
6556 int height = VYSIZE;
6558 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6559 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6562 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6563 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6566 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6567 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6568 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6569 int dst2_x = VX, dst2_y = VY;
6570 int width = i, height = VYSIZE;
6572 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6573 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6576 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6577 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6581 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
6584 int src1_x = g_right->src_x;
6585 int src1_y = g_right->src_y;
6586 int src2_x = g_left->src_x;
6587 int src2_y = g_left->src_y + g_left->height - i;
6589 int dst1_y = VY + VYSIZE - i;
6595 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6596 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6599 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6600 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6603 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6604 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
6605 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
6606 int dst2_x = VX, dst2_y = VY;
6607 int width = VXSIZE, height = i;
6609 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6610 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6613 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6614 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6618 else if (classic_door_2_size && x <= VXSIZE) /* ANIM_DEFAULT */
6620 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
6623 int src1_x = g_right->src_x;
6624 int src1_y = g_right->src_y;
6625 int src2_x = g_left->src_x + g_left->width - i;
6626 int src2_y = g_left->src_y;
6627 int dst1_x = VX + VXSIZE - i;
6632 int height = VYSIZE / 2;
6633 int ypos1 = 0, ypos2 = VYSIZE / 2;
6635 SetClipOrigin(bm_right, gc_right,
6636 dst1_x - src1_x, dst1_y - src1_y + j);
6637 BlitBitmapMasked(bm_right, drawto,
6638 src1_x, src1_y + ypos1, width, height,
6639 dst1_x, dst1_y + ypos1 + j);
6640 SetClipOrigin(bm_left, gc_left,
6641 dst2_x - src2_x, dst2_y - src2_y - j);
6642 BlitBitmapMasked(bm_left, drawto,
6643 src2_x, src2_y + ypos1 + j, width, height - j,
6644 dst2_x, dst2_y + ypos1);
6646 SetClipOrigin(bm_left, gc_left,
6647 dst2_x - src2_x, dst2_y - src2_y - j);
6648 BlitBitmapMasked(bm_left, drawto,
6649 src2_x, src2_y + ypos2, width, height,
6650 dst2_x, dst2_y + ypos2 - j);
6651 SetClipOrigin(bm_right, gc_right,
6652 dst1_x - src1_x, dst1_y - src1_y + j);
6653 BlitBitmapMasked(bm_right, drawto,
6654 src1_x, src1_y + ypos2, width, height - j,
6655 dst1_x, dst1_y + ypos2 + j);
6657 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6658 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6659 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6660 int dst2_x = VX, dst2_y = VY;
6661 int width = i, height = VYSIZE;
6662 int ypos = VYSIZE / 2;
6664 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6665 BlitBitmapMasked(bitmap, drawto,
6666 src1_x, src1_y, width, ypos,
6667 dst1_x, dst1_y + j);
6668 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6669 BlitBitmapMasked(bitmap, drawto,
6670 src2_x, src2_y + j, width, ypos - j,
6673 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6674 BlitBitmapMasked(bitmap, drawto,
6675 src2_x, src2_y + ypos, width, ypos,
6676 dst2_x, dst2_y + ypos - j);
6677 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6678 BlitBitmapMasked(bitmap, drawto,
6679 src1_x, src1_y + ypos, width, ypos - j,
6680 dst1_x, dst1_y + ypos + j);
6683 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6684 BlitBitmapMasked(bitmap, drawto,
6685 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
6686 VX + VXSIZE - i, VY + j);
6687 SetClipOrigin(bitmap, gc,
6688 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
6689 BlitBitmapMasked(bitmap, drawto,
6690 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
6693 BlitBitmapMasked(bitmap, drawto,
6694 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6695 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
6696 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6697 BlitBitmapMasked(bitmap, drawto,
6698 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6700 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
6705 redraw_mask |= REDRAW_DOOR_2;
6706 door_2_done = (a == VXSIZE);
6709 if (!(door_state & DOOR_NO_DELAY))
6713 if (game_status == GAME_MODE_MAIN)
6716 WaitUntilDelayReached(&door_delay, door_delay_value);
6721 if (door_state & DOOR_ACTION_1)
6722 door1 = door_state & DOOR_ACTION_1;
6723 if (door_state & DOOR_ACTION_2)
6724 door2 = door_state & DOOR_ACTION_2;
6726 return (door1 | door2);
6731 void DrawSpecialEditorDoor()
6734 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6735 int top_border_width = gfx1->width;
6736 int top_border_height = gfx1->height;
6737 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6738 int ex = EX - outer_border;
6739 int ey = EY - outer_border;
6740 int vy = VY - outer_border;
6741 int exsize = EXSIZE + 2 * outer_border;
6743 CloseDoor(DOOR_CLOSE_2);
6745 /* draw bigger level editor toolbox window */
6746 BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
6747 top_border_width, top_border_height, ex, ey - top_border_height);
6748 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
6749 exsize, EYSIZE - VYSIZE + outer_border, ex, ey);
6751 /* draw bigger level editor toolbox window */
6752 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
6753 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
6755 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6756 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
6760 redraw_mask |= REDRAW_ALL;
6763 void UndrawSpecialEditorDoor()
6766 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6767 int top_border_width = gfx1->width;
6768 int top_border_height = gfx1->height;
6769 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6770 int ex = EX - outer_border;
6771 int ey = EY - outer_border;
6772 int ey_top = ey - top_border_height;
6773 int exsize = EXSIZE + 2 * outer_border;
6774 int eysize = EYSIZE + 2 * outer_border;
6776 /* draw normal tape recorder window */
6777 if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
6779 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6780 ex, ey_top, top_border_width, top_border_height,
6782 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6783 ex, ey, exsize, eysize, ex, ey);
6787 // if screen background is set to "[NONE]", clear editor toolbox window
6788 ClearRectangle(drawto, ex, ey_top, top_border_width, top_border_height);
6789 ClearRectangle(drawto, ex, ey, exsize, eysize);
6792 /* draw normal tape recorder window */
6793 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6794 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
6798 redraw_mask |= REDRAW_ALL;
6802 /* ---------- new tool button stuff ---------------------------------------- */
6809 struct TextPosInfo *pos;
6812 } toolbutton_info[NUM_TOOL_BUTTONS] =
6815 IMG_REQUEST_BUTTON_GFX_YES, &request.button.yes,
6816 TOOL_CTRL_ID_YES, "yes"
6819 IMG_REQUEST_BUTTON_GFX_NO, &request.button.no,
6820 TOOL_CTRL_ID_NO, "no"
6823 IMG_REQUEST_BUTTON_GFX_CONFIRM, &request.button.confirm,
6824 TOOL_CTRL_ID_CONFIRM, "confirm"
6827 IMG_REQUEST_BUTTON_GFX_PLAYER_1, &request.button.player_1,
6828 TOOL_CTRL_ID_PLAYER_1, "player 1"
6831 IMG_REQUEST_BUTTON_GFX_PLAYER_2, &request.button.player_2,
6832 TOOL_CTRL_ID_PLAYER_2, "player 2"
6835 IMG_REQUEST_BUTTON_GFX_PLAYER_3, &request.button.player_3,
6836 TOOL_CTRL_ID_PLAYER_3, "player 3"
6839 IMG_REQUEST_BUTTON_GFX_PLAYER_4, &request.button.player_4,
6840 TOOL_CTRL_ID_PLAYER_4, "player 4"
6844 void CreateToolButtons()
6848 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6850 struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
6851 struct TextPosInfo *pos = toolbutton_info[i].pos;
6852 struct GadgetInfo *gi;
6853 Bitmap *deco_bitmap = None;
6854 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6855 unsigned int event_mask = GD_EVENT_RELEASED;
6858 int gd_x = gfx->src_x;
6859 int gd_y = gfx->src_y;
6860 int gd_xp = gfx->src_x + gfx->pressed_xoffset;
6861 int gd_yp = gfx->src_y + gfx->pressed_yoffset;
6864 if (global.use_envelope_request)
6865 setRequestPosition(&dx, &dy, TRUE);
6867 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
6869 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
6871 getSizedGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0,
6872 pos->size, &deco_bitmap, &deco_x, &deco_y);
6873 deco_xpos = (gfx->width - pos->size) / 2;
6874 deco_ypos = (gfx->height - pos->size) / 2;
6877 gi = CreateGadget(GDI_CUSTOM_ID, id,
6878 GDI_INFO_TEXT, toolbutton_info[i].infotext,
6879 GDI_X, dx + GDI_ACTIVE_POS(pos->x),
6880 GDI_Y, dy + GDI_ACTIVE_POS(pos->y),
6881 GDI_WIDTH, gfx->width,
6882 GDI_HEIGHT, gfx->height,
6883 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
6884 GDI_STATE, GD_BUTTON_UNPRESSED,
6885 GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y,
6886 GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp,
6887 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
6888 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
6889 GDI_DECORATION_SIZE, pos->size, pos->size,
6890 GDI_DECORATION_SHIFTING, 1, 1,
6891 GDI_DIRECT_DRAW, FALSE,
6892 GDI_EVENT_MASK, event_mask,
6893 GDI_CALLBACK_ACTION, HandleToolButtons,
6897 Error(ERR_EXIT, "cannot create gadget");
6899 tool_gadget[id] = gi;
6905 /* graphic position values for tool buttons */
6906 #define TOOL_BUTTON_YES_XPOS 2
6907 #define TOOL_BUTTON_YES_YPOS 250
6908 #define TOOL_BUTTON_YES_GFX_YPOS 0
6909 #define TOOL_BUTTON_YES_XSIZE 46
6910 #define TOOL_BUTTON_YES_YSIZE 28
6911 #define TOOL_BUTTON_NO_XPOS 52
6912 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
6913 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
6914 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
6915 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
6916 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
6917 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
6918 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
6919 #define TOOL_BUTTON_CONFIRM_XSIZE 96
6920 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
6921 #define TOOL_BUTTON_PLAYER_XSIZE 30
6922 #define TOOL_BUTTON_PLAYER_YSIZE 30
6923 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
6924 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
6925 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
6926 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
6927 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6928 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6929 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6930 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6931 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6932 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6933 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6934 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6935 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6936 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6937 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6938 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6939 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6940 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6941 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6942 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6951 } toolbutton_info[NUM_TOOL_BUTTONS] =
6954 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
6955 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
6956 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
6961 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
6962 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
6963 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
6968 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
6969 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
6970 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
6971 TOOL_CTRL_ID_CONFIRM,
6975 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6976 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
6977 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6978 TOOL_CTRL_ID_PLAYER_1,
6982 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6983 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
6984 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6985 TOOL_CTRL_ID_PLAYER_2,
6989 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6990 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
6991 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6992 TOOL_CTRL_ID_PLAYER_3,
6996 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6997 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
6998 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6999 TOOL_CTRL_ID_PLAYER_4,
7004 void CreateToolButtons()
7008 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
7010 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
7011 Bitmap *deco_bitmap = None;
7012 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
7013 struct GadgetInfo *gi;
7014 unsigned int event_mask;
7015 int gd_xoffset, gd_yoffset;
7016 int gd_x1, gd_x2, gd_y;
7019 event_mask = GD_EVENT_RELEASED;
7021 gd_xoffset = toolbutton_info[i].xpos;
7022 gd_yoffset = toolbutton_info[i].ypos;
7023 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
7024 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
7025 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
7027 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
7029 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
7031 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
7032 &deco_bitmap, &deco_x, &deco_y);
7033 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
7034 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
7037 gi = CreateGadget(GDI_CUSTOM_ID, id,
7038 GDI_INFO_TEXT, toolbutton_info[i].infotext,
7039 GDI_X, DX + GDI_ACTIVE_POS(toolbutton_info[i].x),
7040 GDI_Y, DY + GDI_ACTIVE_POS(toolbutton_info[i].y),
7041 GDI_WIDTH, toolbutton_info[i].width,
7042 GDI_HEIGHT, toolbutton_info[i].height,
7043 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
7044 GDI_STATE, GD_BUTTON_UNPRESSED,
7045 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
7046 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
7047 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
7048 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
7049 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
7050 GDI_DECORATION_SHIFTING, 1, 1,
7051 GDI_DIRECT_DRAW, FALSE,
7052 GDI_EVENT_MASK, event_mask,
7053 GDI_CALLBACK_ACTION, HandleToolButtons,
7057 Error(ERR_EXIT, "cannot create gadget");
7059 tool_gadget[id] = gi;
7065 void FreeToolButtons()
7069 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
7070 FreeGadget(tool_gadget[i]);
7073 static void UnmapToolButtons()
7077 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
7078 UnmapGadget(tool_gadget[i]);
7081 static void HandleToolButtons(struct GadgetInfo *gi)
7083 request_gadget_id = gi->custom_id;
7086 static struct Mapping_EM_to_RND_object
7089 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
7090 boolean is_backside; /* backside of moving element */
7096 em_object_mapping_list[] =
7099 Xblank, TRUE, FALSE,
7103 Yacid_splash_eB, FALSE, FALSE,
7104 EL_ACID_SPLASH_RIGHT, -1, -1
7107 Yacid_splash_wB, FALSE, FALSE,
7108 EL_ACID_SPLASH_LEFT, -1, -1
7111 #ifdef EM_ENGINE_BAD_ROLL
7113 Xstone_force_e, FALSE, FALSE,
7114 EL_ROCK, -1, MV_BIT_RIGHT
7117 Xstone_force_w, FALSE, FALSE,
7118 EL_ROCK, -1, MV_BIT_LEFT
7121 Xnut_force_e, FALSE, FALSE,
7122 EL_NUT, -1, MV_BIT_RIGHT
7125 Xnut_force_w, FALSE, FALSE,
7126 EL_NUT, -1, MV_BIT_LEFT
7129 Xspring_force_e, FALSE, FALSE,
7130 EL_SPRING, -1, MV_BIT_RIGHT
7133 Xspring_force_w, FALSE, FALSE,
7134 EL_SPRING, -1, MV_BIT_LEFT
7137 Xemerald_force_e, FALSE, FALSE,
7138 EL_EMERALD, -1, MV_BIT_RIGHT
7141 Xemerald_force_w, FALSE, FALSE,
7142 EL_EMERALD, -1, MV_BIT_LEFT
7145 Xdiamond_force_e, FALSE, FALSE,
7146 EL_DIAMOND, -1, MV_BIT_RIGHT
7149 Xdiamond_force_w, FALSE, FALSE,
7150 EL_DIAMOND, -1, MV_BIT_LEFT
7153 Xbomb_force_e, FALSE, FALSE,
7154 EL_BOMB, -1, MV_BIT_RIGHT
7157 Xbomb_force_w, FALSE, FALSE,
7158 EL_BOMB, -1, MV_BIT_LEFT
7160 #endif /* EM_ENGINE_BAD_ROLL */
7163 Xstone, TRUE, FALSE,
7167 Xstone_pause, FALSE, FALSE,
7171 Xstone_fall, FALSE, FALSE,
7175 Ystone_s, FALSE, FALSE,
7176 EL_ROCK, ACTION_FALLING, -1
7179 Ystone_sB, FALSE, TRUE,
7180 EL_ROCK, ACTION_FALLING, -1
7183 Ystone_e, FALSE, FALSE,
7184 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
7187 Ystone_eB, FALSE, TRUE,
7188 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
7191 Ystone_w, FALSE, FALSE,
7192 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
7195 Ystone_wB, FALSE, TRUE,
7196 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
7203 Xnut_pause, FALSE, FALSE,
7207 Xnut_fall, FALSE, FALSE,
7211 Ynut_s, FALSE, FALSE,
7212 EL_NUT, ACTION_FALLING, -1
7215 Ynut_sB, FALSE, TRUE,
7216 EL_NUT, ACTION_FALLING, -1
7219 Ynut_e, FALSE, FALSE,
7220 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
7223 Ynut_eB, FALSE, TRUE,
7224 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
7227 Ynut_w, FALSE, FALSE,
7228 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
7231 Ynut_wB, FALSE, TRUE,
7232 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
7235 Xbug_n, TRUE, FALSE,
7239 Xbug_e, TRUE, FALSE,
7240 EL_BUG_RIGHT, -1, -1
7243 Xbug_s, TRUE, FALSE,
7247 Xbug_w, TRUE, FALSE,
7251 Xbug_gon, FALSE, FALSE,
7255 Xbug_goe, FALSE, FALSE,
7256 EL_BUG_RIGHT, -1, -1
7259 Xbug_gos, FALSE, FALSE,
7263 Xbug_gow, FALSE, FALSE,
7267 Ybug_n, FALSE, FALSE,
7268 EL_BUG, ACTION_MOVING, MV_BIT_UP
7271 Ybug_nB, FALSE, TRUE,
7272 EL_BUG, ACTION_MOVING, MV_BIT_UP
7275 Ybug_e, FALSE, FALSE,
7276 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
7279 Ybug_eB, FALSE, TRUE,
7280 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
7283 Ybug_s, FALSE, FALSE,
7284 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
7287 Ybug_sB, FALSE, TRUE,
7288 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
7291 Ybug_w, FALSE, FALSE,
7292 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
7295 Ybug_wB, FALSE, TRUE,
7296 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
7299 Ybug_w_n, FALSE, FALSE,
7300 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
7303 Ybug_n_e, FALSE, FALSE,
7304 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
7307 Ybug_e_s, FALSE, FALSE,
7308 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
7311 Ybug_s_w, FALSE, FALSE,
7312 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
7315 Ybug_e_n, FALSE, FALSE,
7316 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
7319 Ybug_s_e, FALSE, FALSE,
7320 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
7323 Ybug_w_s, FALSE, FALSE,
7324 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
7327 Ybug_n_w, FALSE, FALSE,
7328 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
7331 Ybug_stone, FALSE, FALSE,
7332 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
7335 Ybug_spring, FALSE, FALSE,
7336 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
7339 Xtank_n, TRUE, FALSE,
7340 EL_SPACESHIP_UP, -1, -1
7343 Xtank_e, TRUE, FALSE,
7344 EL_SPACESHIP_RIGHT, -1, -1
7347 Xtank_s, TRUE, FALSE,
7348 EL_SPACESHIP_DOWN, -1, -1
7351 Xtank_w, TRUE, FALSE,
7352 EL_SPACESHIP_LEFT, -1, -1
7355 Xtank_gon, FALSE, FALSE,
7356 EL_SPACESHIP_UP, -1, -1
7359 Xtank_goe, FALSE, FALSE,
7360 EL_SPACESHIP_RIGHT, -1, -1
7363 Xtank_gos, FALSE, FALSE,
7364 EL_SPACESHIP_DOWN, -1, -1
7367 Xtank_gow, FALSE, FALSE,
7368 EL_SPACESHIP_LEFT, -1, -1
7371 Ytank_n, FALSE, FALSE,
7372 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
7375 Ytank_nB, FALSE, TRUE,
7376 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
7379 Ytank_e, FALSE, FALSE,
7380 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
7383 Ytank_eB, FALSE, TRUE,
7384 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
7387 Ytank_s, FALSE, FALSE,
7388 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
7391 Ytank_sB, FALSE, TRUE,
7392 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
7395 Ytank_w, FALSE, FALSE,
7396 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
7399 Ytank_wB, FALSE, TRUE,
7400 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
7403 Ytank_w_n, FALSE, FALSE,
7404 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
7407 Ytank_n_e, FALSE, FALSE,
7408 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
7411 Ytank_e_s, FALSE, FALSE,
7412 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
7415 Ytank_s_w, FALSE, FALSE,
7416 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
7419 Ytank_e_n, FALSE, FALSE,
7420 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
7423 Ytank_s_e, FALSE, FALSE,
7424 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
7427 Ytank_w_s, FALSE, FALSE,
7428 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
7431 Ytank_n_w, FALSE, FALSE,
7432 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
7435 Ytank_stone, FALSE, FALSE,
7436 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
7439 Ytank_spring, FALSE, FALSE,
7440 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
7443 Xandroid, TRUE, FALSE,
7444 EL_EMC_ANDROID, ACTION_ACTIVE, -1
7447 Xandroid_1_n, FALSE, FALSE,
7448 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
7451 Xandroid_2_n, FALSE, FALSE,
7452 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
7455 Xandroid_1_e, FALSE, FALSE,
7456 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
7459 Xandroid_2_e, FALSE, FALSE,
7460 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
7463 Xandroid_1_w, FALSE, FALSE,
7464 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
7467 Xandroid_2_w, FALSE, FALSE,
7468 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
7471 Xandroid_1_s, FALSE, FALSE,
7472 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
7475 Xandroid_2_s, FALSE, FALSE,
7476 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
7479 Yandroid_n, FALSE, FALSE,
7480 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
7483 Yandroid_nB, FALSE, TRUE,
7484 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
7487 Yandroid_ne, FALSE, FALSE,
7488 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
7491 Yandroid_neB, FALSE, TRUE,
7492 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
7495 Yandroid_e, FALSE, FALSE,
7496 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
7499 Yandroid_eB, FALSE, TRUE,
7500 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
7503 Yandroid_se, FALSE, FALSE,
7504 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
7507 Yandroid_seB, FALSE, TRUE,
7508 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
7511 Yandroid_s, FALSE, FALSE,
7512 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
7515 Yandroid_sB, FALSE, TRUE,
7516 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
7519 Yandroid_sw, FALSE, FALSE,
7520 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
7523 Yandroid_swB, FALSE, TRUE,
7524 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
7527 Yandroid_w, FALSE, FALSE,
7528 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
7531 Yandroid_wB, FALSE, TRUE,
7532 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
7535 Yandroid_nw, FALSE, FALSE,
7536 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
7539 Yandroid_nwB, FALSE, TRUE,
7540 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
7543 Xspring, TRUE, FALSE,
7547 Xspring_pause, FALSE, FALSE,
7551 Xspring_e, FALSE, FALSE,
7555 Xspring_w, FALSE, FALSE,
7559 Xspring_fall, FALSE, FALSE,
7563 Yspring_s, FALSE, FALSE,
7564 EL_SPRING, ACTION_FALLING, -1
7567 Yspring_sB, FALSE, TRUE,
7568 EL_SPRING, ACTION_FALLING, -1
7571 Yspring_e, FALSE, FALSE,
7572 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
7575 Yspring_eB, FALSE, TRUE,
7576 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
7579 Yspring_w, FALSE, FALSE,
7580 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
7583 Yspring_wB, FALSE, TRUE,
7584 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
7587 Yspring_kill_e, FALSE, FALSE,
7588 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
7591 Yspring_kill_eB, FALSE, TRUE,
7592 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
7595 Yspring_kill_w, FALSE, FALSE,
7596 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7599 Yspring_kill_wB, FALSE, TRUE,
7600 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7603 Xeater_n, TRUE, FALSE,
7604 EL_YAMYAM_UP, -1, -1
7607 Xeater_e, TRUE, FALSE,
7608 EL_YAMYAM_RIGHT, -1, -1
7611 Xeater_w, TRUE, FALSE,
7612 EL_YAMYAM_LEFT, -1, -1
7615 Xeater_s, TRUE, FALSE,
7616 EL_YAMYAM_DOWN, -1, -1
7619 Yeater_n, FALSE, FALSE,
7620 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7623 Yeater_nB, FALSE, TRUE,
7624 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7627 Yeater_e, FALSE, FALSE,
7628 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7631 Yeater_eB, FALSE, TRUE,
7632 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7635 Yeater_s, FALSE, FALSE,
7636 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7639 Yeater_sB, FALSE, TRUE,
7640 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7643 Yeater_w, FALSE, FALSE,
7644 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7647 Yeater_wB, FALSE, TRUE,
7648 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7651 Yeater_stone, FALSE, FALSE,
7652 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
7655 Yeater_spring, FALSE, FALSE,
7656 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
7659 Xalien, TRUE, FALSE,
7663 Xalien_pause, FALSE, FALSE,
7667 Yalien_n, FALSE, FALSE,
7668 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7671 Yalien_nB, FALSE, TRUE,
7672 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7675 Yalien_e, FALSE, FALSE,
7676 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7679 Yalien_eB, FALSE, TRUE,
7680 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7683 Yalien_s, FALSE, FALSE,
7684 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7687 Yalien_sB, FALSE, TRUE,
7688 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7691 Yalien_w, FALSE, FALSE,
7692 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7695 Yalien_wB, FALSE, TRUE,
7696 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7699 Yalien_stone, FALSE, FALSE,
7700 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
7703 Yalien_spring, FALSE, FALSE,
7704 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
7707 Xemerald, TRUE, FALSE,
7711 Xemerald_pause, FALSE, FALSE,
7715 Xemerald_fall, FALSE, FALSE,
7719 Xemerald_shine, FALSE, FALSE,
7720 EL_EMERALD, ACTION_TWINKLING, -1
7723 Yemerald_s, FALSE, FALSE,
7724 EL_EMERALD, ACTION_FALLING, -1
7727 Yemerald_sB, FALSE, TRUE,
7728 EL_EMERALD, ACTION_FALLING, -1
7731 Yemerald_e, FALSE, FALSE,
7732 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7735 Yemerald_eB, FALSE, TRUE,
7736 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7739 Yemerald_w, FALSE, FALSE,
7740 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7743 Yemerald_wB, FALSE, TRUE,
7744 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7747 Yemerald_eat, FALSE, FALSE,
7748 EL_EMERALD, ACTION_COLLECTING, -1
7751 Yemerald_stone, FALSE, FALSE,
7752 EL_NUT, ACTION_BREAKING, -1
7755 Xdiamond, TRUE, FALSE,
7759 Xdiamond_pause, FALSE, FALSE,
7763 Xdiamond_fall, FALSE, FALSE,
7767 Xdiamond_shine, FALSE, FALSE,
7768 EL_DIAMOND, ACTION_TWINKLING, -1
7771 Ydiamond_s, FALSE, FALSE,
7772 EL_DIAMOND, ACTION_FALLING, -1
7775 Ydiamond_sB, FALSE, TRUE,
7776 EL_DIAMOND, ACTION_FALLING, -1
7779 Ydiamond_e, FALSE, FALSE,
7780 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7783 Ydiamond_eB, FALSE, TRUE,
7784 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7787 Ydiamond_w, FALSE, FALSE,
7788 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7791 Ydiamond_wB, FALSE, TRUE,
7792 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7795 Ydiamond_eat, FALSE, FALSE,
7796 EL_DIAMOND, ACTION_COLLECTING, -1
7799 Ydiamond_stone, FALSE, FALSE,
7800 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
7803 Xdrip_fall, TRUE, FALSE,
7804 EL_AMOEBA_DROP, -1, -1
7807 Xdrip_stretch, FALSE, FALSE,
7808 EL_AMOEBA_DROP, ACTION_FALLING, -1
7811 Xdrip_stretchB, FALSE, TRUE,
7812 EL_AMOEBA_DROP, ACTION_FALLING, -1
7815 Xdrip_eat, FALSE, FALSE,
7816 EL_AMOEBA_DROP, ACTION_GROWING, -1
7819 Ydrip_s1, FALSE, FALSE,
7820 EL_AMOEBA_DROP, ACTION_FALLING, -1
7823 Ydrip_s1B, FALSE, TRUE,
7824 EL_AMOEBA_DROP, ACTION_FALLING, -1
7827 Ydrip_s2, FALSE, FALSE,
7828 EL_AMOEBA_DROP, ACTION_FALLING, -1
7831 Ydrip_s2B, FALSE, TRUE,
7832 EL_AMOEBA_DROP, ACTION_FALLING, -1
7839 Xbomb_pause, FALSE, FALSE,
7843 Xbomb_fall, FALSE, FALSE,
7847 Ybomb_s, FALSE, FALSE,
7848 EL_BOMB, ACTION_FALLING, -1
7851 Ybomb_sB, FALSE, TRUE,
7852 EL_BOMB, ACTION_FALLING, -1
7855 Ybomb_e, FALSE, FALSE,
7856 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7859 Ybomb_eB, FALSE, TRUE,
7860 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7863 Ybomb_w, FALSE, FALSE,
7864 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7867 Ybomb_wB, FALSE, TRUE,
7868 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7871 Ybomb_eat, FALSE, FALSE,
7872 EL_BOMB, ACTION_ACTIVATING, -1
7875 Xballoon, TRUE, FALSE,
7879 Yballoon_n, FALSE, FALSE,
7880 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7883 Yballoon_nB, FALSE, TRUE,
7884 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7887 Yballoon_e, FALSE, FALSE,
7888 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7891 Yballoon_eB, FALSE, TRUE,
7892 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7895 Yballoon_s, FALSE, FALSE,
7896 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7899 Yballoon_sB, FALSE, TRUE,
7900 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7903 Yballoon_w, FALSE, FALSE,
7904 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7907 Yballoon_wB, FALSE, TRUE,
7908 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7911 Xgrass, TRUE, FALSE,
7912 EL_EMC_GRASS, -1, -1
7915 Ygrass_nB, FALSE, FALSE,
7916 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
7919 Ygrass_eB, FALSE, FALSE,
7920 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
7923 Ygrass_sB, FALSE, FALSE,
7924 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
7927 Ygrass_wB, FALSE, FALSE,
7928 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
7935 Ydirt_nB, FALSE, FALSE,
7936 EL_SAND, ACTION_DIGGING, MV_BIT_UP
7939 Ydirt_eB, FALSE, FALSE,
7940 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
7943 Ydirt_sB, FALSE, FALSE,
7944 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
7947 Ydirt_wB, FALSE, FALSE,
7948 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
7951 Xacid_ne, TRUE, FALSE,
7952 EL_ACID_POOL_TOPRIGHT, -1, -1
7955 Xacid_se, TRUE, FALSE,
7956 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
7959 Xacid_s, TRUE, FALSE,
7960 EL_ACID_POOL_BOTTOM, -1, -1
7963 Xacid_sw, TRUE, FALSE,
7964 EL_ACID_POOL_BOTTOMLEFT, -1, -1
7967 Xacid_nw, TRUE, FALSE,
7968 EL_ACID_POOL_TOPLEFT, -1, -1
7971 Xacid_1, TRUE, FALSE,
7975 Xacid_2, FALSE, FALSE,
7979 Xacid_3, FALSE, FALSE,
7983 Xacid_4, FALSE, FALSE,
7987 Xacid_5, FALSE, FALSE,
7991 Xacid_6, FALSE, FALSE,
7995 Xacid_7, FALSE, FALSE,
7999 Xacid_8, FALSE, FALSE,
8003 Xball_1, TRUE, FALSE,
8004 EL_EMC_MAGIC_BALL, -1, -1
8007 Xball_1B, FALSE, FALSE,
8008 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
8011 Xball_2, FALSE, FALSE,
8012 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
8015 Xball_2B, FALSE, FALSE,
8016 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
8019 Yball_eat, FALSE, FALSE,
8020 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
8023 Ykey_1_eat, FALSE, FALSE,
8024 EL_EM_KEY_1, ACTION_COLLECTING, -1
8027 Ykey_2_eat, FALSE, FALSE,
8028 EL_EM_KEY_2, ACTION_COLLECTING, -1
8031 Ykey_3_eat, FALSE, FALSE,
8032 EL_EM_KEY_3, ACTION_COLLECTING, -1
8035 Ykey_4_eat, FALSE, FALSE,
8036 EL_EM_KEY_4, ACTION_COLLECTING, -1
8039 Ykey_5_eat, FALSE, FALSE,
8040 EL_EMC_KEY_5, ACTION_COLLECTING, -1
8043 Ykey_6_eat, FALSE, FALSE,
8044 EL_EMC_KEY_6, ACTION_COLLECTING, -1
8047 Ykey_7_eat, FALSE, FALSE,
8048 EL_EMC_KEY_7, ACTION_COLLECTING, -1
8051 Ykey_8_eat, FALSE, FALSE,
8052 EL_EMC_KEY_8, ACTION_COLLECTING, -1
8055 Ylenses_eat, FALSE, FALSE,
8056 EL_EMC_LENSES, ACTION_COLLECTING, -1
8059 Ymagnify_eat, FALSE, FALSE,
8060 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
8063 Ygrass_eat, FALSE, FALSE,
8064 EL_EMC_GRASS, ACTION_SNAPPING, -1
8067 Ydirt_eat, FALSE, FALSE,
8068 EL_SAND, ACTION_SNAPPING, -1
8071 Xgrow_ns, TRUE, FALSE,
8072 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
8075 Ygrow_ns_eat, FALSE, FALSE,
8076 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
8079 Xgrow_ew, TRUE, FALSE,
8080 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
8083 Ygrow_ew_eat, FALSE, FALSE,
8084 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
8087 Xwonderwall, TRUE, FALSE,
8088 EL_MAGIC_WALL, -1, -1
8091 XwonderwallB, FALSE, FALSE,
8092 EL_MAGIC_WALL, ACTION_ACTIVE, -1
8095 Xamoeba_1, TRUE, FALSE,
8096 EL_AMOEBA_DRY, ACTION_OTHER, -1
8099 Xamoeba_2, FALSE, FALSE,
8100 EL_AMOEBA_DRY, ACTION_OTHER, -1
8103 Xamoeba_3, FALSE, FALSE,
8104 EL_AMOEBA_DRY, ACTION_OTHER, -1
8107 Xamoeba_4, FALSE, FALSE,
8108 EL_AMOEBA_DRY, ACTION_OTHER, -1
8111 Xamoeba_5, TRUE, FALSE,
8112 EL_AMOEBA_WET, ACTION_OTHER, -1
8115 Xamoeba_6, FALSE, FALSE,
8116 EL_AMOEBA_WET, ACTION_OTHER, -1
8119 Xamoeba_7, FALSE, FALSE,
8120 EL_AMOEBA_WET, ACTION_OTHER, -1
8123 Xamoeba_8, FALSE, FALSE,
8124 EL_AMOEBA_WET, ACTION_OTHER, -1
8127 Xdoor_1, TRUE, FALSE,
8128 EL_EM_GATE_1, -1, -1
8131 Xdoor_2, TRUE, FALSE,
8132 EL_EM_GATE_2, -1, -1
8135 Xdoor_3, TRUE, FALSE,
8136 EL_EM_GATE_3, -1, -1
8139 Xdoor_4, TRUE, FALSE,
8140 EL_EM_GATE_4, -1, -1
8143 Xdoor_5, TRUE, FALSE,
8144 EL_EMC_GATE_5, -1, -1
8147 Xdoor_6, TRUE, FALSE,
8148 EL_EMC_GATE_6, -1, -1
8151 Xdoor_7, TRUE, FALSE,
8152 EL_EMC_GATE_7, -1, -1
8155 Xdoor_8, TRUE, FALSE,
8156 EL_EMC_GATE_8, -1, -1
8159 Xkey_1, TRUE, FALSE,
8163 Xkey_2, TRUE, FALSE,
8167 Xkey_3, TRUE, FALSE,
8171 Xkey_4, TRUE, FALSE,
8175 Xkey_5, TRUE, FALSE,
8176 EL_EMC_KEY_5, -1, -1
8179 Xkey_6, TRUE, FALSE,
8180 EL_EMC_KEY_6, -1, -1
8183 Xkey_7, TRUE, FALSE,
8184 EL_EMC_KEY_7, -1, -1
8187 Xkey_8, TRUE, FALSE,
8188 EL_EMC_KEY_8, -1, -1
8191 Xwind_n, TRUE, FALSE,
8192 EL_BALLOON_SWITCH_UP, -1, -1
8195 Xwind_e, TRUE, FALSE,
8196 EL_BALLOON_SWITCH_RIGHT, -1, -1
8199 Xwind_s, TRUE, FALSE,
8200 EL_BALLOON_SWITCH_DOWN, -1, -1
8203 Xwind_w, TRUE, FALSE,
8204 EL_BALLOON_SWITCH_LEFT, -1, -1
8207 Xwind_nesw, TRUE, FALSE,
8208 EL_BALLOON_SWITCH_ANY, -1, -1
8211 Xwind_stop, TRUE, FALSE,
8212 EL_BALLOON_SWITCH_NONE, -1, -1
8216 EL_EM_EXIT_CLOSED, -1, -1
8219 Xexit_1, TRUE, FALSE,
8220 EL_EM_EXIT_OPEN, -1, -1
8223 Xexit_2, FALSE, FALSE,
8224 EL_EM_EXIT_OPEN, -1, -1
8227 Xexit_3, FALSE, FALSE,
8228 EL_EM_EXIT_OPEN, -1, -1
8231 Xdynamite, TRUE, FALSE,
8232 EL_EM_DYNAMITE, -1, -1
8235 Ydynamite_eat, FALSE, FALSE,
8236 EL_EM_DYNAMITE, ACTION_COLLECTING, -1
8239 Xdynamite_1, TRUE, FALSE,
8240 EL_EM_DYNAMITE_ACTIVE, -1, -1
8243 Xdynamite_2, FALSE, FALSE,
8244 EL_EM_DYNAMITE_ACTIVE, -1, -1
8247 Xdynamite_3, FALSE, FALSE,
8248 EL_EM_DYNAMITE_ACTIVE, -1, -1
8251 Xdynamite_4, FALSE, FALSE,
8252 EL_EM_DYNAMITE_ACTIVE, -1, -1
8255 Xbumper, TRUE, FALSE,
8256 EL_EMC_SPRING_BUMPER, -1, -1
8259 XbumperB, FALSE, FALSE,
8260 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
8263 Xwheel, TRUE, FALSE,
8264 EL_ROBOT_WHEEL, -1, -1
8267 XwheelB, FALSE, FALSE,
8268 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
8271 Xswitch, TRUE, FALSE,
8272 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
8275 XswitchB, FALSE, FALSE,
8276 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
8280 EL_QUICKSAND_EMPTY, -1, -1
8283 Xsand_stone, TRUE, FALSE,
8284 EL_QUICKSAND_FULL, -1, -1
8287 Xsand_stonein_1, FALSE, TRUE,
8288 EL_ROCK, ACTION_FILLING, -1
8291 Xsand_stonein_2, FALSE, TRUE,
8292 EL_ROCK, ACTION_FILLING, -1
8295 Xsand_stonein_3, FALSE, TRUE,
8296 EL_ROCK, ACTION_FILLING, -1
8299 Xsand_stonein_4, FALSE, TRUE,
8300 EL_ROCK, ACTION_FILLING, -1
8304 Xsand_stonesand_1, FALSE, FALSE,
8305 EL_QUICKSAND_EMPTYING, -1, -1
8308 Xsand_stonesand_2, FALSE, FALSE,
8309 EL_QUICKSAND_EMPTYING, -1, -1
8312 Xsand_stonesand_3, FALSE, FALSE,
8313 EL_QUICKSAND_EMPTYING, -1, -1
8316 Xsand_stonesand_4, FALSE, FALSE,
8317 EL_QUICKSAND_EMPTYING, -1, -1
8320 Xsand_stonesand_quickout_1, FALSE, FALSE,
8321 EL_QUICKSAND_EMPTYING, -1, -1
8324 Xsand_stonesand_quickout_2, FALSE, FALSE,
8325 EL_QUICKSAND_EMPTYING, -1, -1
8329 Xsand_stonesand_1, FALSE, FALSE,
8330 EL_QUICKSAND_FULL, -1, -1
8333 Xsand_stonesand_2, FALSE, FALSE,
8334 EL_QUICKSAND_FULL, -1, -1
8337 Xsand_stonesand_3, FALSE, FALSE,
8338 EL_QUICKSAND_FULL, -1, -1
8341 Xsand_stonesand_4, FALSE, FALSE,
8342 EL_QUICKSAND_FULL, -1, -1
8346 Xsand_stoneout_1, FALSE, FALSE,
8347 EL_ROCK, ACTION_EMPTYING, -1
8350 Xsand_stoneout_2, FALSE, FALSE,
8351 EL_ROCK, ACTION_EMPTYING, -1
8355 Xsand_sandstone_1, FALSE, FALSE,
8356 EL_QUICKSAND_FILLING, -1, -1
8359 Xsand_sandstone_2, FALSE, FALSE,
8360 EL_QUICKSAND_FILLING, -1, -1
8363 Xsand_sandstone_3, FALSE, FALSE,
8364 EL_QUICKSAND_FILLING, -1, -1
8367 Xsand_sandstone_4, FALSE, FALSE,
8368 EL_QUICKSAND_FILLING, -1, -1
8372 Xsand_sandstone_1, FALSE, FALSE,
8373 EL_QUICKSAND_FULL, -1, -1
8376 Xsand_sandstone_2, FALSE, FALSE,
8377 EL_QUICKSAND_FULL, -1, -1
8380 Xsand_sandstone_3, FALSE, FALSE,
8381 EL_QUICKSAND_FULL, -1, -1
8384 Xsand_sandstone_4, FALSE, FALSE,
8385 EL_QUICKSAND_FULL, -1, -1
8389 Xplant, TRUE, FALSE,
8390 EL_EMC_PLANT, -1, -1
8393 Yplant, FALSE, FALSE,
8394 EL_EMC_PLANT, -1, -1
8397 Xlenses, TRUE, FALSE,
8398 EL_EMC_LENSES, -1, -1
8401 Xmagnify, TRUE, FALSE,
8402 EL_EMC_MAGNIFIER, -1, -1
8405 Xdripper, TRUE, FALSE,
8406 EL_EMC_DRIPPER, -1, -1
8409 XdripperB, FALSE, FALSE,
8410 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
8413 Xfake_blank, TRUE, FALSE,
8414 EL_INVISIBLE_WALL, -1, -1
8417 Xfake_blankB, FALSE, FALSE,
8418 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
8421 Xfake_grass, TRUE, FALSE,
8422 EL_EMC_FAKE_GRASS, -1, -1
8425 Xfake_grassB, FALSE, FALSE,
8426 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
8429 Xfake_door_1, TRUE, FALSE,
8430 EL_EM_GATE_1_GRAY, -1, -1
8433 Xfake_door_2, TRUE, FALSE,
8434 EL_EM_GATE_2_GRAY, -1, -1
8437 Xfake_door_3, TRUE, FALSE,
8438 EL_EM_GATE_3_GRAY, -1, -1
8441 Xfake_door_4, TRUE, FALSE,
8442 EL_EM_GATE_4_GRAY, -1, -1
8445 Xfake_door_5, TRUE, FALSE,
8446 EL_EMC_GATE_5_GRAY, -1, -1
8449 Xfake_door_6, TRUE, FALSE,
8450 EL_EMC_GATE_6_GRAY, -1, -1
8453 Xfake_door_7, TRUE, FALSE,
8454 EL_EMC_GATE_7_GRAY, -1, -1
8457 Xfake_door_8, TRUE, FALSE,
8458 EL_EMC_GATE_8_GRAY, -1, -1
8461 Xfake_acid_1, TRUE, FALSE,
8462 EL_EMC_FAKE_ACID, -1, -1
8465 Xfake_acid_2, FALSE, FALSE,
8466 EL_EMC_FAKE_ACID, -1, -1
8469 Xfake_acid_3, FALSE, FALSE,
8470 EL_EMC_FAKE_ACID, -1, -1
8473 Xfake_acid_4, FALSE, FALSE,
8474 EL_EMC_FAKE_ACID, -1, -1
8477 Xfake_acid_5, FALSE, FALSE,
8478 EL_EMC_FAKE_ACID, -1, -1
8481 Xfake_acid_6, FALSE, FALSE,
8482 EL_EMC_FAKE_ACID, -1, -1
8485 Xfake_acid_7, FALSE, FALSE,
8486 EL_EMC_FAKE_ACID, -1, -1
8489 Xfake_acid_8, FALSE, FALSE,
8490 EL_EMC_FAKE_ACID, -1, -1
8493 Xsteel_1, TRUE, FALSE,
8494 EL_STEELWALL, -1, -1
8497 Xsteel_2, TRUE, FALSE,
8498 EL_EMC_STEELWALL_2, -1, -1
8501 Xsteel_3, TRUE, FALSE,
8502 EL_EMC_STEELWALL_3, -1, -1
8505 Xsteel_4, TRUE, FALSE,
8506 EL_EMC_STEELWALL_4, -1, -1
8509 Xwall_1, TRUE, FALSE,
8513 Xwall_2, TRUE, FALSE,
8514 EL_EMC_WALL_14, -1, -1
8517 Xwall_3, TRUE, FALSE,
8518 EL_EMC_WALL_15, -1, -1
8521 Xwall_4, TRUE, FALSE,
8522 EL_EMC_WALL_16, -1, -1
8525 Xround_wall_1, TRUE, FALSE,
8526 EL_WALL_SLIPPERY, -1, -1
8529 Xround_wall_2, TRUE, FALSE,
8530 EL_EMC_WALL_SLIPPERY_2, -1, -1
8533 Xround_wall_3, TRUE, FALSE,
8534 EL_EMC_WALL_SLIPPERY_3, -1, -1
8537 Xround_wall_4, TRUE, FALSE,
8538 EL_EMC_WALL_SLIPPERY_4, -1, -1
8541 Xdecor_1, TRUE, FALSE,
8542 EL_EMC_WALL_8, -1, -1
8545 Xdecor_2, TRUE, FALSE,
8546 EL_EMC_WALL_6, -1, -1
8549 Xdecor_3, TRUE, FALSE,
8550 EL_EMC_WALL_4, -1, -1
8553 Xdecor_4, TRUE, FALSE,
8554 EL_EMC_WALL_7, -1, -1
8557 Xdecor_5, TRUE, FALSE,
8558 EL_EMC_WALL_5, -1, -1
8561 Xdecor_6, TRUE, FALSE,
8562 EL_EMC_WALL_9, -1, -1
8565 Xdecor_7, TRUE, FALSE,
8566 EL_EMC_WALL_10, -1, -1
8569 Xdecor_8, TRUE, FALSE,
8570 EL_EMC_WALL_1, -1, -1
8573 Xdecor_9, TRUE, FALSE,
8574 EL_EMC_WALL_2, -1, -1
8577 Xdecor_10, TRUE, FALSE,
8578 EL_EMC_WALL_3, -1, -1
8581 Xdecor_11, TRUE, FALSE,
8582 EL_EMC_WALL_11, -1, -1
8585 Xdecor_12, TRUE, FALSE,
8586 EL_EMC_WALL_12, -1, -1
8589 Xalpha_0, TRUE, FALSE,
8590 EL_CHAR('0'), -1, -1
8593 Xalpha_1, TRUE, FALSE,
8594 EL_CHAR('1'), -1, -1
8597 Xalpha_2, TRUE, FALSE,
8598 EL_CHAR('2'), -1, -1
8601 Xalpha_3, TRUE, FALSE,
8602 EL_CHAR('3'), -1, -1
8605 Xalpha_4, TRUE, FALSE,
8606 EL_CHAR('4'), -1, -1
8609 Xalpha_5, TRUE, FALSE,
8610 EL_CHAR('5'), -1, -1
8613 Xalpha_6, TRUE, FALSE,
8614 EL_CHAR('6'), -1, -1
8617 Xalpha_7, TRUE, FALSE,
8618 EL_CHAR('7'), -1, -1
8621 Xalpha_8, TRUE, FALSE,
8622 EL_CHAR('8'), -1, -1
8625 Xalpha_9, TRUE, FALSE,
8626 EL_CHAR('9'), -1, -1
8629 Xalpha_excla, TRUE, FALSE,
8630 EL_CHAR('!'), -1, -1
8633 Xalpha_quote, TRUE, FALSE,
8634 EL_CHAR('"'), -1, -1
8637 Xalpha_comma, TRUE, FALSE,
8638 EL_CHAR(','), -1, -1
8641 Xalpha_minus, TRUE, FALSE,
8642 EL_CHAR('-'), -1, -1
8645 Xalpha_perio, TRUE, FALSE,
8646 EL_CHAR('.'), -1, -1
8649 Xalpha_colon, TRUE, FALSE,
8650 EL_CHAR(':'), -1, -1
8653 Xalpha_quest, TRUE, FALSE,
8654 EL_CHAR('?'), -1, -1
8657 Xalpha_a, TRUE, FALSE,
8658 EL_CHAR('A'), -1, -1
8661 Xalpha_b, TRUE, FALSE,
8662 EL_CHAR('B'), -1, -1
8665 Xalpha_c, TRUE, FALSE,
8666 EL_CHAR('C'), -1, -1
8669 Xalpha_d, TRUE, FALSE,
8670 EL_CHAR('D'), -1, -1
8673 Xalpha_e, TRUE, FALSE,
8674 EL_CHAR('E'), -1, -1
8677 Xalpha_f, TRUE, FALSE,
8678 EL_CHAR('F'), -1, -1
8681 Xalpha_g, TRUE, FALSE,
8682 EL_CHAR('G'), -1, -1
8685 Xalpha_h, TRUE, FALSE,
8686 EL_CHAR('H'), -1, -1
8689 Xalpha_i, TRUE, FALSE,
8690 EL_CHAR('I'), -1, -1
8693 Xalpha_j, TRUE, FALSE,
8694 EL_CHAR('J'), -1, -1
8697 Xalpha_k, TRUE, FALSE,
8698 EL_CHAR('K'), -1, -1
8701 Xalpha_l, TRUE, FALSE,
8702 EL_CHAR('L'), -1, -1
8705 Xalpha_m, TRUE, FALSE,
8706 EL_CHAR('M'), -1, -1
8709 Xalpha_n, TRUE, FALSE,
8710 EL_CHAR('N'), -1, -1
8713 Xalpha_o, TRUE, FALSE,
8714 EL_CHAR('O'), -1, -1
8717 Xalpha_p, TRUE, FALSE,
8718 EL_CHAR('P'), -1, -1
8721 Xalpha_q, TRUE, FALSE,
8722 EL_CHAR('Q'), -1, -1
8725 Xalpha_r, TRUE, FALSE,
8726 EL_CHAR('R'), -1, -1
8729 Xalpha_s, TRUE, FALSE,
8730 EL_CHAR('S'), -1, -1
8733 Xalpha_t, TRUE, FALSE,
8734 EL_CHAR('T'), -1, -1
8737 Xalpha_u, TRUE, FALSE,
8738 EL_CHAR('U'), -1, -1
8741 Xalpha_v, TRUE, FALSE,
8742 EL_CHAR('V'), -1, -1
8745 Xalpha_w, TRUE, FALSE,
8746 EL_CHAR('W'), -1, -1
8749 Xalpha_x, TRUE, FALSE,
8750 EL_CHAR('X'), -1, -1
8753 Xalpha_y, TRUE, FALSE,
8754 EL_CHAR('Y'), -1, -1
8757 Xalpha_z, TRUE, FALSE,
8758 EL_CHAR('Z'), -1, -1
8761 Xalpha_arrow_e, TRUE, FALSE,
8762 EL_CHAR('>'), -1, -1
8765 Xalpha_arrow_w, TRUE, FALSE,
8766 EL_CHAR('<'), -1, -1
8769 Xalpha_copyr, TRUE, FALSE,
8770 EL_CHAR('©'), -1, -1
8774 Xboom_bug, FALSE, FALSE,
8775 EL_BUG, ACTION_EXPLODING, -1
8778 Xboom_bomb, FALSE, FALSE,
8779 EL_BOMB, ACTION_EXPLODING, -1
8782 Xboom_android, FALSE, FALSE,
8783 EL_EMC_ANDROID, ACTION_OTHER, -1
8786 Xboom_1, FALSE, FALSE,
8787 EL_DEFAULT, ACTION_EXPLODING, -1
8790 Xboom_2, FALSE, FALSE,
8791 EL_DEFAULT, ACTION_EXPLODING, -1
8794 Znormal, FALSE, FALSE,
8798 Zdynamite, FALSE, FALSE,
8802 Zplayer, FALSE, FALSE,
8806 ZBORDER, FALSE, FALSE,
8816 static struct Mapping_EM_to_RND_player
8825 em_player_mapping_list[] =
8829 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
8833 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
8837 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
8841 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
8845 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
8849 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
8853 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
8857 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
8861 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
8865 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
8869 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
8873 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
8877 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
8881 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
8885 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
8889 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
8893 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
8897 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
8901 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
8905 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
8909 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
8913 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
8917 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
8921 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
8925 EL_PLAYER_1, ACTION_DEFAULT, -1,
8929 EL_PLAYER_2, ACTION_DEFAULT, -1,
8933 EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
8937 EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
8941 EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
8945 EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
8949 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
8953 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
8957 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
8961 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
8965 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
8969 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
8973 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
8977 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
8981 EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
8985 EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
8989 EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
8993 EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
8997 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
9001 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
9005 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
9009 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
9013 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
9017 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
9021 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
9025 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
9029 EL_PLAYER_3, ACTION_DEFAULT, -1,
9033 EL_PLAYER_4, ACTION_DEFAULT, -1,
9042 int map_element_RND_to_EM(int element_rnd)
9044 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
9045 static boolean mapping_initialized = FALSE;
9047 if (!mapping_initialized)
9051 /* return "Xalpha_quest" for all undefined elements in mapping array */
9052 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
9053 mapping_RND_to_EM[i] = Xalpha_quest;
9055 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
9056 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
9057 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
9058 em_object_mapping_list[i].element_em;
9060 mapping_initialized = TRUE;
9063 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
9064 return mapping_RND_to_EM[element_rnd];
9066 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
9071 int map_element_EM_to_RND(int element_em)
9073 static unsigned short mapping_EM_to_RND[TILE_MAX];
9074 static boolean mapping_initialized = FALSE;
9076 if (!mapping_initialized)
9080 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
9081 for (i = 0; i < TILE_MAX; i++)
9082 mapping_EM_to_RND[i] = EL_UNKNOWN;
9084 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
9085 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
9086 em_object_mapping_list[i].element_rnd;
9088 mapping_initialized = TRUE;
9091 if (element_em >= 0 && element_em < TILE_MAX)
9092 return mapping_EM_to_RND[element_em];
9094 Error(ERR_WARN, "invalid EM level element %d", element_em);
9099 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
9101 struct LevelInfo_EM *level_em = level->native_em_level;
9102 struct LEVEL *lev = level_em->lev;
9105 for (i = 0; i < TILE_MAX; i++)
9106 lev->android_array[i] = Xblank;
9108 for (i = 0; i < level->num_android_clone_elements; i++)
9110 int element_rnd = level->android_clone_element[i];
9111 int element_em = map_element_RND_to_EM(element_rnd);
9113 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
9114 if (em_object_mapping_list[j].element_rnd == element_rnd)
9115 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
9119 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
9121 struct LevelInfo_EM *level_em = level->native_em_level;
9122 struct LEVEL *lev = level_em->lev;
9125 level->num_android_clone_elements = 0;
9127 for (i = 0; i < TILE_MAX; i++)
9129 int element_em = lev->android_array[i];
9131 boolean element_found = FALSE;
9133 if (element_em == Xblank)
9136 element_rnd = map_element_EM_to_RND(element_em);
9138 for (j = 0; j < level->num_android_clone_elements; j++)
9139 if (level->android_clone_element[j] == element_rnd)
9140 element_found = TRUE;
9144 level->android_clone_element[level->num_android_clone_elements++] =
9147 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
9152 if (level->num_android_clone_elements == 0)
9154 level->num_android_clone_elements = 1;
9155 level->android_clone_element[0] = EL_EMPTY;
9159 int map_direction_RND_to_EM(int direction)
9161 return (direction == MV_UP ? 0 :
9162 direction == MV_RIGHT ? 1 :
9163 direction == MV_DOWN ? 2 :
9164 direction == MV_LEFT ? 3 :
9168 int map_direction_EM_to_RND(int direction)
9170 return (direction == 0 ? MV_UP :
9171 direction == 1 ? MV_RIGHT :
9172 direction == 2 ? MV_DOWN :
9173 direction == 3 ? MV_LEFT :
9177 int map_element_RND_to_SP(int element_rnd)
9179 int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
9181 if (element_rnd >= EL_SP_START &&
9182 element_rnd <= EL_SP_END)
9183 element_sp = element_rnd - EL_SP_START;
9184 else if (element_rnd == EL_EMPTY_SPACE)
9186 else if (element_rnd == EL_INVISIBLE_WALL)
9192 int map_element_SP_to_RND(int element_sp)
9194 int element_rnd = EL_UNKNOWN;
9196 if (element_sp >= 0x00 &&
9198 element_rnd = EL_SP_START + element_sp;
9199 else if (element_sp == 0x28)
9200 element_rnd = EL_INVISIBLE_WALL;
9205 int map_action_SP_to_RND(int action_sp)
9209 case actActive: return ACTION_ACTIVE;
9210 case actImpact: return ACTION_IMPACT;
9211 case actExploding: return ACTION_EXPLODING;
9212 case actDigging: return ACTION_DIGGING;
9213 case actSnapping: return ACTION_SNAPPING;
9214 case actCollecting: return ACTION_COLLECTING;
9215 case actPassing: return ACTION_PASSING;
9216 case actPushing: return ACTION_PUSHING;
9217 case actDropping: return ACTION_DROPPING;
9219 default: return ACTION_DEFAULT;
9223 int get_next_element(int element)
9227 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
9228 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
9229 case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL;
9230 case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY;
9231 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
9232 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
9233 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
9234 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
9235 case EL_DC_MAGIC_WALL_FILLING: return EL_DC_MAGIC_WALL_FULL;
9236 case EL_DC_MAGIC_WALL_EMPTYING: return EL_DC_MAGIC_WALL_ACTIVE;
9237 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
9239 default: return element;
9244 int el_act_dir2img(int element, int action, int direction)
9246 element = GFX_ELEMENT(element);
9248 if (direction == MV_NONE)
9249 return element_info[element].graphic[action];
9251 direction = MV_DIR_TO_BIT(direction);
9253 return element_info[element].direction_graphic[action][direction];
9256 int el_act_dir2img(int element, int action, int direction)
9258 element = GFX_ELEMENT(element);
9259 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
9261 /* direction_graphic[][] == graphic[] for undefined direction graphics */
9262 return element_info[element].direction_graphic[action][direction];
9267 static int el_act_dir2crm(int element, int action, int direction)
9269 element = GFX_ELEMENT(element);
9271 if (direction == MV_NONE)
9272 return element_info[element].crumbled[action];
9274 direction = MV_DIR_TO_BIT(direction);
9276 return element_info[element].direction_crumbled[action][direction];
9279 static int el_act_dir2crm(int element, int action, int direction)
9281 element = GFX_ELEMENT(element);
9282 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
9284 /* direction_graphic[][] == graphic[] for undefined direction graphics */
9285 return element_info[element].direction_crumbled[action][direction];
9289 int el_act2img(int element, int action)
9291 element = GFX_ELEMENT(element);
9293 return element_info[element].graphic[action];
9296 int el_act2crm(int element, int action)
9298 element = GFX_ELEMENT(element);
9300 return element_info[element].crumbled[action];
9303 int el_dir2img(int element, int direction)
9305 element = GFX_ELEMENT(element);
9307 return el_act_dir2img(element, ACTION_DEFAULT, direction);
9310 int el2baseimg(int element)
9312 return element_info[element].graphic[ACTION_DEFAULT];
9315 int el2img(int element)
9317 element = GFX_ELEMENT(element);
9319 return element_info[element].graphic[ACTION_DEFAULT];
9322 int el2edimg(int element)
9324 element = GFX_ELEMENT(element);
9326 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
9329 int el2preimg(int element)
9331 element = GFX_ELEMENT(element);
9333 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
9336 int el2panelimg(int element)
9338 element = GFX_ELEMENT(element);
9340 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PANEL];
9343 int font2baseimg(int font_nr)
9345 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
9348 int getBeltNrFromBeltElement(int element)
9350 return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 :
9351 element < EL_CONVEYOR_BELT_3_LEFT ? 1 :
9352 element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3);
9355 int getBeltNrFromBeltActiveElement(int element)
9357 return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 :
9358 element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 :
9359 element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3);
9362 int getBeltNrFromBeltSwitchElement(int element)
9364 return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 :
9365 element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 :
9366 element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3);
9369 int getBeltDirNrFromBeltElement(int element)
9371 static int belt_base_element[4] =
9373 EL_CONVEYOR_BELT_1_LEFT,
9374 EL_CONVEYOR_BELT_2_LEFT,
9375 EL_CONVEYOR_BELT_3_LEFT,
9376 EL_CONVEYOR_BELT_4_LEFT
9379 int belt_nr = getBeltNrFromBeltElement(element);
9380 int belt_dir_nr = element - belt_base_element[belt_nr];
9382 return (belt_dir_nr % 3);
9385 int getBeltDirNrFromBeltSwitchElement(int element)
9387 static int belt_base_element[4] =
9389 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
9390 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
9391 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
9392 EL_CONVEYOR_BELT_4_SWITCH_LEFT
9395 int belt_nr = getBeltNrFromBeltSwitchElement(element);
9396 int belt_dir_nr = element - belt_base_element[belt_nr];
9398 return (belt_dir_nr % 3);
9401 int getBeltDirFromBeltElement(int element)
9403 static int belt_move_dir[3] =
9410 int belt_dir_nr = getBeltDirNrFromBeltElement(element);
9412 return belt_move_dir[belt_dir_nr];
9415 int getBeltDirFromBeltSwitchElement(int element)
9417 static int belt_move_dir[3] =
9424 int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(element);
9426 return belt_move_dir[belt_dir_nr];
9429 int getBeltElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
9431 static int belt_base_element[4] =
9433 EL_CONVEYOR_BELT_1_LEFT,
9434 EL_CONVEYOR_BELT_2_LEFT,
9435 EL_CONVEYOR_BELT_3_LEFT,
9436 EL_CONVEYOR_BELT_4_LEFT
9439 return belt_base_element[belt_nr] + belt_dir_nr;
9442 int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
9444 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
9446 return getBeltElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
9449 int getBeltSwitchElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
9451 static int belt_base_element[4] =
9453 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
9454 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
9455 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
9456 EL_CONVEYOR_BELT_4_SWITCH_LEFT
9459 return belt_base_element[belt_nr] + belt_dir_nr;
9462 int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
9464 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
9466 return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
9470 boolean getTeamMode_EM()
9472 return game.team_mode;
9475 int getNumActivePlayers_EM()
9478 int num_players = 0;
9482 return (setup.team_mode ? MAX_PLAYERS : 1);
9484 for (i = 0; i < MAX_PLAYERS; i++)
9485 if (tape.player_participates[i])
9488 return (num_players > 1 ? MAX_PLAYERS : 1);
9492 int num_players = 0;
9495 /* when recording game, activate all connected players */
9499 for (i = 0; i < MAX_PLAYERS; i++)
9500 if (tape.player_participates[i])
9508 int getGameFrameDelay_EM(int native_em_game_frame_delay)
9510 int game_frame_delay_value;
9512 game_frame_delay_value =
9513 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
9514 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
9517 if (tape.playing && tape.warp_forward && !tape.pausing)
9518 game_frame_delay_value = 0;
9520 return game_frame_delay_value;
9523 unsigned int InitRND(int seed)
9525 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
9526 return InitEngineRandom_EM(seed);
9527 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
9528 return InitEngineRandom_SP(seed);
9530 return InitEngineRandom_RND(seed);
9534 static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
9535 static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
9538 inline static int get_effective_element_EM(int tile, int frame_em)
9540 int element = object_mapping[tile].element_rnd;
9541 int action = object_mapping[tile].action;
9542 boolean is_backside = object_mapping[tile].is_backside;
9543 boolean action_removing = (action == ACTION_DIGGING ||
9544 action == ACTION_SNAPPING ||
9545 action == ACTION_COLLECTING);
9551 case Yacid_splash_eB:
9552 case Yacid_splash_wB:
9553 return (frame_em > 5 ? EL_EMPTY : element);
9557 case Ydiamond_stone:
9558 // if (!game.use_native_emc_graphics_engine)
9566 else /* frame_em == 7 */
9570 case Yacid_splash_eB:
9571 case Yacid_splash_wB:
9574 case Yemerald_stone:
9577 case Ydiamond_stone:
9581 case Xdrip_stretchB:
9600 case Xsand_stonein_1:
9601 case Xsand_stonein_2:
9602 case Xsand_stonein_3:
9603 case Xsand_stonein_4:
9607 return (is_backside || action_removing ? EL_EMPTY : element);
9612 inline static boolean check_linear_animation_EM(int tile)
9616 case Xsand_stonesand_1:
9617 case Xsand_stonesand_quickout_1:
9618 case Xsand_sandstone_1:
9619 case Xsand_stonein_1:
9620 case Xsand_stoneout_1:
9640 case Yacid_splash_eB:
9641 case Yacid_splash_wB:
9642 case Yemerald_stone:
9650 inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
9651 boolean has_crumbled_graphics,
9652 int crumbled, int sync_frame)
9654 /* if element can be crumbled, but certain action graphics are just empty
9655 space (like instantly snapping sand to empty space in 1 frame), do not
9656 treat these empty space graphics as crumbled graphics in EMC engine */
9657 if (crumbled == IMG_EMPTY_SPACE)
9658 has_crumbled_graphics = FALSE;
9660 if (has_crumbled_graphics)
9662 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9663 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
9664 g_crumbled->anim_delay,
9665 g_crumbled->anim_mode,
9666 g_crumbled->anim_start_frame,
9669 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
9670 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
9672 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
9674 g_em->has_crumbled_graphics = TRUE;
9678 g_em->crumbled_bitmap = NULL;
9679 g_em->crumbled_src_x = 0;
9680 g_em->crumbled_src_y = 0;
9681 g_em->crumbled_border_size = 0;
9683 g_em->has_crumbled_graphics = FALSE;
9687 void ResetGfxAnimation_EM(int x, int y, int tile)
9692 void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
9693 int tile, int frame_em, int x, int y)
9695 int action = object_mapping[tile].action;
9697 int direction = object_mapping[tile].direction;
9698 int effective_element = get_effective_element_EM(tile, frame_em);
9699 int graphic = (direction == MV_NONE ?
9700 el_act2img(effective_element, action) :
9701 el_act_dir2img(effective_element, action, direction));
9702 struct GraphicInfo *g = &graphic_info[graphic];
9705 boolean action_removing = (action == ACTION_DIGGING ||
9706 action == ACTION_SNAPPING ||
9707 action == ACTION_COLLECTING);
9708 boolean action_moving = (action == ACTION_FALLING ||
9709 action == ACTION_MOVING ||
9710 action == ACTION_PUSHING ||
9711 action == ACTION_EATING ||
9712 action == ACTION_FILLING ||
9713 action == ACTION_EMPTYING);
9714 boolean action_falling = (action == ACTION_FALLING ||
9715 action == ACTION_FILLING ||
9716 action == ACTION_EMPTYING);
9718 /* special case: graphic uses "2nd movement tile" and has defined
9719 7 frames for movement animation (or less) => use default graphic
9720 for last (8th) frame which ends the movement animation */
9721 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9723 action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
9724 graphic = (direction == MV_NONE ?
9725 el_act2img(effective_element, action) :
9726 el_act_dir2img(effective_element, action, direction));
9728 g = &graphic_info[graphic];
9732 if (tile == Xsand_stonesand_1 ||
9733 tile == Xsand_stonesand_2 ||
9734 tile == Xsand_stonesand_3 ||
9735 tile == Xsand_stonesand_4)
9736 printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9740 if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
9744 // printf("::: resetting... [%d]\n", tile);
9747 if (action_removing || check_linear_animation_EM(tile))
9749 GfxFrame[x][y] = frame_em;
9751 // printf("::: resetting... [%d]\n", tile);
9754 else if (action_moving)
9756 boolean is_backside = object_mapping[tile].is_backside;
9760 int direction = object_mapping[tile].direction;
9761 int move_dir = (action_falling ? MV_DOWN : direction);
9766 /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
9767 if (g->double_movement && frame_em == 0)
9771 // printf("::: resetting... [%d]\n", tile);
9775 if (move_dir == MV_LEFT)
9776 GfxFrame[x - 1][y] = GfxFrame[x][y];
9777 else if (move_dir == MV_RIGHT)
9778 GfxFrame[x + 1][y] = GfxFrame[x][y];
9779 else if (move_dir == MV_UP)
9780 GfxFrame[x][y - 1] = GfxFrame[x][y];
9781 else if (move_dir == MV_DOWN)
9782 GfxFrame[x][y + 1] = GfxFrame[x][y];
9789 /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
9790 if (tile == Xsand_stonesand_quickout_1 ||
9791 tile == Xsand_stonesand_quickout_2)
9796 if (tile == Xsand_stonesand_1 ||
9797 tile == Xsand_stonesand_2 ||
9798 tile == Xsand_stonesand_3 ||
9799 tile == Xsand_stonesand_4)
9800 printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9804 if (graphic_info[graphic].anim_global_sync)
9805 sync_frame = FrameCounter;
9806 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9807 sync_frame = GfxFrame[x][y];
9809 sync_frame = 0; /* playfield border (pseudo steel) */
9811 SetRandomAnimationValue(x, y);
9813 int frame = getAnimationFrame(g->anim_frames,
9816 g->anim_start_frame,
9819 g_em->unique_identifier =
9820 (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
9824 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
9825 int tile, int frame_em, int x, int y)
9827 int action = object_mapping[tile].action;
9828 int direction = object_mapping[tile].direction;
9829 boolean is_backside = object_mapping[tile].is_backside;
9830 int effective_element = get_effective_element_EM(tile, frame_em);
9832 int effective_action = action;
9834 int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
9836 int graphic = (direction == MV_NONE ?
9837 el_act2img(effective_element, effective_action) :
9838 el_act_dir2img(effective_element, effective_action,
9840 int crumbled = (direction == MV_NONE ?
9841 el_act2crm(effective_element, effective_action) :
9842 el_act_dir2crm(effective_element, effective_action,
9844 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
9845 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
9846 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
9847 struct GraphicInfo *g = &graphic_info[graphic];
9849 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9853 /* special case: graphic uses "2nd movement tile" and has defined
9854 7 frames for movement animation (or less) => use default graphic
9855 for last (8th) frame which ends the movement animation */
9856 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9858 effective_action = ACTION_DEFAULT;
9859 graphic = (direction == MV_NONE ?
9860 el_act2img(effective_element, effective_action) :
9861 el_act_dir2img(effective_element, effective_action,
9863 crumbled = (direction == MV_NONE ?
9864 el_act2crm(effective_element, effective_action) :
9865 el_act_dir2crm(effective_element, effective_action,
9868 g = &graphic_info[graphic];
9878 if (frame_em == 0) /* reset animation frame for certain elements */
9880 if (check_linear_animation_EM(tile))
9885 if (graphic_info[graphic].anim_global_sync)
9886 sync_frame = FrameCounter;
9887 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9888 sync_frame = GfxFrame[x][y];
9890 sync_frame = 0; /* playfield border (pseudo steel) */
9892 SetRandomAnimationValue(x, y);
9897 int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
9898 i == Xdrip_stretchB ? 7 :
9899 i == Ydrip_s2 ? j + 8 :
9900 i == Ydrip_s2B ? j + 8 :
9909 i == Xfake_acid_1 ? 0 :
9910 i == Xfake_acid_2 ? 10 :
9911 i == Xfake_acid_3 ? 20 :
9912 i == Xfake_acid_4 ? 30 :
9913 i == Xfake_acid_5 ? 40 :
9914 i == Xfake_acid_6 ? 50 :
9915 i == Xfake_acid_7 ? 60 :
9916 i == Xfake_acid_8 ? 70 :
9918 i == Xball_2B ? j + 8 :
9919 i == Yball_eat ? j + 1 :
9920 i == Ykey_1_eat ? j + 1 :
9921 i == Ykey_2_eat ? j + 1 :
9922 i == Ykey_3_eat ? j + 1 :
9923 i == Ykey_4_eat ? j + 1 :
9924 i == Ykey_5_eat ? j + 1 :
9925 i == Ykey_6_eat ? j + 1 :
9926 i == Ykey_7_eat ? j + 1 :
9927 i == Ykey_8_eat ? j + 1 :
9928 i == Ylenses_eat ? j + 1 :
9929 i == Ymagnify_eat ? j + 1 :
9930 i == Ygrass_eat ? j + 1 :
9931 i == Ydirt_eat ? j + 1 :
9932 i == Xamoeba_1 ? 0 :
9933 i == Xamoeba_2 ? 1 :
9934 i == Xamoeba_3 ? 2 :
9935 i == Xamoeba_4 ? 3 :
9936 i == Xamoeba_5 ? 0 :
9937 i == Xamoeba_6 ? 1 :
9938 i == Xamoeba_7 ? 2 :
9939 i == Xamoeba_8 ? 3 :
9940 i == Xexit_2 ? j + 8 :
9941 i == Xexit_3 ? j + 16 :
9942 i == Xdynamite_1 ? 0 :
9943 i == Xdynamite_2 ? 8 :
9944 i == Xdynamite_3 ? 16 :
9945 i == Xdynamite_4 ? 24 :
9946 i == Xsand_stonein_1 ? j + 1 :
9947 i == Xsand_stonein_2 ? j + 9 :
9948 i == Xsand_stonein_3 ? j + 17 :
9949 i == Xsand_stonein_4 ? j + 25 :
9950 i == Xsand_stoneout_1 && j == 0 ? 0 :
9951 i == Xsand_stoneout_1 && j == 1 ? 0 :
9952 i == Xsand_stoneout_1 && j == 2 ? 1 :
9953 i == Xsand_stoneout_1 && j == 3 ? 2 :
9954 i == Xsand_stoneout_1 && j == 4 ? 2 :
9955 i == Xsand_stoneout_1 && j == 5 ? 3 :
9956 i == Xsand_stoneout_1 && j == 6 ? 4 :
9957 i == Xsand_stoneout_1 && j == 7 ? 4 :
9958 i == Xsand_stoneout_2 && j == 0 ? 5 :
9959 i == Xsand_stoneout_2 && j == 1 ? 6 :
9960 i == Xsand_stoneout_2 && j == 2 ? 7 :
9961 i == Xsand_stoneout_2 && j == 3 ? 8 :
9962 i == Xsand_stoneout_2 && j == 4 ? 9 :
9963 i == Xsand_stoneout_2 && j == 5 ? 11 :
9964 i == Xsand_stoneout_2 && j == 6 ? 13 :
9965 i == Xsand_stoneout_2 && j == 7 ? 15 :
9966 i == Xboom_bug && j == 1 ? 2 :
9967 i == Xboom_bug && j == 2 ? 2 :
9968 i == Xboom_bug && j == 3 ? 4 :
9969 i == Xboom_bug && j == 4 ? 4 :
9970 i == Xboom_bug && j == 5 ? 2 :
9971 i == Xboom_bug && j == 6 ? 2 :
9972 i == Xboom_bug && j == 7 ? 0 :
9973 i == Xboom_bomb && j == 1 ? 2 :
9974 i == Xboom_bomb && j == 2 ? 2 :
9975 i == Xboom_bomb && j == 3 ? 4 :
9976 i == Xboom_bomb && j == 4 ? 4 :
9977 i == Xboom_bomb && j == 5 ? 2 :
9978 i == Xboom_bomb && j == 6 ? 2 :
9979 i == Xboom_bomb && j == 7 ? 0 :
9980 i == Xboom_android && j == 7 ? 6 :
9981 i == Xboom_1 && j == 1 ? 2 :
9982 i == Xboom_1 && j == 2 ? 2 :
9983 i == Xboom_1 && j == 3 ? 4 :
9984 i == Xboom_1 && j == 4 ? 4 :
9985 i == Xboom_1 && j == 5 ? 6 :
9986 i == Xboom_1 && j == 6 ? 6 :
9987 i == Xboom_1 && j == 7 ? 8 :
9988 i == Xboom_2 && j == 0 ? 8 :
9989 i == Xboom_2 && j == 1 ? 8 :
9990 i == Xboom_2 && j == 2 ? 10 :
9991 i == Xboom_2 && j == 3 ? 10 :
9992 i == Xboom_2 && j == 4 ? 10 :
9993 i == Xboom_2 && j == 5 ? 12 :
9994 i == Xboom_2 && j == 6 ? 12 :
9995 i == Xboom_2 && j == 7 ? 12 :
9997 special_animation && j == 4 ? 3 :
9998 effective_action != action ? 0 :
10004 int xxx_effective_action;
10005 int xxx_has_action_graphics;
10008 int element = object_mapping[i].element_rnd;
10009 int action = object_mapping[i].action;
10010 int direction = object_mapping[i].direction;
10011 boolean is_backside = object_mapping[i].is_backside;
10013 boolean action_removing = (action == ACTION_DIGGING ||
10014 action == ACTION_SNAPPING ||
10015 action == ACTION_COLLECTING);
10017 boolean action_exploding = ((action == ACTION_EXPLODING ||
10018 action == ACTION_SMASHED_BY_ROCK ||
10019 action == ACTION_SMASHED_BY_SPRING) &&
10020 element != EL_DIAMOND);
10021 boolean action_active = (action == ACTION_ACTIVE);
10022 boolean action_other = (action == ACTION_OTHER);
10026 int effective_element = get_effective_element_EM(i, j);
10028 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
10029 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
10031 i == Xdrip_stretch ? element :
10032 i == Xdrip_stretchB ? element :
10033 i == Ydrip_s1 ? element :
10034 i == Ydrip_s1B ? element :
10035 i == Xball_1B ? element :
10036 i == Xball_2 ? element :
10037 i == Xball_2B ? element :
10038 i == Yball_eat ? element :
10039 i == Ykey_1_eat ? element :
10040 i == Ykey_2_eat ? element :
10041 i == Ykey_3_eat ? element :
10042 i == Ykey_4_eat ? element :
10043 i == Ykey_5_eat ? element :
10044 i == Ykey_6_eat ? element :
10045 i == Ykey_7_eat ? element :
10046 i == Ykey_8_eat ? element :
10047 i == Ylenses_eat ? element :
10048 i == Ymagnify_eat ? element :
10049 i == Ygrass_eat ? element :
10050 i == Ydirt_eat ? element :
10051 i == Yemerald_stone ? EL_EMERALD :
10052 i == Ydiamond_stone ? EL_ROCK :
10053 i == Xsand_stonein_1 ? element :
10054 i == Xsand_stonein_2 ? element :
10055 i == Xsand_stonein_3 ? element :
10056 i == Xsand_stonein_4 ? element :
10057 is_backside ? EL_EMPTY :
10058 action_removing ? EL_EMPTY :
10061 int effective_action = (j < 7 ? action :
10062 i == Xdrip_stretch ? action :
10063 i == Xdrip_stretchB ? action :
10064 i == Ydrip_s1 ? action :
10065 i == Ydrip_s1B ? action :
10066 i == Xball_1B ? action :
10067 i == Xball_2 ? action :
10068 i == Xball_2B ? action :
10069 i == Yball_eat ? action :
10070 i == Ykey_1_eat ? action :
10071 i == Ykey_2_eat ? action :
10072 i == Ykey_3_eat ? action :
10073 i == Ykey_4_eat ? action :
10074 i == Ykey_5_eat ? action :
10075 i == Ykey_6_eat ? action :
10076 i == Ykey_7_eat ? action :
10077 i == Ykey_8_eat ? action :
10078 i == Ylenses_eat ? action :
10079 i == Ymagnify_eat ? action :
10080 i == Ygrass_eat ? action :
10081 i == Ydirt_eat ? action :
10082 i == Xsand_stonein_1 ? action :
10083 i == Xsand_stonein_2 ? action :
10084 i == Xsand_stonein_3 ? action :
10085 i == Xsand_stonein_4 ? action :
10086 i == Xsand_stoneout_1 ? action :
10087 i == Xsand_stoneout_2 ? action :
10088 i == Xboom_android ? ACTION_EXPLODING :
10089 action_exploding ? ACTION_EXPLODING :
10090 action_active ? action :
10091 action_other ? action :
10093 int graphic = (el_act_dir2img(effective_element, effective_action,
10095 int crumbled = (el_act_dir2crm(effective_element, effective_action,
10097 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
10098 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
10099 boolean has_action_graphics = (graphic != base_graphic);
10100 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
10101 struct GraphicInfo *g = &graphic_info[graphic];
10103 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
10105 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10106 Bitmap *src_bitmap;
10108 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
10109 boolean special_animation = (action != ACTION_DEFAULT &&
10110 g->anim_frames == 3 &&
10111 g->anim_delay == 2 &&
10112 g->anim_mode & ANIM_LINEAR);
10113 xxx_sync_frame = (i == Xdrip_stretch ? 7 :
10114 i == Xdrip_stretchB ? 7 :
10115 i == Ydrip_s2 ? j + 8 :
10116 i == Ydrip_s2B ? j + 8 :
10118 i == Xacid_2 ? 10 :
10119 i == Xacid_3 ? 20 :
10120 i == Xacid_4 ? 30 :
10121 i == Xacid_5 ? 40 :
10122 i == Xacid_6 ? 50 :
10123 i == Xacid_7 ? 60 :
10124 i == Xacid_8 ? 70 :
10125 i == Xfake_acid_1 ? 0 :
10126 i == Xfake_acid_2 ? 10 :
10127 i == Xfake_acid_3 ? 20 :
10128 i == Xfake_acid_4 ? 30 :
10129 i == Xfake_acid_5 ? 40 :
10130 i == Xfake_acid_6 ? 50 :
10131 i == Xfake_acid_7 ? 60 :
10132 i == Xfake_acid_8 ? 70 :
10134 i == Xball_2B ? j + 8 :
10135 i == Yball_eat ? j + 1 :
10136 i == Ykey_1_eat ? j + 1 :
10137 i == Ykey_2_eat ? j + 1 :
10138 i == Ykey_3_eat ? j + 1 :
10139 i == Ykey_4_eat ? j + 1 :
10140 i == Ykey_5_eat ? j + 1 :
10141 i == Ykey_6_eat ? j + 1 :
10142 i == Ykey_7_eat ? j + 1 :
10143 i == Ykey_8_eat ? j + 1 :
10144 i == Ylenses_eat ? j + 1 :
10145 i == Ymagnify_eat ? j + 1 :
10146 i == Ygrass_eat ? j + 1 :
10147 i == Ydirt_eat ? j + 1 :
10148 i == Xamoeba_1 ? 0 :
10149 i == Xamoeba_2 ? 1 :
10150 i == Xamoeba_3 ? 2 :
10151 i == Xamoeba_4 ? 3 :
10152 i == Xamoeba_5 ? 0 :
10153 i == Xamoeba_6 ? 1 :
10154 i == Xamoeba_7 ? 2 :
10155 i == Xamoeba_8 ? 3 :
10156 i == Xexit_2 ? j + 8 :
10157 i == Xexit_3 ? j + 16 :
10158 i == Xdynamite_1 ? 0 :
10159 i == Xdynamite_2 ? 8 :
10160 i == Xdynamite_3 ? 16 :
10161 i == Xdynamite_4 ? 24 :
10162 i == Xsand_stonein_1 ? j + 1 :
10163 i == Xsand_stonein_2 ? j + 9 :
10164 i == Xsand_stonein_3 ? j + 17 :
10165 i == Xsand_stonein_4 ? j + 25 :
10166 i == Xsand_stoneout_1 && j == 0 ? 0 :
10167 i == Xsand_stoneout_1 && j == 1 ? 0 :
10168 i == Xsand_stoneout_1 && j == 2 ? 1 :
10169 i == Xsand_stoneout_1 && j == 3 ? 2 :
10170 i == Xsand_stoneout_1 && j == 4 ? 2 :
10171 i == Xsand_stoneout_1 && j == 5 ? 3 :
10172 i == Xsand_stoneout_1 && j == 6 ? 4 :
10173 i == Xsand_stoneout_1 && j == 7 ? 4 :
10174 i == Xsand_stoneout_2 && j == 0 ? 5 :
10175 i == Xsand_stoneout_2 && j == 1 ? 6 :
10176 i == Xsand_stoneout_2 && j == 2 ? 7 :
10177 i == Xsand_stoneout_2 && j == 3 ? 8 :
10178 i == Xsand_stoneout_2 && j == 4 ? 9 :
10179 i == Xsand_stoneout_2 && j == 5 ? 11 :
10180 i == Xsand_stoneout_2 && j == 6 ? 13 :
10181 i == Xsand_stoneout_2 && j == 7 ? 15 :
10182 i == Xboom_bug && j == 1 ? 2 :
10183 i == Xboom_bug && j == 2 ? 2 :
10184 i == Xboom_bug && j == 3 ? 4 :
10185 i == Xboom_bug && j == 4 ? 4 :
10186 i == Xboom_bug && j == 5 ? 2 :
10187 i == Xboom_bug && j == 6 ? 2 :
10188 i == Xboom_bug && j == 7 ? 0 :
10189 i == Xboom_bomb && j == 1 ? 2 :
10190 i == Xboom_bomb && j == 2 ? 2 :
10191 i == Xboom_bomb && j == 3 ? 4 :
10192 i == Xboom_bomb && j == 4 ? 4 :
10193 i == Xboom_bomb && j == 5 ? 2 :
10194 i == Xboom_bomb && j == 6 ? 2 :
10195 i == Xboom_bomb && j == 7 ? 0 :
10196 i == Xboom_android && j == 7 ? 6 :
10197 i == Xboom_1 && j == 1 ? 2 :
10198 i == Xboom_1 && j == 2 ? 2 :
10199 i == Xboom_1 && j == 3 ? 4 :
10200 i == Xboom_1 && j == 4 ? 4 :
10201 i == Xboom_1 && j == 5 ? 6 :
10202 i == Xboom_1 && j == 6 ? 6 :
10203 i == Xboom_1 && j == 7 ? 8 :
10204 i == Xboom_2 && j == 0 ? 8 :
10205 i == Xboom_2 && j == 1 ? 8 :
10206 i == Xboom_2 && j == 2 ? 10 :
10207 i == Xboom_2 && j == 3 ? 10 :
10208 i == Xboom_2 && j == 4 ? 10 :
10209 i == Xboom_2 && j == 5 ? 12 :
10210 i == Xboom_2 && j == 6 ? 12 :
10211 i == Xboom_2 && j == 7 ? 12 :
10212 special_animation && j == 4 ? 3 :
10213 effective_action != action ? 0 :
10216 xxx_effective_action = effective_action;
10217 xxx_has_action_graphics = has_action_graphics;
10222 int frame = getAnimationFrame(g->anim_frames,
10225 g->anim_start_frame,
10239 int old_src_x = g_em->src_x;
10240 int old_src_y = g_em->src_y;
10244 getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
10245 g->double_movement && is_backside);
10247 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
10248 &g_em->src_x, &g_em->src_y, FALSE);
10253 if (tile == Ydiamond_stone)
10254 printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n",
10259 g->anim_start_frame,
10262 g_em->src_x, g_em->src_y,
10263 g_em->src_offset_x, g_em->src_offset_y,
10264 g_em->dst_offset_x, g_em->dst_offset_y,
10276 if (graphic == IMG_BUG_MOVING_RIGHT)
10277 printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
10278 g->double_movement, is_backside,
10279 old_src_x, old_src_y, g_em->src_x, g_em->src_y);
10287 g_em->src_offset_x = 0;
10288 g_em->src_offset_y = 0;
10289 g_em->dst_offset_x = 0;
10290 g_em->dst_offset_y = 0;
10291 g_em->width = TILEX;
10292 g_em->height = TILEY;
10294 g_em->preserve_background = FALSE;
10297 /* (updating the "crumbled" graphic definitions is probably not really needed,
10298 as animations for crumbled graphics can't be longer than one EMC cycle) */
10300 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10305 g_em->crumbled_bitmap = NULL;
10306 g_em->crumbled_src_x = 0;
10307 g_em->crumbled_src_y = 0;
10309 g_em->has_crumbled_graphics = FALSE;
10311 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10313 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10314 g_crumbled->anim_delay,
10315 g_crumbled->anim_mode,
10316 g_crumbled->anim_start_frame,
10319 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
10320 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
10322 g_em->has_crumbled_graphics = TRUE;
10328 int effective_action = xxx_effective_action;
10329 int has_action_graphics = xxx_has_action_graphics;
10331 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10332 effective_action == ACTION_MOVING ||
10333 effective_action == ACTION_PUSHING ||
10334 effective_action == ACTION_EATING)) ||
10335 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10336 effective_action == ACTION_EMPTYING)))
10339 (effective_action == ACTION_FALLING ||
10340 effective_action == ACTION_FILLING ||
10341 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10342 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10343 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10344 int num_steps = (i == Ydrip_s1 ? 16 :
10345 i == Ydrip_s1B ? 16 :
10346 i == Ydrip_s2 ? 16 :
10347 i == Ydrip_s2B ? 16 :
10348 i == Xsand_stonein_1 ? 32 :
10349 i == Xsand_stonein_2 ? 32 :
10350 i == Xsand_stonein_3 ? 32 :
10351 i == Xsand_stonein_4 ? 32 :
10352 i == Xsand_stoneout_1 ? 16 :
10353 i == Xsand_stoneout_2 ? 16 : 8);
10354 int cx = ABS(dx) * (TILEX / num_steps);
10355 int cy = ABS(dy) * (TILEY / num_steps);
10356 int step_frame = (i == Ydrip_s2 ? j + 8 :
10357 i == Ydrip_s2B ? j + 8 :
10358 i == Xsand_stonein_2 ? j + 8 :
10359 i == Xsand_stonein_3 ? j + 16 :
10360 i == Xsand_stonein_4 ? j + 24 :
10361 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10362 int step = (is_backside ? step_frame : num_steps - step_frame);
10364 if (is_backside) /* tile where movement starts */
10366 if (dx < 0 || dy < 0)
10368 g_em->src_offset_x = cx * step;
10369 g_em->src_offset_y = cy * step;
10373 g_em->dst_offset_x = cx * step;
10374 g_em->dst_offset_y = cy * step;
10377 else /* tile where movement ends */
10379 if (dx < 0 || dy < 0)
10381 g_em->dst_offset_x = cx * step;
10382 g_em->dst_offset_y = cy * step;
10386 g_em->src_offset_x = cx * step;
10387 g_em->src_offset_y = cy * step;
10391 g_em->width = TILEX - cx * step;
10392 g_em->height = TILEY - cy * step;
10395 /* create unique graphic identifier to decide if tile must be redrawn */
10396 /* bit 31 - 16 (16 bit): EM style graphic
10397 bit 15 - 12 ( 4 bit): EM style frame
10398 bit 11 - 6 ( 6 bit): graphic width
10399 bit 5 - 0 ( 6 bit): graphic height */
10400 g_em->unique_identifier =
10401 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10407 void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
10408 int player_nr, int anim, int frame_em)
10410 int element = player_mapping[player_nr][anim].element_rnd;
10411 int action = player_mapping[player_nr][anim].action;
10412 int direction = player_mapping[player_nr][anim].direction;
10413 int graphic = (direction == MV_NONE ?
10414 el_act2img(element, action) :
10415 el_act_dir2img(element, action, direction));
10416 struct GraphicInfo *g = &graphic_info[graphic];
10419 InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
10421 stored_player[player_nr].StepFrame = frame_em;
10423 sync_frame = stored_player[player_nr].Frame;
10425 int frame = getAnimationFrame(g->anim_frames,
10428 g->anim_start_frame,
10431 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
10432 &g_em->src_x, &g_em->src_y, FALSE);
10435 printf("::: %d: %d, %d [%d]\n",
10437 stored_player[player_nr].Frame,
10438 stored_player[player_nr].StepFrame,
10443 void InitGraphicInfo_EM(void)
10446 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
10447 struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
10452 int num_em_gfx_errors = 0;
10454 if (graphic_info_em_object[0][0].bitmap == NULL)
10456 /* EM graphics not yet initialized in em_open_all() */
10461 printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
10464 /* always start with reliable default values */
10465 for (i = 0; i < TILE_MAX; i++)
10467 object_mapping[i].element_rnd = EL_UNKNOWN;
10468 object_mapping[i].is_backside = FALSE;
10469 object_mapping[i].action = ACTION_DEFAULT;
10470 object_mapping[i].direction = MV_NONE;
10473 /* always start with reliable default values */
10474 for (p = 0; p < MAX_PLAYERS; p++)
10476 for (i = 0; i < SPR_MAX; i++)
10478 player_mapping[p][i].element_rnd = EL_UNKNOWN;
10479 player_mapping[p][i].action = ACTION_DEFAULT;
10480 player_mapping[p][i].direction = MV_NONE;
10484 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
10486 int e = em_object_mapping_list[i].element_em;
10488 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
10489 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
10491 if (em_object_mapping_list[i].action != -1)
10492 object_mapping[e].action = em_object_mapping_list[i].action;
10494 if (em_object_mapping_list[i].direction != -1)
10495 object_mapping[e].direction =
10496 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
10499 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
10501 int a = em_player_mapping_list[i].action_em;
10502 int p = em_player_mapping_list[i].player_nr;
10504 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
10506 if (em_player_mapping_list[i].action != -1)
10507 player_mapping[p][a].action = em_player_mapping_list[i].action;
10509 if (em_player_mapping_list[i].direction != -1)
10510 player_mapping[p][a].direction =
10511 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
10514 for (i = 0; i < TILE_MAX; i++)
10516 int element = object_mapping[i].element_rnd;
10517 int action = object_mapping[i].action;
10518 int direction = object_mapping[i].direction;
10519 boolean is_backside = object_mapping[i].is_backside;
10521 boolean action_removing = (action == ACTION_DIGGING ||
10522 action == ACTION_SNAPPING ||
10523 action == ACTION_COLLECTING);
10525 boolean action_exploding = ((action == ACTION_EXPLODING ||
10526 action == ACTION_SMASHED_BY_ROCK ||
10527 action == ACTION_SMASHED_BY_SPRING) &&
10528 element != EL_DIAMOND);
10529 boolean action_active = (action == ACTION_ACTIVE);
10530 boolean action_other = (action == ACTION_OTHER);
10532 for (j = 0; j < 8; j++)
10535 int effective_element = get_effective_element_EM(i, j);
10537 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
10538 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
10540 i == Xdrip_stretch ? element :
10541 i == Xdrip_stretchB ? element :
10542 i == Ydrip_s1 ? element :
10543 i == Ydrip_s1B ? element :
10544 i == Xball_1B ? element :
10545 i == Xball_2 ? element :
10546 i == Xball_2B ? element :
10547 i == Yball_eat ? element :
10548 i == Ykey_1_eat ? element :
10549 i == Ykey_2_eat ? element :
10550 i == Ykey_3_eat ? element :
10551 i == Ykey_4_eat ? element :
10552 i == Ykey_5_eat ? element :
10553 i == Ykey_6_eat ? element :
10554 i == Ykey_7_eat ? element :
10555 i == Ykey_8_eat ? element :
10556 i == Ylenses_eat ? element :
10557 i == Ymagnify_eat ? element :
10558 i == Ygrass_eat ? element :
10559 i == Ydirt_eat ? element :
10560 i == Yemerald_stone ? EL_EMERALD :
10561 i == Ydiamond_stone ? EL_ROCK :
10562 i == Xsand_stonein_1 ? element :
10563 i == Xsand_stonein_2 ? element :
10564 i == Xsand_stonein_3 ? element :
10565 i == Xsand_stonein_4 ? element :
10566 is_backside ? EL_EMPTY :
10567 action_removing ? EL_EMPTY :
10570 int effective_action = (j < 7 ? action :
10571 i == Xdrip_stretch ? action :
10572 i == Xdrip_stretchB ? action :
10573 i == Ydrip_s1 ? action :
10574 i == Ydrip_s1B ? action :
10575 i == Xball_1B ? action :
10576 i == Xball_2 ? action :
10577 i == Xball_2B ? action :
10578 i == Yball_eat ? action :
10579 i == Ykey_1_eat ? action :
10580 i == Ykey_2_eat ? action :
10581 i == Ykey_3_eat ? action :
10582 i == Ykey_4_eat ? action :
10583 i == Ykey_5_eat ? action :
10584 i == Ykey_6_eat ? action :
10585 i == Ykey_7_eat ? action :
10586 i == Ykey_8_eat ? action :
10587 i == Ylenses_eat ? action :
10588 i == Ymagnify_eat ? action :
10589 i == Ygrass_eat ? action :
10590 i == Ydirt_eat ? action :
10591 i == Xsand_stonein_1 ? action :
10592 i == Xsand_stonein_2 ? action :
10593 i == Xsand_stonein_3 ? action :
10594 i == Xsand_stonein_4 ? action :
10595 i == Xsand_stoneout_1 ? action :
10596 i == Xsand_stoneout_2 ? action :
10597 i == Xboom_android ? ACTION_EXPLODING :
10598 action_exploding ? ACTION_EXPLODING :
10599 action_active ? action :
10600 action_other ? action :
10602 int graphic = (el_act_dir2img(effective_element, effective_action,
10604 int crumbled = (el_act_dir2crm(effective_element, effective_action,
10606 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
10607 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
10608 boolean has_action_graphics = (graphic != base_graphic);
10609 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
10610 struct GraphicInfo *g = &graphic_info[graphic];
10612 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
10614 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10615 Bitmap *src_bitmap;
10617 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
10618 boolean special_animation = (action != ACTION_DEFAULT &&
10619 g->anim_frames == 3 &&
10620 g->anim_delay == 2 &&
10621 g->anim_mode & ANIM_LINEAR);
10622 int sync_frame = (i == Xdrip_stretch ? 7 :
10623 i == Xdrip_stretchB ? 7 :
10624 i == Ydrip_s2 ? j + 8 :
10625 i == Ydrip_s2B ? j + 8 :
10627 i == Xacid_2 ? 10 :
10628 i == Xacid_3 ? 20 :
10629 i == Xacid_4 ? 30 :
10630 i == Xacid_5 ? 40 :
10631 i == Xacid_6 ? 50 :
10632 i == Xacid_7 ? 60 :
10633 i == Xacid_8 ? 70 :
10634 i == Xfake_acid_1 ? 0 :
10635 i == Xfake_acid_2 ? 10 :
10636 i == Xfake_acid_3 ? 20 :
10637 i == Xfake_acid_4 ? 30 :
10638 i == Xfake_acid_5 ? 40 :
10639 i == Xfake_acid_6 ? 50 :
10640 i == Xfake_acid_7 ? 60 :
10641 i == Xfake_acid_8 ? 70 :
10643 i == Xball_2B ? j + 8 :
10644 i == Yball_eat ? j + 1 :
10645 i == Ykey_1_eat ? j + 1 :
10646 i == Ykey_2_eat ? j + 1 :
10647 i == Ykey_3_eat ? j + 1 :
10648 i == Ykey_4_eat ? j + 1 :
10649 i == Ykey_5_eat ? j + 1 :
10650 i == Ykey_6_eat ? j + 1 :
10651 i == Ykey_7_eat ? j + 1 :
10652 i == Ykey_8_eat ? j + 1 :
10653 i == Ylenses_eat ? j + 1 :
10654 i == Ymagnify_eat ? j + 1 :
10655 i == Ygrass_eat ? j + 1 :
10656 i == Ydirt_eat ? j + 1 :
10657 i == Xamoeba_1 ? 0 :
10658 i == Xamoeba_2 ? 1 :
10659 i == Xamoeba_3 ? 2 :
10660 i == Xamoeba_4 ? 3 :
10661 i == Xamoeba_5 ? 0 :
10662 i == Xamoeba_6 ? 1 :
10663 i == Xamoeba_7 ? 2 :
10664 i == Xamoeba_8 ? 3 :
10665 i == Xexit_2 ? j + 8 :
10666 i == Xexit_3 ? j + 16 :
10667 i == Xdynamite_1 ? 0 :
10668 i == Xdynamite_2 ? 8 :
10669 i == Xdynamite_3 ? 16 :
10670 i == Xdynamite_4 ? 24 :
10671 i == Xsand_stonein_1 ? j + 1 :
10672 i == Xsand_stonein_2 ? j + 9 :
10673 i == Xsand_stonein_3 ? j + 17 :
10674 i == Xsand_stonein_4 ? j + 25 :
10675 i == Xsand_stoneout_1 && j == 0 ? 0 :
10676 i == Xsand_stoneout_1 && j == 1 ? 0 :
10677 i == Xsand_stoneout_1 && j == 2 ? 1 :
10678 i == Xsand_stoneout_1 && j == 3 ? 2 :
10679 i == Xsand_stoneout_1 && j == 4 ? 2 :
10680 i == Xsand_stoneout_1 && j == 5 ? 3 :
10681 i == Xsand_stoneout_1 && j == 6 ? 4 :
10682 i == Xsand_stoneout_1 && j == 7 ? 4 :
10683 i == Xsand_stoneout_2 && j == 0 ? 5 :
10684 i == Xsand_stoneout_2 && j == 1 ? 6 :
10685 i == Xsand_stoneout_2 && j == 2 ? 7 :
10686 i == Xsand_stoneout_2 && j == 3 ? 8 :
10687 i == Xsand_stoneout_2 && j == 4 ? 9 :
10688 i == Xsand_stoneout_2 && j == 5 ? 11 :
10689 i == Xsand_stoneout_2 && j == 6 ? 13 :
10690 i == Xsand_stoneout_2 && j == 7 ? 15 :
10691 i == Xboom_bug && j == 1 ? 2 :
10692 i == Xboom_bug && j == 2 ? 2 :
10693 i == Xboom_bug && j == 3 ? 4 :
10694 i == Xboom_bug && j == 4 ? 4 :
10695 i == Xboom_bug && j == 5 ? 2 :
10696 i == Xboom_bug && j == 6 ? 2 :
10697 i == Xboom_bug && j == 7 ? 0 :
10698 i == Xboom_bomb && j == 1 ? 2 :
10699 i == Xboom_bomb && j == 2 ? 2 :
10700 i == Xboom_bomb && j == 3 ? 4 :
10701 i == Xboom_bomb && j == 4 ? 4 :
10702 i == Xboom_bomb && j == 5 ? 2 :
10703 i == Xboom_bomb && j == 6 ? 2 :
10704 i == Xboom_bomb && j == 7 ? 0 :
10705 i == Xboom_android && j == 7 ? 6 :
10706 i == Xboom_1 && j == 1 ? 2 :
10707 i == Xboom_1 && j == 2 ? 2 :
10708 i == Xboom_1 && j == 3 ? 4 :
10709 i == Xboom_1 && j == 4 ? 4 :
10710 i == Xboom_1 && j == 5 ? 6 :
10711 i == Xboom_1 && j == 6 ? 6 :
10712 i == Xboom_1 && j == 7 ? 8 :
10713 i == Xboom_2 && j == 0 ? 8 :
10714 i == Xboom_2 && j == 1 ? 8 :
10715 i == Xboom_2 && j == 2 ? 10 :
10716 i == Xboom_2 && j == 3 ? 10 :
10717 i == Xboom_2 && j == 4 ? 10 :
10718 i == Xboom_2 && j == 5 ? 12 :
10719 i == Xboom_2 && j == 6 ? 12 :
10720 i == Xboom_2 && j == 7 ? 12 :
10721 special_animation && j == 4 ? 3 :
10722 effective_action != action ? 0 :
10726 Bitmap *debug_bitmap = g_em->bitmap;
10727 int debug_src_x = g_em->src_x;
10728 int debug_src_y = g_em->src_y;
10731 int frame = getAnimationFrame(g->anim_frames,
10734 g->anim_start_frame,
10737 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
10738 g->double_movement && is_backside);
10740 g_em->bitmap = src_bitmap;
10741 g_em->src_x = src_x;
10742 g_em->src_y = src_y;
10743 g_em->src_offset_x = 0;
10744 g_em->src_offset_y = 0;
10745 g_em->dst_offset_x = 0;
10746 g_em->dst_offset_y = 0;
10747 g_em->width = TILEX;
10748 g_em->height = TILEY;
10750 g_em->preserve_background = FALSE;
10753 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10758 g_em->crumbled_bitmap = NULL;
10759 g_em->crumbled_src_x = 0;
10760 g_em->crumbled_src_y = 0;
10761 g_em->crumbled_border_size = 0;
10763 g_em->has_crumbled_graphics = FALSE;
10766 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
10767 printf("::: empty crumbled: %d [%s], %d, %d\n",
10768 effective_element, element_info[effective_element].token_name,
10769 effective_action, direction);
10772 /* if element can be crumbled, but certain action graphics are just empty
10773 space (like instantly snapping sand to empty space in 1 frame), do not
10774 treat these empty space graphics as crumbled graphics in EMC engine */
10775 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10777 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10778 g_crumbled->anim_delay,
10779 g_crumbled->anim_mode,
10780 g_crumbled->anim_start_frame,
10783 getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
10785 g_em->has_crumbled_graphics = TRUE;
10786 g_em->crumbled_bitmap = src_bitmap;
10787 g_em->crumbled_src_x = src_x;
10788 g_em->crumbled_src_y = src_y;
10789 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
10793 if (g_em == &graphic_info_em_object[207][0])
10794 printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
10795 graphic_info_em_object[207][0].crumbled_src_x,
10796 graphic_info_em_object[207][0].crumbled_src_y,
10798 crumbled, frame, src_x, src_y,
10803 g->anim_start_frame,
10805 gfx.anim_random_frame,
10810 printf("::: EMC tile %d is crumbled\n", i);
10816 if (element == EL_ROCK &&
10817 effective_action == ACTION_FILLING)
10818 printf("::: has_action_graphics == %d\n", has_action_graphics);
10821 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10822 effective_action == ACTION_MOVING ||
10823 effective_action == ACTION_PUSHING ||
10824 effective_action == ACTION_EATING)) ||
10825 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10826 effective_action == ACTION_EMPTYING)))
10829 (effective_action == ACTION_FALLING ||
10830 effective_action == ACTION_FILLING ||
10831 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10832 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10833 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10834 int num_steps = (i == Ydrip_s1 ? 16 :
10835 i == Ydrip_s1B ? 16 :
10836 i == Ydrip_s2 ? 16 :
10837 i == Ydrip_s2B ? 16 :
10838 i == Xsand_stonein_1 ? 32 :
10839 i == Xsand_stonein_2 ? 32 :
10840 i == Xsand_stonein_3 ? 32 :
10841 i == Xsand_stonein_4 ? 32 :
10842 i == Xsand_stoneout_1 ? 16 :
10843 i == Xsand_stoneout_2 ? 16 : 8);
10844 int cx = ABS(dx) * (TILEX / num_steps);
10845 int cy = ABS(dy) * (TILEY / num_steps);
10846 int step_frame = (i == Ydrip_s2 ? j + 8 :
10847 i == Ydrip_s2B ? j + 8 :
10848 i == Xsand_stonein_2 ? j + 8 :
10849 i == Xsand_stonein_3 ? j + 16 :
10850 i == Xsand_stonein_4 ? j + 24 :
10851 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10852 int step = (is_backside ? step_frame : num_steps - step_frame);
10854 if (is_backside) /* tile where movement starts */
10856 if (dx < 0 || dy < 0)
10858 g_em->src_offset_x = cx * step;
10859 g_em->src_offset_y = cy * step;
10863 g_em->dst_offset_x = cx * step;
10864 g_em->dst_offset_y = cy * step;
10867 else /* tile where movement ends */
10869 if (dx < 0 || dy < 0)
10871 g_em->dst_offset_x = cx * step;
10872 g_em->dst_offset_y = cy * step;
10876 g_em->src_offset_x = cx * step;
10877 g_em->src_offset_y = cy * step;
10881 g_em->width = TILEX - cx * step;
10882 g_em->height = TILEY - cy * step;
10885 /* create unique graphic identifier to decide if tile must be redrawn */
10886 /* bit 31 - 16 (16 bit): EM style graphic
10887 bit 15 - 12 ( 4 bit): EM style frame
10888 bit 11 - 6 ( 6 bit): graphic width
10889 bit 5 - 0 ( 6 bit): graphic height */
10890 g_em->unique_identifier =
10891 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10895 /* skip check for EMC elements not contained in original EMC artwork */
10896 if (element == EL_EMC_FAKE_ACID)
10899 if (g_em->bitmap != debug_bitmap ||
10900 g_em->src_x != debug_src_x ||
10901 g_em->src_y != debug_src_y ||
10902 g_em->src_offset_x != 0 ||
10903 g_em->src_offset_y != 0 ||
10904 g_em->dst_offset_x != 0 ||
10905 g_em->dst_offset_y != 0 ||
10906 g_em->width != TILEX ||
10907 g_em->height != TILEY)
10909 static int last_i = -1;
10917 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
10918 i, element, element_info[element].token_name,
10919 element_action_info[effective_action].suffix, direction);
10921 if (element != effective_element)
10922 printf(" [%d ('%s')]",
10924 element_info[effective_element].token_name);
10928 if (g_em->bitmap != debug_bitmap)
10929 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
10930 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
10932 if (g_em->src_x != debug_src_x ||
10933 g_em->src_y != debug_src_y)
10934 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
10935 j, (is_backside ? 'B' : 'F'),
10936 g_em->src_x, g_em->src_y,
10937 g_em->src_x / 32, g_em->src_y / 32,
10938 debug_src_x, debug_src_y,
10939 debug_src_x / 32, debug_src_y / 32);
10941 if (g_em->src_offset_x != 0 ||
10942 g_em->src_offset_y != 0 ||
10943 g_em->dst_offset_x != 0 ||
10944 g_em->dst_offset_y != 0)
10945 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
10947 g_em->src_offset_x, g_em->src_offset_y,
10948 g_em->dst_offset_x, g_em->dst_offset_y);
10950 if (g_em->width != TILEX ||
10951 g_em->height != TILEY)
10952 printf(" %d (%d): size %d,%d should be %d,%d\n",
10954 g_em->width, g_em->height, TILEX, TILEY);
10956 num_em_gfx_errors++;
10963 for (i = 0; i < TILE_MAX; i++)
10965 for (j = 0; j < 8; j++)
10967 int element = object_mapping[i].element_rnd;
10968 int action = object_mapping[i].action;
10969 int direction = object_mapping[i].direction;
10970 boolean is_backside = object_mapping[i].is_backside;
10971 int graphic_action = el_act_dir2img(element, action, direction);
10972 int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
10974 if ((action == ACTION_SMASHED_BY_ROCK ||
10975 action == ACTION_SMASHED_BY_SPRING ||
10976 action == ACTION_EATING) &&
10977 graphic_action == graphic_default)
10979 int e = (action == ACTION_SMASHED_BY_ROCK ? Ystone_s :
10980 action == ACTION_SMASHED_BY_SPRING ? Yspring_s :
10981 direction == MV_LEFT ? (is_backside? Yspring_wB: Yspring_w) :
10982 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
10985 /* no separate animation for "smashed by rock" -- use rock instead */
10986 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10987 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
10989 g_em->bitmap = g_xx->bitmap;
10990 g_em->src_x = g_xx->src_x;
10991 g_em->src_y = g_xx->src_y;
10992 g_em->src_offset_x = g_xx->src_offset_x;
10993 g_em->src_offset_y = g_xx->src_offset_y;
10994 g_em->dst_offset_x = g_xx->dst_offset_x;
10995 g_em->dst_offset_y = g_xx->dst_offset_y;
10996 g_em->width = g_xx->width;
10997 g_em->height = g_xx->height;
10998 g_em->unique_identifier = g_xx->unique_identifier;
11001 g_em->preserve_background = TRUE;
11006 for (p = 0; p < MAX_PLAYERS; p++)
11008 for (i = 0; i < SPR_MAX; i++)
11010 int element = player_mapping[p][i].element_rnd;
11011 int action = player_mapping[p][i].action;
11012 int direction = player_mapping[p][i].direction;
11014 for (j = 0; j < 8; j++)
11016 int effective_element = element;
11017 int effective_action = action;
11018 int graphic = (direction == MV_NONE ?
11019 el_act2img(effective_element, effective_action) :
11020 el_act_dir2img(effective_element, effective_action,
11022 struct GraphicInfo *g = &graphic_info[graphic];
11023 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
11024 Bitmap *src_bitmap;
11026 int sync_frame = j;
11029 Bitmap *debug_bitmap = g_em->bitmap;
11030 int debug_src_x = g_em->src_x;
11031 int debug_src_y = g_em->src_y;
11034 int frame = getAnimationFrame(g->anim_frames,
11037 g->anim_start_frame,
11040 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
11042 g_em->bitmap = src_bitmap;
11043 g_em->src_x = src_x;
11044 g_em->src_y = src_y;
11045 g_em->src_offset_x = 0;
11046 g_em->src_offset_y = 0;
11047 g_em->dst_offset_x = 0;
11048 g_em->dst_offset_y = 0;
11049 g_em->width = TILEX;
11050 g_em->height = TILEY;
11054 /* skip check for EMC elements not contained in original EMC artwork */
11055 if (element == EL_PLAYER_3 ||
11056 element == EL_PLAYER_4)
11059 if (g_em->bitmap != debug_bitmap ||
11060 g_em->src_x != debug_src_x ||
11061 g_em->src_y != debug_src_y)
11063 static int last_i = -1;
11071 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
11072 p, i, element, element_info[element].token_name,
11073 element_action_info[effective_action].suffix, direction);
11075 if (element != effective_element)
11076 printf(" [%d ('%s')]",
11078 element_info[effective_element].token_name);
11082 if (g_em->bitmap != debug_bitmap)
11083 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
11084 j, (int)(g_em->bitmap), (int)(debug_bitmap));
11086 if (g_em->src_x != debug_src_x ||
11087 g_em->src_y != debug_src_y)
11088 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
11090 g_em->src_x, g_em->src_y,
11091 g_em->src_x / 32, g_em->src_y / 32,
11092 debug_src_x, debug_src_y,
11093 debug_src_x / 32, debug_src_y / 32);
11095 num_em_gfx_errors++;
11105 printf("::: [%d errors found]\n", num_em_gfx_errors);
11111 void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
11112 boolean any_player_moving,
11113 boolean player_is_dropping)
11115 if (tape.single_step && tape.recording && !tape.pausing)
11118 boolean active_players = FALSE;
11121 for (i = 0; i < MAX_PLAYERS; i++)
11122 if (action[i] != JOY_NO_ACTION)
11123 active_players = TRUE;
11127 if (frame == 0 && !player_is_dropping)
11128 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
11132 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
11133 boolean murphy_is_dropping)
11136 printf("::: waiting: %d, dropping: %d\n",
11137 murphy_is_waiting, murphy_is_dropping);
11140 if (tape.single_step && tape.recording && !tape.pausing)
11142 // if (murphy_is_waiting || murphy_is_dropping)
11143 if (murphy_is_waiting)
11146 printf("::: murphy is waiting -> pause mode\n");
11149 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
11154 void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
11155 int graphic, int sync_frame, int x, int y)
11157 int frame = getGraphicAnimationFrame(graphic, sync_frame);
11159 getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
11162 boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
11164 return (IS_NEXT_FRAME(sync_frame, graphic));
11167 int getGraphicInfo_Delay(int graphic)
11169 return graphic_info[graphic].anim_delay;
11172 void PlayMenuSoundExt(int sound)
11174 if (sound == SND_UNDEFINED)
11177 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11178 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11181 if (IS_LOOP_SOUND(sound))
11182 PlaySoundLoop(sound);
11187 void PlayMenuSound()
11189 PlayMenuSoundExt(menu.sound[game_status]);
11192 void PlayMenuSoundStereo(int sound, int stereo_position)
11194 if (sound == SND_UNDEFINED)
11197 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11198 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11201 if (IS_LOOP_SOUND(sound))
11202 PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP);
11204 PlaySoundStereo(sound, stereo_position);
11207 void PlayMenuSoundIfLoopExt(int sound)
11209 if (sound == SND_UNDEFINED)
11212 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11213 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11216 if (IS_LOOP_SOUND(sound))
11217 PlaySoundLoop(sound);
11220 void PlayMenuSoundIfLoop()
11222 PlayMenuSoundIfLoopExt(menu.sound[game_status]);
11225 void PlayMenuMusicExt(int music)
11227 if (music == MUS_UNDEFINED)
11230 if (!setup.sound_music)
11236 void PlayMenuMusic()
11238 PlayMenuMusicExt(menu.music[game_status]);
11241 void PlaySoundActivating()
11244 PlaySound(SND_MENU_ITEM_ACTIVATING);
11248 void PlaySoundSelecting()
11251 PlaySound(SND_MENU_ITEM_SELECTING);
11255 void ToggleFullscreenOrChangeWindowScalingIfNeeded()
11257 boolean change_fullscreen = (setup.fullscreen !=
11258 video.fullscreen_enabled);
11259 boolean change_fullscreen_mode = (video.fullscreen_enabled &&
11260 !strEqual(setup.fullscreen_mode,
11261 video.fullscreen_mode_current));
11262 boolean change_window_scaling_percent = (!video.fullscreen_enabled &&
11263 setup.window_scaling_percent !=
11264 video.window_scaling_percent);
11266 if (change_window_scaling_percent && video.fullscreen_enabled)
11269 if (!change_window_scaling_percent && !video.fullscreen_available)
11272 #if defined(TARGET_SDL2)
11273 if (change_window_scaling_percent)
11275 SDLSetWindowScaling(setup.window_scaling_percent);
11279 else if (change_fullscreen)
11281 SDLSetWindowFullscreen(setup.fullscreen);
11283 /* set setup value according to successfully changed fullscreen mode */
11284 setup.fullscreen = video.fullscreen_enabled;
11290 if (change_fullscreen ||
11291 change_fullscreen_mode ||
11292 change_window_scaling_percent)
11294 Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
11296 /* save backbuffer content which gets lost when toggling fullscreen mode */
11297 BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11299 if (change_fullscreen_mode)
11301 /* keep fullscreen, but change fullscreen mode (screen resolution) */
11302 video.fullscreen_enabled = FALSE; /* force new fullscreen mode */
11305 if (change_window_scaling_percent)
11307 /* keep window mode, but change window scaling */
11308 video.fullscreen_enabled = TRUE; /* force new window scaling */
11311 /* toggle fullscreen */
11312 ChangeVideoModeIfNeeded(setup.fullscreen);
11314 /* set setup value according to successfully changed fullscreen mode */
11315 setup.fullscreen = video.fullscreen_enabled;
11317 /* restore backbuffer content from temporary backbuffer backup bitmap */
11318 BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11320 FreeBitmap(tmp_backbuffer);
11323 /* update visible window/screen */
11324 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11326 redraw_mask = REDRAW_ALL;
11331 void ChangeViewportPropertiesIfNeeded()
11334 int *door_1_x = &DX;
11335 int *door_1_y = &DY;
11336 int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
11337 int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
11340 int gfx_game_mode = game_status;
11342 int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
11343 game_status == GAME_MODE_EDITOR ? game_status :
11346 int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
11348 struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
11349 struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
11350 struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode2];
11351 struct RectWithBorder *vp_door_3 = &viewport.door_2[GAME_MODE_EDITOR];
11352 int border_size = vp_playfield->border_size;
11353 int new_sx = vp_playfield->x + border_size;
11354 int new_sy = vp_playfield->y + border_size;
11355 int new_sxsize = vp_playfield->width - 2 * border_size;
11356 int new_sysize = vp_playfield->height - 2 * border_size;
11357 int new_real_sx = vp_playfield->x;
11358 int new_real_sy = vp_playfield->y;
11359 int new_full_sxsize = vp_playfield->width;
11360 int new_full_sysize = vp_playfield->height;
11361 int new_dx = vp_door_1->x;
11362 int new_dy = vp_door_1->y;
11363 int new_dxsize = vp_door_1->width;
11364 int new_dysize = vp_door_1->height;
11365 int new_vx = vp_door_2->x;
11366 int new_vy = vp_door_2->y;
11367 int new_vxsize = vp_door_2->width;
11368 int new_vysize = vp_door_2->height;
11369 int new_ex = vp_door_3->x;
11370 int new_ey = vp_door_3->y;
11371 int new_exsize = vp_door_3->width;
11372 int new_eysize = vp_door_3->height;
11374 int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
11375 int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
11376 gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
11377 int new_scr_fieldx = new_sxsize / tilesize;
11378 int new_scr_fieldy = new_sysize / tilesize;
11379 int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var;
11380 int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
11382 int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE;
11383 int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE;
11385 boolean init_gfx_buffers = FALSE;
11386 boolean init_video_buffer = FALSE;
11387 boolean init_gadgets_and_toons = FALSE;
11390 /* !!! TEST ONLY !!! */
11391 // InitGfxBuffers();
11395 if (viewport.window.width != WIN_XSIZE ||
11396 viewport.window.height != WIN_YSIZE)
11398 WIN_XSIZE = viewport.window.width;
11399 WIN_YSIZE = viewport.window.height;
11402 init_video_buffer = TRUE;
11403 init_gfx_buffers = TRUE;
11405 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
11409 SetDrawDeactivationMask(REDRAW_NONE);
11410 SetDrawBackgroundMask(REDRAW_FIELD);
11412 // RedrawBackground();
11416 // printf("::: video: init_video_buffer, init_gfx_buffers\n");
11419 if (new_scr_fieldx != SCR_FIELDX ||
11420 new_scr_fieldy != SCR_FIELDY)
11422 /* this always toggles between MAIN and GAME when using small tile size */
11424 SCR_FIELDX = new_scr_fieldx;
11425 SCR_FIELDY = new_scr_fieldy;
11427 // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
11431 if (new_tilesize_var != TILESIZE_VAR &&
11432 gfx_game_mode == GAME_MODE_PLAYING)
11434 /* doing this outside GAME_MODE_PLAYING would give wrong playfield size */
11436 TILESIZE_VAR = new_tilesize_var;
11438 init_gfx_buffers = TRUE;
11440 // printf("::: tilesize: init_gfx_buffers\n");
11444 if (new_sx != SX ||
11452 new_sxsize != SXSIZE ||
11453 new_sysize != SYSIZE ||
11454 new_dxsize != DXSIZE ||
11455 new_dysize != DYSIZE ||
11456 new_vxsize != VXSIZE ||
11457 new_vysize != VYSIZE ||
11458 new_exsize != EXSIZE ||
11459 new_eysize != EYSIZE ||
11460 new_real_sx != REAL_SX ||
11461 new_real_sy != REAL_SY ||
11462 new_full_sxsize != FULL_SXSIZE ||
11463 new_full_sysize != FULL_SYSIZE ||
11464 new_tilesize_var != TILESIZE_VAR
11467 vp_door_1->x != *door_1_x ||
11468 vp_door_1->y != *door_1_y ||
11469 vp_door_2->x != *door_2_x ||
11470 vp_door_2->y != *door_2_y
11482 SXSIZE = new_sxsize;
11483 SYSIZE = new_sysize;
11484 DXSIZE = new_dxsize;
11485 DYSIZE = new_dysize;
11486 VXSIZE = new_vxsize;
11487 VYSIZE = new_vysize;
11488 EXSIZE = new_exsize;
11489 EYSIZE = new_eysize;
11490 REAL_SX = new_real_sx;
11491 REAL_SY = new_real_sy;
11492 FULL_SXSIZE = new_full_sxsize;
11493 FULL_SYSIZE = new_full_sysize;
11494 TILESIZE_VAR = new_tilesize_var;
11497 printf("::: %d, %d, %d [%d]\n",
11498 SCR_FIELDX, SCR_FIELDY, TILESIZE_VAR,
11499 setup.small_game_graphics);
11503 *door_1_x = vp_door_1->x;
11504 *door_1_y = vp_door_1->y;
11505 *door_2_x = vp_door_2->x;
11506 *door_2_y = vp_door_2->y;
11510 init_gfx_buffers = TRUE;
11512 // printf("::: viewports: init_gfx_buffers\n");
11518 if (gfx_game_mode == GAME_MODE_MAIN)
11522 init_gadgets_and_toons = TRUE;
11524 // printf("::: viewports: init_gadgets_and_toons\n");
11532 if (init_gfx_buffers)
11534 // printf("::: init_gfx_buffers\n");
11536 SCR_FIELDX = new_scr_fieldx_buffers;
11537 SCR_FIELDY = new_scr_fieldy_buffers;
11541 SCR_FIELDX = new_scr_fieldx;
11542 SCR_FIELDY = new_scr_fieldy;
11545 if (init_video_buffer)
11547 // printf("::: init_video_buffer\n");
11549 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
11551 SetDrawDeactivationMask(REDRAW_NONE);
11552 SetDrawBackgroundMask(REDRAW_FIELD);
11555 if (init_gadgets_and_toons)
11557 // printf("::: init_gadgets_and_toons\n");
11564 printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status);