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 ***********************************************************/
14 #include "libgame/libgame.h"
26 /* select level set with EMC X11 graphics before activating EM GFX debugging */
27 #define DEBUG_EM_GFX 0
29 /* tool button identifiers */
30 #define TOOL_CTRL_ID_YES 0
31 #define TOOL_CTRL_ID_NO 1
32 #define TOOL_CTRL_ID_CONFIRM 2
33 #define TOOL_CTRL_ID_PLAYER_1 3
34 #define TOOL_CTRL_ID_PLAYER_2 4
35 #define TOOL_CTRL_ID_PLAYER_3 5
36 #define TOOL_CTRL_ID_PLAYER_4 6
38 #define NUM_TOOL_BUTTONS 7
40 /* forward declaration for internal use */
41 static void UnmapToolButtons();
42 static void HandleToolButtons(struct GadgetInfo *);
43 static int el_act_dir2crm(int, int, int);
44 static int el_act2crm(int, int);
46 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
47 static int request_gadget_id = -1;
49 static char *print_if_not_empty(int element)
51 static char *s = NULL;
52 char *token_name = element_info[element].token_name;
57 s = checked_malloc(strlen(token_name) + 10 + 1);
59 if (element != EL_EMPTY)
60 sprintf(s, "%d\t['%s']", element, token_name);
62 sprintf(s, "%d", element);
67 void DumpTile(int x, int y)
72 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
79 printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
82 if (!IN_LEV_FIELD(x, y))
84 printf("(not in level field)\n");
90 printf(" Feld: %d\t['%s']\n", Feld[x][y],
91 element_info[Feld[x][y]].token_name);
92 printf(" Back: %s\n", print_if_not_empty(Back[x][y]));
93 printf(" Store: %s\n", print_if_not_empty(Store[x][y]));
94 printf(" Store2: %s\n", print_if_not_empty(Store2[x][y]));
95 printf(" StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
96 printf(" MovPos: %d\n", MovPos[x][y]);
97 printf(" MovDir: %d\n", MovDir[x][y]);
98 printf(" MovDelay: %d\n", MovDelay[x][y]);
99 printf(" ChangeDelay: %d\n", ChangeDelay[x][y]);
100 printf(" CustomValue: %d\n", CustomValue[x][y]);
101 printf(" GfxElement: %d\n", GfxElement[x][y]);
102 printf(" GfxAction: %d\n", GfxAction[x][y]);
103 printf(" GfxFrame: %d\n", GfxFrame[x][y]);
107 void SetDrawtoField(int mode)
109 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
117 BX2 = SCR_FIELDX + 1;
118 BY2 = SCR_FIELDY + 1;
137 BX2 = SCR_FIELDX + 1;
138 BY2 = SCR_FIELDY + 1;
153 drawto_field = fieldbuffer;
155 else /* DRAW_BACKBUFFER */
161 BX2 = SCR_FIELDX - 1;
162 BY2 = SCR_FIELDY - 1;
166 drawto_field = backbuffer;
170 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
172 if (game_status == GAME_MODE_PLAYING &&
173 level.game_engine_type == GAME_ENGINE_TYPE_EM)
175 /* currently there is no partial redraw -- always redraw whole playfield */
176 RedrawPlayfield_EM(TRUE);
178 /* blit playfield from scroll buffer to normal back buffer for fading in */
179 BlitScreenToBitmap_EM(backbuffer);
181 else if (game_status == GAME_MODE_PLAYING &&
182 level.game_engine_type == GAME_ENGINE_TYPE_SP)
184 /* currently there is no partial redraw -- always redraw whole playfield */
185 RedrawPlayfield_SP(TRUE);
187 /* blit playfield from scroll buffer to normal back buffer for fading in */
188 BlitScreenToBitmap_SP(backbuffer);
190 else if (game_status == GAME_MODE_PLAYING &&
191 !game.envelope_active)
197 width = gfx.sxsize + 2 * TILEX;
198 height = gfx.sysize + 2 * TILEY;
204 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
205 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
207 for (xx = BX1; xx <= BX2; xx++)
208 for (yy = BY1; yy <= BY2; yy++)
209 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
210 DrawScreenField(xx, yy);
214 if (setup.soft_scrolling)
216 int fx = FX, fy = FY;
218 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
219 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
221 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
233 BlitBitmap(drawto, window, x, y, width, height, x, y);
236 void DrawMaskedBorder_Rect(int x, int y, int width, int height)
238 Bitmap *bitmap = graphic_info[IMG_GLOBAL_BORDER].bitmap;
240 SetClipOrigin(bitmap, bitmap->stored_clip_gc, 0, 0);
241 BlitBitmapMasked(bitmap, backbuffer, x, y, width, height, x, y);
244 void DrawMaskedBorder_FIELD()
246 if (global.border_status >= GAME_MODE_TITLE &&
247 global.border_status <= GAME_MODE_PLAYING &&
248 border.draw_masked[global.border_status])
249 DrawMaskedBorder_Rect(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
252 void DrawMaskedBorder_DOOR_1()
254 if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
255 (global.border_status != GAME_MODE_EDITOR ||
256 border.draw_masked[GFX_SPECIAL_ARG_EDITOR]))
257 DrawMaskedBorder_Rect(DX, DY, DXSIZE, DYSIZE);
260 void DrawMaskedBorder_DOOR_2()
262 if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
263 global.border_status != GAME_MODE_EDITOR)
264 DrawMaskedBorder_Rect(VX, VY, VXSIZE, VYSIZE);
267 void DrawMaskedBorder_DOOR_3()
269 /* currently not available */
272 void DrawMaskedBorder_ALL()
274 DrawMaskedBorder_FIELD();
275 DrawMaskedBorder_DOOR_1();
276 DrawMaskedBorder_DOOR_2();
277 DrawMaskedBorder_DOOR_3();
280 void DrawMaskedBorder(int redraw_mask)
282 /* never draw masked screen borders on borderless screens */
283 if (effectiveGameStatus() == GAME_MODE_LOADING ||
284 effectiveGameStatus() == GAME_MODE_TITLE)
287 /* never draw masked screen borders when displaying request outside door */
288 if (effectiveGameStatus() == GAME_MODE_PSEUDO_DOOR &&
289 global.use_envelope_request)
292 if (redraw_mask & REDRAW_ALL)
293 DrawMaskedBorder_ALL();
296 if (redraw_mask & REDRAW_FIELD)
297 DrawMaskedBorder_FIELD();
298 if (redraw_mask & REDRAW_DOOR_1)
299 DrawMaskedBorder_DOOR_1();
300 if (redraw_mask & REDRAW_DOOR_2)
301 DrawMaskedBorder_DOOR_2();
302 if (redraw_mask & REDRAW_DOOR_3)
303 DrawMaskedBorder_DOOR_3();
307 void BlitScreenToBitmap(Bitmap *target_bitmap)
309 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
310 int fx = FX, fy = FY;
313 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
314 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
315 int dx_var = dx * TILESIZE_VAR / TILESIZE;
316 int dy_var = dy * TILESIZE_VAR / TILESIZE;
319 // fx += dx * TILESIZE_VAR / TILESIZE;
320 // fy += dy * TILESIZE_VAR / TILESIZE;
322 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
323 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
326 /* !!! THIS WORKS !!! */
328 printf("::: (%d, %d) [(%d / %d, %d / %d)]\n",
331 SBY_Upper, SBY_Lower);
333 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
334 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
336 if (EVEN(SCR_FIELDX))
338 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
339 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
341 fx += (dx > 0 ? TILEX_VAR : 0);
348 if (EVEN(SCR_FIELDY))
350 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
351 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
353 fy += (dy > 0 ? TILEY_VAR : 0);
360 if (border.draw_masked[GAME_MODE_PLAYING])
362 if (buffer != backbuffer)
364 /* copy playfield buffer to backbuffer to add masked border */
365 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
366 DrawMaskedBorder(REDRAW_FIELD);
369 BlitBitmap(backbuffer, target_bitmap,
370 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
375 BlitBitmap(buffer, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
382 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
385 printf("::: TILES TO REFRESH: %d\n", redraw_tiles);
386 for (x = 0; x < SCR_FIELDX; x++)
387 for (y = 0 ; y < SCR_FIELDY; y++)
388 if (redraw[redraw_x1 + x][redraw_y1 + y])
389 printf("::: - %d, %d [%s]\n",
390 LEVELX(x), LEVELY(y),
391 EL_NAME(Feld[LEVELX(x)][LEVELY(y)]));
394 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
395 redraw_mask |= REDRAW_FIELD;
397 if (redraw_mask & REDRAW_FIELD)
398 redraw_mask &= ~REDRAW_TILES;
400 if (redraw_mask == REDRAW_NONE)
403 if (redraw_mask & REDRAW_TILES &&
404 game_status == GAME_MODE_PLAYING &&
405 border.draw_masked[GAME_MODE_PLAYING])
406 redraw_mask |= REDRAW_FIELD;
408 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
410 static boolean last_frame_skipped = FALSE;
411 boolean skip_even_when_not_scrolling = TRUE;
412 boolean just_scrolling = (ScreenMovDir != 0);
413 boolean verbose = FALSE;
415 if (global.fps_slowdown_factor > 1 &&
416 (FrameCounter % global.fps_slowdown_factor) &&
417 (just_scrolling || skip_even_when_not_scrolling))
419 redraw_mask &= ~REDRAW_MAIN;
421 last_frame_skipped = TRUE;
424 printf("FRAME SKIPPED\n");
428 if (last_frame_skipped)
429 redraw_mask |= REDRAW_FIELD;
431 last_frame_skipped = FALSE;
434 printf("frame not skipped\n");
438 /* synchronize X11 graphics at this point; if we would synchronize the
439 display immediately after the buffer switching (after the XFlush),
440 this could mean that we have to wait for the graphics to complete,
441 although we could go on doing calculations for the next frame */
445 /* never draw masked border to backbuffer when using playfield buffer */
446 if (game_status != GAME_MODE_PLAYING ||
447 redraw_mask & REDRAW_FROM_BACKBUFFER ||
448 buffer == backbuffer)
449 DrawMaskedBorder(redraw_mask);
451 DrawMaskedBorder(redraw_mask & REDRAW_DOORS);
453 if (redraw_mask & REDRAW_ALL)
455 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
457 redraw_mask = REDRAW_NONE;
460 if (redraw_mask & REDRAW_FIELD)
463 printf("::: REDRAW_FIELD\n");
466 if (game_status != GAME_MODE_PLAYING ||
467 redraw_mask & REDRAW_FROM_BACKBUFFER)
469 BlitBitmap(backbuffer, window,
470 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
475 BlitScreenToBitmap(window);
477 int fx = FX, fy = FY;
480 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
481 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
482 int dx_var = dx * TILESIZE_VAR / TILESIZE;
483 int dy_var = dy * TILESIZE_VAR / TILESIZE;
486 // fx += dx * TILESIZE_VAR / TILESIZE;
487 // fy += dy * TILESIZE_VAR / TILESIZE;
489 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
490 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
493 /* !!! THIS WORKS !!! */
495 printf("::: %d, %d\n", scroll_x, scroll_y);
497 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
498 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
500 if (EVEN(SCR_FIELDX))
502 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
503 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
505 fx += (dx > 0 ? TILEX_VAR : 0);
512 if (EVEN(SCR_FIELDY))
514 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
515 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
517 fy += (dy > 0 ? TILEY_VAR : 0);
524 if (border.draw_masked[GAME_MODE_PLAYING])
526 if (buffer != backbuffer)
528 /* copy playfield buffer to backbuffer to add masked border */
529 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
530 DrawMaskedBorder(REDRAW_FIELD);
533 BlitBitmap(backbuffer, window,
534 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
539 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
545 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
547 (setup.soft_scrolling ?
548 "setup.soft_scrolling" :
549 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
550 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
551 ABS(ScreenGfxPos) == ScrollStepSize ?
552 "ABS(ScreenGfxPos) == ScrollStepSize" :
553 "redraw_tiles > REDRAWTILES_THRESHOLD"));
558 redraw_mask &= ~REDRAW_MAIN;
561 if (redraw_mask & REDRAW_DOORS)
563 if (redraw_mask & REDRAW_DOOR_1)
564 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
566 if (redraw_mask & REDRAW_DOOR_2)
567 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
569 if (redraw_mask & REDRAW_DOOR_3)
570 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
572 redraw_mask &= ~REDRAW_DOORS;
575 if (redraw_mask & REDRAW_MICROLEVEL)
577 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
578 SX, SY + 10 * TILEY);
580 redraw_mask &= ~REDRAW_MICROLEVEL;
583 if (redraw_mask & REDRAW_TILES)
586 printf("::: REDRAW_TILES\n");
592 InitGfxClipRegion(TRUE, SX, SY, SXSIZE, SYSIZE);
595 int sx = SX; // - (EVEN(SCR_FIELDX) ? TILEX_VAR / 2 : 0);
596 int sy = SY; // + (EVEN(SCR_FIELDY) ? TILEY_VAR / 2 : 0);
600 int fx = FX, fy = FY;
602 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx * TILESIZE_VAR / TILESIZE;
603 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy * TILESIZE_VAR / TILESIZE;
605 if (EVEN(SCR_FIELDX))
607 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
609 fx = fx + dx * TILESIZE_VAR / TILESIZE - MIN(ffx, TILEX_VAR / 2) +
619 fx = fx - (dx <= 0 ? TILEX_VAR : 0) + TILEX_VAR;
623 if (EVEN(SCR_FIELDY))
625 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
627 fy = fy + dy * TILESIZE_VAR / TILESIZE - MIN(ffy, TILEY_VAR / 2) +
637 fy = fy - (dy <= 0 ? TILEY_VAR : 0) + TILEY_VAR;
641 for (x = 0; x < SCR_FIELDX; x++)
642 for (y = 0 ; y < SCR_FIELDY; y++)
643 if (redraw[redraw_x1 + x][redraw_y1 + y])
644 BlitBitmap(buffer, window,
645 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
646 TILEX_VAR, TILEY_VAR,
647 sx + x * TILEX_VAR, sy + y * TILEY_VAR);
650 InitGfxClipRegion(FALSE, -1, -1, -1, -1);
652 for (x = 0; x < SCR_FIELDX; x++)
653 for (y = 0 ; y < SCR_FIELDY; y++)
654 if (redraw[redraw_x1 + x][redraw_y1 + y])
655 BlitBitmap(buffer, window,
656 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
657 TILEX_VAR, TILEY_VAR,
658 SX + x * TILEX_VAR, SY + y * TILEY_VAR);
662 for (x = 0; x < SCR_FIELDX; x++)
663 for (y = 0 ; y < SCR_FIELDY; y++)
664 if (redraw[redraw_x1 + x][redraw_y1 + y])
665 BlitBitmap(buffer, window,
666 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
667 SX + x * TILEX, SY + y * TILEY);
671 if (redraw_mask & REDRAW_FPS) /* display frames per second */
676 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
677 if (!global.fps_slowdown)
680 sprintf(text, "%04.1f fps%s", global.frames_per_second, info1);
682 DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE);
684 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
690 for (x = 0; x < MAX_BUF_XSIZE; x++)
691 for (y = 0; y < MAX_BUF_YSIZE; y++)
694 redraw_mask = REDRAW_NONE;
697 static void FadeCrossSaveBackbuffer()
699 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
702 static void FadeExt(int fade_mask, int fade_mode, int fade_type)
704 static int fade_type_skip = FADE_TYPE_NONE;
705 void (*draw_border_function)(void) = NULL;
706 Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL);
707 int x, y, width, height;
708 int fade_delay, post_delay;
710 if (fade_type == FADE_TYPE_FADE_OUT)
712 if (fade_type_skip != FADE_TYPE_NONE)
715 printf("::: skipping %d ... [%d] (X)\n", fade_mode, fade_type_skip);
718 /* skip all fade operations until specified fade operation */
719 if (fade_type & fade_type_skip)
720 fade_type_skip = FADE_TYPE_NONE;
725 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
727 FadeCrossSaveBackbuffer();
733 redraw_mask |= fade_mask;
735 if (fade_type == FADE_TYPE_SKIP)
738 printf("::: will skip %d ... [%d]\n", fade_mode, fade_type_skip);
741 fade_type_skip = fade_mode;
747 printf("::: !!! FADING %d ... [%d] [%d]\n", fade_mode, fade_type,
752 fade_delay = fading.fade_delay;
753 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
756 if (fade_type_skip != FADE_TYPE_NONE)
759 printf("::: skipping %d ... [%d]\n", fade_mode, fade_type_skip);
762 /* skip all fade operations until specified fade operation */
763 if (fade_type & fade_type_skip)
764 fade_type_skip = FADE_TYPE_NONE;
774 if (global.autoplay_leveldir)
776 // fading.fade_mode = FADE_MODE_NONE;
783 if (fading.fade_mode == FADE_MODE_NONE)
791 /* !!! what about fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */
794 printf("::: NOW FADING %d ... [%d]\n", fade_mode, fade_type);
798 if (fade_mask == REDRAW_NONE)
799 fade_mask = REDRAW_FIELD;
802 // if (fade_mask & REDRAW_FIELD)
803 if (fade_mask == REDRAW_FIELD)
808 height = FULL_SYSIZE;
811 fade_delay = fading.fade_delay;
812 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
815 if (border.draw_masked_when_fading)
816 draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */
818 DrawMaskedBorder_FIELD(); /* draw once */
820 else /* REDRAW_ALL */
828 fade_delay = fading.fade_delay;
829 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
834 if (!setup.fade_screens ||
836 fading.fade_mode == FADE_MODE_NONE)
838 if (!setup.fade_screens || fade_delay == 0)
841 if (fade_mode == FADE_MODE_FADE_OUT)
845 if (fade_mode == FADE_MODE_FADE_OUT &&
846 fading.fade_mode != FADE_MODE_NONE)
847 ClearRectangle(backbuffer, x, y, width, height);
851 BlitBitmap(backbuffer, window, x, y, width, height, x, y);
852 redraw_mask = REDRAW_NONE;
860 FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay,
861 draw_border_function);
863 redraw_mask &= ~fade_mask;
866 void FadeIn(int fade_mask)
868 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
869 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN);
871 FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN);
874 void FadeOut(int fade_mask)
876 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
877 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_OUT);
879 FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT);
881 global.border_status = game_status;
884 static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set)
886 static struct TitleFadingInfo fading_leave_stored;
889 fading_leave_stored = fading_leave;
891 fading = fading_leave_stored;
894 void FadeSetEnterMenu()
896 fading = menu.enter_menu;
899 printf("::: storing enter_menu\n");
902 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
905 void FadeSetLeaveMenu()
907 fading = menu.leave_menu;
910 printf("::: storing leave_menu\n");
913 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
916 void FadeSetEnterScreen()
918 fading = menu.enter_screen[game_status];
921 printf("::: storing leave_screen[%d]\n", game_status);
924 FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */
927 void FadeSetNextScreen()
929 fading = menu.next_screen;
932 printf("::: storing next_screen\n");
935 // (do not overwrite fade mode set by FadeSetEnterScreen)
936 // FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
939 void FadeSetLeaveScreen()
942 printf("::: recalling last stored value\n");
945 FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */
948 void FadeSetFromType(int type)
950 if (type & TYPE_ENTER_SCREEN)
951 FadeSetEnterScreen();
952 else if (type & TYPE_ENTER)
954 else if (type & TYPE_LEAVE)
958 void FadeSetDisabled()
960 static struct TitleFadingInfo fading_none = { FADE_MODE_NONE, -1, -1, -1 };
962 fading = fading_none;
965 void FadeSkipNextFadeIn()
967 FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP);
970 void FadeSkipNextFadeOut()
972 FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
975 void SetWindowBackgroundImageIfDefined(int graphic)
977 if (graphic_info[graphic].bitmap)
978 SetWindowBackgroundBitmap(graphic_info[graphic].bitmap);
981 void SetMainBackgroundImageIfDefined(int graphic)
983 if (graphic_info[graphic].bitmap)
984 SetMainBackgroundBitmap(graphic_info[graphic].bitmap);
987 void SetDoorBackgroundImageIfDefined(int graphic)
989 if (graphic_info[graphic].bitmap)
990 SetDoorBackgroundBitmap(graphic_info[graphic].bitmap);
993 void SetWindowBackgroundImage(int graphic)
995 SetWindowBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
996 graphic_info[graphic].bitmap ?
997 graphic_info[graphic].bitmap :
998 graphic_info[IMG_BACKGROUND].bitmap);
1001 void SetMainBackgroundImage(int graphic)
1003 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1004 graphic_info[graphic].bitmap ?
1005 graphic_info[graphic].bitmap :
1006 graphic_info[IMG_BACKGROUND].bitmap);
1009 void SetDoorBackgroundImage(int graphic)
1011 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1012 graphic_info[graphic].bitmap ?
1013 graphic_info[graphic].bitmap :
1014 graphic_info[IMG_BACKGROUND].bitmap);
1017 void SetPanelBackground()
1020 struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL];
1023 BlitBitmapTiled(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1024 gfx->width, gfx->height, 0, 0, DXSIZE, DYSIZE);
1026 /* (ClearRectangle() only needed if panel bitmap is smaller than panel) */
1027 ClearRectangle(bitmap_db_panel, DX, DY, DXSIZE, DYSIZE);
1028 BlitBitmap(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1029 MIN(gfx->width, DXSIZE), MIN(gfx->height, DYSIZE), 0, 0);
1032 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, bitmap_db_panel,
1033 DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, 0, 0);
1036 SetDoorBackgroundBitmap(bitmap_db_panel);
1039 void DrawBackground(int x, int y, int width, int height)
1041 /* !!! "drawto" might still point to playfield buffer here (see below) !!! */
1042 /* (when entering hall of fame after playing) */
1044 ClearRectangleOnBackground(drawto, x, y, width, height);
1046 ClearRectangleOnBackground(backbuffer, x, y, width, height);
1049 redraw_mask |= REDRAW_FIELD;
1052 void DrawBackgroundForFont(int x, int y, int width, int height, int font_nr)
1054 struct FontBitmapInfo *font = getFontBitmapInfo(font_nr);
1056 if (font->bitmap == NULL)
1059 DrawBackground(x, y, width, height);
1062 void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic)
1064 struct GraphicInfo *g = &graphic_info[graphic];
1066 if (g->bitmap == NULL)
1069 DrawBackground(x, y, width, height);
1074 /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
1075 /* (when entering hall of fame after playing) */
1076 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
1078 /* !!! maybe this should be done before clearing the background !!! */
1079 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
1081 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
1082 SetDrawtoField(DRAW_BUFFERED);
1085 SetDrawtoField(DRAW_BACKBUFFER);
1088 void MarkTileDirty(int x, int y)
1090 int xx = redraw_x1 + x;
1091 int yy = redraw_y1 + y;
1093 if (!redraw[xx][yy])
1096 redraw[xx][yy] = TRUE;
1097 redraw_mask |= REDRAW_TILES;
1100 void SetBorderElement()
1104 BorderElement = EL_EMPTY;
1106 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
1108 for (x = 0; x < lev_fieldx; x++)
1110 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
1111 BorderElement = EL_STEELWALL;
1113 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
1119 void FloodFillLevel(int from_x, int from_y, int fill_element,
1120 short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
1121 int max_fieldx, int max_fieldy)
1125 static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
1126 static int safety = 0;
1128 /* check if starting field still has the desired content */
1129 if (field[from_x][from_y] == fill_element)
1134 if (safety > max_fieldx * max_fieldy)
1135 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
1137 old_element = field[from_x][from_y];
1138 field[from_x][from_y] = fill_element;
1140 for (i = 0; i < 4; i++)
1142 x = from_x + check[i][0];
1143 y = from_y + check[i][1];
1145 if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
1146 FloodFillLevel(x, y, fill_element, field, max_fieldx, max_fieldy);
1152 void SetRandomAnimationValue(int x, int y)
1154 gfx.anim_random_frame = GfxRandom[x][y];
1157 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
1159 /* animation synchronized with global frame counter, not move position */
1160 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
1161 sync_frame = FrameCounter;
1163 return getAnimationFrame(graphic_info[graphic].anim_frames,
1164 graphic_info[graphic].anim_delay,
1165 graphic_info[graphic].anim_mode,
1166 graphic_info[graphic].anim_start_frame,
1170 void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw,
1171 Bitmap **bitmap, int *x, int *y,
1172 boolean get_backside)
1176 int width_mult, width_div;
1177 int height_mult, height_div;
1181 { 15, 16, 2, 3 }, /* 1 x 1 */
1182 { 7, 8, 2, 3 }, /* 2 x 2 */
1183 { 3, 4, 2, 3 }, /* 4 x 4 */
1184 { 1, 2, 2, 3 }, /* 8 x 8 */
1185 { 0, 1, 2, 3 }, /* 16 x 16 */
1186 { 0, 1, 0, 1 }, /* 32 x 32 */
1188 struct GraphicInfo *g = &graphic_info[graphic];
1189 Bitmap *src_bitmap = g->bitmap;
1190 int tilesize = MIN(MAX(1, tilesize_raw), TILESIZE);
1191 int offset_calc_pos = log_2(tilesize);
1192 int width_mult = offset_calc[offset_calc_pos].width_mult;
1193 int width_div = offset_calc[offset_calc_pos].width_div;
1194 int height_mult = offset_calc[offset_calc_pos].height_mult;
1195 int height_div = offset_calc[offset_calc_pos].height_div;
1196 int startx = src_bitmap->width * width_mult / width_div;
1197 int starty = src_bitmap->height * height_mult / height_div;
1199 int src_x = (g->src_x + (get_backside ? g->offset2_x : 0)) *
1200 tilesize / TILESIZE;
1201 int src_y = (g->src_y + (get_backside ? g->offset2_y : 0)) *
1202 tilesize / TILESIZE;
1204 int src_x = g->src_x * tilesize / TILESIZE;
1205 int src_y = g->src_y * tilesize / TILESIZE;
1207 int width = g->width * tilesize / TILESIZE;
1208 int height = g->height * tilesize / TILESIZE;
1209 int offset_x = g->offset_x * tilesize / TILESIZE;
1210 int offset_y = g->offset_y * tilesize / TILESIZE;
1212 if (g->offset_y == 0) /* frames are ordered horizontally */
1214 int max_width = g->anim_frames_per_line * width;
1215 int pos = (src_y / height) * max_width + src_x + frame * offset_x;
1217 src_x = pos % max_width;
1218 src_y = src_y % height + pos / max_width * height;
1220 else if (g->offset_x == 0) /* frames are ordered vertically */
1222 int max_height = g->anim_frames_per_line * height;
1223 int pos = (src_x / width) * max_height + src_y + frame * offset_y;
1225 src_x = src_x % width + pos / max_height * width;
1226 src_y = pos % max_height;
1228 else /* frames are ordered diagonally */
1230 src_x = src_x + frame * offset_x;
1231 src_y = src_y + frame * offset_y;
1234 *bitmap = src_bitmap;
1235 *x = startx + src_x;
1236 *y = starty + src_y;
1239 void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1240 int *x, int *y, boolean get_backside)
1242 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y,
1246 void getSizedGraphicSource(int graphic, int frame, int tilesize_raw,
1247 Bitmap **bitmap, int *x, int *y)
1249 getSizedGraphicSourceExt(graphic, frame, tilesize_raw, bitmap, x, y, FALSE);
1252 void getFixedGraphicSource(int graphic, int frame,
1253 Bitmap **bitmap, int *x, int *y)
1255 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y, FALSE);
1258 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1261 getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
1263 struct GraphicInfo *g = &graphic_info[graphic];
1264 int mini_startx = 0;
1265 int mini_starty = g->bitmap->height * 2 / 3;
1267 *bitmap = g->bitmap;
1268 *x = mini_startx + g->src_x / 2;
1269 *y = mini_starty + g->src_y / 2;
1273 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1274 int *x, int *y, boolean get_backside)
1276 struct GraphicInfo *g = &graphic_info[graphic];
1277 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
1278 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
1281 if (TILESIZE_VAR != TILESIZE)
1282 return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
1286 *bitmap = g->bitmap;
1288 if (g->offset_y == 0) /* frames are ordered horizontally */
1290 int max_width = g->anim_frames_per_line * g->width;
1291 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
1293 *x = pos % max_width;
1294 *y = src_y % g->height + pos / max_width * g->height;
1296 else if (g->offset_x == 0) /* frames are ordered vertically */
1298 int max_height = g->anim_frames_per_line * g->height;
1299 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
1301 *x = src_x % g->width + pos / max_height * g->width;
1302 *y = pos % max_height;
1304 else /* frames are ordered diagonally */
1306 *x = src_x + frame * g->offset_x;
1307 *y = src_y + frame * g->offset_y;
1311 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
1313 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
1316 void DrawGraphic(int x, int y, int graphic, int frame)
1319 if (!IN_SCR_FIELD(x, y))
1321 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1322 printf("DrawGraphic(): This should never happen!\n");
1328 DrawGraphicExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR, graphic,
1331 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
1333 MarkTileDirty(x, y);
1336 void DrawFixedGraphic(int x, int y, int graphic, int frame)
1339 if (!IN_SCR_FIELD(x, y))
1341 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1342 printf("DrawGraphic(): This should never happen!\n");
1347 DrawFixedGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1349 MarkTileDirty(x, y);
1352 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1358 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1360 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX_VAR, TILEY_VAR, x, y);
1362 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1366 void DrawFixedGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1372 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1373 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1376 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
1379 if (!IN_SCR_FIELD(x, y))
1381 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1382 printf("DrawGraphicThruMask(): This should never happen!\n");
1388 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
1391 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1394 MarkTileDirty(x, y);
1397 void DrawFixedGraphicThruMask(int x, int y, int graphic, int frame)
1400 if (!IN_SCR_FIELD(x, y))
1402 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1403 printf("DrawGraphicThruMask(): This should never happen!\n");
1408 DrawFixedGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1410 MarkTileDirty(x, y);
1413 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
1419 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1421 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1422 dst_x - src_x, dst_y - src_y);
1424 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX_VAR, TILEY_VAR,
1427 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1431 void DrawFixedGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y,
1432 int graphic, int frame)
1437 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1439 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1440 dst_x - src_x, dst_y - src_y);
1441 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1444 void DrawSizedGraphic(int x, int y, int graphic, int frame, int tilesize)
1446 DrawSizedGraphicExt(drawto, SX + x * tilesize, SY + y * tilesize, graphic,
1448 MarkTileDirty(x / tilesize, y / tilesize);
1451 void DrawSizedGraphicExt(DrawBuffer *d, int x, int y, int graphic, int frame,
1457 getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
1458 BlitBitmap(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
1461 void DrawMiniGraphic(int x, int y, int graphic)
1463 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1464 MarkTileDirty(x / 2, y / 2);
1467 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1472 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1473 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1476 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
1477 int graphic, int frame,
1478 int cut_mode, int mask_mode)
1483 int width = TILEX, height = TILEY;
1486 if (dx || dy) /* shifted graphic */
1488 if (x < BX1) /* object enters playfield from the left */
1495 else if (x > BX2) /* object enters playfield from the right */
1501 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1507 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1509 else if (dx) /* general horizontal movement */
1510 MarkTileDirty(x + SIGN(dx), y);
1512 if (y < BY1) /* object enters playfield from the top */
1514 if (cut_mode==CUT_BELOW) /* object completely above top border */
1522 else if (y > BY2) /* object enters playfield from the bottom */
1528 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1534 else if (dy > 0 && cut_mode == CUT_ABOVE)
1536 if (y == BY2) /* object completely above bottom border */
1542 MarkTileDirty(x, y + 1);
1543 } /* object leaves playfield to the bottom */
1544 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1546 else if (dy) /* general vertical movement */
1547 MarkTileDirty(x, y + SIGN(dy));
1551 if (!IN_SCR_FIELD(x, y))
1553 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1554 printf("DrawGraphicShifted(): This should never happen!\n");
1560 width = width * TILESIZE_VAR / TILESIZE;
1561 height = height * TILESIZE_VAR / TILESIZE;
1562 cx = cx * TILESIZE_VAR / TILESIZE;
1563 cy = cy * TILESIZE_VAR / TILESIZE;
1564 dx = dx * TILESIZE_VAR / TILESIZE;
1565 dy = dy * TILESIZE_VAR / TILESIZE;
1568 if (width > 0 && height > 0)
1570 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1576 dst_x = FX + x * TILEX_VAR + dx;
1577 dst_y = FY + y * TILEY_VAR + dy;
1579 dst_x = FX + x * TILEX + dx;
1580 dst_y = FY + y * TILEY + dy;
1583 if (mask_mode == USE_MASKING)
1585 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1586 dst_x - src_x, dst_y - src_y);
1587 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1591 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1594 MarkTileDirty(x, y);
1598 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
1599 int graphic, int frame,
1600 int cut_mode, int mask_mode)
1606 int width = TILEX_VAR, height = TILEY_VAR;
1608 int width = TILEX, height = TILEY;
1612 int x2 = x + SIGN(dx);
1613 int y2 = y + SIGN(dy);
1615 /* !!! DOES NOT WORK FOR SLOW MOVEMENT !!! */
1616 int sync_frame = GfxFrame[LEVELX(x)][LEVELY(y)];
1618 /* movement with two-tile animations must be sync'ed with movement position,
1619 not with current GfxFrame (which can be higher when using slow movement) */
1620 int anim_pos = (dx ? ABS(dx) : ABS(dy));
1621 int anim_frames = graphic_info[graphic].anim_frames;
1623 /* (we also need anim_delay here for movement animations with less frames) */
1624 int anim_delay = graphic_info[graphic].anim_delay;
1625 int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
1627 int sync_frame = anim_pos * anim_frames / TILESIZE;
1630 boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */
1631 boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */
1633 /* re-calculate animation frame for two-tile movement animation */
1634 frame = getGraphicAnimationFrame(graphic, sync_frame);
1638 printf("::: %d, %d, %d => %d [%d]\n",
1639 anim_pos, anim_frames, anim_delay, sync_frame, graphic);
1641 printf("::: %d, %d => %d\n",
1642 anim_pos, anim_frames, sync_frame);
1647 printf("::: %d [%d, %d] [%d] [%d]\n", frame, sync_frame, dy,
1648 GfxFrame[LEVELX(x)][LEVELY(y)], mask_mode);
1651 /* check if movement start graphic inside screen area and should be drawn */
1652 if (draw_start_tile && IN_SCR_FIELD(x1, y1))
1654 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
1657 dst_x = FX + x1 * TILEX_VAR;
1658 dst_y = FY + y1 * TILEY_VAR;
1660 dst_x = FX + x1 * TILEX;
1661 dst_y = FY + y1 * TILEY;
1664 if (mask_mode == USE_MASKING)
1666 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1667 dst_x - src_x, dst_y - src_y);
1668 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1672 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1675 MarkTileDirty(x1, y1);
1678 /* check if movement end graphic inside screen area and should be drawn */
1679 if (draw_end_tile && IN_SCR_FIELD(x2, y2))
1681 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
1684 dst_x = FX + x2 * TILEX_VAR;
1685 dst_y = FY + y2 * TILEY_VAR;
1687 dst_x = FX + x2 * TILEX;
1688 dst_y = FY + y2 * TILEY;
1691 if (mask_mode == USE_MASKING)
1693 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1694 dst_x - src_x, dst_y - src_y);
1695 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1699 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1702 MarkTileDirty(x2, y2);
1706 static void DrawGraphicShifted(int x, int y, int dx, int dy,
1707 int graphic, int frame,
1708 int cut_mode, int mask_mode)
1712 DrawGraphic(x, y, graphic, frame);
1717 if (graphic_info[graphic].double_movement) /* EM style movement images */
1718 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1720 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1723 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1724 int frame, int cut_mode)
1726 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1729 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1730 int cut_mode, int mask_mode)
1732 int lx = LEVELX(x), ly = LEVELY(y);
1736 if (IN_LEV_FIELD(lx, ly))
1738 SetRandomAnimationValue(lx, ly);
1740 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1741 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1743 /* do not use double (EM style) movement graphic when not moving */
1744 if (graphic_info[graphic].double_movement && !dx && !dy)
1746 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
1747 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1750 else /* border element */
1752 graphic = el2img(element);
1753 frame = getGraphicAnimationFrame(graphic, -1);
1756 if (element == EL_EXPANDABLE_WALL)
1758 boolean left_stopped = FALSE, right_stopped = FALSE;
1760 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1761 left_stopped = TRUE;
1762 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1763 right_stopped = TRUE;
1765 if (left_stopped && right_stopped)
1767 else if (left_stopped)
1769 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1770 frame = graphic_info[graphic].anim_frames - 1;
1772 else if (right_stopped)
1774 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1775 frame = graphic_info[graphic].anim_frames - 1;
1780 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1781 else if (mask_mode == USE_MASKING)
1782 DrawGraphicThruMask(x, y, graphic, frame);
1784 DrawGraphic(x, y, graphic, frame);
1787 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1788 int cut_mode, int mask_mode)
1790 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1791 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1792 cut_mode, mask_mode);
1795 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1798 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1801 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1804 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1807 void DrawLevelElementThruMask(int x, int y, int element)
1809 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1812 void DrawLevelFieldThruMask(int x, int y)
1814 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1817 /* !!! implementation of quicksand is totally broken !!! */
1818 #define IS_CRUMBLED_TILE(x, y, e) \
1819 (GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) || \
1820 !IS_MOVING(x, y) || \
1821 (e) == EL_QUICKSAND_EMPTYING || \
1822 (e) == EL_QUICKSAND_FAST_EMPTYING))
1824 static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
1829 int width, height, cx, cy;
1830 int sx = SCREENX(x), sy = SCREENY(y);
1831 int crumbled_border_size = graphic_info[graphic].border_size;
1834 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1836 for (i = 1; i < 4; i++)
1838 int dxx = (i & 1 ? dx : 0);
1839 int dyy = (i & 2 ? dy : 0);
1842 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1845 /* check if neighbour field is of same crumble type */
1846 boolean same = (IS_CRUMBLED_TILE(xx, yy, element) &&
1847 graphic_info[graphic].class ==
1848 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class);
1850 /* return if check prevents inner corner */
1851 if (same == (dxx == dx && dyy == dy))
1855 /* if we reach this point, we have an inner corner */
1857 getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
1860 width = crumbled_border_size * TILESIZE_VAR / TILESIZE;
1861 height = crumbled_border_size * TILESIZE_VAR / TILESIZE;
1862 cx = (dx > 0 ? TILEX - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
1863 cy = (dy > 0 ? TILEY - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
1865 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1866 width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
1868 width = crumbled_border_size;
1869 height = crumbled_border_size;
1870 cx = (dx > 0 ? TILEX - crumbled_border_size : 0);
1871 cy = (dy > 0 ? TILEY - crumbled_border_size : 0);
1873 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1874 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1878 static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
1883 int width, height, bx, by, cx, cy;
1884 int sx = SCREENX(x), sy = SCREENY(y);
1885 int crumbled_border_size = graphic_info[graphic].border_size;
1888 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1890 /* draw simple, sloppy, non-corner-accurate crumbled border */
1893 width = (dir == 1 || dir == 2 ? crumbled_border_size : TILEX);
1894 height = (dir == 0 || dir == 3 ? crumbled_border_size : TILEY);
1895 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
1896 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
1898 if (dir == 1 || dir == 2) /* left or right crumbled border */
1900 width = crumbled_border_size;
1902 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
1905 else /* top or bottom crumbled border */
1908 height = crumbled_border_size;
1910 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
1915 BlitBitmap(src_bitmap, drawto_field,
1916 src_x + cx * TILESIZE_VAR / TILESIZE,
1917 src_y + cy * TILESIZE_VAR / TILESIZE,
1918 width * TILESIZE_VAR / TILESIZE,
1919 height * TILESIZE_VAR / TILESIZE,
1920 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
1921 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
1923 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1924 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1927 /* (remaining middle border part must be at least as big as corner part) */
1928 if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
1929 crumbled_border_size >= TILESIZE / 3)
1932 /* correct corners of crumbled border, if needed */
1935 for (i = -1; i <= 1; i+=2)
1937 int xx = x + (dir == 0 || dir == 3 ? i : 0);
1938 int yy = y + (dir == 1 || dir == 2 ? i : 0);
1939 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1942 /* check if neighbour field is of same crumble type */
1943 if (IS_CRUMBLED_TILE(xx, yy, element) &&
1944 graphic_info[graphic].class ==
1945 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
1947 /* no crumbled corner, but continued crumbled border */
1949 int c1 = (dir == 2 || dir == 3 ? TILESIZE - crumbled_border_size : 0);
1950 int c2 = (i == 1 ? TILESIZE - crumbled_border_size : 0);
1951 int b1 = (i == 1 ? crumbled_border_size :
1952 TILESIZE - 2 * crumbled_border_size);
1954 width = crumbled_border_size;
1955 height = crumbled_border_size;
1957 if (dir == 1 || dir == 2)
1973 BlitBitmap(src_bitmap, drawto_field,
1974 src_x + bx * TILESIZE_VAR / TILESIZE,
1975 src_y + by * TILESIZE_VAR / TILESIZE,
1976 width * TILESIZE_VAR / TILESIZE,
1977 height * TILESIZE_VAR / TILESIZE,
1978 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
1979 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
1981 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
1982 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1987 if (dir == 1 || dir == 2) /* left or right crumbled border */
1989 for (i = -1; i <= 1; i+=2)
1993 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1996 /* check if neighbour field is of same crumble type */
1997 if (IS_CRUMBLED_TILE(xx, yy, element) &&
1998 graphic_info[graphic].class ==
1999 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2001 /* no crumbled corner, but continued crumbled border */
2003 width = crumbled_border_size;
2004 height = crumbled_border_size;
2005 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2006 cy = (i == 1 ? TILEY - crumbled_border_size : 0);
2008 by = (i == 1 ? crumbled_border_size :
2009 TILEY - 2 * crumbled_border_size);
2011 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2012 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2016 else /* top or bottom crumbled border */
2018 for (i = -1; i <= 1; i+=2)
2022 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2025 /* check if neighbour field is of same crumble type */
2026 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2027 graphic_info[graphic].class ==
2028 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2030 /* no crumbled corner, but continued crumbled border */
2032 width = crumbled_border_size;
2033 height = crumbled_border_size;
2034 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
2035 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2036 bx = (i == 1 ? crumbled_border_size :
2037 TILEX - 2 * crumbled_border_size);
2040 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2041 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2048 static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
2050 int sx = SCREENX(x), sy = SCREENY(y);
2053 static int xy[4][2] =
2061 if (!IN_LEV_FIELD(x, y))
2064 element = TILE_GFX_ELEMENT(x, y);
2066 /* crumble field itself */
2067 if (IS_CRUMBLED_TILE(x, y, element))
2069 if (!IN_SCR_FIELD(sx, sy))
2072 for (i = 0; i < 4; i++)
2074 int xx = x + xy[i][0];
2075 int yy = y + xy[i][1];
2077 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2080 /* check if neighbour field is of same crumble type */
2082 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2083 graphic_info[graphic].class ==
2084 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2087 if (IS_CRUMBLED_TILE(xx, yy, element))
2091 DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
2094 if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
2095 graphic_info[graphic].anim_frames == 2)
2097 for (i = 0; i < 4; i++)
2099 int dx = (i & 1 ? +1 : -1);
2100 int dy = (i & 2 ? +1 : -1);
2102 DrawLevelFieldCrumbledInnerCorners(x, y, dx, dy, graphic);
2106 MarkTileDirty(sx, sy);
2108 else /* center field not crumbled -- crumble neighbour fields */
2110 for (i = 0; i < 4; i++)
2112 int xx = x + xy[i][0];
2113 int yy = y + xy[i][1];
2114 int sxx = sx + xy[i][0];
2115 int syy = sy + xy[i][1];
2117 if (!IN_LEV_FIELD(xx, yy) ||
2118 !IN_SCR_FIELD(sxx, syy))
2121 if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
2124 element = TILE_GFX_ELEMENT(xx, yy);
2126 if (!IS_CRUMBLED_TILE(xx, yy, element))
2129 graphic = el_act2crm(element, ACTION_DEFAULT);
2131 DrawLevelFieldCrumbledBorders(xx, yy, graphic, 0, 3 - i);
2133 MarkTileDirty(sxx, syy);
2138 void DrawLevelFieldCrumbled(int x, int y)
2142 if (!IN_LEV_FIELD(x, y))
2146 /* !!! CHECK THIS !!! */
2149 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2150 GFX_CRUMBLED(GfxElement[x][y]))
2153 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2154 GfxElement[x][y] != EL_UNDEFINED &&
2155 GFX_CRUMBLED(GfxElement[x][y]))
2157 DrawLevelFieldCrumbledDigging(x, y, GfxDir[x][y], GfxFrame[x][y]);
2164 graphic = el_act2crm(TILE_GFX_ELEMENT(x, y), ACTION_DEFAULT);
2166 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
2169 DrawLevelFieldCrumbledExt(x, y, graphic, 0);
2172 void DrawLevelFieldCrumbledDigging(int x, int y, int direction,
2175 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
2176 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
2177 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
2178 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
2179 int sx = SCREENX(x), sy = SCREENY(y);
2181 DrawGraphic(sx, sy, graphic1, frame1);
2182 DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
2185 void DrawLevelFieldCrumbledNeighbours(int x, int y)
2187 int sx = SCREENX(x), sy = SCREENY(y);
2188 static int xy[4][2] =
2197 for (i = 0; i < 4; i++)
2199 int xx = x + xy[i][0];
2200 int yy = y + xy[i][1];
2201 int sxx = sx + xy[i][0];
2202 int syy = sy + xy[i][1];
2204 if (!IN_LEV_FIELD(xx, yy) ||
2205 !IN_SCR_FIELD(sxx, syy) ||
2206 !GFX_CRUMBLED(Feld[xx][yy]) ||
2210 DrawLevelField(xx, yy);
2214 static int getBorderElement(int x, int y)
2218 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
2219 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
2220 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
2221 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
2222 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
2223 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
2224 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
2226 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2227 int steel_position = (x == -1 && y == -1 ? 0 :
2228 x == lev_fieldx && y == -1 ? 1 :
2229 x == -1 && y == lev_fieldy ? 2 :
2230 x == lev_fieldx && y == lev_fieldy ? 3 :
2231 x == -1 || x == lev_fieldx ? 4 :
2232 y == -1 || y == lev_fieldy ? 5 : 6);
2234 return border[steel_position][steel_type];
2237 void DrawScreenElement(int x, int y, int element)
2239 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
2240 DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
2243 void DrawLevelElement(int x, int y, int element)
2245 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2246 DrawScreenElement(SCREENX(x), SCREENY(y), element);
2249 void DrawScreenField(int x, int y)
2251 int lx = LEVELX(x), ly = LEVELY(y);
2252 int element, content;
2254 if (!IN_LEV_FIELD(lx, ly))
2256 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
2259 element = getBorderElement(lx, ly);
2261 DrawScreenElement(x, y, element);
2266 element = Feld[lx][ly];
2267 content = Store[lx][ly];
2269 if (IS_MOVING(lx, ly))
2271 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
2272 boolean cut_mode = NO_CUTTING;
2274 if (element == EL_QUICKSAND_EMPTYING ||
2275 element == EL_QUICKSAND_FAST_EMPTYING ||
2276 element == EL_MAGIC_WALL_EMPTYING ||
2277 element == EL_BD_MAGIC_WALL_EMPTYING ||
2278 element == EL_DC_MAGIC_WALL_EMPTYING ||
2279 element == EL_AMOEBA_DROPPING)
2280 cut_mode = CUT_ABOVE;
2281 else if (element == EL_QUICKSAND_FILLING ||
2282 element == EL_QUICKSAND_FAST_FILLING ||
2283 element == EL_MAGIC_WALL_FILLING ||
2284 element == EL_BD_MAGIC_WALL_FILLING ||
2285 element == EL_DC_MAGIC_WALL_FILLING)
2286 cut_mode = CUT_BELOW;
2289 if (lx == 9 && ly == 1)
2290 printf("::: %s [%d] [%d, %d] [%d]\n",
2291 EL_NAME(TILE_GFX_ELEMENT(lx, ly)),
2292 el_act2crm(TILE_GFX_ELEMENT(lx, ly), ACTION_DEFAULT),
2293 element_info[EL_QUICKSAND_EMPTYING].graphic[ACTION_DEFAULT],
2294 element_info[EL_QUICKSAND_EMPTYING].crumbled[ACTION_DEFAULT],
2295 GFX_CRUMBLED(TILE_GFX_ELEMENT(lx, ly)));
2298 if (cut_mode == CUT_ABOVE)
2300 DrawScreenElement(x, y, element);
2302 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
2305 DrawScreenElement(x, y, EL_EMPTY);
2308 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
2309 else if (cut_mode == NO_CUTTING)
2310 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
2313 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
2316 if (cut_mode == CUT_BELOW &&
2317 IN_LEV_FIELD(lx, ly + 1) && IN_SCR_FIELD(x, y + 1))
2318 DrawLevelElement(lx, ly + 1, element);
2322 if (content == EL_ACID)
2324 int dir = MovDir[lx][ly];
2325 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
2326 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
2328 DrawLevelElementThruMask(newlx, newly, EL_ACID);
2331 else if (IS_BLOCKED(lx, ly))
2336 boolean cut_mode = NO_CUTTING;
2337 int element_old, content_old;
2339 Blocked2Moving(lx, ly, &oldx, &oldy);
2342 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
2343 MovDir[oldx][oldy] == MV_RIGHT);
2345 element_old = Feld[oldx][oldy];
2346 content_old = Store[oldx][oldy];
2348 if (element_old == EL_QUICKSAND_EMPTYING ||
2349 element_old == EL_QUICKSAND_FAST_EMPTYING ||
2350 element_old == EL_MAGIC_WALL_EMPTYING ||
2351 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2352 element_old == EL_DC_MAGIC_WALL_EMPTYING ||
2353 element_old == EL_AMOEBA_DROPPING)
2354 cut_mode = CUT_ABOVE;
2356 DrawScreenElement(x, y, EL_EMPTY);
2359 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2361 else if (cut_mode == NO_CUTTING)
2362 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2365 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2368 else if (IS_DRAWABLE(element))
2369 DrawScreenElement(x, y, element);
2371 DrawScreenElement(x, y, EL_EMPTY);
2374 void DrawLevelField(int x, int y)
2376 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2377 DrawScreenField(SCREENX(x), SCREENY(y));
2378 else if (IS_MOVING(x, y))
2382 Moving2Blocked(x, y, &newx, &newy);
2383 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2384 DrawScreenField(SCREENX(newx), SCREENY(newy));
2386 else if (IS_BLOCKED(x, y))
2390 Blocked2Moving(x, y, &oldx, &oldy);
2391 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2392 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2396 void DrawMiniElement(int x, int y, int element)
2400 graphic = el2edimg(element);
2401 DrawMiniGraphic(x, y, graphic);
2404 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2406 int x = sx + scroll_x, y = sy + scroll_y;
2408 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2409 DrawMiniElement(sx, sy, EL_EMPTY);
2410 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2411 DrawMiniElement(sx, sy, Feld[x][y]);
2413 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
2416 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
2417 int x, int y, int xsize, int ysize, int font_nr)
2419 int font_width = getFontWidth(font_nr);
2420 int font_height = getFontHeight(font_nr);
2421 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2424 int dst_x = SX + startx + x * font_width;
2425 int dst_y = SY + starty + y * font_height;
2426 int width = graphic_info[graphic].width;
2427 int height = graphic_info[graphic].height;
2428 int inner_width = MAX(width - 2 * font_width, font_width);
2429 int inner_height = MAX(height - 2 * font_height, font_height);
2430 int inner_sx = (width >= 3 * font_width ? font_width : 0);
2431 int inner_sy = (height >= 3 * font_height ? font_height : 0);
2432 boolean draw_masked = graphic_info[graphic].draw_masked;
2434 getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2436 if (src_bitmap == NULL || width < font_width || height < font_height)
2438 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
2442 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
2443 inner_sx + (x - 1) * font_width % inner_width);
2444 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
2445 inner_sy + (y - 1) * font_height % inner_height);
2449 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
2450 dst_x - src_x, dst_y - src_y);
2451 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
2455 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
2459 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
2461 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2462 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2463 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2464 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2465 boolean no_delay = (tape.warp_forward);
2466 unsigned long anim_delay = 0;
2467 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2468 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
2469 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2470 int font_width = getFontWidth(font_nr);
2471 int font_height = getFontHeight(font_nr);
2472 int max_xsize = level.envelope[envelope_nr].xsize;
2473 int max_ysize = level.envelope[envelope_nr].ysize;
2474 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2475 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2476 int xend = max_xsize;
2477 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2478 int xstep = (xstart < xend ? 1 : 0);
2479 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2482 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2484 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2485 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2486 int sx = (SXSIZE - xsize * font_width) / 2;
2487 int sy = (SYSIZE - ysize * font_height) / 2;
2490 SetDrawtoField(DRAW_BUFFERED);
2492 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2494 SetDrawtoField(DRAW_BACKBUFFER);
2496 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
2497 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
2500 DrawTextBuffer(SX + sx + font_width, SY + sy + font_height,
2501 level.envelope[envelope_nr].text, font_nr, max_xsize,
2502 xsize - 2, ysize - 2, 0, mask_mode,
2503 level.envelope[envelope_nr].autowrap,
2504 level.envelope[envelope_nr].centered, FALSE);
2506 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
2507 level.envelope[envelope_nr].text, font_nr, max_xsize,
2508 xsize - 2, ysize - 2, mask_mode);
2511 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2514 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2518 void AnimateEnvelopeDoor(char *text, int anim_mode, int action)
2521 int envelope_nr = 0;
2523 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2524 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2525 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2526 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2527 boolean no_delay = (tape.warp_forward);
2528 unsigned long anim_delay = 0;
2529 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2530 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
2532 int max_word_len = maxWordLengthInString(text);
2533 int font_nr = (max_word_len > 7 ? FONT_TEXT_1 : FONT_TEXT_2);
2535 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2537 int font_width = getFontWidth(font_nr);
2538 int font_height = getFontHeight(font_nr);
2542 int max_xsize = DXSIZE / font_width;
2543 int max_ysize = DYSIZE / font_height;
2545 int max_xsize = 7; /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
2546 int max_ysize = 13; /* tools.c: MAX_REQUEST_LINES == 13 */
2550 int max_xsize = level.envelope[envelope_nr].xsize;
2551 int max_ysize = level.envelope[envelope_nr].ysize;
2553 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2554 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2555 int xend = max_xsize;
2556 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2557 int xstep = (xstart < xend ? 1 : 0);
2558 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2563 char *text_copy = getStringCopy(text);
2566 font_nr = FONT_TEXT_2;
2568 if (maxWordLengthInString(text) > 7) /* MAX_REQUEST_LINE_FONT1_LEN == 7 */
2570 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
2571 font_nr = FONT_TEXT_1;
2574 int max_word_len = 0;
2576 char *text_copy = getStringCopy(text);
2578 font_nr = FONT_TEXT_2;
2580 for (text_ptr = text; *text_ptr; text_ptr++)
2582 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2584 if (max_word_len > 7) /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
2586 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
2587 font_nr = FONT_TEXT_1;
2596 for (text_ptr = text_copy; *text_ptr; text_ptr++)
2597 if (*text_ptr == ' ')
2602 dDX = SX + (SXSIZE - DXSIZE) / 2 - DX;
2603 dDY = SY + (SYSIZE - DYSIZE) / 2 - DY;
2605 dDX = SX + SXSIZE / 2 - max_xsize * font_width / 2 - DX;
2606 dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY;
2609 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2611 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2612 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2613 int sx = (SXSIZE - xsize * font_width) / 2;
2614 int sy = (SYSIZE - ysize * font_height) / 2;
2618 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2620 SetDrawtoField(DRAW_BUFFERED);
2622 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2624 SetDrawtoField(DRAW_BACKBUFFER);
2627 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
2628 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
2633 DrawTextBuffer(SX + sx + font_width, SY + sy + font_height + 8,
2634 text_copy, font_nr, max_xsize,
2635 xsize - 2, ysize - 2, 2, mask_mode,
2636 FALSE, TRUE, FALSE);
2638 DrawTextBuffer(SX + sx + font_width, SY + sy + font_height,
2639 level.envelope[envelope_nr].text, font_nr, max_xsize,
2640 xsize - 2, ysize - 2, 0, mask_mode,
2641 level.envelope[envelope_nr].autowrap,
2642 level.envelope[envelope_nr].centered, FALSE);
2646 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
2647 level.envelope[envelope_nr].text, font_nr, max_xsize,
2648 xsize - 2, ysize - 2, mask_mode);
2651 /* copy request gadgets to door backbuffer */
2653 if ((ysize - 2) > 13)
2654 BlitBitmap(bitmap_db_door, drawto,
2655 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
2656 DOOR_GFX_PAGEY1 + 13 * font_height,
2657 (xsize - 2) * font_width,
2658 (ysize - 2 - 13) * font_height,
2659 SX + sx + font_width,
2660 SY + sy + font_height * (1 + 13));
2662 if ((ysize - 2) > 13)
2663 BlitBitmap(bitmap_db_door, drawto,
2664 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
2665 DOOR_GFX_PAGEY1 + 13 * font_height,
2666 (xsize - 2) * font_width,
2667 (ysize - 2 - 13) * font_height,
2668 SX + sx + font_width,
2669 SY + sy + font_height * (1 + 13));
2673 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2674 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
2676 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2686 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2694 void ShowEnvelope(int envelope_nr)
2696 int element = EL_ENVELOPE_1 + envelope_nr;
2697 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2698 int sound_opening = element_info[element].sound[ACTION_OPENING];
2699 int sound_closing = element_info[element].sound[ACTION_CLOSING];
2700 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2701 boolean no_delay = (tape.warp_forward);
2702 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
2703 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
2704 int anim_mode = graphic_info[graphic].anim_mode;
2705 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
2706 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
2708 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
2710 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
2712 if (anim_mode == ANIM_DEFAULT)
2713 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
2715 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
2718 Delay(wait_delay_value);
2720 WaitForEventToContinue();
2722 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
2724 if (anim_mode != ANIM_NONE)
2725 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
2727 if (anim_mode == ANIM_DEFAULT)
2728 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
2730 game.envelope_active = FALSE;
2732 SetDrawtoField(DRAW_BUFFERED);
2734 redraw_mask |= REDRAW_FIELD;
2738 void ShowEnvelopeDoor(char *text, int action)
2741 int last_game_status = game_status; /* save current game status */
2742 // int last_draw_background_mask = gfx.draw_background_mask;
2743 int envelope_nr = 0;
2745 int element = EL_ENVELOPE_1 + envelope_nr;
2746 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2747 int sound_opening = element_info[element].sound[ACTION_OPENING];
2748 int sound_closing = element_info[element].sound[ACTION_CLOSING];
2750 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2751 boolean no_delay = (tape.warp_forward);
2752 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
2753 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
2755 int anim_mode = graphic_info[graphic].anim_mode;
2756 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
2757 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
2760 if (game_status == GAME_MODE_PLAYING)
2762 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2763 BlitScreenToBitmap_EM(backbuffer);
2764 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
2765 BlitScreenToBitmap_SP(backbuffer);
2768 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2772 SetDrawtoField(DRAW_BACKBUFFER);
2774 // SetDrawBackgroundMask(REDRAW_NONE);
2776 if (action == ACTION_OPENING)
2778 BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2780 if (game_status != GAME_MODE_MAIN)
2784 /* force DOOR font inside door area */
2785 game_status = GAME_MODE_PSEUDO_DOOR;
2788 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
2790 if (action == ACTION_OPENING)
2792 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
2794 if (anim_mode == ANIM_DEFAULT)
2795 AnimateEnvelopeDoor(text, ANIM_DEFAULT, ACTION_OPENING);
2797 AnimateEnvelopeDoor(text, main_anim_mode, ACTION_OPENING);
2801 Delay(wait_delay_value);
2803 WaitForEventToContinue();
2808 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
2810 if (anim_mode != ANIM_NONE)
2811 AnimateEnvelopeDoor(text, main_anim_mode, ACTION_CLOSING);
2813 if (anim_mode == ANIM_DEFAULT)
2814 AnimateEnvelopeDoor(text, ANIM_DEFAULT, ACTION_CLOSING);
2817 game.envelope_active = FALSE;
2820 // game_status = last_game_status; /* restore current game status */
2822 if (action == ACTION_CLOSING)
2824 if (game_status != GAME_MODE_MAIN)
2827 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2830 SetDrawtoField(DRAW_BUFFERED);
2833 // SetDrawBackgroundMask(last_draw_background_mask);
2836 redraw_mask = REDRAW_FIELD;
2837 // redraw_mask |= REDRAW_ALL;
2839 redraw_mask |= REDRAW_FIELD;
2843 if (game_status == GAME_MODE_MAIN)
2848 /* (important: after "BackToFront()", but before "SetDrawtoField()") */
2849 game_status = last_game_status; /* restore current game status */
2851 if (game_status == GAME_MODE_PLAYING &&
2852 level.game_engine_type == GAME_ENGINE_TYPE_RND)
2853 SetDrawtoField(DRAW_BUFFERED);
2859 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
2863 int graphic = el2preimg(element);
2865 getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
2866 BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
2874 SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
2875 SetDrawBackgroundMask(REDRAW_FIELD);
2877 SetDrawBackgroundMask(REDRAW_NONE);
2882 for (x = BX1; x <= BX2; x++)
2883 for (y = BY1; y <= BY2; y++)
2884 DrawScreenField(x, y);
2886 redraw_mask |= REDRAW_FIELD;
2889 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2893 for (x = 0; x < size_x; x++)
2894 for (y = 0; y < size_y; y++)
2895 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2897 redraw_mask |= REDRAW_FIELD;
2900 static void DrawPreviewLevelExt(int from_x, int from_y)
2902 boolean show_level_border = (BorderElement != EL_EMPTY);
2903 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
2904 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
2905 int tile_size = preview.tile_size;
2906 int preview_width = preview.xsize * tile_size;
2907 int preview_height = preview.ysize * tile_size;
2908 int real_preview_xsize = MIN(level_xsize, preview.xsize);
2909 int real_preview_ysize = MIN(level_ysize, preview.ysize);
2910 int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
2911 int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
2914 DrawBackground(dst_x, dst_y, preview_width, preview_height);
2916 dst_x += (preview_width - real_preview_xsize * tile_size) / 2;
2917 dst_y += (preview_height - real_preview_ysize * tile_size) / 2;
2919 for (x = 0; x < real_preview_xsize; x++)
2921 for (y = 0; y < real_preview_ysize; y++)
2923 int lx = from_x + x + (show_level_border ? -1 : 0);
2924 int ly = from_y + y + (show_level_border ? -1 : 0);
2925 int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
2926 getBorderElement(lx, ly));
2928 DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size,
2929 element, tile_size);
2933 redraw_mask |= REDRAW_MICROLEVEL;
2936 #define MICROLABEL_EMPTY 0
2937 #define MICROLABEL_LEVEL_NAME 1
2938 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
2939 #define MICROLABEL_LEVEL_AUTHOR 3
2940 #define MICROLABEL_IMPORTED_FROM_HEAD 4
2941 #define MICROLABEL_IMPORTED_FROM 5
2942 #define MICROLABEL_IMPORTED_BY_HEAD 6
2943 #define MICROLABEL_IMPORTED_BY 7
2945 static int getMaxTextLength(struct TextPosInfo *pos, int font_nr)
2947 int max_text_width = SXSIZE;
2948 int font_width = getFontWidth(font_nr);
2950 if (pos->align == ALIGN_CENTER)
2951 max_text_width = (pos->x < SXSIZE / 2 ? pos->x * 2 : (SXSIZE - pos->x) * 2);
2952 else if (pos->align == ALIGN_RIGHT)
2953 max_text_width = pos->x;
2955 max_text_width = SXSIZE - pos->x;
2957 return max_text_width / font_width;
2960 static void DrawPreviewLevelLabelExt(int mode)
2962 struct TextPosInfo *pos = &menu.main.text.level_info_2;
2963 char label_text[MAX_OUTPUT_LINESIZE + 1];
2964 int max_len_label_text;
2966 int font_nr = pos->font;
2969 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
2970 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
2971 mode == MICROLABEL_IMPORTED_BY_HEAD)
2972 font_nr = pos->font_alt;
2974 int font_nr = FONT_TEXT_2;
2977 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
2978 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
2979 mode == MICROLABEL_IMPORTED_BY_HEAD)
2980 font_nr = FONT_TEXT_3;
2984 max_len_label_text = getMaxTextLength(pos, font_nr);
2986 max_len_label_text = SXSIZE / getFontWidth(font_nr);
2990 if (pos->size != -1)
2991 max_len_label_text = pos->size;
2994 for (i = 0; i < max_len_label_text; i++)
2995 label_text[i] = ' ';
2996 label_text[max_len_label_text] = '\0';
2998 if (strlen(label_text) > 0)
3001 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3003 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3004 int lypos = MICROLABEL2_YPOS;
3006 DrawText(lxpos, lypos, label_text, font_nr);
3011 (mode == MICROLABEL_LEVEL_NAME ? level.name :
3012 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
3013 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
3014 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
3015 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
3016 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
3017 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
3018 max_len_label_text);
3019 label_text[max_len_label_text] = '\0';
3021 if (strlen(label_text) > 0)
3024 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3026 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3027 int lypos = MICROLABEL2_YPOS;
3029 DrawText(lxpos, lypos, label_text, font_nr);
3033 redraw_mask |= REDRAW_MICROLEVEL;
3036 void DrawPreviewLevel(boolean restart)
3038 static unsigned long scroll_delay = 0;
3039 static unsigned long label_delay = 0;
3040 static int from_x, from_y, scroll_direction;
3041 static int label_state, label_counter;
3042 unsigned long scroll_delay_value = preview.step_delay;
3043 boolean show_level_border = (BorderElement != EL_EMPTY);
3044 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3045 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3046 int last_game_status = game_status; /* save current game status */
3049 /* force PREVIEW font on preview level */
3050 game_status = GAME_MODE_PSEUDO_PREVIEW;
3058 if (preview.anim_mode == ANIM_CENTERED)
3060 if (level_xsize > preview.xsize)
3061 from_x = (level_xsize - preview.xsize) / 2;
3062 if (level_ysize > preview.ysize)
3063 from_y = (level_ysize - preview.ysize) / 2;
3066 from_x += preview.xoffset;
3067 from_y += preview.yoffset;
3069 scroll_direction = MV_RIGHT;
3073 DrawPreviewLevelExt(from_x, from_y);
3074 DrawPreviewLevelLabelExt(label_state);
3076 /* initialize delay counters */
3077 DelayReached(&scroll_delay, 0);
3078 DelayReached(&label_delay, 0);
3080 if (leveldir_current->name)
3082 struct TextPosInfo *pos = &menu.main.text.level_info_1;
3083 char label_text[MAX_OUTPUT_LINESIZE + 1];
3085 int font_nr = pos->font;
3087 int font_nr = FONT_TEXT_1;
3090 int max_len_label_text = getMaxTextLength(pos, font_nr);
3092 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
3100 if (pos->size != -1)
3101 max_len_label_text = pos->size;
3104 strncpy(label_text, leveldir_current->name, max_len_label_text);
3105 label_text[max_len_label_text] = '\0';
3108 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3110 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3111 lypos = SY + MICROLABEL1_YPOS;
3113 DrawText(lxpos, lypos, label_text, font_nr);
3117 game_status = last_game_status; /* restore current game status */
3122 /* scroll preview level, if needed */
3123 if (preview.anim_mode != ANIM_NONE &&
3124 (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
3125 DelayReached(&scroll_delay, scroll_delay_value))
3127 switch (scroll_direction)
3132 from_x -= preview.step_offset;
3133 from_x = (from_x < 0 ? 0 : from_x);
3136 scroll_direction = MV_UP;
3140 if (from_x < level_xsize - preview.xsize)
3142 from_x += preview.step_offset;
3143 from_x = (from_x > level_xsize - preview.xsize ?
3144 level_xsize - preview.xsize : from_x);
3147 scroll_direction = MV_DOWN;
3153 from_y -= preview.step_offset;
3154 from_y = (from_y < 0 ? 0 : from_y);
3157 scroll_direction = MV_RIGHT;
3161 if (from_y < level_ysize - preview.ysize)
3163 from_y += preview.step_offset;
3164 from_y = (from_y > level_ysize - preview.ysize ?
3165 level_ysize - preview.ysize : from_y);
3168 scroll_direction = MV_LEFT;
3175 DrawPreviewLevelExt(from_x, from_y);
3178 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
3179 /* redraw micro level label, if needed */
3180 if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
3181 !strEqual(level.author, ANONYMOUS_NAME) &&
3182 !strEqual(level.author, leveldir_current->name) &&
3183 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
3185 int max_label_counter = 23;
3187 if (leveldir_current->imported_from != NULL &&
3188 strlen(leveldir_current->imported_from) > 0)
3189 max_label_counter += 14;
3190 if (leveldir_current->imported_by != NULL &&
3191 strlen(leveldir_current->imported_by) > 0)
3192 max_label_counter += 14;
3194 label_counter = (label_counter + 1) % max_label_counter;
3195 label_state = (label_counter >= 0 && label_counter <= 7 ?
3196 MICROLABEL_LEVEL_NAME :
3197 label_counter >= 9 && label_counter <= 12 ?
3198 MICROLABEL_LEVEL_AUTHOR_HEAD :
3199 label_counter >= 14 && label_counter <= 21 ?
3200 MICROLABEL_LEVEL_AUTHOR :
3201 label_counter >= 23 && label_counter <= 26 ?
3202 MICROLABEL_IMPORTED_FROM_HEAD :
3203 label_counter >= 28 && label_counter <= 35 ?
3204 MICROLABEL_IMPORTED_FROM :
3205 label_counter >= 37 && label_counter <= 40 ?
3206 MICROLABEL_IMPORTED_BY_HEAD :
3207 label_counter >= 42 && label_counter <= 49 ?
3208 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
3210 if (leveldir_current->imported_from == NULL &&
3211 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
3212 label_state == MICROLABEL_IMPORTED_FROM))
3213 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
3214 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
3216 DrawPreviewLevelLabelExt(label_state);
3219 game_status = last_game_status; /* restore current game status */
3222 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3223 int graphic, int sync_frame, int mask_mode)
3225 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3227 if (mask_mode == USE_MASKING)
3228 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3230 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
3233 inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3234 int graphic, int sync_frame,
3237 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3239 if (mask_mode == USE_MASKING)
3240 DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3242 DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
3245 inline void DrawGraphicAnimation(int x, int y, int graphic)
3247 int lx = LEVELX(x), ly = LEVELY(y);
3249 if (!IN_SCR_FIELD(x, y))
3253 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
3254 graphic, GfxFrame[lx][ly], NO_MASKING);
3256 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3257 graphic, GfxFrame[lx][ly], NO_MASKING);
3259 MarkTileDirty(x, y);
3262 inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
3264 int lx = LEVELX(x), ly = LEVELY(y);
3266 if (!IN_SCR_FIELD(x, y))
3269 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3270 graphic, GfxFrame[lx][ly], NO_MASKING);
3271 MarkTileDirty(x, y);
3274 void DrawLevelGraphicAnimation(int x, int y, int graphic)
3276 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3279 void DrawLevelElementAnimation(int x, int y, int element)
3281 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3283 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3286 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
3288 int sx = SCREENX(x), sy = SCREENY(y);
3290 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3293 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3296 DrawGraphicAnimation(sx, sy, graphic);
3299 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
3300 DrawLevelFieldCrumbled(x, y);
3302 if (GFX_CRUMBLED(Feld[x][y]))
3303 DrawLevelFieldCrumbled(x, y);
3307 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
3309 int sx = SCREENX(x), sy = SCREENY(y);
3312 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3315 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3317 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3320 DrawGraphicAnimation(sx, sy, graphic);
3322 if (GFX_CRUMBLED(element))
3323 DrawLevelFieldCrumbled(x, y);
3326 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
3328 if (player->use_murphy)
3330 /* this works only because currently only one player can be "murphy" ... */
3331 static int last_horizontal_dir = MV_LEFT;
3332 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
3334 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3335 last_horizontal_dir = move_dir;
3337 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
3339 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
3341 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
3347 return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
3350 static boolean equalGraphics(int graphic1, int graphic2)
3352 struct GraphicInfo *g1 = &graphic_info[graphic1];
3353 struct GraphicInfo *g2 = &graphic_info[graphic2];
3355 return (g1->bitmap == g2->bitmap &&
3356 g1->src_x == g2->src_x &&
3357 g1->src_y == g2->src_y &&
3358 g1->anim_frames == g2->anim_frames &&
3359 g1->anim_delay == g2->anim_delay &&
3360 g1->anim_mode == g2->anim_mode);
3363 void DrawAllPlayers()
3367 for (i = 0; i < MAX_PLAYERS; i++)
3368 if (stored_player[i].active)
3369 DrawPlayer(&stored_player[i]);
3372 void DrawPlayerField(int x, int y)
3374 if (!IS_PLAYER(x, y))
3377 DrawPlayer(PLAYERINFO(x, y));
3380 #define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
3382 void DrawPlayer(struct PlayerInfo *player)
3384 int jx = player->jx;
3385 int jy = player->jy;
3386 int move_dir = player->MovDir;
3387 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
3388 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
3389 int last_jx = (player->is_moving ? jx - dx : jx);
3390 int last_jy = (player->is_moving ? jy - dy : jy);
3391 int next_jx = jx + dx;
3392 int next_jy = jy + dy;
3393 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
3394 boolean player_is_opaque = FALSE;
3395 int sx = SCREENX(jx), sy = SCREENY(jy);
3396 int sxx = 0, syy = 0;
3397 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
3399 int action = ACTION_DEFAULT;
3400 int last_player_graphic = getPlayerGraphic(player, move_dir);
3401 int last_player_frame = player->Frame;
3404 /* GfxElement[][] is set to the element the player is digging or collecting;
3405 remove also for off-screen player if the player is not moving anymore */
3406 if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
3407 GfxElement[jx][jy] = EL_UNDEFINED;
3409 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
3413 if (!IN_LEV_FIELD(jx, jy))
3415 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
3416 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
3417 printf("DrawPlayerField(): This should never happen!\n");
3422 if (element == EL_EXPLOSION)
3425 action = (player->is_pushing ? ACTION_PUSHING :
3426 player->is_digging ? ACTION_DIGGING :
3427 player->is_collecting ? ACTION_COLLECTING :
3428 player->is_moving ? ACTION_MOVING :
3429 player->is_snapping ? ACTION_SNAPPING :
3430 player->is_dropping ? ACTION_DROPPING :
3431 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
3433 if (player->is_waiting)
3434 move_dir = player->dir_waiting;
3436 InitPlayerGfxAnimation(player, action, move_dir);
3438 /* ----------------------------------------------------------------------- */
3439 /* draw things in the field the player is leaving, if needed */
3440 /* ----------------------------------------------------------------------- */
3442 if (player->is_moving)
3444 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
3446 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
3448 if (last_element == EL_DYNAMITE_ACTIVE ||
3449 last_element == EL_EM_DYNAMITE_ACTIVE ||
3450 last_element == EL_SP_DISK_RED_ACTIVE)
3451 DrawDynamite(last_jx, last_jy);
3453 DrawLevelFieldThruMask(last_jx, last_jy);
3455 else if (last_element == EL_DYNAMITE_ACTIVE ||
3456 last_element == EL_EM_DYNAMITE_ACTIVE ||
3457 last_element == EL_SP_DISK_RED_ACTIVE)
3458 DrawDynamite(last_jx, last_jy);
3460 /* !!! this is not enough to prevent flickering of players which are
3461 moving next to each others without a free tile between them -- this
3462 can only be solved by drawing all players layer by layer (first the
3463 background, then the foreground etc.) !!! => TODO */
3464 else if (!IS_PLAYER(last_jx, last_jy))
3465 DrawLevelField(last_jx, last_jy);
3468 DrawLevelField(last_jx, last_jy);
3471 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
3472 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
3475 if (!IN_SCR_FIELD(sx, sy))
3478 /* ----------------------------------------------------------------------- */
3479 /* draw things behind the player, if needed */
3480 /* ----------------------------------------------------------------------- */
3483 DrawLevelElement(jx, jy, Back[jx][jy]);
3484 else if (IS_ACTIVE_BOMB(element))
3485 DrawLevelElement(jx, jy, EL_EMPTY);
3488 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
3490 int old_element = GfxElement[jx][jy];
3491 int old_graphic = el_act_dir2img(old_element, action, move_dir);
3492 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
3494 if (GFX_CRUMBLED(old_element))
3495 DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
3497 DrawGraphic(sx, sy, old_graphic, frame);
3499 if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
3500 player_is_opaque = TRUE;
3504 GfxElement[jx][jy] = EL_UNDEFINED;
3506 /* make sure that pushed elements are drawn with correct frame rate */
3508 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
3510 if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
3511 GfxFrame[jx][jy] = player->StepFrame;
3513 if (player->is_pushing && player->is_moving)
3514 GfxFrame[jx][jy] = player->StepFrame;
3517 DrawLevelField(jx, jy);
3521 #if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
3522 /* ----------------------------------------------------------------------- */
3523 /* draw player himself */
3524 /* ----------------------------------------------------------------------- */
3526 graphic = getPlayerGraphic(player, move_dir);
3528 /* in the case of changed player action or direction, prevent the current
3529 animation frame from being restarted for identical animations */
3530 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
3531 player->Frame = last_player_frame;
3533 frame = getGraphicAnimationFrame(graphic, player->Frame);
3537 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3538 sxx = player->GfxPos;
3540 syy = player->GfxPos;
3543 if (!setup.soft_scrolling && ScreenMovPos)
3546 if (player_is_opaque)
3547 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
3549 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3551 if (SHIELD_ON(player))
3553 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
3554 IMG_SHIELD_NORMAL_ACTIVE);
3555 int frame = getGraphicAnimationFrame(graphic, -1);
3557 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3561 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
3564 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3565 sxx = player->GfxPos;
3567 syy = player->GfxPos;
3571 /* ----------------------------------------------------------------------- */
3572 /* draw things the player is pushing, if needed */
3573 /* ----------------------------------------------------------------------- */
3576 printf("::: %d, %d [%d, %d] [%d]\n",
3577 player->is_pushing, player_is_moving, player->GfxAction,
3578 player->is_moving, player_is_moving);
3582 if (player->is_pushing && player->is_moving)
3584 int px = SCREENX(jx), py = SCREENY(jy);
3585 int pxx = (TILEX - ABS(sxx)) * dx;
3586 int pyy = (TILEY - ABS(syy)) * dy;
3587 int gfx_frame = GfxFrame[jx][jy];
3593 if (!IS_MOVING(jx, jy)) /* push movement already finished */
3595 element = Feld[next_jx][next_jy];
3596 gfx_frame = GfxFrame[next_jx][next_jy];
3599 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
3602 sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
3603 frame = getGraphicAnimationFrame(graphic, sync_frame);
3605 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
3608 /* draw background element under pushed element (like the Sokoban field) */
3610 if (game.use_masked_pushing && IS_MOVING(jx, jy))
3612 /* this allows transparent pushing animation over non-black background */
3615 DrawLevelElement(jx, jy, Back[jx][jy]);
3617 DrawLevelElement(jx, jy, EL_EMPTY);
3619 if (Back[next_jx][next_jy])
3620 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
3622 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
3624 else if (Back[next_jx][next_jy])
3625 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
3627 if (Back[next_jx][next_jy])
3628 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
3632 printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
3633 jx, px, player->GfxPos, player->StepFrame,
3638 GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
3642 /* do not draw (EM style) pushing animation when pushing is finished */
3643 /* (two-tile animations usually do not contain start and end frame) */
3644 if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
3645 DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
3647 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
3649 /* masked drawing is needed for EMC style (double) movement graphics */
3650 /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
3651 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
3656 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
3657 /* ----------------------------------------------------------------------- */
3658 /* draw player himself */
3659 /* ----------------------------------------------------------------------- */
3661 graphic = getPlayerGraphic(player, move_dir);
3663 /* in the case of changed player action or direction, prevent the current
3664 animation frame from being restarted for identical animations */
3665 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
3666 player->Frame = last_player_frame;
3668 frame = getGraphicAnimationFrame(graphic, player->Frame);
3672 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3673 sxx = player->GfxPos;
3675 syy = player->GfxPos;
3678 if (!setup.soft_scrolling && ScreenMovPos)
3681 if (player_is_opaque)
3682 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
3684 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3686 if (SHIELD_ON(player))
3688 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
3689 IMG_SHIELD_NORMAL_ACTIVE);
3690 int frame = getGraphicAnimationFrame(graphic, -1);
3692 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3696 /* ----------------------------------------------------------------------- */
3697 /* draw things in front of player (active dynamite or dynabombs) */
3698 /* ----------------------------------------------------------------------- */
3700 if (IS_ACTIVE_BOMB(element))
3702 graphic = el2img(element);
3703 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
3705 if (game.emulation == EMU_SUPAPLEX)
3706 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
3708 DrawGraphicThruMask(sx, sy, graphic, frame);
3711 if (player_is_moving && last_element == EL_EXPLOSION)
3713 int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
3714 GfxElement[last_jx][last_jy] : EL_EMPTY);
3715 int graphic = el_act2img(element, ACTION_EXPLODING);
3716 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
3717 int phase = ExplodePhase[last_jx][last_jy] - 1;
3718 int frame = getGraphicAnimationFrame(graphic, phase - delay);
3721 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
3724 /* ----------------------------------------------------------------------- */
3725 /* draw elements the player is just walking/passing through/under */
3726 /* ----------------------------------------------------------------------- */
3728 if (player_is_moving)
3730 /* handle the field the player is leaving ... */
3731 if (IS_ACCESSIBLE_INSIDE(last_element))
3732 DrawLevelField(last_jx, last_jy);
3733 else if (IS_ACCESSIBLE_UNDER(last_element))
3734 DrawLevelFieldThruMask(last_jx, last_jy);
3737 /* do not redraw accessible elements if the player is just pushing them */
3738 if (!player_is_moving || !player->is_pushing)
3740 /* ... and the field the player is entering */
3741 if (IS_ACCESSIBLE_INSIDE(element))
3742 DrawLevelField(jx, jy);
3743 else if (IS_ACCESSIBLE_UNDER(element))
3744 DrawLevelFieldThruMask(jx, jy);
3747 MarkTileDirty(sx, sy);
3750 /* ------------------------------------------------------------------------- */
3752 void WaitForEventToContinue()
3754 boolean still_wait = TRUE;
3756 /* simulate releasing mouse button over last gadget, if still pressed */
3758 HandleGadgets(-1, -1, 0);
3760 button_status = MB_RELEASED;
3776 case EVENT_BUTTONPRESS:
3777 case EVENT_KEYPRESS:
3781 case EVENT_KEYRELEASE:
3782 ClearPlayerAction();
3786 HandleOtherEvents(&event);
3790 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
3797 /* don't eat all CPU time */
3802 #define MAX_REQUEST_LINES 13
3803 #define MAX_REQUEST_LINE_FONT1_LEN 7
3804 #define MAX_REQUEST_LINE_FONT2_LEN 10
3806 boolean Request(char *text, unsigned int req_state)
3808 int mx, my, ty, result = -1;
3809 unsigned int old_door_state;
3810 int last_game_status = game_status; /* save current game status */
3811 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
3812 int font_nr = FONT_TEXT_2;
3814 int max_word_len = 0;
3820 global.use_envelope_request = 0;
3824 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
3826 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
3827 font_nr = FONT_TEXT_1;
3830 for (text_ptr = text; *text_ptr; text_ptr++)
3832 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
3834 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
3836 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
3838 font_nr = FONT_TEXT_1;
3840 font_nr = FONT_LEVEL_NUMBER;
3848 if (game_status == GAME_MODE_PLAYING)
3850 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
3851 BlitScreenToBitmap_EM(backbuffer);
3852 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3853 BlitScreenToBitmap_SP(backbuffer);
3856 /* disable deactivated drawing when quick-loading level tape recording */
3857 if (tape.playing && tape.deactivate_display)
3858 TapeDeactivateDisplayOff(TRUE);
3860 SetMouseCursor(CURSOR_DEFAULT);
3862 #if defined(NETWORK_AVALIABLE)
3863 /* pause network game while waiting for request to answer */
3864 if (options.network &&
3865 game_status == GAME_MODE_PLAYING &&
3866 req_state & REQUEST_WAIT_FOR_INPUT)
3867 SendToServer_PausePlaying();
3870 old_door_state = GetDoorState();
3872 /* simulate releasing mouse button over last gadget, if still pressed */
3874 HandleGadgets(-1, -1, 0);
3878 /* draw released gadget before proceeding */
3882 if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request)
3884 if (old_door_state & DOOR_OPEN_1)
3888 if (!global.use_envelope_request)
3889 CloseDoor(DOOR_CLOSE_1);
3891 CloseDoor(DOOR_CLOSE_1);
3894 /* save old door content */
3895 BlitBitmap(bitmap_db_door, bitmap_db_door,
3896 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
3897 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
3901 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
3904 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
3906 /* clear door drawing field */
3907 DrawBackground(DX, DY, DXSIZE, DYSIZE);
3909 /* force DOOR font inside door area */
3910 game_status = GAME_MODE_PSEUDO_DOOR;
3912 /* write text for request */
3913 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
3915 char text_line[max_request_line_len + 1];
3921 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
3923 tc = *(text_ptr + tx);
3924 if (!tc || tc == ' ')
3935 strncpy(text_line, text_ptr, tl);
3938 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
3939 DY + 8 + ty * (getFontHeight(font_nr) + 2),
3940 text_line, font_nr);
3942 text_ptr += tl + (tc == ' ' ? 1 : 0);
3945 game_status = last_game_status; /* restore current game status */
3948 if (global.use_envelope_request)
3952 CreateToolButtons();
3956 if (req_state & REQ_ASK)
3958 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
3959 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
3961 else if (req_state & REQ_CONFIRM)
3963 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
3965 else if (req_state & REQ_PLAYER)
3967 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
3968 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
3969 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
3970 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
3973 /* copy request gadgets to door backbuffer */
3974 BlitBitmap(drawto, bitmap_db_door,
3975 DX, DY, DXSIZE, DYSIZE,
3976 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3979 if (global.use_envelope_request)
3981 ShowEnvelopeDoor(text, ACTION_OPENING);
3983 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3985 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
3986 i == TOOL_CTRL_ID_NO)) ||
3987 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
3988 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
3989 i == TOOL_CTRL_ID_PLAYER_2 &&
3990 i == TOOL_CTRL_ID_PLAYER_3 &&
3991 i == TOOL_CTRL_ID_PLAYER_4)))
3993 int x = tool_gadget[i]->x + dDX;
3994 int y = tool_gadget[i]->y + dDY;
3996 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
4003 if (!global.use_envelope_request)
4004 OpenDoor(DOOR_OPEN_1);
4006 OpenDoor(DOOR_OPEN_1);
4009 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4011 if (game_status == GAME_MODE_PLAYING)
4013 SetPanelBackground();
4014 SetDrawBackgroundMask(REDRAW_DOOR_1);
4018 SetDrawBackgroundMask(REDRAW_FIELD);
4025 if (game_status != GAME_MODE_MAIN && !global.use_envelope_request)
4028 if (game_status != GAME_MODE_MAIN)
4032 button_status = MB_RELEASED;
4034 request_gadget_id = -1;
4036 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4048 case EVENT_BUTTONPRESS:
4049 case EVENT_BUTTONRELEASE:
4050 case EVENT_MOTIONNOTIFY:
4052 if (event.type == EVENT_MOTIONNOTIFY)
4054 if (!PointerInWindow(window))
4055 continue; /* window and pointer are on different screens */
4060 motion_status = TRUE;
4061 mx = ((MotionEvent *) &event)->x;
4062 my = ((MotionEvent *) &event)->y;
4066 motion_status = FALSE;
4067 mx = ((ButtonEvent *) &event)->x;
4068 my = ((ButtonEvent *) &event)->y;
4069 if (event.type == EVENT_BUTTONPRESS)
4070 button_status = ((ButtonEvent *) &event)->button;
4072 button_status = MB_RELEASED;
4075 /* this sets 'request_gadget_id' */
4076 HandleGadgets(mx, my, button_status);
4078 switch (request_gadget_id)
4080 case TOOL_CTRL_ID_YES:
4083 case TOOL_CTRL_ID_NO:
4086 case TOOL_CTRL_ID_CONFIRM:
4087 result = TRUE | FALSE;
4090 case TOOL_CTRL_ID_PLAYER_1:
4093 case TOOL_CTRL_ID_PLAYER_2:
4096 case TOOL_CTRL_ID_PLAYER_3:
4099 case TOOL_CTRL_ID_PLAYER_4:
4110 case EVENT_KEYPRESS:
4111 switch (GetEventKey((KeyEvent *)&event, TRUE))
4114 if (req_state & REQ_CONFIRM)
4130 if (req_state & REQ_PLAYER)
4134 case EVENT_KEYRELEASE:
4135 ClearPlayerAction();
4139 HandleOtherEvents(&event);
4143 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4145 int joy = AnyJoystick();
4147 if (joy & JOY_BUTTON_1)
4149 else if (joy & JOY_BUTTON_2)
4155 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
4157 HandleGameActions();
4163 if (!PendingEvent()) /* delay only if no pending events */
4168 game_status = GAME_MODE_PSEUDO_DOOR;
4174 game_status = last_game_status; /* restore current game status */
4182 if (!PendingEvent()) /* delay only if no pending events */
4185 /* don't eat all CPU time */
4192 if (game_status != GAME_MODE_MAIN)
4198 if (global.use_envelope_request)
4199 ShowEnvelopeDoor(text, ACTION_CLOSING);
4203 if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request)
4205 if (!(req_state & REQ_STAY_OPEN))
4208 CloseDoor(DOOR_CLOSE_1);
4210 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
4211 (req_state & REQ_REOPEN))
4212 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
4217 if (game_status == GAME_MODE_PLAYING)
4219 SetPanelBackground();
4220 SetDrawBackgroundMask(REDRAW_DOOR_1);
4224 SetDrawBackgroundMask(REDRAW_FIELD);
4227 #if defined(NETWORK_AVALIABLE)
4228 /* continue network game after request */
4229 if (options.network &&
4230 game_status == GAME_MODE_PLAYING &&
4231 req_state & REQUEST_WAIT_FOR_INPUT)
4232 SendToServer_ContinuePlaying();
4235 /* restore deactivated drawing when quick-loading level tape recording */
4236 if (tape.playing && tape.deactivate_display)
4237 TapeDeactivateDisplayOn();
4242 unsigned int OpenDoor(unsigned int door_state)
4244 if (door_state & DOOR_COPY_BACK)
4246 if (door_state & DOOR_OPEN_1)
4247 BlitBitmap(bitmap_db_door, bitmap_db_door,
4248 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4249 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4251 if (door_state & DOOR_OPEN_2)
4252 BlitBitmap(bitmap_db_door, bitmap_db_door,
4253 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
4254 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
4256 door_state &= ~DOOR_COPY_BACK;
4259 return MoveDoor(door_state);
4262 unsigned int CloseDoor(unsigned int door_state)
4264 unsigned int old_door_state = GetDoorState();
4266 if (!(door_state & DOOR_NO_COPY_BACK))
4268 if (old_door_state & DOOR_OPEN_1)
4269 BlitBitmap(backbuffer, bitmap_db_door,
4270 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4272 if (old_door_state & DOOR_OPEN_2)
4273 BlitBitmap(backbuffer, bitmap_db_door,
4274 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
4276 door_state &= ~DOOR_NO_COPY_BACK;
4279 return MoveDoor(door_state);
4282 unsigned int GetDoorState()
4284 return MoveDoor(DOOR_GET_STATE);
4287 unsigned int SetDoorState(unsigned int door_state)
4289 return MoveDoor(door_state | DOOR_SET_STATE);
4292 unsigned int MoveDoor(unsigned int door_state)
4294 static int door1 = DOOR_OPEN_1;
4295 static int door2 = DOOR_CLOSE_2;
4296 unsigned long door_delay = 0;
4297 unsigned long door_delay_value;
4300 if (door_1.width < 0 || door_1.width > DXSIZE)
4301 door_1.width = DXSIZE;
4302 if (door_1.height < 0 || door_1.height > DYSIZE)
4303 door_1.height = DYSIZE;
4304 if (door_2.width < 0 || door_2.width > VXSIZE)
4305 door_2.width = VXSIZE;
4306 if (door_2.height < 0 || door_2.height > VYSIZE)
4307 door_2.height = VYSIZE;
4309 if (door_state == DOOR_GET_STATE)
4310 return (door1 | door2);
4312 if (door_state & DOOR_SET_STATE)
4314 if (door_state & DOOR_ACTION_1)
4315 door1 = door_state & DOOR_ACTION_1;
4316 if (door_state & DOOR_ACTION_2)
4317 door2 = door_state & DOOR_ACTION_2;
4319 return (door1 | door2);
4322 if (!(door_state & DOOR_FORCE_REDRAW))
4324 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
4325 door_state &= ~DOOR_OPEN_1;
4326 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
4327 door_state &= ~DOOR_CLOSE_1;
4328 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
4329 door_state &= ~DOOR_OPEN_2;
4330 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
4331 door_state &= ~DOOR_CLOSE_2;
4334 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
4337 if (setup.quick_doors)
4339 stepsize = 20; /* must be chosen to always draw last frame */
4340 door_delay_value = 0;
4343 if (global.autoplay_leveldir)
4345 door_state |= DOOR_NO_DELAY;
4346 door_state &= ~DOOR_CLOSE_ALL;
4350 if (game_status == GAME_MODE_EDITOR)
4351 door_state |= DOOR_NO_DELAY;
4354 if (door_state & DOOR_ACTION)
4356 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
4357 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
4358 boolean door_1_done = (!handle_door_1);
4359 boolean door_2_done = (!handle_door_2);
4360 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
4361 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
4362 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
4363 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
4364 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
4365 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
4366 int door_size = (handle_door_1 ? door_size_1 : door_size_2);
4367 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
4368 int door_skip = max_door_size - door_size;
4369 int end = door_size;
4370 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
4373 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
4375 /* opening door sound has priority over simultaneously closing door */
4376 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
4377 PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
4378 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
4379 PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
4382 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
4385 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
4386 GC gc = bitmap->stored_clip_gc;
4388 if (door_state & DOOR_ACTION_1)
4390 int a = MIN(x * door_1.step_offset, end);
4391 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
4392 int i = p + door_skip;
4394 if (door_1.anim_mode & ANIM_STATIC_PANEL)
4396 BlitBitmap(bitmap_db_door, drawto,
4397 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
4398 DXSIZE, DYSIZE, DX, DY);
4402 BlitBitmap(bitmap_db_door, drawto,
4403 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
4404 DXSIZE, DYSIZE - p / 2, DX, DY);
4406 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
4409 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
4411 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
4412 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
4413 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
4414 int dst2_x = DX, dst2_y = DY;
4415 int width = i, height = DYSIZE;
4417 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4418 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4421 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4422 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4425 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
4427 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
4428 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
4429 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
4430 int dst2_x = DX, dst2_y = DY;
4431 int width = DXSIZE, height = i;
4433 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4434 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4437 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4438 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4441 else if (x <= DXSIZE) /* ANIM_DEFAULT */
4443 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
4445 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
4446 BlitBitmapMasked(bitmap, drawto,
4447 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
4448 DX + DXSIZE - i, DY + j);
4449 BlitBitmapMasked(bitmap, drawto,
4450 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
4451 DX + DXSIZE - i, DY + 140 + j);
4452 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
4453 DY - (DOOR_GFX_PAGEY1 + j));
4454 BlitBitmapMasked(bitmap, drawto,
4455 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
4457 BlitBitmapMasked(bitmap, drawto,
4458 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
4461 BlitBitmapMasked(bitmap, drawto,
4462 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
4464 BlitBitmapMasked(bitmap, drawto,
4465 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
4467 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
4468 BlitBitmapMasked(bitmap, drawto,
4469 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
4470 DX + DXSIZE - i, DY + 77 + j);
4471 BlitBitmapMasked(bitmap, drawto,
4472 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
4473 DX + DXSIZE - i, DY + 203 + j);
4476 redraw_mask |= REDRAW_DOOR_1;
4477 door_1_done = (a == end);
4480 if (door_state & DOOR_ACTION_2)
4482 int a = MIN(x * door_2.step_offset, door_size);
4483 int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
4484 int i = p + door_skip;
4486 if (door_2.anim_mode & ANIM_STATIC_PANEL)
4488 BlitBitmap(bitmap_db_door, drawto,
4489 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
4490 VXSIZE, VYSIZE, VX, VY);
4492 else if (x <= VYSIZE)
4494 BlitBitmap(bitmap_db_door, drawto,
4495 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
4496 VXSIZE, VYSIZE - p / 2, VX, VY);
4498 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
4501 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
4503 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
4504 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
4505 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
4506 int dst2_x = VX, dst2_y = VY;
4507 int width = i, height = VYSIZE;
4509 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4510 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4513 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4514 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4517 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
4519 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
4520 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
4521 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
4522 int dst2_x = VX, dst2_y = VY;
4523 int width = VXSIZE, height = i;
4525 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4526 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4529 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4530 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4533 else if (x <= VXSIZE) /* ANIM_DEFAULT */
4535 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
4537 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
4538 BlitBitmapMasked(bitmap, drawto,
4539 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
4540 VX + VXSIZE - i, VY + j);
4541 SetClipOrigin(bitmap, gc,
4542 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
4543 BlitBitmapMasked(bitmap, drawto,
4544 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
4547 BlitBitmapMasked(bitmap, drawto,
4548 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
4549 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
4550 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
4551 BlitBitmapMasked(bitmap, drawto,
4552 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
4554 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
4557 redraw_mask |= REDRAW_DOOR_2;
4558 door_2_done = (a == VXSIZE);
4561 if (!(door_state & DOOR_NO_DELAY))
4565 if (game_status == GAME_MODE_MAIN)
4568 WaitUntilDelayReached(&door_delay, door_delay_value);
4573 if (door_state & DOOR_ACTION_1)
4574 door1 = door_state & DOOR_ACTION_1;
4575 if (door_state & DOOR_ACTION_2)
4576 door2 = door_state & DOOR_ACTION_2;
4578 return (door1 | door2);
4581 void DrawSpecialEditorDoor()
4583 /* draw bigger toolbox window */
4584 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
4585 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
4587 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
4588 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
4591 redraw_mask |= REDRAW_ALL;
4594 void UndrawSpecialEditorDoor()
4596 /* draw normal tape recorder window */
4597 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
4598 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
4601 redraw_mask |= REDRAW_ALL;
4605 /* ---------- new tool button stuff ---------------------------------------- */
4607 /* graphic position values for tool buttons */
4608 #define TOOL_BUTTON_YES_XPOS 2
4609 #define TOOL_BUTTON_YES_YPOS 250
4610 #define TOOL_BUTTON_YES_GFX_YPOS 0
4611 #define TOOL_BUTTON_YES_XSIZE 46
4612 #define TOOL_BUTTON_YES_YSIZE 28
4613 #define TOOL_BUTTON_NO_XPOS 52
4614 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
4615 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
4616 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
4617 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
4618 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
4619 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
4620 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
4621 #define TOOL_BUTTON_CONFIRM_XSIZE 96
4622 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
4623 #define TOOL_BUTTON_PLAYER_XSIZE 30
4624 #define TOOL_BUTTON_PLAYER_YSIZE 30
4625 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
4626 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
4627 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
4628 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
4629 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4630 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
4631 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4632 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
4633 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4634 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
4635 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4636 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
4637 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4638 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
4639 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4640 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
4641 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4642 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
4643 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4644 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
4653 } toolbutton_info[NUM_TOOL_BUTTONS] =
4656 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
4657 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
4658 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
4663 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
4664 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
4665 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
4670 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
4671 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
4672 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
4673 TOOL_CTRL_ID_CONFIRM,
4677 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4678 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
4679 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4680 TOOL_CTRL_ID_PLAYER_1,
4684 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4685 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
4686 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4687 TOOL_CTRL_ID_PLAYER_2,
4691 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4692 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
4693 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4694 TOOL_CTRL_ID_PLAYER_3,
4698 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4699 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
4700 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4701 TOOL_CTRL_ID_PLAYER_4,
4706 void CreateToolButtons()
4710 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4712 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
4713 Bitmap *deco_bitmap = None;
4714 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
4715 struct GadgetInfo *gi;
4716 unsigned long event_mask;
4717 int gd_xoffset, gd_yoffset;
4718 int gd_x1, gd_x2, gd_y;
4721 event_mask = GD_EVENT_RELEASED;
4723 gd_xoffset = toolbutton_info[i].xpos;
4724 gd_yoffset = toolbutton_info[i].ypos;
4725 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
4726 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
4727 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
4729 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
4731 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
4733 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
4734 &deco_bitmap, &deco_x, &deco_y);
4735 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
4736 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
4739 gi = CreateGadget(GDI_CUSTOM_ID, id,
4740 GDI_INFO_TEXT, toolbutton_info[i].infotext,
4741 GDI_X, DX + toolbutton_info[i].x,
4742 GDI_Y, DY + toolbutton_info[i].y,
4743 GDI_WIDTH, toolbutton_info[i].width,
4744 GDI_HEIGHT, toolbutton_info[i].height,
4745 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
4746 GDI_STATE, GD_BUTTON_UNPRESSED,
4747 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
4748 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
4749 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
4750 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
4751 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
4752 GDI_DECORATION_SHIFTING, 1, 1,
4753 GDI_DIRECT_DRAW, FALSE,
4754 GDI_EVENT_MASK, event_mask,
4755 GDI_CALLBACK_ACTION, HandleToolButtons,
4759 Error(ERR_EXIT, "cannot create gadget");
4761 tool_gadget[id] = gi;
4765 void FreeToolButtons()
4769 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4770 FreeGadget(tool_gadget[i]);
4773 static void UnmapToolButtons()
4777 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4778 UnmapGadget(tool_gadget[i]);
4781 static void HandleToolButtons(struct GadgetInfo *gi)
4783 request_gadget_id = gi->custom_id;
4786 static struct Mapping_EM_to_RND_object
4789 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
4790 boolean is_backside; /* backside of moving element */
4796 em_object_mapping_list[] =
4799 Xblank, TRUE, FALSE,
4803 Yacid_splash_eB, FALSE, FALSE,
4804 EL_ACID_SPLASH_RIGHT, -1, -1
4807 Yacid_splash_wB, FALSE, FALSE,
4808 EL_ACID_SPLASH_LEFT, -1, -1
4811 #ifdef EM_ENGINE_BAD_ROLL
4813 Xstone_force_e, FALSE, FALSE,
4814 EL_ROCK, -1, MV_BIT_RIGHT
4817 Xstone_force_w, FALSE, FALSE,
4818 EL_ROCK, -1, MV_BIT_LEFT
4821 Xnut_force_e, FALSE, FALSE,
4822 EL_NUT, -1, MV_BIT_RIGHT
4825 Xnut_force_w, FALSE, FALSE,
4826 EL_NUT, -1, MV_BIT_LEFT
4829 Xspring_force_e, FALSE, FALSE,
4830 EL_SPRING, -1, MV_BIT_RIGHT
4833 Xspring_force_w, FALSE, FALSE,
4834 EL_SPRING, -1, MV_BIT_LEFT
4837 Xemerald_force_e, FALSE, FALSE,
4838 EL_EMERALD, -1, MV_BIT_RIGHT
4841 Xemerald_force_w, FALSE, FALSE,
4842 EL_EMERALD, -1, MV_BIT_LEFT
4845 Xdiamond_force_e, FALSE, FALSE,
4846 EL_DIAMOND, -1, MV_BIT_RIGHT
4849 Xdiamond_force_w, FALSE, FALSE,
4850 EL_DIAMOND, -1, MV_BIT_LEFT
4853 Xbomb_force_e, FALSE, FALSE,
4854 EL_BOMB, -1, MV_BIT_RIGHT
4857 Xbomb_force_w, FALSE, FALSE,
4858 EL_BOMB, -1, MV_BIT_LEFT
4860 #endif /* EM_ENGINE_BAD_ROLL */
4863 Xstone, TRUE, FALSE,
4867 Xstone_pause, FALSE, FALSE,
4871 Xstone_fall, FALSE, FALSE,
4875 Ystone_s, FALSE, FALSE,
4876 EL_ROCK, ACTION_FALLING, -1
4879 Ystone_sB, FALSE, TRUE,
4880 EL_ROCK, ACTION_FALLING, -1
4883 Ystone_e, FALSE, FALSE,
4884 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
4887 Ystone_eB, FALSE, TRUE,
4888 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
4891 Ystone_w, FALSE, FALSE,
4892 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
4895 Ystone_wB, FALSE, TRUE,
4896 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
4903 Xnut_pause, FALSE, FALSE,
4907 Xnut_fall, FALSE, FALSE,
4911 Ynut_s, FALSE, FALSE,
4912 EL_NUT, ACTION_FALLING, -1
4915 Ynut_sB, FALSE, TRUE,
4916 EL_NUT, ACTION_FALLING, -1
4919 Ynut_e, FALSE, FALSE,
4920 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
4923 Ynut_eB, FALSE, TRUE,
4924 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
4927 Ynut_w, FALSE, FALSE,
4928 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
4931 Ynut_wB, FALSE, TRUE,
4932 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
4935 Xbug_n, TRUE, FALSE,
4939 Xbug_e, TRUE, FALSE,
4940 EL_BUG_RIGHT, -1, -1
4943 Xbug_s, TRUE, FALSE,
4947 Xbug_w, TRUE, FALSE,
4951 Xbug_gon, FALSE, FALSE,
4955 Xbug_goe, FALSE, FALSE,
4956 EL_BUG_RIGHT, -1, -1
4959 Xbug_gos, FALSE, FALSE,
4963 Xbug_gow, FALSE, FALSE,
4967 Ybug_n, FALSE, FALSE,
4968 EL_BUG, ACTION_MOVING, MV_BIT_UP
4971 Ybug_nB, FALSE, TRUE,
4972 EL_BUG, ACTION_MOVING, MV_BIT_UP
4975 Ybug_e, FALSE, FALSE,
4976 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
4979 Ybug_eB, FALSE, TRUE,
4980 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
4983 Ybug_s, FALSE, FALSE,
4984 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
4987 Ybug_sB, FALSE, TRUE,
4988 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
4991 Ybug_w, FALSE, FALSE,
4992 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
4995 Ybug_wB, FALSE, TRUE,
4996 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
4999 Ybug_w_n, FALSE, FALSE,
5000 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
5003 Ybug_n_e, FALSE, FALSE,
5004 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
5007 Ybug_e_s, FALSE, FALSE,
5008 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
5011 Ybug_s_w, FALSE, FALSE,
5012 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
5015 Ybug_e_n, FALSE, FALSE,
5016 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
5019 Ybug_s_e, FALSE, FALSE,
5020 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
5023 Ybug_w_s, FALSE, FALSE,
5024 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
5027 Ybug_n_w, FALSE, FALSE,
5028 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
5031 Ybug_stone, FALSE, FALSE,
5032 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
5035 Ybug_spring, FALSE, FALSE,
5036 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
5039 Xtank_n, TRUE, FALSE,
5040 EL_SPACESHIP_UP, -1, -1
5043 Xtank_e, TRUE, FALSE,
5044 EL_SPACESHIP_RIGHT, -1, -1
5047 Xtank_s, TRUE, FALSE,
5048 EL_SPACESHIP_DOWN, -1, -1
5051 Xtank_w, TRUE, FALSE,
5052 EL_SPACESHIP_LEFT, -1, -1
5055 Xtank_gon, FALSE, FALSE,
5056 EL_SPACESHIP_UP, -1, -1
5059 Xtank_goe, FALSE, FALSE,
5060 EL_SPACESHIP_RIGHT, -1, -1
5063 Xtank_gos, FALSE, FALSE,
5064 EL_SPACESHIP_DOWN, -1, -1
5067 Xtank_gow, FALSE, FALSE,
5068 EL_SPACESHIP_LEFT, -1, -1
5071 Ytank_n, FALSE, FALSE,
5072 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
5075 Ytank_nB, FALSE, TRUE,
5076 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
5079 Ytank_e, FALSE, FALSE,
5080 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
5083 Ytank_eB, FALSE, TRUE,
5084 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
5087 Ytank_s, FALSE, FALSE,
5088 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
5091 Ytank_sB, FALSE, TRUE,
5092 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
5095 Ytank_w, FALSE, FALSE,
5096 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
5099 Ytank_wB, FALSE, TRUE,
5100 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
5103 Ytank_w_n, FALSE, FALSE,
5104 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
5107 Ytank_n_e, FALSE, FALSE,
5108 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
5111 Ytank_e_s, FALSE, FALSE,
5112 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
5115 Ytank_s_w, FALSE, FALSE,
5116 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
5119 Ytank_e_n, FALSE, FALSE,
5120 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
5123 Ytank_s_e, FALSE, FALSE,
5124 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
5127 Ytank_w_s, FALSE, FALSE,
5128 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
5131 Ytank_n_w, FALSE, FALSE,
5132 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
5135 Ytank_stone, FALSE, FALSE,
5136 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
5139 Ytank_spring, FALSE, FALSE,
5140 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
5143 Xandroid, TRUE, FALSE,
5144 EL_EMC_ANDROID, ACTION_ACTIVE, -1
5147 Xandroid_1_n, FALSE, FALSE,
5148 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
5151 Xandroid_2_n, FALSE, FALSE,
5152 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
5155 Xandroid_1_e, FALSE, FALSE,
5156 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
5159 Xandroid_2_e, FALSE, FALSE,
5160 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
5163 Xandroid_1_w, FALSE, FALSE,
5164 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
5167 Xandroid_2_w, FALSE, FALSE,
5168 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
5171 Xandroid_1_s, FALSE, FALSE,
5172 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
5175 Xandroid_2_s, FALSE, FALSE,
5176 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
5179 Yandroid_n, FALSE, FALSE,
5180 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
5183 Yandroid_nB, FALSE, TRUE,
5184 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
5187 Yandroid_ne, FALSE, FALSE,
5188 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
5191 Yandroid_neB, FALSE, TRUE,
5192 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
5195 Yandroid_e, FALSE, FALSE,
5196 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
5199 Yandroid_eB, FALSE, TRUE,
5200 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
5203 Yandroid_se, FALSE, FALSE,
5204 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
5207 Yandroid_seB, FALSE, TRUE,
5208 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
5211 Yandroid_s, FALSE, FALSE,
5212 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
5215 Yandroid_sB, FALSE, TRUE,
5216 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
5219 Yandroid_sw, FALSE, FALSE,
5220 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
5223 Yandroid_swB, FALSE, TRUE,
5224 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
5227 Yandroid_w, FALSE, FALSE,
5228 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
5231 Yandroid_wB, FALSE, TRUE,
5232 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
5235 Yandroid_nw, FALSE, FALSE,
5236 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
5239 Yandroid_nwB, FALSE, TRUE,
5240 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
5243 Xspring, TRUE, FALSE,
5247 Xspring_pause, FALSE, FALSE,
5251 Xspring_e, FALSE, FALSE,
5255 Xspring_w, FALSE, FALSE,
5259 Xspring_fall, FALSE, FALSE,
5263 Yspring_s, FALSE, FALSE,
5264 EL_SPRING, ACTION_FALLING, -1
5267 Yspring_sB, FALSE, TRUE,
5268 EL_SPRING, ACTION_FALLING, -1
5271 Yspring_e, FALSE, FALSE,
5272 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
5275 Yspring_eB, FALSE, TRUE,
5276 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
5279 Yspring_w, FALSE, FALSE,
5280 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
5283 Yspring_wB, FALSE, TRUE,
5284 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
5287 Yspring_kill_e, FALSE, FALSE,
5288 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
5291 Yspring_kill_eB, FALSE, TRUE,
5292 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
5295 Yspring_kill_w, FALSE, FALSE,
5296 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
5299 Yspring_kill_wB, FALSE, TRUE,
5300 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
5303 Xeater_n, TRUE, FALSE,
5304 EL_YAMYAM_UP, -1, -1
5307 Xeater_e, TRUE, FALSE,
5308 EL_YAMYAM_RIGHT, -1, -1
5311 Xeater_w, TRUE, FALSE,
5312 EL_YAMYAM_LEFT, -1, -1
5315 Xeater_s, TRUE, FALSE,
5316 EL_YAMYAM_DOWN, -1, -1
5319 Yeater_n, FALSE, FALSE,
5320 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
5323 Yeater_nB, FALSE, TRUE,
5324 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
5327 Yeater_e, FALSE, FALSE,
5328 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
5331 Yeater_eB, FALSE, TRUE,
5332 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
5335 Yeater_s, FALSE, FALSE,
5336 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
5339 Yeater_sB, FALSE, TRUE,
5340 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
5343 Yeater_w, FALSE, FALSE,
5344 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
5347 Yeater_wB, FALSE, TRUE,
5348 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
5351 Yeater_stone, FALSE, FALSE,
5352 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
5355 Yeater_spring, FALSE, FALSE,
5356 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
5359 Xalien, TRUE, FALSE,
5363 Xalien_pause, FALSE, FALSE,
5367 Yalien_n, FALSE, FALSE,
5368 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
5371 Yalien_nB, FALSE, TRUE,
5372 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
5375 Yalien_e, FALSE, FALSE,
5376 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
5379 Yalien_eB, FALSE, TRUE,
5380 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
5383 Yalien_s, FALSE, FALSE,
5384 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
5387 Yalien_sB, FALSE, TRUE,
5388 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
5391 Yalien_w, FALSE, FALSE,
5392 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
5395 Yalien_wB, FALSE, TRUE,
5396 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
5399 Yalien_stone, FALSE, FALSE,
5400 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
5403 Yalien_spring, FALSE, FALSE,
5404 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
5407 Xemerald, TRUE, FALSE,
5411 Xemerald_pause, FALSE, FALSE,
5415 Xemerald_fall, FALSE, FALSE,
5419 Xemerald_shine, FALSE, FALSE,
5420 EL_EMERALD, ACTION_TWINKLING, -1
5423 Yemerald_s, FALSE, FALSE,
5424 EL_EMERALD, ACTION_FALLING, -1
5427 Yemerald_sB, FALSE, TRUE,
5428 EL_EMERALD, ACTION_FALLING, -1
5431 Yemerald_e, FALSE, FALSE,
5432 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
5435 Yemerald_eB, FALSE, TRUE,
5436 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
5439 Yemerald_w, FALSE, FALSE,
5440 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
5443 Yemerald_wB, FALSE, TRUE,
5444 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
5447 Yemerald_eat, FALSE, FALSE,
5448 EL_EMERALD, ACTION_COLLECTING, -1
5451 Yemerald_stone, FALSE, FALSE,
5452 EL_NUT, ACTION_BREAKING, -1
5455 Xdiamond, TRUE, FALSE,
5459 Xdiamond_pause, FALSE, FALSE,
5463 Xdiamond_fall, FALSE, FALSE,
5467 Xdiamond_shine, FALSE, FALSE,
5468 EL_DIAMOND, ACTION_TWINKLING, -1
5471 Ydiamond_s, FALSE, FALSE,
5472 EL_DIAMOND, ACTION_FALLING, -1
5475 Ydiamond_sB, FALSE, TRUE,
5476 EL_DIAMOND, ACTION_FALLING, -1
5479 Ydiamond_e, FALSE, FALSE,
5480 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
5483 Ydiamond_eB, FALSE, TRUE,
5484 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
5487 Ydiamond_w, FALSE, FALSE,
5488 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
5491 Ydiamond_wB, FALSE, TRUE,
5492 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
5495 Ydiamond_eat, FALSE, FALSE,
5496 EL_DIAMOND, ACTION_COLLECTING, -1
5499 Ydiamond_stone, FALSE, FALSE,
5500 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
5503 Xdrip_fall, TRUE, FALSE,
5504 EL_AMOEBA_DROP, -1, -1
5507 Xdrip_stretch, FALSE, FALSE,
5508 EL_AMOEBA_DROP, ACTION_FALLING, -1
5511 Xdrip_stretchB, FALSE, TRUE,
5512 EL_AMOEBA_DROP, ACTION_FALLING, -1
5515 Xdrip_eat, FALSE, FALSE,
5516 EL_AMOEBA_DROP, ACTION_GROWING, -1
5519 Ydrip_s1, FALSE, FALSE,
5520 EL_AMOEBA_DROP, ACTION_FALLING, -1
5523 Ydrip_s1B, FALSE, TRUE,
5524 EL_AMOEBA_DROP, ACTION_FALLING, -1
5527 Ydrip_s2, FALSE, FALSE,
5528 EL_AMOEBA_DROP, ACTION_FALLING, -1
5531 Ydrip_s2B, FALSE, TRUE,
5532 EL_AMOEBA_DROP, ACTION_FALLING, -1
5539 Xbomb_pause, FALSE, FALSE,
5543 Xbomb_fall, FALSE, FALSE,
5547 Ybomb_s, FALSE, FALSE,
5548 EL_BOMB, ACTION_FALLING, -1
5551 Ybomb_sB, FALSE, TRUE,
5552 EL_BOMB, ACTION_FALLING, -1
5555 Ybomb_e, FALSE, FALSE,
5556 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
5559 Ybomb_eB, FALSE, TRUE,
5560 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
5563 Ybomb_w, FALSE, FALSE,
5564 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
5567 Ybomb_wB, FALSE, TRUE,
5568 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
5571 Ybomb_eat, FALSE, FALSE,
5572 EL_BOMB, ACTION_ACTIVATING, -1
5575 Xballoon, TRUE, FALSE,
5579 Yballoon_n, FALSE, FALSE,
5580 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
5583 Yballoon_nB, FALSE, TRUE,
5584 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
5587 Yballoon_e, FALSE, FALSE,
5588 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
5591 Yballoon_eB, FALSE, TRUE,
5592 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
5595 Yballoon_s, FALSE, FALSE,
5596 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
5599 Yballoon_sB, FALSE, TRUE,
5600 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
5603 Yballoon_w, FALSE, FALSE,
5604 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
5607 Yballoon_wB, FALSE, TRUE,
5608 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
5611 Xgrass, TRUE, FALSE,
5612 EL_EMC_GRASS, -1, -1
5615 Ygrass_nB, FALSE, FALSE,
5616 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
5619 Ygrass_eB, FALSE, FALSE,
5620 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
5623 Ygrass_sB, FALSE, FALSE,
5624 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
5627 Ygrass_wB, FALSE, FALSE,
5628 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
5635 Ydirt_nB, FALSE, FALSE,
5636 EL_SAND, ACTION_DIGGING, MV_BIT_UP
5639 Ydirt_eB, FALSE, FALSE,
5640 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
5643 Ydirt_sB, FALSE, FALSE,
5644 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
5647 Ydirt_wB, FALSE, FALSE,
5648 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
5651 Xacid_ne, TRUE, FALSE,
5652 EL_ACID_POOL_TOPRIGHT, -1, -1
5655 Xacid_se, TRUE, FALSE,
5656 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
5659 Xacid_s, TRUE, FALSE,
5660 EL_ACID_POOL_BOTTOM, -1, -1
5663 Xacid_sw, TRUE, FALSE,
5664 EL_ACID_POOL_BOTTOMLEFT, -1, -1
5667 Xacid_nw, TRUE, FALSE,
5668 EL_ACID_POOL_TOPLEFT, -1, -1
5671 Xacid_1, TRUE, FALSE,
5675 Xacid_2, FALSE, FALSE,
5679 Xacid_3, FALSE, FALSE,
5683 Xacid_4, FALSE, FALSE,
5687 Xacid_5, FALSE, FALSE,
5691 Xacid_6, FALSE, FALSE,
5695 Xacid_7, FALSE, FALSE,
5699 Xacid_8, FALSE, FALSE,
5703 Xball_1, TRUE, FALSE,
5704 EL_EMC_MAGIC_BALL, -1, -1
5707 Xball_1B, FALSE, FALSE,
5708 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
5711 Xball_2, FALSE, FALSE,
5712 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
5715 Xball_2B, FALSE, FALSE,
5716 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
5719 Yball_eat, FALSE, FALSE,
5720 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
5723 Ykey_1_eat, FALSE, FALSE,
5724 EL_EM_KEY_1, ACTION_COLLECTING, -1
5727 Ykey_2_eat, FALSE, FALSE,
5728 EL_EM_KEY_2, ACTION_COLLECTING, -1
5731 Ykey_3_eat, FALSE, FALSE,
5732 EL_EM_KEY_3, ACTION_COLLECTING, -1
5735 Ykey_4_eat, FALSE, FALSE,
5736 EL_EM_KEY_4, ACTION_COLLECTING, -1
5739 Ykey_5_eat, FALSE, FALSE,
5740 EL_EMC_KEY_5, ACTION_COLLECTING, -1
5743 Ykey_6_eat, FALSE, FALSE,
5744 EL_EMC_KEY_6, ACTION_COLLECTING, -1
5747 Ykey_7_eat, FALSE, FALSE,
5748 EL_EMC_KEY_7, ACTION_COLLECTING, -1
5751 Ykey_8_eat, FALSE, FALSE,
5752 EL_EMC_KEY_8, ACTION_COLLECTING, -1
5755 Ylenses_eat, FALSE, FALSE,
5756 EL_EMC_LENSES, ACTION_COLLECTING, -1
5759 Ymagnify_eat, FALSE, FALSE,
5760 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
5763 Ygrass_eat, FALSE, FALSE,
5764 EL_EMC_GRASS, ACTION_SNAPPING, -1
5767 Ydirt_eat, FALSE, FALSE,
5768 EL_SAND, ACTION_SNAPPING, -1
5771 Xgrow_ns, TRUE, FALSE,
5772 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
5775 Ygrow_ns_eat, FALSE, FALSE,
5776 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
5779 Xgrow_ew, TRUE, FALSE,
5780 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
5783 Ygrow_ew_eat, FALSE, FALSE,
5784 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
5787 Xwonderwall, TRUE, FALSE,
5788 EL_MAGIC_WALL, -1, -1
5791 XwonderwallB, FALSE, FALSE,
5792 EL_MAGIC_WALL, ACTION_ACTIVE, -1
5795 Xamoeba_1, TRUE, FALSE,
5796 EL_AMOEBA_DRY, ACTION_OTHER, -1
5799 Xamoeba_2, FALSE, FALSE,
5800 EL_AMOEBA_DRY, ACTION_OTHER, -1
5803 Xamoeba_3, FALSE, FALSE,
5804 EL_AMOEBA_DRY, ACTION_OTHER, -1
5807 Xamoeba_4, FALSE, FALSE,
5808 EL_AMOEBA_DRY, ACTION_OTHER, -1
5811 Xamoeba_5, TRUE, FALSE,
5812 EL_AMOEBA_WET, ACTION_OTHER, -1
5815 Xamoeba_6, FALSE, FALSE,
5816 EL_AMOEBA_WET, ACTION_OTHER, -1
5819 Xamoeba_7, FALSE, FALSE,
5820 EL_AMOEBA_WET, ACTION_OTHER, -1
5823 Xamoeba_8, FALSE, FALSE,
5824 EL_AMOEBA_WET, ACTION_OTHER, -1
5827 Xdoor_1, TRUE, FALSE,
5828 EL_EM_GATE_1, -1, -1
5831 Xdoor_2, TRUE, FALSE,
5832 EL_EM_GATE_2, -1, -1
5835 Xdoor_3, TRUE, FALSE,
5836 EL_EM_GATE_3, -1, -1
5839 Xdoor_4, TRUE, FALSE,
5840 EL_EM_GATE_4, -1, -1
5843 Xdoor_5, TRUE, FALSE,
5844 EL_EMC_GATE_5, -1, -1
5847 Xdoor_6, TRUE, FALSE,
5848 EL_EMC_GATE_6, -1, -1
5851 Xdoor_7, TRUE, FALSE,
5852 EL_EMC_GATE_7, -1, -1
5855 Xdoor_8, TRUE, FALSE,
5856 EL_EMC_GATE_8, -1, -1
5859 Xkey_1, TRUE, FALSE,
5863 Xkey_2, TRUE, FALSE,
5867 Xkey_3, TRUE, FALSE,
5871 Xkey_4, TRUE, FALSE,
5875 Xkey_5, TRUE, FALSE,
5876 EL_EMC_KEY_5, -1, -1
5879 Xkey_6, TRUE, FALSE,
5880 EL_EMC_KEY_6, -1, -1
5883 Xkey_7, TRUE, FALSE,
5884 EL_EMC_KEY_7, -1, -1
5887 Xkey_8, TRUE, FALSE,
5888 EL_EMC_KEY_8, -1, -1
5891 Xwind_n, TRUE, FALSE,
5892 EL_BALLOON_SWITCH_UP, -1, -1
5895 Xwind_e, TRUE, FALSE,
5896 EL_BALLOON_SWITCH_RIGHT, -1, -1
5899 Xwind_s, TRUE, FALSE,
5900 EL_BALLOON_SWITCH_DOWN, -1, -1
5903 Xwind_w, TRUE, FALSE,
5904 EL_BALLOON_SWITCH_LEFT, -1, -1
5907 Xwind_nesw, TRUE, FALSE,
5908 EL_BALLOON_SWITCH_ANY, -1, -1
5911 Xwind_stop, TRUE, FALSE,
5912 EL_BALLOON_SWITCH_NONE, -1, -1
5916 EL_EM_EXIT_CLOSED, -1, -1
5919 Xexit_1, TRUE, FALSE,
5920 EL_EM_EXIT_OPEN, -1, -1
5923 Xexit_2, FALSE, FALSE,
5924 EL_EM_EXIT_OPEN, -1, -1
5927 Xexit_3, FALSE, FALSE,
5928 EL_EM_EXIT_OPEN, -1, -1
5931 Xdynamite, TRUE, FALSE,
5932 EL_EM_DYNAMITE, -1, -1
5935 Ydynamite_eat, FALSE, FALSE,
5936 EL_EM_DYNAMITE, ACTION_COLLECTING, -1
5939 Xdynamite_1, TRUE, FALSE,
5940 EL_EM_DYNAMITE_ACTIVE, -1, -1
5943 Xdynamite_2, FALSE, FALSE,
5944 EL_EM_DYNAMITE_ACTIVE, -1, -1
5947 Xdynamite_3, FALSE, FALSE,
5948 EL_EM_DYNAMITE_ACTIVE, -1, -1
5951 Xdynamite_4, FALSE, FALSE,
5952 EL_EM_DYNAMITE_ACTIVE, -1, -1
5955 Xbumper, TRUE, FALSE,
5956 EL_EMC_SPRING_BUMPER, -1, -1
5959 XbumperB, FALSE, FALSE,
5960 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
5963 Xwheel, TRUE, FALSE,
5964 EL_ROBOT_WHEEL, -1, -1
5967 XwheelB, FALSE, FALSE,
5968 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
5971 Xswitch, TRUE, FALSE,
5972 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
5975 XswitchB, FALSE, FALSE,
5976 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
5980 EL_QUICKSAND_EMPTY, -1, -1
5983 Xsand_stone, TRUE, FALSE,
5984 EL_QUICKSAND_FULL, -1, -1
5987 Xsand_stonein_1, FALSE, TRUE,
5988 EL_ROCK, ACTION_FILLING, -1
5991 Xsand_stonein_2, FALSE, TRUE,
5992 EL_ROCK, ACTION_FILLING, -1
5995 Xsand_stonein_3, FALSE, TRUE,
5996 EL_ROCK, ACTION_FILLING, -1
5999 Xsand_stonein_4, FALSE, TRUE,
6000 EL_ROCK, ACTION_FILLING, -1
6004 Xsand_stonesand_1, FALSE, FALSE,
6005 EL_QUICKSAND_EMPTYING, -1, -1
6008 Xsand_stonesand_2, FALSE, FALSE,
6009 EL_QUICKSAND_EMPTYING, -1, -1
6012 Xsand_stonesand_3, FALSE, FALSE,
6013 EL_QUICKSAND_EMPTYING, -1, -1
6016 Xsand_stonesand_4, FALSE, FALSE,
6017 EL_QUICKSAND_EMPTYING, -1, -1
6020 Xsand_stonesand_quickout_1, FALSE, FALSE,
6021 EL_QUICKSAND_EMPTYING, -1, -1
6024 Xsand_stonesand_quickout_2, FALSE, FALSE,
6025 EL_QUICKSAND_EMPTYING, -1, -1
6029 Xsand_stonesand_1, FALSE, FALSE,
6030 EL_QUICKSAND_FULL, -1, -1
6033 Xsand_stonesand_2, FALSE, FALSE,
6034 EL_QUICKSAND_FULL, -1, -1
6037 Xsand_stonesand_3, FALSE, FALSE,
6038 EL_QUICKSAND_FULL, -1, -1
6041 Xsand_stonesand_4, FALSE, FALSE,
6042 EL_QUICKSAND_FULL, -1, -1
6046 Xsand_stoneout_1, FALSE, FALSE,
6047 EL_ROCK, ACTION_EMPTYING, -1
6050 Xsand_stoneout_2, FALSE, FALSE,
6051 EL_ROCK, ACTION_EMPTYING, -1
6055 Xsand_sandstone_1, FALSE, FALSE,
6056 EL_QUICKSAND_FILLING, -1, -1
6059 Xsand_sandstone_2, FALSE, FALSE,
6060 EL_QUICKSAND_FILLING, -1, -1
6063 Xsand_sandstone_3, FALSE, FALSE,
6064 EL_QUICKSAND_FILLING, -1, -1
6067 Xsand_sandstone_4, FALSE, FALSE,
6068 EL_QUICKSAND_FILLING, -1, -1
6072 Xsand_sandstone_1, FALSE, FALSE,
6073 EL_QUICKSAND_FULL, -1, -1
6076 Xsand_sandstone_2, FALSE, FALSE,
6077 EL_QUICKSAND_FULL, -1, -1
6080 Xsand_sandstone_3, FALSE, FALSE,
6081 EL_QUICKSAND_FULL, -1, -1
6084 Xsand_sandstone_4, FALSE, FALSE,
6085 EL_QUICKSAND_FULL, -1, -1
6089 Xplant, TRUE, FALSE,
6090 EL_EMC_PLANT, -1, -1
6093 Yplant, FALSE, FALSE,
6094 EL_EMC_PLANT, -1, -1
6097 Xlenses, TRUE, FALSE,
6098 EL_EMC_LENSES, -1, -1
6101 Xmagnify, TRUE, FALSE,
6102 EL_EMC_MAGNIFIER, -1, -1
6105 Xdripper, TRUE, FALSE,
6106 EL_EMC_DRIPPER, -1, -1
6109 XdripperB, FALSE, FALSE,
6110 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
6113 Xfake_blank, TRUE, FALSE,
6114 EL_INVISIBLE_WALL, -1, -1
6117 Xfake_blankB, FALSE, FALSE,
6118 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
6121 Xfake_grass, TRUE, FALSE,
6122 EL_EMC_FAKE_GRASS, -1, -1
6125 Xfake_grassB, FALSE, FALSE,
6126 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
6129 Xfake_door_1, TRUE, FALSE,
6130 EL_EM_GATE_1_GRAY, -1, -1
6133 Xfake_door_2, TRUE, FALSE,
6134 EL_EM_GATE_2_GRAY, -1, -1
6137 Xfake_door_3, TRUE, FALSE,
6138 EL_EM_GATE_3_GRAY, -1, -1
6141 Xfake_door_4, TRUE, FALSE,
6142 EL_EM_GATE_4_GRAY, -1, -1
6145 Xfake_door_5, TRUE, FALSE,
6146 EL_EMC_GATE_5_GRAY, -1, -1
6149 Xfake_door_6, TRUE, FALSE,
6150 EL_EMC_GATE_6_GRAY, -1, -1
6153 Xfake_door_7, TRUE, FALSE,
6154 EL_EMC_GATE_7_GRAY, -1, -1
6157 Xfake_door_8, TRUE, FALSE,
6158 EL_EMC_GATE_8_GRAY, -1, -1
6161 Xfake_acid_1, TRUE, FALSE,
6162 EL_EMC_FAKE_ACID, -1, -1
6165 Xfake_acid_2, FALSE, FALSE,
6166 EL_EMC_FAKE_ACID, -1, -1
6169 Xfake_acid_3, FALSE, FALSE,
6170 EL_EMC_FAKE_ACID, -1, -1
6173 Xfake_acid_4, FALSE, FALSE,
6174 EL_EMC_FAKE_ACID, -1, -1
6177 Xfake_acid_5, FALSE, FALSE,
6178 EL_EMC_FAKE_ACID, -1, -1
6181 Xfake_acid_6, FALSE, FALSE,
6182 EL_EMC_FAKE_ACID, -1, -1
6185 Xfake_acid_7, FALSE, FALSE,
6186 EL_EMC_FAKE_ACID, -1, -1
6189 Xfake_acid_8, FALSE, FALSE,
6190 EL_EMC_FAKE_ACID, -1, -1
6193 Xsteel_1, TRUE, FALSE,
6194 EL_STEELWALL, -1, -1
6197 Xsteel_2, TRUE, FALSE,
6198 EL_EMC_STEELWALL_2, -1, -1
6201 Xsteel_3, TRUE, FALSE,
6202 EL_EMC_STEELWALL_3, -1, -1
6205 Xsteel_4, TRUE, FALSE,
6206 EL_EMC_STEELWALL_4, -1, -1
6209 Xwall_1, TRUE, FALSE,
6213 Xwall_2, TRUE, FALSE,
6214 EL_EMC_WALL_14, -1, -1
6217 Xwall_3, TRUE, FALSE,
6218 EL_EMC_WALL_15, -1, -1
6221 Xwall_4, TRUE, FALSE,
6222 EL_EMC_WALL_16, -1, -1
6225 Xround_wall_1, TRUE, FALSE,
6226 EL_WALL_SLIPPERY, -1, -1
6229 Xround_wall_2, TRUE, FALSE,
6230 EL_EMC_WALL_SLIPPERY_2, -1, -1
6233 Xround_wall_3, TRUE, FALSE,
6234 EL_EMC_WALL_SLIPPERY_3, -1, -1
6237 Xround_wall_4, TRUE, FALSE,
6238 EL_EMC_WALL_SLIPPERY_4, -1, -1
6241 Xdecor_1, TRUE, FALSE,
6242 EL_EMC_WALL_8, -1, -1
6245 Xdecor_2, TRUE, FALSE,
6246 EL_EMC_WALL_6, -1, -1
6249 Xdecor_3, TRUE, FALSE,
6250 EL_EMC_WALL_4, -1, -1
6253 Xdecor_4, TRUE, FALSE,
6254 EL_EMC_WALL_7, -1, -1
6257 Xdecor_5, TRUE, FALSE,
6258 EL_EMC_WALL_5, -1, -1
6261 Xdecor_6, TRUE, FALSE,
6262 EL_EMC_WALL_9, -1, -1
6265 Xdecor_7, TRUE, FALSE,
6266 EL_EMC_WALL_10, -1, -1
6269 Xdecor_8, TRUE, FALSE,
6270 EL_EMC_WALL_1, -1, -1
6273 Xdecor_9, TRUE, FALSE,
6274 EL_EMC_WALL_2, -1, -1
6277 Xdecor_10, TRUE, FALSE,
6278 EL_EMC_WALL_3, -1, -1
6281 Xdecor_11, TRUE, FALSE,
6282 EL_EMC_WALL_11, -1, -1
6285 Xdecor_12, TRUE, FALSE,
6286 EL_EMC_WALL_12, -1, -1
6289 Xalpha_0, TRUE, FALSE,
6290 EL_CHAR('0'), -1, -1
6293 Xalpha_1, TRUE, FALSE,
6294 EL_CHAR('1'), -1, -1
6297 Xalpha_2, TRUE, FALSE,
6298 EL_CHAR('2'), -1, -1
6301 Xalpha_3, TRUE, FALSE,
6302 EL_CHAR('3'), -1, -1
6305 Xalpha_4, TRUE, FALSE,
6306 EL_CHAR('4'), -1, -1
6309 Xalpha_5, TRUE, FALSE,
6310 EL_CHAR('5'), -1, -1
6313 Xalpha_6, TRUE, FALSE,
6314 EL_CHAR('6'), -1, -1
6317 Xalpha_7, TRUE, FALSE,
6318 EL_CHAR('7'), -1, -1
6321 Xalpha_8, TRUE, FALSE,
6322 EL_CHAR('8'), -1, -1
6325 Xalpha_9, TRUE, FALSE,
6326 EL_CHAR('9'), -1, -1
6329 Xalpha_excla, TRUE, FALSE,
6330 EL_CHAR('!'), -1, -1
6333 Xalpha_quote, TRUE, FALSE,
6334 EL_CHAR('"'), -1, -1
6337 Xalpha_comma, TRUE, FALSE,
6338 EL_CHAR(','), -1, -1
6341 Xalpha_minus, TRUE, FALSE,
6342 EL_CHAR('-'), -1, -1
6345 Xalpha_perio, TRUE, FALSE,
6346 EL_CHAR('.'), -1, -1
6349 Xalpha_colon, TRUE, FALSE,
6350 EL_CHAR(':'), -1, -1
6353 Xalpha_quest, TRUE, FALSE,
6354 EL_CHAR('?'), -1, -1
6357 Xalpha_a, TRUE, FALSE,
6358 EL_CHAR('A'), -1, -1
6361 Xalpha_b, TRUE, FALSE,
6362 EL_CHAR('B'), -1, -1
6365 Xalpha_c, TRUE, FALSE,
6366 EL_CHAR('C'), -1, -1
6369 Xalpha_d, TRUE, FALSE,
6370 EL_CHAR('D'), -1, -1
6373 Xalpha_e, TRUE, FALSE,
6374 EL_CHAR('E'), -1, -1
6377 Xalpha_f, TRUE, FALSE,
6378 EL_CHAR('F'), -1, -1
6381 Xalpha_g, TRUE, FALSE,
6382 EL_CHAR('G'), -1, -1
6385 Xalpha_h, TRUE, FALSE,
6386 EL_CHAR('H'), -1, -1
6389 Xalpha_i, TRUE, FALSE,
6390 EL_CHAR('I'), -1, -1
6393 Xalpha_j, TRUE, FALSE,
6394 EL_CHAR('J'), -1, -1
6397 Xalpha_k, TRUE, FALSE,
6398 EL_CHAR('K'), -1, -1
6401 Xalpha_l, TRUE, FALSE,
6402 EL_CHAR('L'), -1, -1
6405 Xalpha_m, TRUE, FALSE,
6406 EL_CHAR('M'), -1, -1
6409 Xalpha_n, TRUE, FALSE,
6410 EL_CHAR('N'), -1, -1
6413 Xalpha_o, TRUE, FALSE,
6414 EL_CHAR('O'), -1, -1
6417 Xalpha_p, TRUE, FALSE,
6418 EL_CHAR('P'), -1, -1
6421 Xalpha_q, TRUE, FALSE,
6422 EL_CHAR('Q'), -1, -1
6425 Xalpha_r, TRUE, FALSE,
6426 EL_CHAR('R'), -1, -1
6429 Xalpha_s, TRUE, FALSE,
6430 EL_CHAR('S'), -1, -1
6433 Xalpha_t, TRUE, FALSE,
6434 EL_CHAR('T'), -1, -1
6437 Xalpha_u, TRUE, FALSE,
6438 EL_CHAR('U'), -1, -1
6441 Xalpha_v, TRUE, FALSE,
6442 EL_CHAR('V'), -1, -1
6445 Xalpha_w, TRUE, FALSE,
6446 EL_CHAR('W'), -1, -1
6449 Xalpha_x, TRUE, FALSE,
6450 EL_CHAR('X'), -1, -1
6453 Xalpha_y, TRUE, FALSE,
6454 EL_CHAR('Y'), -1, -1
6457 Xalpha_z, TRUE, FALSE,
6458 EL_CHAR('Z'), -1, -1
6461 Xalpha_arrow_e, TRUE, FALSE,
6462 EL_CHAR('>'), -1, -1
6465 Xalpha_arrow_w, TRUE, FALSE,
6466 EL_CHAR('<'), -1, -1
6469 Xalpha_copyr, TRUE, FALSE,
6470 EL_CHAR('©'), -1, -1
6474 Xboom_bug, FALSE, FALSE,
6475 EL_BUG, ACTION_EXPLODING, -1
6478 Xboom_bomb, FALSE, FALSE,
6479 EL_BOMB, ACTION_EXPLODING, -1
6482 Xboom_android, FALSE, FALSE,
6483 EL_EMC_ANDROID, ACTION_OTHER, -1
6486 Xboom_1, FALSE, FALSE,
6487 EL_DEFAULT, ACTION_EXPLODING, -1
6490 Xboom_2, FALSE, FALSE,
6491 EL_DEFAULT, ACTION_EXPLODING, -1
6494 Znormal, FALSE, FALSE,
6498 Zdynamite, FALSE, FALSE,
6502 Zplayer, FALSE, FALSE,
6506 ZBORDER, FALSE, FALSE,
6516 static struct Mapping_EM_to_RND_player
6525 em_player_mapping_list[] =
6529 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
6533 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
6537 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
6541 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
6545 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
6549 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
6553 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
6557 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
6561 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
6565 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
6569 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
6573 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
6577 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
6581 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
6585 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
6589 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
6593 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
6597 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
6601 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
6605 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
6609 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
6613 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
6617 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
6621 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
6625 EL_PLAYER_1, ACTION_DEFAULT, -1,
6629 EL_PLAYER_2, ACTION_DEFAULT, -1,
6633 EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
6637 EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
6641 EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
6645 EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
6649 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
6653 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
6657 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
6661 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
6665 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
6669 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
6673 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
6677 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
6681 EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
6685 EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
6689 EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
6693 EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
6697 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
6701 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
6705 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
6709 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
6713 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
6717 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
6721 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
6725 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
6729 EL_PLAYER_3, ACTION_DEFAULT, -1,
6733 EL_PLAYER_4, ACTION_DEFAULT, -1,
6742 int map_element_RND_to_EM(int element_rnd)
6744 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
6745 static boolean mapping_initialized = FALSE;
6747 if (!mapping_initialized)
6751 /* return "Xalpha_quest" for all undefined elements in mapping array */
6752 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
6753 mapping_RND_to_EM[i] = Xalpha_quest;
6755 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
6756 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
6757 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
6758 em_object_mapping_list[i].element_em;
6760 mapping_initialized = TRUE;
6763 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
6764 return mapping_RND_to_EM[element_rnd];
6766 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
6771 int map_element_EM_to_RND(int element_em)
6773 static unsigned short mapping_EM_to_RND[TILE_MAX];
6774 static boolean mapping_initialized = FALSE;
6776 if (!mapping_initialized)
6780 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
6781 for (i = 0; i < TILE_MAX; i++)
6782 mapping_EM_to_RND[i] = EL_UNKNOWN;
6784 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
6785 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
6786 em_object_mapping_list[i].element_rnd;
6788 mapping_initialized = TRUE;
6791 if (element_em >= 0 && element_em < TILE_MAX)
6792 return mapping_EM_to_RND[element_em];
6794 Error(ERR_WARN, "invalid EM level element %d", element_em);
6799 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
6801 struct LevelInfo_EM *level_em = level->native_em_level;
6802 struct LEVEL *lev = level_em->lev;
6805 for (i = 0; i < TILE_MAX; i++)
6806 lev->android_array[i] = Xblank;
6808 for (i = 0; i < level->num_android_clone_elements; i++)
6810 int element_rnd = level->android_clone_element[i];
6811 int element_em = map_element_RND_to_EM(element_rnd);
6813 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
6814 if (em_object_mapping_list[j].element_rnd == element_rnd)
6815 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
6819 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
6821 struct LevelInfo_EM *level_em = level->native_em_level;
6822 struct LEVEL *lev = level_em->lev;
6825 level->num_android_clone_elements = 0;
6827 for (i = 0; i < TILE_MAX; i++)
6829 int element_em = lev->android_array[i];
6831 boolean element_found = FALSE;
6833 if (element_em == Xblank)
6836 element_rnd = map_element_EM_to_RND(element_em);
6838 for (j = 0; j < level->num_android_clone_elements; j++)
6839 if (level->android_clone_element[j] == element_rnd)
6840 element_found = TRUE;
6844 level->android_clone_element[level->num_android_clone_elements++] =
6847 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
6852 if (level->num_android_clone_elements == 0)
6854 level->num_android_clone_elements = 1;
6855 level->android_clone_element[0] = EL_EMPTY;
6859 int map_direction_RND_to_EM(int direction)
6861 return (direction == MV_UP ? 0 :
6862 direction == MV_RIGHT ? 1 :
6863 direction == MV_DOWN ? 2 :
6864 direction == MV_LEFT ? 3 :
6868 int map_direction_EM_to_RND(int direction)
6870 return (direction == 0 ? MV_UP :
6871 direction == 1 ? MV_RIGHT :
6872 direction == 2 ? MV_DOWN :
6873 direction == 3 ? MV_LEFT :
6877 int map_element_RND_to_SP(int element_rnd)
6879 int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
6881 if (element_rnd >= EL_SP_START &&
6882 element_rnd <= EL_SP_END)
6883 element_sp = element_rnd - EL_SP_START;
6884 else if (element_rnd == EL_EMPTY_SPACE)
6886 else if (element_rnd == EL_INVISIBLE_WALL)
6892 int map_element_SP_to_RND(int element_sp)
6894 int element_rnd = EL_UNKNOWN;
6896 if (element_sp >= 0x00 &&
6898 element_rnd = EL_SP_START + element_sp;
6899 else if (element_sp == 0x28)
6900 element_rnd = EL_INVISIBLE_WALL;
6905 int map_action_SP_to_RND(int action_sp)
6909 case actActive: return ACTION_ACTIVE;
6910 case actImpact: return ACTION_IMPACT;
6911 case actExploding: return ACTION_EXPLODING;
6912 case actDigging: return ACTION_DIGGING;
6913 case actSnapping: return ACTION_SNAPPING;
6914 case actCollecting: return ACTION_COLLECTING;
6915 case actPassing: return ACTION_PASSING;
6916 case actPushing: return ACTION_PUSHING;
6917 case actDropping: return ACTION_DROPPING;
6919 default: return ACTION_DEFAULT;
6923 int get_next_element(int element)
6927 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
6928 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
6929 case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL;
6930 case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY;
6931 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
6932 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
6933 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
6934 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
6935 case EL_DC_MAGIC_WALL_FILLING: return EL_DC_MAGIC_WALL_FULL;
6936 case EL_DC_MAGIC_WALL_EMPTYING: return EL_DC_MAGIC_WALL_ACTIVE;
6937 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
6939 default: return element;
6944 int el_act_dir2img(int element, int action, int direction)
6946 element = GFX_ELEMENT(element);
6948 if (direction == MV_NONE)
6949 return element_info[element].graphic[action];
6951 direction = MV_DIR_TO_BIT(direction);
6953 return element_info[element].direction_graphic[action][direction];
6956 int el_act_dir2img(int element, int action, int direction)
6958 element = GFX_ELEMENT(element);
6959 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
6961 /* direction_graphic[][] == graphic[] for undefined direction graphics */
6962 return element_info[element].direction_graphic[action][direction];
6967 static int el_act_dir2crm(int element, int action, int direction)
6969 element = GFX_ELEMENT(element);
6971 if (direction == MV_NONE)
6972 return element_info[element].crumbled[action];
6974 direction = MV_DIR_TO_BIT(direction);
6976 return element_info[element].direction_crumbled[action][direction];
6979 static int el_act_dir2crm(int element, int action, int direction)
6981 element = GFX_ELEMENT(element);
6982 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
6984 /* direction_graphic[][] == graphic[] for undefined direction graphics */
6985 return element_info[element].direction_crumbled[action][direction];
6989 int el_act2img(int element, int action)
6991 element = GFX_ELEMENT(element);
6993 return element_info[element].graphic[action];
6996 int el_act2crm(int element, int action)
6998 element = GFX_ELEMENT(element);
7000 return element_info[element].crumbled[action];
7003 int el_dir2img(int element, int direction)
7005 element = GFX_ELEMENT(element);
7007 return el_act_dir2img(element, ACTION_DEFAULT, direction);
7010 int el2baseimg(int element)
7012 return element_info[element].graphic[ACTION_DEFAULT];
7015 int el2img(int element)
7017 element = GFX_ELEMENT(element);
7019 return element_info[element].graphic[ACTION_DEFAULT];
7022 int el2edimg(int element)
7024 element = GFX_ELEMENT(element);
7026 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
7029 int el2preimg(int element)
7031 element = GFX_ELEMENT(element);
7033 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
7036 int el2panelimg(int element)
7038 element = GFX_ELEMENT(element);
7040 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PANEL];
7043 int font2baseimg(int font_nr)
7045 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
7048 int getBeltNrFromBeltElement(int element)
7050 return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 :
7051 element < EL_CONVEYOR_BELT_3_LEFT ? 1 :
7052 element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3);
7055 int getBeltNrFromBeltActiveElement(int element)
7057 return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 :
7058 element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 :
7059 element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3);
7062 int getBeltNrFromBeltSwitchElement(int element)
7064 return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 :
7065 element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 :
7066 element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3);
7069 int getBeltDirNrFromBeltElement(int element)
7071 static int belt_base_element[4] =
7073 EL_CONVEYOR_BELT_1_LEFT,
7074 EL_CONVEYOR_BELT_2_LEFT,
7075 EL_CONVEYOR_BELT_3_LEFT,
7076 EL_CONVEYOR_BELT_4_LEFT
7079 int belt_nr = getBeltNrFromBeltElement(element);
7080 int belt_dir_nr = element - belt_base_element[belt_nr];
7082 return (belt_dir_nr % 3);
7085 int getBeltDirNrFromBeltSwitchElement(int element)
7087 static int belt_base_element[4] =
7089 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
7090 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
7091 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
7092 EL_CONVEYOR_BELT_4_SWITCH_LEFT
7095 int belt_nr = getBeltNrFromBeltSwitchElement(element);
7096 int belt_dir_nr = element - belt_base_element[belt_nr];
7098 return (belt_dir_nr % 3);
7101 int getBeltDirFromBeltElement(int element)
7103 static int belt_move_dir[3] =
7110 int belt_dir_nr = getBeltDirNrFromBeltElement(element);
7112 return belt_move_dir[belt_dir_nr];
7115 int getBeltDirFromBeltSwitchElement(int element)
7117 static int belt_move_dir[3] =
7124 int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(element);
7126 return belt_move_dir[belt_dir_nr];
7129 int getBeltElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
7131 static int belt_base_element[4] =
7133 EL_CONVEYOR_BELT_1_LEFT,
7134 EL_CONVEYOR_BELT_2_LEFT,
7135 EL_CONVEYOR_BELT_3_LEFT,
7136 EL_CONVEYOR_BELT_4_LEFT
7139 return belt_base_element[belt_nr] + belt_dir_nr;
7142 int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
7144 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
7146 return getBeltElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
7149 int getBeltSwitchElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
7151 static int belt_base_element[4] =
7153 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
7154 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
7155 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
7156 EL_CONVEYOR_BELT_4_SWITCH_LEFT
7159 return belt_base_element[belt_nr] + belt_dir_nr;
7162 int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
7164 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
7166 return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
7169 int getNumActivePlayers_EM()
7171 int num_players = 0;
7177 for (i = 0; i < MAX_PLAYERS; i++)
7178 if (tape.player_participates[i])
7184 int getGameFrameDelay_EM(int native_em_game_frame_delay)
7186 int game_frame_delay_value;
7188 game_frame_delay_value =
7189 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
7190 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
7193 if (tape.playing && tape.warp_forward && !tape.pausing)
7194 game_frame_delay_value = 0;
7196 return game_frame_delay_value;
7199 unsigned int InitRND(long seed)
7201 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
7202 return InitEngineRandom_EM(seed);
7203 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
7204 return InitEngineRandom_SP(seed);
7206 return InitEngineRandom_RND(seed);
7210 static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
7211 static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
7214 inline static int get_effective_element_EM(int tile, int frame_em)
7216 int element = object_mapping[tile].element_rnd;
7217 int action = object_mapping[tile].action;
7218 boolean is_backside = object_mapping[tile].is_backside;
7219 boolean action_removing = (action == ACTION_DIGGING ||
7220 action == ACTION_SNAPPING ||
7221 action == ACTION_COLLECTING);
7227 case Yacid_splash_eB:
7228 case Yacid_splash_wB:
7229 return (frame_em > 5 ? EL_EMPTY : element);
7233 case Ydiamond_stone:
7234 // if (!game.use_native_emc_graphics_engine)
7242 else /* frame_em == 7 */
7246 case Yacid_splash_eB:
7247 case Yacid_splash_wB:
7250 case Yemerald_stone:
7253 case Ydiamond_stone:
7257 case Xdrip_stretchB:
7276 case Xsand_stonein_1:
7277 case Xsand_stonein_2:
7278 case Xsand_stonein_3:
7279 case Xsand_stonein_4:
7283 return (is_backside || action_removing ? EL_EMPTY : element);
7288 inline static boolean check_linear_animation_EM(int tile)
7292 case Xsand_stonesand_1:
7293 case Xsand_stonesand_quickout_1:
7294 case Xsand_sandstone_1:
7295 case Xsand_stonein_1:
7296 case Xsand_stoneout_1:
7316 case Yacid_splash_eB:
7317 case Yacid_splash_wB:
7318 case Yemerald_stone:
7326 inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
7327 boolean has_crumbled_graphics,
7328 int crumbled, int sync_frame)
7330 /* if element can be crumbled, but certain action graphics are just empty
7331 space (like instantly snapping sand to empty space in 1 frame), do not
7332 treat these empty space graphics as crumbled graphics in EMC engine */
7333 if (crumbled == IMG_EMPTY_SPACE)
7334 has_crumbled_graphics = FALSE;
7336 if (has_crumbled_graphics)
7338 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
7339 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
7340 g_crumbled->anim_delay,
7341 g_crumbled->anim_mode,
7342 g_crumbled->anim_start_frame,
7345 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
7346 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
7348 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
7350 g_em->has_crumbled_graphics = TRUE;
7354 g_em->crumbled_bitmap = NULL;
7355 g_em->crumbled_src_x = 0;
7356 g_em->crumbled_src_y = 0;
7357 g_em->crumbled_border_size = 0;
7359 g_em->has_crumbled_graphics = FALSE;
7363 void ResetGfxAnimation_EM(int x, int y, int tile)
7368 void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
7369 int tile, int frame_em, int x, int y)
7371 int action = object_mapping[tile].action;
7373 int direction = object_mapping[tile].direction;
7374 int effective_element = get_effective_element_EM(tile, frame_em);
7375 int graphic = (direction == MV_NONE ?
7376 el_act2img(effective_element, action) :
7377 el_act_dir2img(effective_element, action, direction));
7378 struct GraphicInfo *g = &graphic_info[graphic];
7381 boolean action_removing = (action == ACTION_DIGGING ||
7382 action == ACTION_SNAPPING ||
7383 action == ACTION_COLLECTING);
7384 boolean action_moving = (action == ACTION_FALLING ||
7385 action == ACTION_MOVING ||
7386 action == ACTION_PUSHING ||
7387 action == ACTION_EATING ||
7388 action == ACTION_FILLING ||
7389 action == ACTION_EMPTYING);
7390 boolean action_falling = (action == ACTION_FALLING ||
7391 action == ACTION_FILLING ||
7392 action == ACTION_EMPTYING);
7394 /* special case: graphic uses "2nd movement tile" and has defined
7395 7 frames for movement animation (or less) => use default graphic
7396 for last (8th) frame which ends the movement animation */
7397 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
7399 action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
7400 graphic = (direction == MV_NONE ?
7401 el_act2img(effective_element, action) :
7402 el_act_dir2img(effective_element, action, direction));
7404 g = &graphic_info[graphic];
7408 if (tile == Xsand_stonesand_1 ||
7409 tile == Xsand_stonesand_2 ||
7410 tile == Xsand_stonesand_3 ||
7411 tile == Xsand_stonesand_4)
7412 printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
7416 if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
7420 // printf("::: resetting... [%d]\n", tile);
7423 if (action_removing || check_linear_animation_EM(tile))
7425 GfxFrame[x][y] = frame_em;
7427 // printf("::: resetting... [%d]\n", tile);
7430 else if (action_moving)
7432 boolean is_backside = object_mapping[tile].is_backside;
7436 int direction = object_mapping[tile].direction;
7437 int move_dir = (action_falling ? MV_DOWN : direction);
7442 /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
7443 if (g->double_movement && frame_em == 0)
7447 // printf("::: resetting... [%d]\n", tile);
7451 if (move_dir == MV_LEFT)
7452 GfxFrame[x - 1][y] = GfxFrame[x][y];
7453 else if (move_dir == MV_RIGHT)
7454 GfxFrame[x + 1][y] = GfxFrame[x][y];
7455 else if (move_dir == MV_UP)
7456 GfxFrame[x][y - 1] = GfxFrame[x][y];
7457 else if (move_dir == MV_DOWN)
7458 GfxFrame[x][y + 1] = GfxFrame[x][y];
7465 /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
7466 if (tile == Xsand_stonesand_quickout_1 ||
7467 tile == Xsand_stonesand_quickout_2)
7472 if (tile == Xsand_stonesand_1 ||
7473 tile == Xsand_stonesand_2 ||
7474 tile == Xsand_stonesand_3 ||
7475 tile == Xsand_stonesand_4)
7476 printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
7480 if (graphic_info[graphic].anim_global_sync)
7481 sync_frame = FrameCounter;
7482 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
7483 sync_frame = GfxFrame[x][y];
7485 sync_frame = 0; /* playfield border (pseudo steel) */
7487 SetRandomAnimationValue(x, y);
7489 int frame = getAnimationFrame(g->anim_frames,
7492 g->anim_start_frame,
7495 g_em->unique_identifier =
7496 (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
7500 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
7501 int tile, int frame_em, int x, int y)
7503 int action = object_mapping[tile].action;
7504 int direction = object_mapping[tile].direction;
7505 boolean is_backside = object_mapping[tile].is_backside;
7506 int effective_element = get_effective_element_EM(tile, frame_em);
7508 int effective_action = action;
7510 int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
7512 int graphic = (direction == MV_NONE ?
7513 el_act2img(effective_element, effective_action) :
7514 el_act_dir2img(effective_element, effective_action,
7516 int crumbled = (direction == MV_NONE ?
7517 el_act2crm(effective_element, effective_action) :
7518 el_act_dir2crm(effective_element, effective_action,
7520 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
7521 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
7522 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
7523 struct GraphicInfo *g = &graphic_info[graphic];
7525 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
7529 /* special case: graphic uses "2nd movement tile" and has defined
7530 7 frames for movement animation (or less) => use default graphic
7531 for last (8th) frame which ends the movement animation */
7532 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
7534 effective_action = ACTION_DEFAULT;
7535 graphic = (direction == MV_NONE ?
7536 el_act2img(effective_element, effective_action) :
7537 el_act_dir2img(effective_element, effective_action,
7539 crumbled = (direction == MV_NONE ?
7540 el_act2crm(effective_element, effective_action) :
7541 el_act_dir2crm(effective_element, effective_action,
7544 g = &graphic_info[graphic];
7554 if (frame_em == 0) /* reset animation frame for certain elements */
7556 if (check_linear_animation_EM(tile))
7561 if (graphic_info[graphic].anim_global_sync)
7562 sync_frame = FrameCounter;
7563 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
7564 sync_frame = GfxFrame[x][y];
7566 sync_frame = 0; /* playfield border (pseudo steel) */
7568 SetRandomAnimationValue(x, y);
7573 int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
7574 i == Xdrip_stretchB ? 7 :
7575 i == Ydrip_s2 ? j + 8 :
7576 i == Ydrip_s2B ? j + 8 :
7585 i == Xfake_acid_1 ? 0 :
7586 i == Xfake_acid_2 ? 10 :
7587 i == Xfake_acid_3 ? 20 :
7588 i == Xfake_acid_4 ? 30 :
7589 i == Xfake_acid_5 ? 40 :
7590 i == Xfake_acid_6 ? 50 :
7591 i == Xfake_acid_7 ? 60 :
7592 i == Xfake_acid_8 ? 70 :
7594 i == Xball_2B ? j + 8 :
7595 i == Yball_eat ? j + 1 :
7596 i == Ykey_1_eat ? j + 1 :
7597 i == Ykey_2_eat ? j + 1 :
7598 i == Ykey_3_eat ? j + 1 :
7599 i == Ykey_4_eat ? j + 1 :
7600 i == Ykey_5_eat ? j + 1 :
7601 i == Ykey_6_eat ? j + 1 :
7602 i == Ykey_7_eat ? j + 1 :
7603 i == Ykey_8_eat ? j + 1 :
7604 i == Ylenses_eat ? j + 1 :
7605 i == Ymagnify_eat ? j + 1 :
7606 i == Ygrass_eat ? j + 1 :
7607 i == Ydirt_eat ? j + 1 :
7608 i == Xamoeba_1 ? 0 :
7609 i == Xamoeba_2 ? 1 :
7610 i == Xamoeba_3 ? 2 :
7611 i == Xamoeba_4 ? 3 :
7612 i == Xamoeba_5 ? 0 :
7613 i == Xamoeba_6 ? 1 :
7614 i == Xamoeba_7 ? 2 :
7615 i == Xamoeba_8 ? 3 :
7616 i == Xexit_2 ? j + 8 :
7617 i == Xexit_3 ? j + 16 :
7618 i == Xdynamite_1 ? 0 :
7619 i == Xdynamite_2 ? 8 :
7620 i == Xdynamite_3 ? 16 :
7621 i == Xdynamite_4 ? 24 :
7622 i == Xsand_stonein_1 ? j + 1 :
7623 i == Xsand_stonein_2 ? j + 9 :
7624 i == Xsand_stonein_3 ? j + 17 :
7625 i == Xsand_stonein_4 ? j + 25 :
7626 i == Xsand_stoneout_1 && j == 0 ? 0 :
7627 i == Xsand_stoneout_1 && j == 1 ? 0 :
7628 i == Xsand_stoneout_1 && j == 2 ? 1 :
7629 i == Xsand_stoneout_1 && j == 3 ? 2 :
7630 i == Xsand_stoneout_1 && j == 4 ? 2 :
7631 i == Xsand_stoneout_1 && j == 5 ? 3 :
7632 i == Xsand_stoneout_1 && j == 6 ? 4 :
7633 i == Xsand_stoneout_1 && j == 7 ? 4 :
7634 i == Xsand_stoneout_2 && j == 0 ? 5 :
7635 i == Xsand_stoneout_2 && j == 1 ? 6 :
7636 i == Xsand_stoneout_2 && j == 2 ? 7 :
7637 i == Xsand_stoneout_2 && j == 3 ? 8 :
7638 i == Xsand_stoneout_2 && j == 4 ? 9 :
7639 i == Xsand_stoneout_2 && j == 5 ? 11 :
7640 i == Xsand_stoneout_2 && j == 6 ? 13 :
7641 i == Xsand_stoneout_2 && j == 7 ? 15 :
7642 i == Xboom_bug && j == 1 ? 2 :
7643 i == Xboom_bug && j == 2 ? 2 :
7644 i == Xboom_bug && j == 3 ? 4 :
7645 i == Xboom_bug && j == 4 ? 4 :
7646 i == Xboom_bug && j == 5 ? 2 :
7647 i == Xboom_bug && j == 6 ? 2 :
7648 i == Xboom_bug && j == 7 ? 0 :
7649 i == Xboom_bomb && j == 1 ? 2 :
7650 i == Xboom_bomb && j == 2 ? 2 :
7651 i == Xboom_bomb && j == 3 ? 4 :
7652 i == Xboom_bomb && j == 4 ? 4 :
7653 i == Xboom_bomb && j == 5 ? 2 :
7654 i == Xboom_bomb && j == 6 ? 2 :
7655 i == Xboom_bomb && j == 7 ? 0 :
7656 i == Xboom_android && j == 7 ? 6 :
7657 i == Xboom_1 && j == 1 ? 2 :
7658 i == Xboom_1 && j == 2 ? 2 :
7659 i == Xboom_1 && j == 3 ? 4 :
7660 i == Xboom_1 && j == 4 ? 4 :
7661 i == Xboom_1 && j == 5 ? 6 :
7662 i == Xboom_1 && j == 6 ? 6 :
7663 i == Xboom_1 && j == 7 ? 8 :
7664 i == Xboom_2 && j == 0 ? 8 :
7665 i == Xboom_2 && j == 1 ? 8 :
7666 i == Xboom_2 && j == 2 ? 10 :
7667 i == Xboom_2 && j == 3 ? 10 :
7668 i == Xboom_2 && j == 4 ? 10 :
7669 i == Xboom_2 && j == 5 ? 12 :
7670 i == Xboom_2 && j == 6 ? 12 :
7671 i == Xboom_2 && j == 7 ? 12 :
7673 special_animation && j == 4 ? 3 :
7674 effective_action != action ? 0 :
7680 int xxx_effective_action;
7681 int xxx_has_action_graphics;
7684 int element = object_mapping[i].element_rnd;
7685 int action = object_mapping[i].action;
7686 int direction = object_mapping[i].direction;
7687 boolean is_backside = object_mapping[i].is_backside;
7689 boolean action_removing = (action == ACTION_DIGGING ||
7690 action == ACTION_SNAPPING ||
7691 action == ACTION_COLLECTING);
7693 boolean action_exploding = ((action == ACTION_EXPLODING ||
7694 action == ACTION_SMASHED_BY_ROCK ||
7695 action == ACTION_SMASHED_BY_SPRING) &&
7696 element != EL_DIAMOND);
7697 boolean action_active = (action == ACTION_ACTIVE);
7698 boolean action_other = (action == ACTION_OTHER);
7702 int effective_element = get_effective_element_EM(i, j);
7704 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
7705 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
7707 i == Xdrip_stretch ? element :
7708 i == Xdrip_stretchB ? element :
7709 i == Ydrip_s1 ? element :
7710 i == Ydrip_s1B ? element :
7711 i == Xball_1B ? element :
7712 i == Xball_2 ? element :
7713 i == Xball_2B ? element :
7714 i == Yball_eat ? element :
7715 i == Ykey_1_eat ? element :
7716 i == Ykey_2_eat ? element :
7717 i == Ykey_3_eat ? element :
7718 i == Ykey_4_eat ? element :
7719 i == Ykey_5_eat ? element :
7720 i == Ykey_6_eat ? element :
7721 i == Ykey_7_eat ? element :
7722 i == Ykey_8_eat ? element :
7723 i == Ylenses_eat ? element :
7724 i == Ymagnify_eat ? element :
7725 i == Ygrass_eat ? element :
7726 i == Ydirt_eat ? element :
7727 i == Yemerald_stone ? EL_EMERALD :
7728 i == Ydiamond_stone ? EL_ROCK :
7729 i == Xsand_stonein_1 ? element :
7730 i == Xsand_stonein_2 ? element :
7731 i == Xsand_stonein_3 ? element :
7732 i == Xsand_stonein_4 ? element :
7733 is_backside ? EL_EMPTY :
7734 action_removing ? EL_EMPTY :
7737 int effective_action = (j < 7 ? action :
7738 i == Xdrip_stretch ? action :
7739 i == Xdrip_stretchB ? action :
7740 i == Ydrip_s1 ? action :
7741 i == Ydrip_s1B ? action :
7742 i == Xball_1B ? action :
7743 i == Xball_2 ? action :
7744 i == Xball_2B ? action :
7745 i == Yball_eat ? action :
7746 i == Ykey_1_eat ? action :
7747 i == Ykey_2_eat ? action :
7748 i == Ykey_3_eat ? action :
7749 i == Ykey_4_eat ? action :
7750 i == Ykey_5_eat ? action :
7751 i == Ykey_6_eat ? action :
7752 i == Ykey_7_eat ? action :
7753 i == Ykey_8_eat ? action :
7754 i == Ylenses_eat ? action :
7755 i == Ymagnify_eat ? action :
7756 i == Ygrass_eat ? action :
7757 i == Ydirt_eat ? action :
7758 i == Xsand_stonein_1 ? action :
7759 i == Xsand_stonein_2 ? action :
7760 i == Xsand_stonein_3 ? action :
7761 i == Xsand_stonein_4 ? action :
7762 i == Xsand_stoneout_1 ? action :
7763 i == Xsand_stoneout_2 ? action :
7764 i == Xboom_android ? ACTION_EXPLODING :
7765 action_exploding ? ACTION_EXPLODING :
7766 action_active ? action :
7767 action_other ? action :
7769 int graphic = (el_act_dir2img(effective_element, effective_action,
7771 int crumbled = (el_act_dir2crm(effective_element, effective_action,
7773 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
7774 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
7775 boolean has_action_graphics = (graphic != base_graphic);
7776 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
7777 struct GraphicInfo *g = &graphic_info[graphic];
7779 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
7781 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
7784 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
7785 boolean special_animation = (action != ACTION_DEFAULT &&
7786 g->anim_frames == 3 &&
7787 g->anim_delay == 2 &&
7788 g->anim_mode & ANIM_LINEAR);
7789 xxx_sync_frame = (i == Xdrip_stretch ? 7 :
7790 i == Xdrip_stretchB ? 7 :
7791 i == Ydrip_s2 ? j + 8 :
7792 i == Ydrip_s2B ? j + 8 :
7801 i == Xfake_acid_1 ? 0 :
7802 i == Xfake_acid_2 ? 10 :
7803 i == Xfake_acid_3 ? 20 :
7804 i == Xfake_acid_4 ? 30 :
7805 i == Xfake_acid_5 ? 40 :
7806 i == Xfake_acid_6 ? 50 :
7807 i == Xfake_acid_7 ? 60 :
7808 i == Xfake_acid_8 ? 70 :
7810 i == Xball_2B ? j + 8 :
7811 i == Yball_eat ? j + 1 :
7812 i == Ykey_1_eat ? j + 1 :
7813 i == Ykey_2_eat ? j + 1 :
7814 i == Ykey_3_eat ? j + 1 :
7815 i == Ykey_4_eat ? j + 1 :
7816 i == Ykey_5_eat ? j + 1 :
7817 i == Ykey_6_eat ? j + 1 :
7818 i == Ykey_7_eat ? j + 1 :
7819 i == Ykey_8_eat ? j + 1 :
7820 i == Ylenses_eat ? j + 1 :
7821 i == Ymagnify_eat ? j + 1 :
7822 i == Ygrass_eat ? j + 1 :
7823 i == Ydirt_eat ? j + 1 :
7824 i == Xamoeba_1 ? 0 :
7825 i == Xamoeba_2 ? 1 :
7826 i == Xamoeba_3 ? 2 :
7827 i == Xamoeba_4 ? 3 :
7828 i == Xamoeba_5 ? 0 :
7829 i == Xamoeba_6 ? 1 :
7830 i == Xamoeba_7 ? 2 :
7831 i == Xamoeba_8 ? 3 :
7832 i == Xexit_2 ? j + 8 :
7833 i == Xexit_3 ? j + 16 :
7834 i == Xdynamite_1 ? 0 :
7835 i == Xdynamite_2 ? 8 :
7836 i == Xdynamite_3 ? 16 :
7837 i == Xdynamite_4 ? 24 :
7838 i == Xsand_stonein_1 ? j + 1 :
7839 i == Xsand_stonein_2 ? j + 9 :
7840 i == Xsand_stonein_3 ? j + 17 :
7841 i == Xsand_stonein_4 ? j + 25 :
7842 i == Xsand_stoneout_1 && j == 0 ? 0 :
7843 i == Xsand_stoneout_1 && j == 1 ? 0 :
7844 i == Xsand_stoneout_1 && j == 2 ? 1 :
7845 i == Xsand_stoneout_1 && j == 3 ? 2 :
7846 i == Xsand_stoneout_1 && j == 4 ? 2 :
7847 i == Xsand_stoneout_1 && j == 5 ? 3 :
7848 i == Xsand_stoneout_1 && j == 6 ? 4 :
7849 i == Xsand_stoneout_1 && j == 7 ? 4 :
7850 i == Xsand_stoneout_2 && j == 0 ? 5 :
7851 i == Xsand_stoneout_2 && j == 1 ? 6 :
7852 i == Xsand_stoneout_2 && j == 2 ? 7 :
7853 i == Xsand_stoneout_2 && j == 3 ? 8 :
7854 i == Xsand_stoneout_2 && j == 4 ? 9 :
7855 i == Xsand_stoneout_2 && j == 5 ? 11 :
7856 i == Xsand_stoneout_2 && j == 6 ? 13 :
7857 i == Xsand_stoneout_2 && j == 7 ? 15 :
7858 i == Xboom_bug && j == 1 ? 2 :
7859 i == Xboom_bug && j == 2 ? 2 :
7860 i == Xboom_bug && j == 3 ? 4 :
7861 i == Xboom_bug && j == 4 ? 4 :
7862 i == Xboom_bug && j == 5 ? 2 :
7863 i == Xboom_bug && j == 6 ? 2 :
7864 i == Xboom_bug && j == 7 ? 0 :
7865 i == Xboom_bomb && j == 1 ? 2 :
7866 i == Xboom_bomb && j == 2 ? 2 :
7867 i == Xboom_bomb && j == 3 ? 4 :
7868 i == Xboom_bomb && j == 4 ? 4 :
7869 i == Xboom_bomb && j == 5 ? 2 :
7870 i == Xboom_bomb && j == 6 ? 2 :
7871 i == Xboom_bomb && j == 7 ? 0 :
7872 i == Xboom_android && j == 7 ? 6 :
7873 i == Xboom_1 && j == 1 ? 2 :
7874 i == Xboom_1 && j == 2 ? 2 :
7875 i == Xboom_1 && j == 3 ? 4 :
7876 i == Xboom_1 && j == 4 ? 4 :
7877 i == Xboom_1 && j == 5 ? 6 :
7878 i == Xboom_1 && j == 6 ? 6 :
7879 i == Xboom_1 && j == 7 ? 8 :
7880 i == Xboom_2 && j == 0 ? 8 :
7881 i == Xboom_2 && j == 1 ? 8 :
7882 i == Xboom_2 && j == 2 ? 10 :
7883 i == Xboom_2 && j == 3 ? 10 :
7884 i == Xboom_2 && j == 4 ? 10 :
7885 i == Xboom_2 && j == 5 ? 12 :
7886 i == Xboom_2 && j == 6 ? 12 :
7887 i == Xboom_2 && j == 7 ? 12 :
7888 special_animation && j == 4 ? 3 :
7889 effective_action != action ? 0 :
7892 xxx_effective_action = effective_action;
7893 xxx_has_action_graphics = has_action_graphics;
7898 int frame = getAnimationFrame(g->anim_frames,
7901 g->anim_start_frame,
7915 int old_src_x = g_em->src_x;
7916 int old_src_y = g_em->src_y;
7920 getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
7921 g->double_movement && is_backside);
7923 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
7924 &g_em->src_x, &g_em->src_y, FALSE);
7929 if (tile == Ydiamond_stone)
7930 printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n",
7935 g->anim_start_frame,
7938 g_em->src_x, g_em->src_y,
7939 g_em->src_offset_x, g_em->src_offset_y,
7940 g_em->dst_offset_x, g_em->dst_offset_y,
7952 if (graphic == IMG_BUG_MOVING_RIGHT)
7953 printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
7954 g->double_movement, is_backside,
7955 old_src_x, old_src_y, g_em->src_x, g_em->src_y);
7963 g_em->src_offset_x = 0;
7964 g_em->src_offset_y = 0;
7965 g_em->dst_offset_x = 0;
7966 g_em->dst_offset_y = 0;
7967 g_em->width = TILEX;
7968 g_em->height = TILEY;
7970 g_em->preserve_background = FALSE;
7973 /* (updating the "crumbled" graphic definitions is probably not really needed,
7974 as animations for crumbled graphics can't be longer than one EMC cycle) */
7976 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
7981 g_em->crumbled_bitmap = NULL;
7982 g_em->crumbled_src_x = 0;
7983 g_em->crumbled_src_y = 0;
7985 g_em->has_crumbled_graphics = FALSE;
7987 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
7989 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
7990 g_crumbled->anim_delay,
7991 g_crumbled->anim_mode,
7992 g_crumbled->anim_start_frame,
7995 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
7996 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
7998 g_em->has_crumbled_graphics = TRUE;
8004 int effective_action = xxx_effective_action;
8005 int has_action_graphics = xxx_has_action_graphics;
8007 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
8008 effective_action == ACTION_MOVING ||
8009 effective_action == ACTION_PUSHING ||
8010 effective_action == ACTION_EATING)) ||
8011 (!has_action_graphics && (effective_action == ACTION_FILLING ||
8012 effective_action == ACTION_EMPTYING)))
8015 (effective_action == ACTION_FALLING ||
8016 effective_action == ACTION_FILLING ||
8017 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
8018 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
8019 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
8020 int num_steps = (i == Ydrip_s1 ? 16 :
8021 i == Ydrip_s1B ? 16 :
8022 i == Ydrip_s2 ? 16 :
8023 i == Ydrip_s2B ? 16 :
8024 i == Xsand_stonein_1 ? 32 :
8025 i == Xsand_stonein_2 ? 32 :
8026 i == Xsand_stonein_3 ? 32 :
8027 i == Xsand_stonein_4 ? 32 :
8028 i == Xsand_stoneout_1 ? 16 :
8029 i == Xsand_stoneout_2 ? 16 : 8);
8030 int cx = ABS(dx) * (TILEX / num_steps);
8031 int cy = ABS(dy) * (TILEY / num_steps);
8032 int step_frame = (i == Ydrip_s2 ? j + 8 :
8033 i == Ydrip_s2B ? j + 8 :
8034 i == Xsand_stonein_2 ? j + 8 :
8035 i == Xsand_stonein_3 ? j + 16 :
8036 i == Xsand_stonein_4 ? j + 24 :
8037 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
8038 int step = (is_backside ? step_frame : num_steps - step_frame);
8040 if (is_backside) /* tile where movement starts */
8042 if (dx < 0 || dy < 0)
8044 g_em->src_offset_x = cx * step;
8045 g_em->src_offset_y = cy * step;
8049 g_em->dst_offset_x = cx * step;
8050 g_em->dst_offset_y = cy * step;
8053 else /* tile where movement ends */
8055 if (dx < 0 || dy < 0)
8057 g_em->dst_offset_x = cx * step;
8058 g_em->dst_offset_y = cy * step;
8062 g_em->src_offset_x = cx * step;
8063 g_em->src_offset_y = cy * step;
8067 g_em->width = TILEX - cx * step;
8068 g_em->height = TILEY - cy * step;
8071 /* create unique graphic identifier to decide if tile must be redrawn */
8072 /* bit 31 - 16 (16 bit): EM style graphic
8073 bit 15 - 12 ( 4 bit): EM style frame
8074 bit 11 - 6 ( 6 bit): graphic width
8075 bit 5 - 0 ( 6 bit): graphic height */
8076 g_em->unique_identifier =
8077 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
8083 void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
8084 int player_nr, int anim, int frame_em)
8086 int element = player_mapping[player_nr][anim].element_rnd;
8087 int action = player_mapping[player_nr][anim].action;
8088 int direction = player_mapping[player_nr][anim].direction;
8089 int graphic = (direction == MV_NONE ?
8090 el_act2img(element, action) :
8091 el_act_dir2img(element, action, direction));
8092 struct GraphicInfo *g = &graphic_info[graphic];
8095 InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
8097 stored_player[player_nr].StepFrame = frame_em;
8099 sync_frame = stored_player[player_nr].Frame;
8101 int frame = getAnimationFrame(g->anim_frames,
8104 g->anim_start_frame,
8107 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
8108 &g_em->src_x, &g_em->src_y, FALSE);
8111 printf("::: %d: %d, %d [%d]\n",
8113 stored_player[player_nr].Frame,
8114 stored_player[player_nr].StepFrame,
8119 void InitGraphicInfo_EM(void)
8122 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
8123 struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
8128 int num_em_gfx_errors = 0;
8130 if (graphic_info_em_object[0][0].bitmap == NULL)
8132 /* EM graphics not yet initialized in em_open_all() */
8137 printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
8140 /* always start with reliable default values */
8141 for (i = 0; i < TILE_MAX; i++)
8143 object_mapping[i].element_rnd = EL_UNKNOWN;
8144 object_mapping[i].is_backside = FALSE;
8145 object_mapping[i].action = ACTION_DEFAULT;
8146 object_mapping[i].direction = MV_NONE;
8149 /* always start with reliable default values */
8150 for (p = 0; p < MAX_PLAYERS; p++)
8152 for (i = 0; i < SPR_MAX; i++)
8154 player_mapping[p][i].element_rnd = EL_UNKNOWN;
8155 player_mapping[p][i].action = ACTION_DEFAULT;
8156 player_mapping[p][i].direction = MV_NONE;
8160 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
8162 int e = em_object_mapping_list[i].element_em;
8164 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
8165 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
8167 if (em_object_mapping_list[i].action != -1)
8168 object_mapping[e].action = em_object_mapping_list[i].action;
8170 if (em_object_mapping_list[i].direction != -1)
8171 object_mapping[e].direction =
8172 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
8175 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
8177 int a = em_player_mapping_list[i].action_em;
8178 int p = em_player_mapping_list[i].player_nr;
8180 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
8182 if (em_player_mapping_list[i].action != -1)
8183 player_mapping[p][a].action = em_player_mapping_list[i].action;
8185 if (em_player_mapping_list[i].direction != -1)
8186 player_mapping[p][a].direction =
8187 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
8190 for (i = 0; i < TILE_MAX; i++)
8192 int element = object_mapping[i].element_rnd;
8193 int action = object_mapping[i].action;
8194 int direction = object_mapping[i].direction;
8195 boolean is_backside = object_mapping[i].is_backside;
8197 boolean action_removing = (action == ACTION_DIGGING ||
8198 action == ACTION_SNAPPING ||
8199 action == ACTION_COLLECTING);
8201 boolean action_exploding = ((action == ACTION_EXPLODING ||
8202 action == ACTION_SMASHED_BY_ROCK ||
8203 action == ACTION_SMASHED_BY_SPRING) &&
8204 element != EL_DIAMOND);
8205 boolean action_active = (action == ACTION_ACTIVE);
8206 boolean action_other = (action == ACTION_OTHER);
8208 for (j = 0; j < 8; j++)
8211 int effective_element = get_effective_element_EM(i, j);
8213 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
8214 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
8216 i == Xdrip_stretch ? element :
8217 i == Xdrip_stretchB ? element :
8218 i == Ydrip_s1 ? element :
8219 i == Ydrip_s1B ? element :
8220 i == Xball_1B ? element :
8221 i == Xball_2 ? element :
8222 i == Xball_2B ? element :
8223 i == Yball_eat ? element :
8224 i == Ykey_1_eat ? element :
8225 i == Ykey_2_eat ? element :
8226 i == Ykey_3_eat ? element :
8227 i == Ykey_4_eat ? element :
8228 i == Ykey_5_eat ? element :
8229 i == Ykey_6_eat ? element :
8230 i == Ykey_7_eat ? element :
8231 i == Ykey_8_eat ? element :
8232 i == Ylenses_eat ? element :
8233 i == Ymagnify_eat ? element :
8234 i == Ygrass_eat ? element :
8235 i == Ydirt_eat ? element :
8236 i == Yemerald_stone ? EL_EMERALD :
8237 i == Ydiamond_stone ? EL_ROCK :
8238 i == Xsand_stonein_1 ? element :
8239 i == Xsand_stonein_2 ? element :
8240 i == Xsand_stonein_3 ? element :
8241 i == Xsand_stonein_4 ? element :
8242 is_backside ? EL_EMPTY :
8243 action_removing ? EL_EMPTY :
8246 int effective_action = (j < 7 ? action :
8247 i == Xdrip_stretch ? action :
8248 i == Xdrip_stretchB ? action :
8249 i == Ydrip_s1 ? action :
8250 i == Ydrip_s1B ? action :
8251 i == Xball_1B ? action :
8252 i == Xball_2 ? action :
8253 i == Xball_2B ? action :
8254 i == Yball_eat ? action :
8255 i == Ykey_1_eat ? action :
8256 i == Ykey_2_eat ? action :
8257 i == Ykey_3_eat ? action :
8258 i == Ykey_4_eat ? action :
8259 i == Ykey_5_eat ? action :
8260 i == Ykey_6_eat ? action :
8261 i == Ykey_7_eat ? action :
8262 i == Ykey_8_eat ? action :
8263 i == Ylenses_eat ? action :
8264 i == Ymagnify_eat ? action :
8265 i == Ygrass_eat ? action :
8266 i == Ydirt_eat ? action :
8267 i == Xsand_stonein_1 ? action :
8268 i == Xsand_stonein_2 ? action :
8269 i == Xsand_stonein_3 ? action :
8270 i == Xsand_stonein_4 ? action :
8271 i == Xsand_stoneout_1 ? action :
8272 i == Xsand_stoneout_2 ? action :
8273 i == Xboom_android ? ACTION_EXPLODING :
8274 action_exploding ? ACTION_EXPLODING :
8275 action_active ? action :
8276 action_other ? action :
8278 int graphic = (el_act_dir2img(effective_element, effective_action,
8280 int crumbled = (el_act_dir2crm(effective_element, effective_action,
8282 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
8283 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
8284 boolean has_action_graphics = (graphic != base_graphic);
8285 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
8286 struct GraphicInfo *g = &graphic_info[graphic];
8288 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
8290 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
8293 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
8294 boolean special_animation = (action != ACTION_DEFAULT &&
8295 g->anim_frames == 3 &&
8296 g->anim_delay == 2 &&
8297 g->anim_mode & ANIM_LINEAR);
8298 int sync_frame = (i == Xdrip_stretch ? 7 :
8299 i == Xdrip_stretchB ? 7 :
8300 i == Ydrip_s2 ? j + 8 :
8301 i == Ydrip_s2B ? j + 8 :
8310 i == Xfake_acid_1 ? 0 :
8311 i == Xfake_acid_2 ? 10 :
8312 i == Xfake_acid_3 ? 20 :
8313 i == Xfake_acid_4 ? 30 :
8314 i == Xfake_acid_5 ? 40 :
8315 i == Xfake_acid_6 ? 50 :
8316 i == Xfake_acid_7 ? 60 :
8317 i == Xfake_acid_8 ? 70 :
8319 i == Xball_2B ? j + 8 :
8320 i == Yball_eat ? j + 1 :
8321 i == Ykey_1_eat ? j + 1 :
8322 i == Ykey_2_eat ? j + 1 :
8323 i == Ykey_3_eat ? j + 1 :
8324 i == Ykey_4_eat ? j + 1 :
8325 i == Ykey_5_eat ? j + 1 :
8326 i == Ykey_6_eat ? j + 1 :
8327 i == Ykey_7_eat ? j + 1 :
8328 i == Ykey_8_eat ? j + 1 :
8329 i == Ylenses_eat ? j + 1 :
8330 i == Ymagnify_eat ? j + 1 :
8331 i == Ygrass_eat ? j + 1 :
8332 i == Ydirt_eat ? j + 1 :
8333 i == Xamoeba_1 ? 0 :
8334 i == Xamoeba_2 ? 1 :
8335 i == Xamoeba_3 ? 2 :
8336 i == Xamoeba_4 ? 3 :
8337 i == Xamoeba_5 ? 0 :
8338 i == Xamoeba_6 ? 1 :
8339 i == Xamoeba_7 ? 2 :
8340 i == Xamoeba_8 ? 3 :
8341 i == Xexit_2 ? j + 8 :
8342 i == Xexit_3 ? j + 16 :
8343 i == Xdynamite_1 ? 0 :
8344 i == Xdynamite_2 ? 8 :
8345 i == Xdynamite_3 ? 16 :
8346 i == Xdynamite_4 ? 24 :
8347 i == Xsand_stonein_1 ? j + 1 :
8348 i == Xsand_stonein_2 ? j + 9 :
8349 i == Xsand_stonein_3 ? j + 17 :
8350 i == Xsand_stonein_4 ? j + 25 :
8351 i == Xsand_stoneout_1 && j == 0 ? 0 :
8352 i == Xsand_stoneout_1 && j == 1 ? 0 :
8353 i == Xsand_stoneout_1 && j == 2 ? 1 :
8354 i == Xsand_stoneout_1 && j == 3 ? 2 :
8355 i == Xsand_stoneout_1 && j == 4 ? 2 :
8356 i == Xsand_stoneout_1 && j == 5 ? 3 :
8357 i == Xsand_stoneout_1 && j == 6 ? 4 :
8358 i == Xsand_stoneout_1 && j == 7 ? 4 :
8359 i == Xsand_stoneout_2 && j == 0 ? 5 :
8360 i == Xsand_stoneout_2 && j == 1 ? 6 :
8361 i == Xsand_stoneout_2 && j == 2 ? 7 :
8362 i == Xsand_stoneout_2 && j == 3 ? 8 :
8363 i == Xsand_stoneout_2 && j == 4 ? 9 :
8364 i == Xsand_stoneout_2 && j == 5 ? 11 :
8365 i == Xsand_stoneout_2 && j == 6 ? 13 :
8366 i == Xsand_stoneout_2 && j == 7 ? 15 :
8367 i == Xboom_bug && j == 1 ? 2 :
8368 i == Xboom_bug && j == 2 ? 2 :
8369 i == Xboom_bug && j == 3 ? 4 :
8370 i == Xboom_bug && j == 4 ? 4 :
8371 i == Xboom_bug && j == 5 ? 2 :
8372 i == Xboom_bug && j == 6 ? 2 :
8373 i == Xboom_bug && j == 7 ? 0 :
8374 i == Xboom_bomb && j == 1 ? 2 :
8375 i == Xboom_bomb && j == 2 ? 2 :
8376 i == Xboom_bomb && j == 3 ? 4 :
8377 i == Xboom_bomb && j == 4 ? 4 :
8378 i == Xboom_bomb && j == 5 ? 2 :
8379 i == Xboom_bomb && j == 6 ? 2 :
8380 i == Xboom_bomb && j == 7 ? 0 :
8381 i == Xboom_android && j == 7 ? 6 :
8382 i == Xboom_1 && j == 1 ? 2 :
8383 i == Xboom_1 && j == 2 ? 2 :
8384 i == Xboom_1 && j == 3 ? 4 :
8385 i == Xboom_1 && j == 4 ? 4 :
8386 i == Xboom_1 && j == 5 ? 6 :
8387 i == Xboom_1 && j == 6 ? 6 :
8388 i == Xboom_1 && j == 7 ? 8 :
8389 i == Xboom_2 && j == 0 ? 8 :
8390 i == Xboom_2 && j == 1 ? 8 :
8391 i == Xboom_2 && j == 2 ? 10 :
8392 i == Xboom_2 && j == 3 ? 10 :
8393 i == Xboom_2 && j == 4 ? 10 :
8394 i == Xboom_2 && j == 5 ? 12 :
8395 i == Xboom_2 && j == 6 ? 12 :
8396 i == Xboom_2 && j == 7 ? 12 :
8397 special_animation && j == 4 ? 3 :
8398 effective_action != action ? 0 :
8402 Bitmap *debug_bitmap = g_em->bitmap;
8403 int debug_src_x = g_em->src_x;
8404 int debug_src_y = g_em->src_y;
8407 int frame = getAnimationFrame(g->anim_frames,
8410 g->anim_start_frame,
8413 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
8414 g->double_movement && is_backside);
8416 g_em->bitmap = src_bitmap;
8417 g_em->src_x = src_x;
8418 g_em->src_y = src_y;
8419 g_em->src_offset_x = 0;
8420 g_em->src_offset_y = 0;
8421 g_em->dst_offset_x = 0;
8422 g_em->dst_offset_y = 0;
8423 g_em->width = TILEX;
8424 g_em->height = TILEY;
8426 g_em->preserve_background = FALSE;
8429 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
8434 g_em->crumbled_bitmap = NULL;
8435 g_em->crumbled_src_x = 0;
8436 g_em->crumbled_src_y = 0;
8437 g_em->crumbled_border_size = 0;
8439 g_em->has_crumbled_graphics = FALSE;
8442 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
8443 printf("::: empty crumbled: %d [%s], %d, %d\n",
8444 effective_element, element_info[effective_element].token_name,
8445 effective_action, direction);
8448 /* if element can be crumbled, but certain action graphics are just empty
8449 space (like instantly snapping sand to empty space in 1 frame), do not
8450 treat these empty space graphics as crumbled graphics in EMC engine */
8451 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
8453 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
8454 g_crumbled->anim_delay,
8455 g_crumbled->anim_mode,
8456 g_crumbled->anim_start_frame,
8459 getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
8461 g_em->has_crumbled_graphics = TRUE;
8462 g_em->crumbled_bitmap = src_bitmap;
8463 g_em->crumbled_src_x = src_x;
8464 g_em->crumbled_src_y = src_y;
8465 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
8469 if (g_em == &graphic_info_em_object[207][0])
8470 printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
8471 graphic_info_em_object[207][0].crumbled_src_x,
8472 graphic_info_em_object[207][0].crumbled_src_y,
8474 crumbled, frame, src_x, src_y,
8479 g->anim_start_frame,
8481 gfx.anim_random_frame,
8486 printf("::: EMC tile %d is crumbled\n", i);
8492 if (element == EL_ROCK &&
8493 effective_action == ACTION_FILLING)
8494 printf("::: has_action_graphics == %d\n", has_action_graphics);
8497 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
8498 effective_action == ACTION_MOVING ||
8499 effective_action == ACTION_PUSHING ||
8500 effective_action == ACTION_EATING)) ||
8501 (!has_action_graphics && (effective_action == ACTION_FILLING ||
8502 effective_action == ACTION_EMPTYING)))
8505 (effective_action == ACTION_FALLING ||
8506 effective_action == ACTION_FILLING ||
8507 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
8508 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
8509 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
8510 int num_steps = (i == Ydrip_s1 ? 16 :
8511 i == Ydrip_s1B ? 16 :
8512 i == Ydrip_s2 ? 16 :
8513 i == Ydrip_s2B ? 16 :
8514 i == Xsand_stonein_1 ? 32 :
8515 i == Xsand_stonein_2 ? 32 :
8516 i == Xsand_stonein_3 ? 32 :
8517 i == Xsand_stonein_4 ? 32 :
8518 i == Xsand_stoneout_1 ? 16 :
8519 i == Xsand_stoneout_2 ? 16 : 8);
8520 int cx = ABS(dx) * (TILEX / num_steps);
8521 int cy = ABS(dy) * (TILEY / num_steps);
8522 int step_frame = (i == Ydrip_s2 ? j + 8 :
8523 i == Ydrip_s2B ? j + 8 :
8524 i == Xsand_stonein_2 ? j + 8 :
8525 i == Xsand_stonein_3 ? j + 16 :
8526 i == Xsand_stonein_4 ? j + 24 :
8527 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
8528 int step = (is_backside ? step_frame : num_steps - step_frame);
8530 if (is_backside) /* tile where movement starts */
8532 if (dx < 0 || dy < 0)
8534 g_em->src_offset_x = cx * step;
8535 g_em->src_offset_y = cy * step;
8539 g_em->dst_offset_x = cx * step;
8540 g_em->dst_offset_y = cy * step;
8543 else /* tile where movement ends */
8545 if (dx < 0 || dy < 0)
8547 g_em->dst_offset_x = cx * step;
8548 g_em->dst_offset_y = cy * step;
8552 g_em->src_offset_x = cx * step;
8553 g_em->src_offset_y = cy * step;
8557 g_em->width = TILEX - cx * step;
8558 g_em->height = TILEY - cy * step;
8561 /* create unique graphic identifier to decide if tile must be redrawn */
8562 /* bit 31 - 16 (16 bit): EM style graphic
8563 bit 15 - 12 ( 4 bit): EM style frame
8564 bit 11 - 6 ( 6 bit): graphic width
8565 bit 5 - 0 ( 6 bit): graphic height */
8566 g_em->unique_identifier =
8567 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
8571 /* skip check for EMC elements not contained in original EMC artwork */
8572 if (element == EL_EMC_FAKE_ACID)
8575 if (g_em->bitmap != debug_bitmap ||
8576 g_em->src_x != debug_src_x ||
8577 g_em->src_y != debug_src_y ||
8578 g_em->src_offset_x != 0 ||
8579 g_em->src_offset_y != 0 ||
8580 g_em->dst_offset_x != 0 ||
8581 g_em->dst_offset_y != 0 ||
8582 g_em->width != TILEX ||
8583 g_em->height != TILEY)
8585 static int last_i = -1;
8593 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
8594 i, element, element_info[element].token_name,
8595 element_action_info[effective_action].suffix, direction);
8597 if (element != effective_element)
8598 printf(" [%d ('%s')]",
8600 element_info[effective_element].token_name);
8604 if (g_em->bitmap != debug_bitmap)
8605 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
8606 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
8608 if (g_em->src_x != debug_src_x ||
8609 g_em->src_y != debug_src_y)
8610 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
8611 j, (is_backside ? 'B' : 'F'),
8612 g_em->src_x, g_em->src_y,
8613 g_em->src_x / 32, g_em->src_y / 32,
8614 debug_src_x, debug_src_y,
8615 debug_src_x / 32, debug_src_y / 32);
8617 if (g_em->src_offset_x != 0 ||
8618 g_em->src_offset_y != 0 ||
8619 g_em->dst_offset_x != 0 ||
8620 g_em->dst_offset_y != 0)
8621 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
8623 g_em->src_offset_x, g_em->src_offset_y,
8624 g_em->dst_offset_x, g_em->dst_offset_y);
8626 if (g_em->width != TILEX ||
8627 g_em->height != TILEY)
8628 printf(" %d (%d): size %d,%d should be %d,%d\n",
8630 g_em->width, g_em->height, TILEX, TILEY);
8632 num_em_gfx_errors++;
8639 for (i = 0; i < TILE_MAX; i++)
8641 for (j = 0; j < 8; j++)
8643 int element = object_mapping[i].element_rnd;
8644 int action = object_mapping[i].action;
8645 int direction = object_mapping[i].direction;
8646 boolean is_backside = object_mapping[i].is_backside;
8647 int graphic_action = el_act_dir2img(element, action, direction);
8648 int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
8650 if ((action == ACTION_SMASHED_BY_ROCK ||
8651 action == ACTION_SMASHED_BY_SPRING ||
8652 action == ACTION_EATING) &&
8653 graphic_action == graphic_default)
8655 int e = (action == ACTION_SMASHED_BY_ROCK ? Ystone_s :
8656 action == ACTION_SMASHED_BY_SPRING ? Yspring_s :
8657 direction == MV_LEFT ? (is_backside? Yspring_wB: Yspring_w) :
8658 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
8661 /* no separate animation for "smashed by rock" -- use rock instead */
8662 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
8663 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
8665 g_em->bitmap = g_xx->bitmap;
8666 g_em->src_x = g_xx->src_x;
8667 g_em->src_y = g_xx->src_y;
8668 g_em->src_offset_x = g_xx->src_offset_x;
8669 g_em->src_offset_y = g_xx->src_offset_y;
8670 g_em->dst_offset_x = g_xx->dst_offset_x;
8671 g_em->dst_offset_y = g_xx->dst_offset_y;
8672 g_em->width = g_xx->width;
8673 g_em->height = g_xx->height;
8674 g_em->unique_identifier = g_xx->unique_identifier;
8677 g_em->preserve_background = TRUE;
8682 for (p = 0; p < MAX_PLAYERS; p++)
8684 for (i = 0; i < SPR_MAX; i++)
8686 int element = player_mapping[p][i].element_rnd;
8687 int action = player_mapping[p][i].action;
8688 int direction = player_mapping[p][i].direction;
8690 for (j = 0; j < 8; j++)
8692 int effective_element = element;
8693 int effective_action = action;
8694 int graphic = (direction == MV_NONE ?
8695 el_act2img(effective_element, effective_action) :
8696 el_act_dir2img(effective_element, effective_action,
8698 struct GraphicInfo *g = &graphic_info[graphic];
8699 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
8705 Bitmap *debug_bitmap = g_em->bitmap;
8706 int debug_src_x = g_em->src_x;
8707 int debug_src_y = g_em->src_y;
8710 int frame = getAnimationFrame(g->anim_frames,
8713 g->anim_start_frame,
8716 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
8718 g_em->bitmap = src_bitmap;
8719 g_em->src_x = src_x;
8720 g_em->src_y = src_y;
8721 g_em->src_offset_x = 0;
8722 g_em->src_offset_y = 0;
8723 g_em->dst_offset_x = 0;
8724 g_em->dst_offset_y = 0;
8725 g_em->width = TILEX;
8726 g_em->height = TILEY;
8730 /* skip check for EMC elements not contained in original EMC artwork */
8731 if (element == EL_PLAYER_3 ||
8732 element == EL_PLAYER_4)
8735 if (g_em->bitmap != debug_bitmap ||
8736 g_em->src_x != debug_src_x ||
8737 g_em->src_y != debug_src_y)
8739 static int last_i = -1;
8747 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
8748 p, i, element, element_info[element].token_name,
8749 element_action_info[effective_action].suffix, direction);
8751 if (element != effective_element)
8752 printf(" [%d ('%s')]",
8754 element_info[effective_element].token_name);
8758 if (g_em->bitmap != debug_bitmap)
8759 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
8760 j, (int)(g_em->bitmap), (int)(debug_bitmap));
8762 if (g_em->src_x != debug_src_x ||
8763 g_em->src_y != debug_src_y)
8764 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
8766 g_em->src_x, g_em->src_y,
8767 g_em->src_x / 32, g_em->src_y / 32,
8768 debug_src_x, debug_src_y,
8769 debug_src_x / 32, debug_src_y / 32);
8771 num_em_gfx_errors++;
8781 printf("::: [%d errors found]\n", num_em_gfx_errors);
8787 void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
8788 boolean any_player_moving,
8789 boolean player_is_dropping)
8793 if (tape.single_step && tape.recording && !tape.pausing)
8795 boolean active_players = FALSE;
8797 for (i = 0; i < MAX_PLAYERS; i++)
8798 if (action[i] != JOY_NO_ACTION)
8799 active_players = TRUE;
8802 if (frame == 0 && !player_is_dropping)
8803 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
8807 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
8808 boolean murphy_is_dropping)
8811 printf("::: waiting: %d, dropping: %d\n",
8812 murphy_is_waiting, murphy_is_dropping);
8815 if (tape.single_step && tape.recording && !tape.pausing)
8817 // if (murphy_is_waiting || murphy_is_dropping)
8818 if (murphy_is_waiting)
8821 printf("::: murphy is waiting -> pause mode\n");
8824 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
8829 void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
8830 int graphic, int sync_frame, int x, int y)
8832 int frame = getGraphicAnimationFrame(graphic, sync_frame);
8834 getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
8837 boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
8839 return (IS_NEXT_FRAME(sync_frame, graphic));
8842 int getGraphicInfo_Delay(int graphic)
8844 return graphic_info[graphic].anim_delay;
8847 void PlayMenuSoundExt(int sound)
8849 if (sound == SND_UNDEFINED)
8852 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
8853 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
8856 if (IS_LOOP_SOUND(sound))
8857 PlaySoundLoop(sound);
8862 void PlayMenuSound()
8864 PlayMenuSoundExt(menu.sound[game_status]);
8867 void PlayMenuSoundStereo(int sound, int stereo_position)
8869 if (sound == SND_UNDEFINED)
8872 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
8873 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
8876 if (IS_LOOP_SOUND(sound))
8877 PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP);
8879 PlaySoundStereo(sound, stereo_position);
8882 void PlayMenuSoundIfLoopExt(int sound)
8884 if (sound == SND_UNDEFINED)
8887 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
8888 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
8891 if (IS_LOOP_SOUND(sound))
8892 PlaySoundLoop(sound);
8895 void PlayMenuSoundIfLoop()
8897 PlayMenuSoundIfLoopExt(menu.sound[game_status]);
8900 void PlayMenuMusicExt(int music)
8902 if (music == MUS_UNDEFINED)
8905 if (!setup.sound_music)
8911 void PlayMenuMusic()
8913 PlayMenuMusicExt(menu.music[game_status]);
8916 void PlaySoundActivating()
8919 PlaySound(SND_MENU_ITEM_ACTIVATING);
8923 void PlaySoundSelecting()
8926 PlaySound(SND_MENU_ITEM_SELECTING);
8930 void ToggleFullscreenIfNeeded()
8932 boolean change_fullscreen = (setup.fullscreen !=
8933 video.fullscreen_enabled);
8934 boolean change_fullscreen_mode = (video.fullscreen_enabled &&
8935 !strEqual(setup.fullscreen_mode,
8936 video.fullscreen_mode_current));
8938 if (!video.fullscreen_available)
8941 if (change_fullscreen || change_fullscreen_mode)
8943 Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
8945 /* save backbuffer content which gets lost when toggling fullscreen mode */
8946 BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
8948 if (change_fullscreen_mode)
8950 /* keep fullscreen, but change fullscreen mode (screen resolution) */
8951 video.fullscreen_enabled = FALSE; /* force new fullscreen mode */
8954 /* toggle fullscreen */
8955 ChangeVideoModeIfNeeded(setup.fullscreen);
8957 setup.fullscreen = video.fullscreen_enabled;
8959 /* restore backbuffer content from temporary backbuffer backup bitmap */
8960 BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
8962 FreeBitmap(tmp_backbuffer);
8965 /* update visible window/screen */
8966 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
8968 redraw_mask = REDRAW_ALL;
8973 void ChangeViewportPropertiesIfNeeded()
8975 int *door_1_x = &DX;
8976 int *door_1_y = &DY;
8977 int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
8978 int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
8979 int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
8980 game_status == GAME_MODE_EDITOR ? game_status :
8982 struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
8983 struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
8984 struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode];
8985 int border_size = vp_playfield->border_size;
8986 int new_sx = vp_playfield->x + border_size;
8987 int new_sy = vp_playfield->y + border_size;
8988 int new_sxsize = vp_playfield->width - 2 * border_size;
8989 int new_sysize = vp_playfield->height - 2 * border_size;
8990 int new_real_sx = vp_playfield->x;
8991 int new_real_sy = vp_playfield->y;
8992 int new_full_sxsize = vp_playfield->width;
8993 int new_full_sysize = vp_playfield->height;
8995 int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
8996 int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
8997 gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
8998 int new_scr_fieldx = new_sxsize / tilesize;
8999 int new_scr_fieldy = new_sysize / tilesize;
9000 int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var;
9001 int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
9003 int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE;
9004 int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE;
9006 boolean init_gfx_buffers = FALSE;
9007 boolean init_video_buffer = FALSE;
9008 boolean init_gadgets_and_toons = FALSE;
9011 /* !!! TEST ONLY !!! */
9012 // InitGfxBuffers();
9016 if (viewport.window.width != WIN_XSIZE ||
9017 viewport.window.height != WIN_YSIZE)
9019 WIN_XSIZE = viewport.window.width;
9020 WIN_YSIZE = viewport.window.height;
9023 init_video_buffer = TRUE;
9024 init_gfx_buffers = TRUE;
9026 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
9030 SetDrawDeactivationMask(REDRAW_NONE);
9031 SetDrawBackgroundMask(REDRAW_FIELD);
9033 // RedrawBackground();
9037 // printf("::: video: init_video_buffer, init_gfx_buffers\n");
9040 if (new_scr_fieldx != SCR_FIELDX ||
9041 new_scr_fieldy != SCR_FIELDY)
9043 /* this always toggles between MAIN and GAME when using small tile size */
9045 SCR_FIELDX = new_scr_fieldx;
9046 SCR_FIELDY = new_scr_fieldy;
9048 // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
9052 if (new_tilesize_var != TILESIZE_VAR &&
9053 gfx_game_mode == GAME_MODE_PLAYING)
9055 /* doing this outside GAME_MODE_PLAYING would give wrong playfield size */
9057 TILESIZE_VAR = new_tilesize_var;
9059 init_gfx_buffers = TRUE;
9061 // printf("::: tilesize: init_gfx_buffers\n");
9067 new_sxsize != SXSIZE ||
9068 new_sysize != SYSIZE ||
9069 new_real_sx != REAL_SX ||
9070 new_real_sy != REAL_SY ||
9071 new_full_sxsize != FULL_SXSIZE ||
9072 new_full_sysize != FULL_SYSIZE ||
9073 new_tilesize_var != TILESIZE_VAR ||
9074 vp_door_1->x != *door_1_x ||
9075 vp_door_1->y != *door_1_y ||
9076 vp_door_2->x != *door_2_x ||
9077 vp_door_2->y != *door_2_y)
9081 SXSIZE = new_sxsize;
9082 SYSIZE = new_sysize;
9083 REAL_SX = new_real_sx;
9084 REAL_SY = new_real_sy;
9085 FULL_SXSIZE = new_full_sxsize;
9086 FULL_SYSIZE = new_full_sysize;
9087 TILESIZE_VAR = new_tilesize_var;
9090 printf("::: %d, %d, %d [%d]\n",
9091 SCR_FIELDX, SCR_FIELDY, TILESIZE_VAR,
9092 setup.small_game_graphics);
9095 *door_1_x = vp_door_1->x;
9096 *door_1_y = vp_door_1->y;
9097 *door_2_x = vp_door_2->x;
9098 *door_2_y = vp_door_2->y;
9101 init_gfx_buffers = TRUE;
9103 // printf("::: viewports: init_gfx_buffers\n");
9108 if (gfx_game_mode == GAME_MODE_MAIN)
9111 init_gadgets_and_toons = TRUE;
9113 // printf("::: viewports: init_gadgets_and_toons\n");
9121 if (init_gfx_buffers)
9123 // printf("::: init_gfx_buffers\n");
9125 SCR_FIELDX = new_scr_fieldx_buffers;
9126 SCR_FIELDY = new_scr_fieldy_buffers;
9130 SCR_FIELDX = new_scr_fieldx;
9131 SCR_FIELDY = new_scr_fieldy;
9134 if (init_video_buffer)
9136 // printf("::: init_video_buffer\n");
9138 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
9140 SetDrawDeactivationMask(REDRAW_NONE);
9141 SetDrawBackgroundMask(REDRAW_FIELD);
9144 if (init_gadgets_and_toons)
9146 // printf("::: init_gadgets_and_toons\n");
9153 printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status);