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 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
327 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
329 if (EVEN(SCR_FIELDX))
331 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
332 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
334 fx += (dx_var > 0 ? TILEX_VAR : 0);
341 if (EVEN(SCR_FIELDY))
343 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
344 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
346 fy += (dy_var > 0 ? TILEY_VAR : 0);
354 printf("::: (%d, %d) [(%d / %d, %d / %d)] => %d, %d\n",
357 SBY_Upper, SBY_Lower,
361 if (border.draw_masked[GAME_MODE_PLAYING])
363 if (buffer != backbuffer)
365 /* copy playfield buffer to backbuffer to add masked border */
366 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
367 DrawMaskedBorder(REDRAW_FIELD);
370 BlitBitmap(backbuffer, target_bitmap,
371 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
376 BlitBitmap(buffer, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
383 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
386 printf("::: TILES TO REFRESH: %d\n", redraw_tiles);
387 for (x = 0; x < SCR_FIELDX; x++)
388 for (y = 0 ; y < SCR_FIELDY; y++)
389 if (redraw[redraw_x1 + x][redraw_y1 + y])
390 printf("::: - %d, %d [%s]\n",
391 LEVELX(x), LEVELY(y),
392 EL_NAME(Feld[LEVELX(x)][LEVELY(y)]));
395 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
396 redraw_mask |= REDRAW_FIELD;
399 // never redraw single tiles, always redraw the whole field
400 // (redrawing single tiles up to a certain threshold was faster on old,
401 // now legacy graphics, but slows things down on modern graphics now)
402 // UPDATE: this is now globally defined by value of REDRAWTILES_THRESHOLD
403 if (redraw_mask & REDRAW_TILES)
404 redraw_mask |= REDRAW_FIELD;
408 /* !!! TEST ONLY !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
409 /* (force full redraw) */
410 if (game_status == GAME_MODE_PLAYING)
411 redraw_mask |= REDRAW_FIELD;
414 if (redraw_mask & REDRAW_FIELD)
415 redraw_mask &= ~REDRAW_TILES;
417 if (redraw_mask == REDRAW_NONE)
422 if (redraw_mask & REDRAW_ALL)
423 printf("[REDRAW_ALL]");
424 if (redraw_mask & REDRAW_FIELD)
425 printf("[REDRAW_FIELD]");
426 if (redraw_mask & REDRAW_TILES)
427 printf("[REDRAW_TILES]");
428 if (redraw_mask & REDRAW_DOOR_1)
429 printf("[REDRAW_DOOR_1]");
430 if (redraw_mask & REDRAW_DOOR_2)
431 printf("[REDRAW_DOOR_2]");
432 if (redraw_mask & REDRAW_FROM_BACKBUFFER)
433 printf("[REDRAW_FROM_BACKBUFFER]");
434 printf(" [%d]\n", FrameCounter);
437 if (redraw_mask & REDRAW_TILES &&
438 game_status == GAME_MODE_PLAYING &&
439 border.draw_masked[GAME_MODE_PLAYING])
440 redraw_mask |= REDRAW_FIELD;
442 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
444 static boolean last_frame_skipped = FALSE;
445 boolean skip_even_when_not_scrolling = TRUE;
446 boolean just_scrolling = (ScreenMovDir != 0);
447 boolean verbose = FALSE;
449 if (global.fps_slowdown_factor > 1 &&
450 (FrameCounter % global.fps_slowdown_factor) &&
451 (just_scrolling || skip_even_when_not_scrolling))
453 redraw_mask &= ~REDRAW_MAIN;
455 last_frame_skipped = TRUE;
458 printf("FRAME SKIPPED\n");
462 if (last_frame_skipped)
463 redraw_mask |= REDRAW_FIELD;
465 last_frame_skipped = FALSE;
468 printf("frame not skipped\n");
472 /* synchronize X11 graphics at this point; if we would synchronize the
473 display immediately after the buffer switching (after the XFlush),
474 this could mean that we have to wait for the graphics to complete,
475 although we could go on doing calculations for the next frame */
479 /* never draw masked border to backbuffer when using playfield buffer */
480 if (game_status != GAME_MODE_PLAYING ||
481 redraw_mask & REDRAW_FROM_BACKBUFFER ||
482 buffer == backbuffer)
483 DrawMaskedBorder(redraw_mask);
485 DrawMaskedBorder(redraw_mask & REDRAW_DOORS);
487 if (redraw_mask & REDRAW_ALL)
489 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
491 redraw_mask = REDRAW_NONE;
494 if (redraw_mask & REDRAW_FIELD)
497 printf("::: REDRAW_FIELD\n");
500 if (game_status != GAME_MODE_PLAYING ||
501 redraw_mask & REDRAW_FROM_BACKBUFFER)
503 BlitBitmap(backbuffer, window,
504 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
509 BlitScreenToBitmap(window);
511 int fx = FX, fy = FY;
514 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
515 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
516 int dx_var = dx * TILESIZE_VAR / TILESIZE;
517 int dy_var = dy * TILESIZE_VAR / TILESIZE;
520 // fx += dx * TILESIZE_VAR / TILESIZE;
521 // fy += dy * TILESIZE_VAR / TILESIZE;
523 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
524 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
527 /* !!! THIS WORKS !!! */
529 printf("::: %d, %d\n", scroll_x, scroll_y);
531 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
532 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
534 if (EVEN(SCR_FIELDX))
536 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
537 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
539 fx += (dx > 0 ? TILEX_VAR : 0);
546 if (EVEN(SCR_FIELDY))
548 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
549 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
551 fy += (dy > 0 ? TILEY_VAR : 0);
558 if (border.draw_masked[GAME_MODE_PLAYING])
560 if (buffer != backbuffer)
562 /* copy playfield buffer to backbuffer to add masked border */
563 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
564 DrawMaskedBorder(REDRAW_FIELD);
567 BlitBitmap(backbuffer, window,
568 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
573 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
579 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
581 (setup.soft_scrolling ?
582 "setup.soft_scrolling" :
583 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
584 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
585 ABS(ScreenGfxPos) == ScrollStepSize ?
586 "ABS(ScreenGfxPos) == ScrollStepSize" :
587 "redraw_tiles > REDRAWTILES_THRESHOLD"));
592 redraw_mask &= ~REDRAW_MAIN;
595 if (redraw_mask & REDRAW_DOORS)
597 if (redraw_mask & REDRAW_DOOR_1)
598 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
600 if (redraw_mask & REDRAW_DOOR_2)
601 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
603 if (redraw_mask & REDRAW_DOOR_3)
604 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
606 redraw_mask &= ~REDRAW_DOORS;
609 if (redraw_mask & REDRAW_MICROLEVEL)
611 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
612 SX, SY + 10 * TILEY);
614 redraw_mask &= ~REDRAW_MICROLEVEL;
617 if (redraw_mask & REDRAW_TILES)
620 printf("::: REDRAW_TILES\n");
626 InitGfxClipRegion(TRUE, SX, SY, SXSIZE, SYSIZE);
629 int sx = SX; // - (EVEN(SCR_FIELDX) ? TILEX_VAR / 2 : 0);
630 int sy = SY; // + (EVEN(SCR_FIELDY) ? TILEY_VAR / 2 : 0);
633 int dx_var = dx * TILESIZE_VAR / TILESIZE;
634 int dy_var = dy * TILESIZE_VAR / TILESIZE;
636 int fx = FX, fy = FY;
638 int scr_fieldx = SCR_FIELDX + (EVEN(SCR_FIELDX) ? 2 : 0);
639 int scr_fieldy = SCR_FIELDY + (EVEN(SCR_FIELDY) ? 2 : 0);
641 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
642 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
644 if (EVEN(SCR_FIELDX))
646 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
648 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
657 fx += (dx_var > 0 ? TILEX_VAR : 0);
661 if (EVEN(SCR_FIELDY))
663 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
665 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
674 fy += (dy_var > 0 ? TILEY_VAR : 0);
679 printf("::: %d, %d, %d, %d\n", sx, sy, SCR_FIELDX, SCR_FIELDY);
682 for (x = 0; x < scr_fieldx; x++)
683 for (y = 0 ; y < scr_fieldy; y++)
684 if (redraw[redraw_x1 + x][redraw_y1 + y])
685 BlitBitmap(buffer, window,
686 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
687 TILEX_VAR, TILEY_VAR,
688 sx + x * TILEX_VAR, sy + y * TILEY_VAR);
691 InitGfxClipRegion(FALSE, -1, -1, -1, -1);
693 for (x = 0; x < SCR_FIELDX; x++)
694 for (y = 0 ; y < SCR_FIELDY; y++)
695 if (redraw[redraw_x1 + x][redraw_y1 + y])
696 BlitBitmap(buffer, window,
697 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
698 TILEX_VAR, TILEY_VAR,
699 SX + x * TILEX_VAR, SY + y * TILEY_VAR);
703 for (x = 0; x < SCR_FIELDX; x++)
704 for (y = 0 ; y < SCR_FIELDY; y++)
705 if (redraw[redraw_x1 + x][redraw_y1 + y])
706 BlitBitmap(buffer, window,
707 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
708 SX + x * TILEX, SY + y * TILEY);
712 if (redraw_mask & REDRAW_FPS) /* display frames per second */
717 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
718 if (!global.fps_slowdown)
721 sprintf(text, "%04.1f fps%s", global.frames_per_second, info1);
723 DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE);
725 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
731 for (x = 0; x < MAX_BUF_XSIZE; x++)
732 for (y = 0; y < MAX_BUF_YSIZE; y++)
735 redraw_mask = REDRAW_NONE;
738 static void FadeCrossSaveBackbuffer()
740 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
743 static void FadeExt(int fade_mask, int fade_mode, int fade_type)
745 static int fade_type_skip = FADE_TYPE_NONE;
746 void (*draw_border_function)(void) = NULL;
747 Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL);
748 int x, y, width, height;
749 int fade_delay, post_delay;
751 if (fade_type == FADE_TYPE_FADE_OUT)
753 if (fade_type_skip != FADE_TYPE_NONE)
756 printf("::: skipping %d ... [%d] (X)\n", fade_mode, fade_type_skip);
759 /* skip all fade operations until specified fade operation */
760 if (fade_type & fade_type_skip)
761 fade_type_skip = FADE_TYPE_NONE;
766 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
768 FadeCrossSaveBackbuffer();
774 redraw_mask |= fade_mask;
776 if (fade_type == FADE_TYPE_SKIP)
779 printf("::: will skip %d ... [%d]\n", fade_mode, fade_type_skip);
782 fade_type_skip = fade_mode;
788 printf("::: !!! FADING %d ... [%d] [%d]\n", fade_mode, fade_type,
793 fade_delay = fading.fade_delay;
794 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
797 if (fade_type_skip != FADE_TYPE_NONE)
800 printf("::: skipping %d ... [%d]\n", fade_mode, fade_type_skip);
803 /* skip all fade operations until specified fade operation */
804 if (fade_type & fade_type_skip)
805 fade_type_skip = FADE_TYPE_NONE;
815 if (global.autoplay_leveldir)
817 // fading.fade_mode = FADE_MODE_NONE;
824 if (fading.fade_mode == FADE_MODE_NONE)
832 /* !!! what about fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */
835 printf("::: NOW FADING %d ... [%d]\n", fade_mode, fade_type);
839 if (fade_mask == REDRAW_NONE)
840 fade_mask = REDRAW_FIELD;
843 // if (fade_mask & REDRAW_FIELD)
844 if (fade_mask == REDRAW_FIELD)
849 height = FULL_SYSIZE;
852 fade_delay = fading.fade_delay;
853 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
856 if (border.draw_masked_when_fading)
857 draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */
859 DrawMaskedBorder_FIELD(); /* draw once */
861 else /* REDRAW_ALL */
869 fade_delay = fading.fade_delay;
870 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
875 if (!setup.fade_screens ||
877 fading.fade_mode == FADE_MODE_NONE)
879 if (!setup.fade_screens || fade_delay == 0)
882 if (fade_mode == FADE_MODE_FADE_OUT)
886 if (fade_mode == FADE_MODE_FADE_OUT &&
887 fading.fade_mode != FADE_MODE_NONE)
888 ClearRectangle(backbuffer, x, y, width, height);
892 BlitBitmap(backbuffer, window, x, y, width, height, x, y);
893 redraw_mask = REDRAW_NONE;
901 FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay,
902 draw_border_function);
904 redraw_mask &= ~fade_mask;
907 void FadeIn(int fade_mask)
909 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
910 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN);
912 FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN);
915 void FadeOut(int fade_mask)
917 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
918 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_OUT);
920 FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT);
922 global.border_status = game_status;
925 static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set)
927 static struct TitleFadingInfo fading_leave_stored;
930 fading_leave_stored = fading_leave;
932 fading = fading_leave_stored;
935 void FadeSetEnterMenu()
937 fading = menu.enter_menu;
940 printf("::: storing enter_menu\n");
943 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
946 void FadeSetLeaveMenu()
948 fading = menu.leave_menu;
951 printf("::: storing leave_menu\n");
954 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
957 void FadeSetEnterScreen()
959 fading = menu.enter_screen[game_status];
962 printf("::: storing leave_screen[%d]\n", game_status);
965 FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */
968 void FadeSetNextScreen()
970 fading = menu.next_screen;
973 printf("::: storing next_screen\n");
976 // (do not overwrite fade mode set by FadeSetEnterScreen)
977 // FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
980 void FadeSetLeaveScreen()
983 printf("::: recalling last stored value\n");
986 FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */
989 void FadeSetFromType(int type)
991 if (type & TYPE_ENTER_SCREEN)
992 FadeSetEnterScreen();
993 else if (type & TYPE_ENTER)
995 else if (type & TYPE_LEAVE)
999 void FadeSetDisabled()
1001 static struct TitleFadingInfo fading_none = { FADE_MODE_NONE, -1, -1, -1 };
1003 fading = fading_none;
1006 void FadeSkipNextFadeIn()
1008 FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP);
1011 void FadeSkipNextFadeOut()
1013 FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
1016 void SetWindowBackgroundImageIfDefined(int graphic)
1018 if (graphic_info[graphic].bitmap)
1019 SetWindowBackgroundBitmap(graphic_info[graphic].bitmap);
1022 void SetMainBackgroundImageIfDefined(int graphic)
1024 if (graphic_info[graphic].bitmap)
1025 SetMainBackgroundBitmap(graphic_info[graphic].bitmap);
1028 void SetDoorBackgroundImageIfDefined(int graphic)
1030 if (graphic_info[graphic].bitmap)
1031 SetDoorBackgroundBitmap(graphic_info[graphic].bitmap);
1034 void SetWindowBackgroundImage(int graphic)
1036 SetWindowBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1037 graphic_info[graphic].bitmap ?
1038 graphic_info[graphic].bitmap :
1039 graphic_info[IMG_BACKGROUND].bitmap);
1042 void SetMainBackgroundImage(int graphic)
1044 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1045 graphic_info[graphic].bitmap ?
1046 graphic_info[graphic].bitmap :
1047 graphic_info[IMG_BACKGROUND].bitmap);
1050 void SetDoorBackgroundImage(int graphic)
1052 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1053 graphic_info[graphic].bitmap ?
1054 graphic_info[graphic].bitmap :
1055 graphic_info[IMG_BACKGROUND].bitmap);
1058 void SetPanelBackground()
1061 struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL];
1064 BlitBitmapTiled(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1065 gfx->width, gfx->height, 0, 0, DXSIZE, DYSIZE);
1067 /* (ClearRectangle() only needed if panel bitmap is smaller than panel) */
1068 ClearRectangle(bitmap_db_panel, DX, DY, DXSIZE, DYSIZE);
1069 BlitBitmap(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1070 MIN(gfx->width, DXSIZE), MIN(gfx->height, DYSIZE), 0, 0);
1073 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, bitmap_db_panel,
1074 DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, 0, 0);
1077 SetDoorBackgroundBitmap(bitmap_db_panel);
1080 void DrawBackground(int x, int y, int width, int height)
1082 /* !!! "drawto" might still point to playfield buffer here (see below) !!! */
1083 /* (when entering hall of fame after playing) */
1085 ClearRectangleOnBackground(drawto, x, y, width, height);
1087 ClearRectangleOnBackground(backbuffer, x, y, width, height);
1091 /* (this only works for the current arrangement of playfield and panels) */
1093 redraw_mask |= REDRAW_FIELD;
1094 else if (y < gfx.vy)
1095 redraw_mask |= REDRAW_DOOR_1;
1097 redraw_mask |= REDRAW_DOOR_2;
1099 /* (this is just wrong (when drawing to one of the two door panel areas)) */
1100 redraw_mask |= REDRAW_FIELD;
1104 void DrawBackgroundForFont(int x, int y, int width, int height, int font_nr)
1106 struct FontBitmapInfo *font = getFontBitmapInfo(font_nr);
1108 if (font->bitmap == NULL)
1111 DrawBackground(x, y, width, height);
1114 void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic)
1116 struct GraphicInfo *g = &graphic_info[graphic];
1118 if (g->bitmap == NULL)
1121 DrawBackground(x, y, width, height);
1126 /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
1127 /* (when entering hall of fame after playing) */
1128 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
1130 /* !!! maybe this should be done before clearing the background !!! */
1131 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
1133 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
1134 SetDrawtoField(DRAW_BUFFERED);
1137 SetDrawtoField(DRAW_BACKBUFFER);
1140 void MarkTileDirty(int x, int y)
1142 int xx = redraw_x1 + x;
1143 int yy = redraw_y1 + y;
1145 if (!redraw[xx][yy])
1148 redraw[xx][yy] = TRUE;
1149 redraw_mask |= REDRAW_TILES;
1152 void SetBorderElement()
1156 BorderElement = EL_EMPTY;
1158 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
1160 for (x = 0; x < lev_fieldx; x++)
1162 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
1163 BorderElement = EL_STEELWALL;
1165 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
1171 void FloodFillLevel(int from_x, int from_y, int fill_element,
1172 short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
1173 int max_fieldx, int max_fieldy)
1177 static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
1178 static int safety = 0;
1180 /* check if starting field still has the desired content */
1181 if (field[from_x][from_y] == fill_element)
1186 if (safety > max_fieldx * max_fieldy)
1187 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
1189 old_element = field[from_x][from_y];
1190 field[from_x][from_y] = fill_element;
1192 for (i = 0; i < 4; i++)
1194 x = from_x + check[i][0];
1195 y = from_y + check[i][1];
1197 if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
1198 FloodFillLevel(x, y, fill_element, field, max_fieldx, max_fieldy);
1204 void SetRandomAnimationValue(int x, int y)
1206 gfx.anim_random_frame = GfxRandom[x][y];
1209 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
1211 /* animation synchronized with global frame counter, not move position */
1212 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
1213 sync_frame = FrameCounter;
1215 return getAnimationFrame(graphic_info[graphic].anim_frames,
1216 graphic_info[graphic].anim_delay,
1217 graphic_info[graphic].anim_mode,
1218 graphic_info[graphic].anim_start_frame,
1222 void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw,
1223 Bitmap **bitmap, int *x, int *y,
1224 boolean get_backside)
1228 int width_mult, width_div;
1229 int height_mult, height_div;
1233 { 15, 16, 2, 3 }, /* 1 x 1 */
1234 { 7, 8, 2, 3 }, /* 2 x 2 */
1235 { 3, 4, 2, 3 }, /* 4 x 4 */
1236 { 1, 2, 2, 3 }, /* 8 x 8 */
1237 { 0, 1, 2, 3 }, /* 16 x 16 */
1238 { 0, 1, 0, 1 }, /* 32 x 32 */
1240 struct GraphicInfo *g = &graphic_info[graphic];
1241 Bitmap *src_bitmap = g->bitmap;
1242 int tilesize = MIN(MAX(1, tilesize_raw), TILESIZE);
1243 int offset_calc_pos = log_2(tilesize);
1244 int width_mult = offset_calc[offset_calc_pos].width_mult;
1245 int width_div = offset_calc[offset_calc_pos].width_div;
1246 int height_mult = offset_calc[offset_calc_pos].height_mult;
1247 int height_div = offset_calc[offset_calc_pos].height_div;
1248 int startx = src_bitmap->width * width_mult / width_div;
1249 int starty = src_bitmap->height * height_mult / height_div;
1251 int src_x = (g->src_x + (get_backside ? g->offset2_x : 0)) *
1252 tilesize / TILESIZE;
1253 int src_y = (g->src_y + (get_backside ? g->offset2_y : 0)) *
1254 tilesize / TILESIZE;
1256 int src_x = g->src_x * tilesize / TILESIZE;
1257 int src_y = g->src_y * tilesize / TILESIZE;
1259 int width = g->width * tilesize / TILESIZE;
1260 int height = g->height * tilesize / TILESIZE;
1261 int offset_x = g->offset_x * tilesize / TILESIZE;
1262 int offset_y = g->offset_y * tilesize / TILESIZE;
1264 if (g->offset_y == 0) /* frames are ordered horizontally */
1266 int max_width = g->anim_frames_per_line * width;
1267 int pos = (src_y / height) * max_width + src_x + frame * offset_x;
1269 src_x = pos % max_width;
1270 src_y = src_y % height + pos / max_width * height;
1272 else if (g->offset_x == 0) /* frames are ordered vertically */
1274 int max_height = g->anim_frames_per_line * height;
1275 int pos = (src_x / width) * max_height + src_y + frame * offset_y;
1277 src_x = src_x % width + pos / max_height * width;
1278 src_y = pos % max_height;
1280 else /* frames are ordered diagonally */
1282 src_x = src_x + frame * offset_x;
1283 src_y = src_y + frame * offset_y;
1286 *bitmap = src_bitmap;
1287 *x = startx + src_x;
1288 *y = starty + src_y;
1291 void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1292 int *x, int *y, boolean get_backside)
1294 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y,
1298 void getSizedGraphicSource(int graphic, int frame, int tilesize_raw,
1299 Bitmap **bitmap, int *x, int *y)
1301 getSizedGraphicSourceExt(graphic, frame, tilesize_raw, bitmap, x, y, FALSE);
1304 void getFixedGraphicSource(int graphic, int frame,
1305 Bitmap **bitmap, int *x, int *y)
1307 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y, FALSE);
1310 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1313 getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
1315 struct GraphicInfo *g = &graphic_info[graphic];
1316 int mini_startx = 0;
1317 int mini_starty = g->bitmap->height * 2 / 3;
1319 *bitmap = g->bitmap;
1320 *x = mini_startx + g->src_x / 2;
1321 *y = mini_starty + g->src_y / 2;
1325 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1326 int *x, int *y, boolean get_backside)
1328 struct GraphicInfo *g = &graphic_info[graphic];
1329 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
1330 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
1333 if (TILESIZE_VAR != TILESIZE)
1334 return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
1338 *bitmap = g->bitmap;
1340 if (g->offset_y == 0) /* frames are ordered horizontally */
1342 int max_width = g->anim_frames_per_line * g->width;
1343 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
1345 *x = pos % max_width;
1346 *y = src_y % g->height + pos / max_width * g->height;
1348 else if (g->offset_x == 0) /* frames are ordered vertically */
1350 int max_height = g->anim_frames_per_line * g->height;
1351 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
1353 *x = src_x % g->width + pos / max_height * g->width;
1354 *y = pos % max_height;
1356 else /* frames are ordered diagonally */
1358 *x = src_x + frame * g->offset_x;
1359 *y = src_y + frame * g->offset_y;
1363 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
1365 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
1368 void DrawGraphic(int x, int y, int graphic, int frame)
1371 if (!IN_SCR_FIELD(x, y))
1373 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1374 printf("DrawGraphic(): This should never happen!\n");
1380 DrawGraphicExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR, graphic,
1383 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
1385 MarkTileDirty(x, y);
1388 void DrawFixedGraphic(int x, int y, int graphic, int frame)
1391 if (!IN_SCR_FIELD(x, y))
1393 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1394 printf("DrawGraphic(): This should never happen!\n");
1399 DrawFixedGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1401 MarkTileDirty(x, y);
1404 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1410 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1412 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX_VAR, TILEY_VAR, x, y);
1414 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1418 void DrawFixedGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1424 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1425 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1428 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
1431 if (!IN_SCR_FIELD(x, y))
1433 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1434 printf("DrawGraphicThruMask(): This should never happen!\n");
1440 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
1443 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1446 MarkTileDirty(x, y);
1449 void DrawFixedGraphicThruMask(int x, int y, int graphic, int frame)
1452 if (!IN_SCR_FIELD(x, y))
1454 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1455 printf("DrawGraphicThruMask(): This should never happen!\n");
1460 DrawFixedGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1462 MarkTileDirty(x, y);
1465 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
1471 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1473 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1474 dst_x - src_x, dst_y - src_y);
1476 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX_VAR, TILEY_VAR,
1479 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1483 void DrawFixedGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y,
1484 int graphic, int frame)
1489 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1491 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1492 dst_x - src_x, dst_y - src_y);
1493 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1496 void DrawSizedGraphic(int x, int y, int graphic, int frame, int tilesize)
1498 DrawSizedGraphicExt(drawto, SX + x * tilesize, SY + y * tilesize, graphic,
1500 MarkTileDirty(x / tilesize, y / tilesize);
1503 void DrawSizedGraphicExt(DrawBuffer *d, int x, int y, int graphic, int frame,
1509 getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
1510 BlitBitmap(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
1513 void DrawMiniGraphic(int x, int y, int graphic)
1515 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1516 MarkTileDirty(x / 2, y / 2);
1519 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1524 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1525 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1528 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
1529 int graphic, int frame,
1530 int cut_mode, int mask_mode)
1535 int width = TILEX, height = TILEY;
1538 if (dx || dy) /* shifted graphic */
1540 if (x < BX1) /* object enters playfield from the left */
1547 else if (x > BX2) /* object enters playfield from the right */
1553 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1559 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1561 else if (dx) /* general horizontal movement */
1562 MarkTileDirty(x + SIGN(dx), y);
1564 if (y < BY1) /* object enters playfield from the top */
1566 if (cut_mode==CUT_BELOW) /* object completely above top border */
1574 else if (y > BY2) /* object enters playfield from the bottom */
1580 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1586 else if (dy > 0 && cut_mode == CUT_ABOVE)
1588 if (y == BY2) /* object completely above bottom border */
1594 MarkTileDirty(x, y + 1);
1595 } /* object leaves playfield to the bottom */
1596 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1598 else if (dy) /* general vertical movement */
1599 MarkTileDirty(x, y + SIGN(dy));
1603 if (!IN_SCR_FIELD(x, y))
1605 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1606 printf("DrawGraphicShifted(): This should never happen!\n");
1612 width = width * TILESIZE_VAR / TILESIZE;
1613 height = height * TILESIZE_VAR / TILESIZE;
1614 cx = cx * TILESIZE_VAR / TILESIZE;
1615 cy = cy * TILESIZE_VAR / TILESIZE;
1616 dx = dx * TILESIZE_VAR / TILESIZE;
1617 dy = dy * TILESIZE_VAR / TILESIZE;
1620 if (width > 0 && height > 0)
1622 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1628 dst_x = FX + x * TILEX_VAR + dx;
1629 dst_y = FY + y * TILEY_VAR + dy;
1631 dst_x = FX + x * TILEX + dx;
1632 dst_y = FY + y * TILEY + dy;
1635 if (mask_mode == USE_MASKING)
1637 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1638 dst_x - src_x, dst_y - src_y);
1639 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1643 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1646 MarkTileDirty(x, y);
1650 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
1651 int graphic, int frame,
1652 int cut_mode, int mask_mode)
1658 int width = TILEX_VAR, height = TILEY_VAR;
1660 int width = TILEX, height = TILEY;
1664 int x2 = x + SIGN(dx);
1665 int y2 = y + SIGN(dy);
1667 /* !!! DOES NOT WORK FOR SLOW MOVEMENT !!! */
1668 int sync_frame = GfxFrame[LEVELX(x)][LEVELY(y)];
1670 /* movement with two-tile animations must be sync'ed with movement position,
1671 not with current GfxFrame (which can be higher when using slow movement) */
1672 int anim_pos = (dx ? ABS(dx) : ABS(dy));
1673 int anim_frames = graphic_info[graphic].anim_frames;
1675 /* (we also need anim_delay here for movement animations with less frames) */
1676 int anim_delay = graphic_info[graphic].anim_delay;
1677 int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
1679 int sync_frame = anim_pos * anim_frames / TILESIZE;
1682 boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */
1683 boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */
1685 /* re-calculate animation frame for two-tile movement animation */
1686 frame = getGraphicAnimationFrame(graphic, sync_frame);
1690 printf("::: %d, %d, %d => %d [%d]\n",
1691 anim_pos, anim_frames, anim_delay, sync_frame, graphic);
1693 printf("::: %d, %d => %d\n",
1694 anim_pos, anim_frames, sync_frame);
1699 printf("::: %d [%d, %d] [%d] [%d]\n", frame, sync_frame, dy,
1700 GfxFrame[LEVELX(x)][LEVELY(y)], mask_mode);
1703 /* check if movement start graphic inside screen area and should be drawn */
1704 if (draw_start_tile && IN_SCR_FIELD(x1, y1))
1706 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
1709 dst_x = FX + x1 * TILEX_VAR;
1710 dst_y = FY + y1 * TILEY_VAR;
1712 dst_x = FX + x1 * TILEX;
1713 dst_y = FY + y1 * TILEY;
1716 if (mask_mode == USE_MASKING)
1718 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1719 dst_x - src_x, dst_y - src_y);
1720 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1724 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1727 MarkTileDirty(x1, y1);
1730 /* check if movement end graphic inside screen area and should be drawn */
1731 if (draw_end_tile && IN_SCR_FIELD(x2, y2))
1733 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
1736 dst_x = FX + x2 * TILEX_VAR;
1737 dst_y = FY + y2 * TILEY_VAR;
1739 dst_x = FX + x2 * TILEX;
1740 dst_y = FY + y2 * TILEY;
1743 if (mask_mode == USE_MASKING)
1745 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1746 dst_x - src_x, dst_y - src_y);
1747 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1751 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1754 MarkTileDirty(x2, y2);
1758 static void DrawGraphicShifted(int x, int y, int dx, int dy,
1759 int graphic, int frame,
1760 int cut_mode, int mask_mode)
1764 DrawGraphic(x, y, graphic, frame);
1769 if (graphic_info[graphic].double_movement) /* EM style movement images */
1770 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1772 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1775 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1776 int frame, int cut_mode)
1778 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1781 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1782 int cut_mode, int mask_mode)
1784 int lx = LEVELX(x), ly = LEVELY(y);
1788 if (IN_LEV_FIELD(lx, ly))
1790 SetRandomAnimationValue(lx, ly);
1792 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1793 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1795 /* do not use double (EM style) movement graphic when not moving */
1796 if (graphic_info[graphic].double_movement && !dx && !dy)
1798 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
1799 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1802 else /* border element */
1804 graphic = el2img(element);
1805 frame = getGraphicAnimationFrame(graphic, -1);
1808 if (element == EL_EXPANDABLE_WALL)
1810 boolean left_stopped = FALSE, right_stopped = FALSE;
1812 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1813 left_stopped = TRUE;
1814 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1815 right_stopped = TRUE;
1817 if (left_stopped && right_stopped)
1819 else if (left_stopped)
1821 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1822 frame = graphic_info[graphic].anim_frames - 1;
1824 else if (right_stopped)
1826 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1827 frame = graphic_info[graphic].anim_frames - 1;
1832 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1833 else if (mask_mode == USE_MASKING)
1834 DrawGraphicThruMask(x, y, graphic, frame);
1836 DrawGraphic(x, y, graphic, frame);
1839 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1840 int cut_mode, int mask_mode)
1842 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1843 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1844 cut_mode, mask_mode);
1847 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1850 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1853 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1856 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1859 void DrawLevelElementThruMask(int x, int y, int element)
1861 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1864 void DrawLevelFieldThruMask(int x, int y)
1866 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1869 /* !!! implementation of quicksand is totally broken !!! */
1870 #define IS_CRUMBLED_TILE(x, y, e) \
1871 (GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) || \
1872 !IS_MOVING(x, y) || \
1873 (e) == EL_QUICKSAND_EMPTYING || \
1874 (e) == EL_QUICKSAND_FAST_EMPTYING))
1876 static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
1881 int width, height, cx, cy;
1882 int sx = SCREENX(x), sy = SCREENY(y);
1883 int crumbled_border_size = graphic_info[graphic].border_size;
1886 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1888 for (i = 1; i < 4; i++)
1890 int dxx = (i & 1 ? dx : 0);
1891 int dyy = (i & 2 ? dy : 0);
1894 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1897 /* check if neighbour field is of same crumble type */
1898 boolean same = (IS_CRUMBLED_TILE(xx, yy, element) &&
1899 graphic_info[graphic].class ==
1900 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class);
1902 /* return if check prevents inner corner */
1903 if (same == (dxx == dx && dyy == dy))
1907 /* if we reach this point, we have an inner corner */
1909 getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
1912 width = crumbled_border_size * TILESIZE_VAR / TILESIZE;
1913 height = crumbled_border_size * TILESIZE_VAR / TILESIZE;
1914 cx = (dx > 0 ? TILEX - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
1915 cy = (dy > 0 ? TILEY - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
1917 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1918 width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
1920 width = crumbled_border_size;
1921 height = crumbled_border_size;
1922 cx = (dx > 0 ? TILEX - crumbled_border_size : 0);
1923 cy = (dy > 0 ? TILEY - crumbled_border_size : 0);
1925 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1926 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1930 static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
1935 int width, height, bx, by, cx, cy;
1936 int sx = SCREENX(x), sy = SCREENY(y);
1937 int crumbled_border_size = graphic_info[graphic].border_size;
1940 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1942 /* draw simple, sloppy, non-corner-accurate crumbled border */
1945 width = (dir == 1 || dir == 2 ? crumbled_border_size : TILEX);
1946 height = (dir == 0 || dir == 3 ? crumbled_border_size : TILEY);
1947 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
1948 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
1950 if (dir == 1 || dir == 2) /* left or right crumbled border */
1952 width = crumbled_border_size;
1954 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
1957 else /* top or bottom crumbled border */
1960 height = crumbled_border_size;
1962 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
1967 BlitBitmap(src_bitmap, drawto_field,
1968 src_x + cx * TILESIZE_VAR / TILESIZE,
1969 src_y + cy * TILESIZE_VAR / TILESIZE,
1970 width * TILESIZE_VAR / TILESIZE,
1971 height * TILESIZE_VAR / TILESIZE,
1972 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
1973 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
1975 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1976 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1979 /* (remaining middle border part must be at least as big as corner part) */
1980 if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
1981 crumbled_border_size >= TILESIZE / 3)
1984 /* correct corners of crumbled border, if needed */
1987 for (i = -1; i <= 1; i+=2)
1989 int xx = x + (dir == 0 || dir == 3 ? i : 0);
1990 int yy = y + (dir == 1 || dir == 2 ? i : 0);
1991 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1994 /* check if neighbour field is of same crumble type */
1995 if (IS_CRUMBLED_TILE(xx, yy, element) &&
1996 graphic_info[graphic].class ==
1997 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
1999 /* no crumbled corner, but continued crumbled border */
2001 int c1 = (dir == 2 || dir == 3 ? TILESIZE - crumbled_border_size : 0);
2002 int c2 = (i == 1 ? TILESIZE - crumbled_border_size : 0);
2003 int b1 = (i == 1 ? crumbled_border_size :
2004 TILESIZE - 2 * crumbled_border_size);
2006 width = crumbled_border_size;
2007 height = crumbled_border_size;
2009 if (dir == 1 || dir == 2)
2025 BlitBitmap(src_bitmap, drawto_field,
2026 src_x + bx * TILESIZE_VAR / TILESIZE,
2027 src_y + by * TILESIZE_VAR / TILESIZE,
2028 width * TILESIZE_VAR / TILESIZE,
2029 height * TILESIZE_VAR / TILESIZE,
2030 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
2031 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
2033 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2034 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2039 if (dir == 1 || dir == 2) /* left or right crumbled border */
2041 for (i = -1; i <= 1; i+=2)
2045 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2048 /* check if neighbour field is of same crumble type */
2049 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2050 graphic_info[graphic].class ==
2051 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2053 /* no crumbled corner, but continued crumbled border */
2055 width = crumbled_border_size;
2056 height = crumbled_border_size;
2057 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2058 cy = (i == 1 ? TILEY - crumbled_border_size : 0);
2060 by = (i == 1 ? crumbled_border_size :
2061 TILEY - 2 * crumbled_border_size);
2063 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2064 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2068 else /* top or bottom crumbled border */
2070 for (i = -1; i <= 1; i+=2)
2074 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2077 /* check if neighbour field is of same crumble type */
2078 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2079 graphic_info[graphic].class ==
2080 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2082 /* no crumbled corner, but continued crumbled border */
2084 width = crumbled_border_size;
2085 height = crumbled_border_size;
2086 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
2087 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2088 bx = (i == 1 ? crumbled_border_size :
2089 TILEX - 2 * crumbled_border_size);
2092 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2093 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2100 static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
2102 int sx = SCREENX(x), sy = SCREENY(y);
2105 static int xy[4][2] =
2113 if (!IN_LEV_FIELD(x, y))
2116 element = TILE_GFX_ELEMENT(x, y);
2118 /* crumble field itself */
2119 if (IS_CRUMBLED_TILE(x, y, element))
2121 if (!IN_SCR_FIELD(sx, sy))
2124 for (i = 0; i < 4; i++)
2126 int xx = x + xy[i][0];
2127 int yy = y + xy[i][1];
2129 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2132 /* check if neighbour field is of same crumble type */
2134 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2135 graphic_info[graphic].class ==
2136 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2139 if (IS_CRUMBLED_TILE(xx, yy, element))
2143 DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
2146 if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
2147 graphic_info[graphic].anim_frames == 2)
2149 for (i = 0; i < 4; i++)
2151 int dx = (i & 1 ? +1 : -1);
2152 int dy = (i & 2 ? +1 : -1);
2154 DrawLevelFieldCrumbledInnerCorners(x, y, dx, dy, graphic);
2158 MarkTileDirty(sx, sy);
2160 else /* center field not crumbled -- crumble neighbour fields */
2162 for (i = 0; i < 4; i++)
2164 int xx = x + xy[i][0];
2165 int yy = y + xy[i][1];
2166 int sxx = sx + xy[i][0];
2167 int syy = sy + xy[i][1];
2169 if (!IN_LEV_FIELD(xx, yy) ||
2170 !IN_SCR_FIELD(sxx, syy))
2173 if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
2176 element = TILE_GFX_ELEMENT(xx, yy);
2178 if (!IS_CRUMBLED_TILE(xx, yy, element))
2181 graphic = el_act2crm(element, ACTION_DEFAULT);
2183 DrawLevelFieldCrumbledBorders(xx, yy, graphic, 0, 3 - i);
2185 MarkTileDirty(sxx, syy);
2190 void DrawLevelFieldCrumbled(int x, int y)
2194 if (!IN_LEV_FIELD(x, y))
2198 /* !!! CHECK THIS !!! */
2201 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2202 GFX_CRUMBLED(GfxElement[x][y]))
2205 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2206 GfxElement[x][y] != EL_UNDEFINED &&
2207 GFX_CRUMBLED(GfxElement[x][y]))
2209 DrawLevelFieldCrumbledDigging(x, y, GfxDir[x][y], GfxFrame[x][y]);
2216 graphic = el_act2crm(TILE_GFX_ELEMENT(x, y), ACTION_DEFAULT);
2218 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
2221 DrawLevelFieldCrumbledExt(x, y, graphic, 0);
2224 void DrawLevelFieldCrumbledDigging(int x, int y, int direction,
2227 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
2228 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
2229 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
2230 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
2231 int sx = SCREENX(x), sy = SCREENY(y);
2233 DrawGraphic(sx, sy, graphic1, frame1);
2234 DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
2237 void DrawLevelFieldCrumbledNeighbours(int x, int y)
2239 int sx = SCREENX(x), sy = SCREENY(y);
2240 static int xy[4][2] =
2249 for (i = 0; i < 4; i++)
2251 int xx = x + xy[i][0];
2252 int yy = y + xy[i][1];
2253 int sxx = sx + xy[i][0];
2254 int syy = sy + xy[i][1];
2256 if (!IN_LEV_FIELD(xx, yy) ||
2257 !IN_SCR_FIELD(sxx, syy) ||
2258 !GFX_CRUMBLED(Feld[xx][yy]) ||
2262 DrawLevelField(xx, yy);
2266 static int getBorderElement(int x, int y)
2270 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
2271 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
2272 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
2273 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
2274 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
2275 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
2276 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
2278 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2279 int steel_position = (x == -1 && y == -1 ? 0 :
2280 x == lev_fieldx && y == -1 ? 1 :
2281 x == -1 && y == lev_fieldy ? 2 :
2282 x == lev_fieldx && y == lev_fieldy ? 3 :
2283 x == -1 || x == lev_fieldx ? 4 :
2284 y == -1 || y == lev_fieldy ? 5 : 6);
2286 return border[steel_position][steel_type];
2289 void DrawScreenElement(int x, int y, int element)
2291 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
2292 DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
2295 void DrawLevelElement(int x, int y, int element)
2297 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2298 DrawScreenElement(SCREENX(x), SCREENY(y), element);
2301 void DrawScreenField(int x, int y)
2303 int lx = LEVELX(x), ly = LEVELY(y);
2304 int element, content;
2306 if (!IN_LEV_FIELD(lx, ly))
2308 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
2311 element = getBorderElement(lx, ly);
2313 DrawScreenElement(x, y, element);
2318 element = Feld[lx][ly];
2319 content = Store[lx][ly];
2321 if (IS_MOVING(lx, ly))
2323 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
2324 boolean cut_mode = NO_CUTTING;
2326 if (element == EL_QUICKSAND_EMPTYING ||
2327 element == EL_QUICKSAND_FAST_EMPTYING ||
2328 element == EL_MAGIC_WALL_EMPTYING ||
2329 element == EL_BD_MAGIC_WALL_EMPTYING ||
2330 element == EL_DC_MAGIC_WALL_EMPTYING ||
2331 element == EL_AMOEBA_DROPPING)
2332 cut_mode = CUT_ABOVE;
2333 else if (element == EL_QUICKSAND_FILLING ||
2334 element == EL_QUICKSAND_FAST_FILLING ||
2335 element == EL_MAGIC_WALL_FILLING ||
2336 element == EL_BD_MAGIC_WALL_FILLING ||
2337 element == EL_DC_MAGIC_WALL_FILLING)
2338 cut_mode = CUT_BELOW;
2341 if (lx == 9 && ly == 1)
2342 printf("::: %s [%d] [%d, %d] [%d]\n",
2343 EL_NAME(TILE_GFX_ELEMENT(lx, ly)),
2344 el_act2crm(TILE_GFX_ELEMENT(lx, ly), ACTION_DEFAULT),
2345 element_info[EL_QUICKSAND_EMPTYING].graphic[ACTION_DEFAULT],
2346 element_info[EL_QUICKSAND_EMPTYING].crumbled[ACTION_DEFAULT],
2347 GFX_CRUMBLED(TILE_GFX_ELEMENT(lx, ly)));
2350 if (cut_mode == CUT_ABOVE)
2352 DrawScreenElement(x, y, element);
2354 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
2357 DrawScreenElement(x, y, EL_EMPTY);
2360 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
2361 else if (cut_mode == NO_CUTTING)
2362 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
2365 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
2368 if (cut_mode == CUT_BELOW &&
2369 IN_LEV_FIELD(lx, ly + 1) && IN_SCR_FIELD(x, y + 1))
2370 DrawLevelElement(lx, ly + 1, element);
2374 if (content == EL_ACID)
2376 int dir = MovDir[lx][ly];
2377 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
2378 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
2380 DrawLevelElementThruMask(newlx, newly, EL_ACID);
2383 else if (IS_BLOCKED(lx, ly))
2388 boolean cut_mode = NO_CUTTING;
2389 int element_old, content_old;
2391 Blocked2Moving(lx, ly, &oldx, &oldy);
2394 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
2395 MovDir[oldx][oldy] == MV_RIGHT);
2397 element_old = Feld[oldx][oldy];
2398 content_old = Store[oldx][oldy];
2400 if (element_old == EL_QUICKSAND_EMPTYING ||
2401 element_old == EL_QUICKSAND_FAST_EMPTYING ||
2402 element_old == EL_MAGIC_WALL_EMPTYING ||
2403 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2404 element_old == EL_DC_MAGIC_WALL_EMPTYING ||
2405 element_old == EL_AMOEBA_DROPPING)
2406 cut_mode = CUT_ABOVE;
2408 DrawScreenElement(x, y, EL_EMPTY);
2411 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2413 else if (cut_mode == NO_CUTTING)
2414 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2417 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2420 else if (IS_DRAWABLE(element))
2421 DrawScreenElement(x, y, element);
2423 DrawScreenElement(x, y, EL_EMPTY);
2426 void DrawLevelField(int x, int y)
2428 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2429 DrawScreenField(SCREENX(x), SCREENY(y));
2430 else if (IS_MOVING(x, y))
2434 Moving2Blocked(x, y, &newx, &newy);
2435 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2436 DrawScreenField(SCREENX(newx), SCREENY(newy));
2438 else if (IS_BLOCKED(x, y))
2442 Blocked2Moving(x, y, &oldx, &oldy);
2443 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2444 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2448 void DrawMiniElement(int x, int y, int element)
2452 graphic = el2edimg(element);
2453 DrawMiniGraphic(x, y, graphic);
2456 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2458 int x = sx + scroll_x, y = sy + scroll_y;
2460 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2461 DrawMiniElement(sx, sy, EL_EMPTY);
2462 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2463 DrawMiniElement(sx, sy, Feld[x][y]);
2465 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
2468 void DrawEnvelopeBackground(int graphic, int startx, int starty,
2469 int x, int y, int xsize, int ysize, int font_nr,
2472 int font_width = getFontWidth(font_nr);
2473 int font_height = getFontHeight(font_nr) + line_spacing;
2476 int dst_x = SX + startx + x * font_width;
2477 int dst_y = SY + starty + y * font_height;
2478 int width = graphic_info[graphic].width;
2479 int height = graphic_info[graphic].height;
2480 int inner_width = MAX(width - 2 * font_width, font_width);
2481 int inner_height = MAX(height - 2 * font_height, font_height);
2482 int inner_sx = (width >= 3 * font_width ? font_width : 0);
2483 int inner_sy = (height >= 3 * font_height ? font_height : 0);
2484 boolean draw_masked = graphic_info[graphic].draw_masked;
2486 getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2488 if (src_bitmap == NULL || width < font_width || height < font_height)
2490 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
2494 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
2495 inner_sx + (x - 1) * font_width % inner_width);
2496 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
2497 inner_sy + (y - 1) * font_height % inner_height);
2501 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
2502 dst_x - src_x, dst_y - src_y);
2503 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
2507 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
2511 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
2513 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2514 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2515 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2516 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2517 boolean no_delay = (tape.warp_forward);
2518 unsigned int anim_delay = 0;
2519 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2520 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
2521 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2522 int font_width = getFontWidth(font_nr);
2523 int font_height = getFontHeight(font_nr);
2524 int max_xsize = level.envelope[envelope_nr].xsize;
2525 int max_ysize = level.envelope[envelope_nr].ysize;
2526 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2527 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2528 int xend = max_xsize;
2529 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2530 int xstep = (xstart < xend ? 1 : 0);
2531 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2534 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2536 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2537 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2538 int sx = (SXSIZE - xsize * font_width) / 2;
2539 int sy = (SYSIZE - ysize * font_height) / 2;
2542 SetDrawtoField(DRAW_BUFFERED);
2545 BlitScreenToBitmap(backbuffer);
2547 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2550 SetDrawtoField(DRAW_BACKBUFFER);
2552 for (yy = 0; yy < ysize; yy++)
2553 for (xx = 0; xx < xsize; xx++)
2554 DrawEnvelopeBackground(graphic, sx,sy, xx,yy, xsize, ysize,
2558 DrawTextBuffer(SX + sx + font_width, SY + sy + font_height,
2559 level.envelope[envelope_nr].text, font_nr, max_xsize,
2560 xsize - 2, ysize - 2, 0, mask_mode,
2561 level.envelope[envelope_nr].autowrap,
2562 level.envelope[envelope_nr].centered, FALSE);
2564 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
2565 level.envelope[envelope_nr].text, font_nr, max_xsize,
2566 xsize - 2, ysize - 2, mask_mode);
2569 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2572 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2576 void AnimateEnvelopeRequest(char *text, int anim_mode, int action)
2579 int envelope_nr = 0;
2582 int graphic = IMG_BACKGROUND_REQUEST;
2584 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2586 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2587 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2588 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2589 boolean no_delay = (tape.warp_forward);
2590 unsigned int anim_delay = 0;
2591 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2592 int anim_delay_value = (no_delay ? 0 : frame_delay_value + 500 * 0);
2594 int max_word_len = maxWordLengthInString(text);
2595 int font_nr = (max_word_len > 7 ? FONT_TEXT_1 : FONT_TEXT_2);
2597 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2599 int font_width = getFontWidth(font_nr);
2600 int font_height = getFontHeight(font_nr);
2601 int line_spacing = 2 * 1;
2605 int max_xsize = DXSIZE / font_width;
2606 // int max_ysize = DYSIZE / font_height;
2607 int max_ysize = DYSIZE / (font_height + line_spacing);
2609 int max_xsize = 7; /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
2610 int max_ysize = 13; /* tools.c: MAX_REQUEST_LINES == 13 */
2614 int max_xsize = level.envelope[envelope_nr].xsize;
2615 int max_ysize = level.envelope[envelope_nr].ysize;
2617 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2618 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2619 int xend = max_xsize;
2620 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2621 int xstep = (xstart < xend ? 1 : 0);
2622 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2627 char *text_copy = getStringCopy(text);
2630 font_nr = FONT_TEXT_2;
2632 if (maxWordLengthInString(text) > 7) /* MAX_REQUEST_LINE_FONT1_LEN == 7 */
2634 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
2635 font_nr = FONT_TEXT_1;
2638 int max_word_len = 0;
2640 char *text_copy = getStringCopy(text);
2642 font_nr = FONT_TEXT_2;
2644 for (text_ptr = text; *text_ptr; text_ptr++)
2646 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2648 if (max_word_len > 7) /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
2650 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
2651 font_nr = FONT_TEXT_1;
2660 for (text_ptr = text_copy; *text_ptr; text_ptr++)
2661 if (*text_ptr == ' ')
2666 dDX = SX + (SXSIZE - DXSIZE) / 2 - DX;
2667 dDY = SY + (SYSIZE - DYSIZE) / 2 - DY;
2669 dDX = SX + SXSIZE / 2 - max_xsize * font_width / 2 - DX;
2670 dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY;
2673 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2675 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2676 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2677 int sx = (SXSIZE - xsize * font_width) / 2;
2678 // int sy = (SYSIZE - ysize * font_height) / 2;
2679 int sy = (SYSIZE - ysize * (font_height + line_spacing)) / 2;
2683 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2685 SetDrawtoField(DRAW_BUFFERED);
2688 BlitScreenToBitmap(backbuffer);
2690 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2693 SetDrawtoField(DRAW_BACKBUFFER);
2696 for (yy = 0; yy < ysize; yy++)
2697 for (xx = 0; xx < xsize; xx++)
2698 DrawEnvelopeBackground(graphic, sx,sy, xx,yy, xsize, ysize,
2699 font_nr, line_spacing);
2704 DrawTextBuffer(SX + sx + font_width, SY + sy + font_height + 8,
2705 text_copy, font_nr, max_xsize,
2706 xsize - 2, ysize - 2, line_spacing, mask_mode,
2707 FALSE, TRUE, FALSE);
2709 DrawTextBuffer(SX + sx + font_width, SY + sy + font_height,
2710 level.envelope[envelope_nr].text, font_nr, max_xsize,
2711 xsize - 2, ysize - 2, 0, mask_mode,
2712 level.envelope[envelope_nr].autowrap,
2713 level.envelope[envelope_nr].centered, FALSE);
2717 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
2718 level.envelope[envelope_nr].text, font_nr, max_xsize,
2719 xsize - 2, ysize - 2, mask_mode);
2722 /* copy request gadgets to door backbuffer */
2725 if ((ysize - 2) > 13)
2726 BlitBitmap(bitmap_db_door, drawto,
2727 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
2728 DOOR_GFX_PAGEY1 + 13 * font_height,
2729 (xsize - 2) * font_width,
2730 (ysize - 2 - 13) * font_height,
2731 SX + sx + font_width,
2732 SY + sy + font_height * (1 + 13));
2734 if ((ysize - 2) > 13)
2735 BlitBitmap(bitmap_db_door, drawto,
2736 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
2737 DOOR_GFX_PAGEY1 + 11 * (font_height + line_spacing * 0),
2738 (xsize - 2) * font_width,
2739 (ysize - 2 - 13) * (font_height + line_spacing),
2740 SX + sx + font_width,
2741 SY + sy + (font_height + line_spacing) * (1 + 13));
2743 if ((ysize - 2) > 13)
2744 BlitBitmap(bitmap_db_door, drawto,
2745 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
2746 DOOR_GFX_PAGEY1 + 13 * font_height,
2747 (xsize - 2) * font_width,
2748 (ysize - 2 - 13) * font_height,
2749 SX + sx + font_width,
2750 SY + sy + font_height * (1 + 13));
2754 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2755 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
2757 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2767 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2775 void ShowEnvelope(int envelope_nr)
2777 int element = EL_ENVELOPE_1 + envelope_nr;
2778 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2779 int sound_opening = element_info[element].sound[ACTION_OPENING];
2780 int sound_closing = element_info[element].sound[ACTION_CLOSING];
2781 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2782 boolean no_delay = (tape.warp_forward);
2783 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
2784 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
2785 int anim_mode = graphic_info[graphic].anim_mode;
2786 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
2787 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
2789 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
2791 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
2793 if (anim_mode == ANIM_DEFAULT)
2794 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
2796 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
2799 Delay(wait_delay_value);
2801 WaitForEventToContinue();
2803 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
2805 if (anim_mode != ANIM_NONE)
2806 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
2808 if (anim_mode == ANIM_DEFAULT)
2809 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
2811 game.envelope_active = FALSE;
2813 SetDrawtoField(DRAW_BUFFERED);
2815 redraw_mask |= REDRAW_FIELD;
2819 void ShowEnvelopeRequest(char *text, int action)
2822 int last_game_status = game_status; /* save current game status */
2823 // int last_draw_background_mask = gfx.draw_background_mask;
2826 int graphic = IMG_BACKGROUND_REQUEST;
2827 int sound_opening = SND_REQUEST_OPENING;
2828 int sound_closing = SND_REQUEST_CLOSING;
2830 int envelope_nr = 0;
2831 int element = EL_ENVELOPE_1 + envelope_nr;
2832 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2833 int sound_opening = element_info[element].sound[ACTION_OPENING];
2834 int sound_closing = element_info[element].sound[ACTION_CLOSING];
2837 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2838 boolean no_delay = (tape.warp_forward);
2839 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
2840 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
2842 int anim_mode = graphic_info[graphic].anim_mode;
2843 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
2844 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
2847 if (game_status == GAME_MODE_PLAYING)
2849 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2850 BlitScreenToBitmap_EM(backbuffer);
2851 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
2852 BlitScreenToBitmap_SP(backbuffer);
2855 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2859 SetDrawtoField(DRAW_BACKBUFFER);
2861 // SetDrawBackgroundMask(REDRAW_NONE);
2863 if (action == ACTION_OPENING)
2865 BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2867 if (game_status != GAME_MODE_MAIN)
2871 /* force DOOR font inside door area */
2872 game_status = GAME_MODE_PSEUDO_DOOR;
2875 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
2877 if (action == ACTION_OPENING)
2879 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
2881 if (anim_mode == ANIM_DEFAULT)
2882 AnimateEnvelopeRequest(text, ANIM_DEFAULT, ACTION_OPENING);
2884 AnimateEnvelopeRequest(text, main_anim_mode, ACTION_OPENING);
2888 Delay(wait_delay_value);
2890 WaitForEventToContinue();
2895 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
2897 if (anim_mode != ANIM_NONE)
2898 AnimateEnvelopeRequest(text, main_anim_mode, ACTION_CLOSING);
2900 if (anim_mode == ANIM_DEFAULT)
2901 AnimateEnvelopeRequest(text, ANIM_DEFAULT, ACTION_CLOSING);
2904 game.envelope_active = FALSE;
2907 // game_status = last_game_status; /* restore current game status */
2909 if (action == ACTION_CLOSING)
2911 if (game_status != GAME_MODE_MAIN)
2914 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2917 SetDrawtoField(DRAW_BUFFERED);
2920 // SetDrawBackgroundMask(last_draw_background_mask);
2923 redraw_mask = REDRAW_FIELD;
2924 // redraw_mask |= REDRAW_ALL;
2926 redraw_mask |= REDRAW_FIELD;
2930 if (game_status == GAME_MODE_MAIN)
2935 /* (important: after "BackToFront()", but before "SetDrawtoField()") */
2936 game_status = last_game_status; /* restore current game status */
2938 if (game_status == GAME_MODE_PLAYING &&
2939 level.game_engine_type == GAME_ENGINE_TYPE_RND)
2940 SetDrawtoField(DRAW_BUFFERED);
2946 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
2950 int graphic = el2preimg(element);
2952 getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
2953 BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
2961 SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
2962 SetDrawBackgroundMask(REDRAW_FIELD);
2964 SetDrawBackgroundMask(REDRAW_NONE);
2969 for (x = BX1; x <= BX2; x++)
2970 for (y = BY1; y <= BY2; y++)
2971 DrawScreenField(x, y);
2973 redraw_mask |= REDRAW_FIELD;
2976 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2980 for (x = 0; x < size_x; x++)
2981 for (y = 0; y < size_y; y++)
2982 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2984 redraw_mask |= REDRAW_FIELD;
2987 static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y)
2989 boolean show_level_border = (BorderElement != EL_EMPTY);
2990 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
2991 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
2992 int tile_size = preview.tile_size;
2993 int preview_width = preview.xsize * tile_size;
2994 int preview_height = preview.ysize * tile_size;
2995 int real_preview_xsize = MIN(level_xsize, preview.xsize);
2996 int real_preview_ysize = MIN(level_ysize, preview.ysize);
2997 int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
2998 int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
3001 DrawBackground(dst_x, dst_y, preview_width, preview_height);
3003 dst_x += (preview_width - real_preview_xsize * tile_size) / 2;
3004 dst_y += (preview_height - real_preview_ysize * tile_size) / 2;
3006 for (x = 0; x < real_preview_xsize; x++)
3008 for (y = 0; y < real_preview_ysize; y++)
3010 int lx = from_x + x + (show_level_border ? -1 : 0);
3011 int ly = from_y + y + (show_level_border ? -1 : 0);
3012 int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
3013 getBorderElement(lx, ly));
3015 DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size,
3016 element, tile_size);
3020 redraw_mask |= REDRAW_MICROLEVEL;
3023 #define MICROLABEL_EMPTY 0
3024 #define MICROLABEL_LEVEL_NAME 1
3025 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
3026 #define MICROLABEL_LEVEL_AUTHOR 3
3027 #define MICROLABEL_IMPORTED_FROM_HEAD 4
3028 #define MICROLABEL_IMPORTED_FROM 5
3029 #define MICROLABEL_IMPORTED_BY_HEAD 6
3030 #define MICROLABEL_IMPORTED_BY 7
3032 static int getMaxTextLength(struct TextPosInfo *pos, int font_nr)
3034 int max_text_width = SXSIZE;
3035 int font_width = getFontWidth(font_nr);
3037 if (pos->align == ALIGN_CENTER)
3038 max_text_width = (pos->x < SXSIZE / 2 ? pos->x * 2 : (SXSIZE - pos->x) * 2);
3039 else if (pos->align == ALIGN_RIGHT)
3040 max_text_width = pos->x;
3042 max_text_width = SXSIZE - pos->x;
3044 return max_text_width / font_width;
3047 static void DrawPreviewLevelLabelExt(int mode)
3049 struct TextPosInfo *pos = &menu.main.text.level_info_2;
3050 char label_text[MAX_OUTPUT_LINESIZE + 1];
3051 int max_len_label_text;
3053 int font_nr = pos->font;
3056 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3057 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3058 mode == MICROLABEL_IMPORTED_BY_HEAD)
3059 font_nr = pos->font_alt;
3061 int font_nr = FONT_TEXT_2;
3064 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3065 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3066 mode == MICROLABEL_IMPORTED_BY_HEAD)
3067 font_nr = FONT_TEXT_3;
3071 max_len_label_text = getMaxTextLength(pos, font_nr);
3073 max_len_label_text = SXSIZE / getFontWidth(font_nr);
3077 if (pos->size != -1)
3078 max_len_label_text = pos->size;
3081 for (i = 0; i < max_len_label_text; i++)
3082 label_text[i] = ' ';
3083 label_text[max_len_label_text] = '\0';
3085 if (strlen(label_text) > 0)
3088 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3090 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3091 int lypos = MICROLABEL2_YPOS;
3093 DrawText(lxpos, lypos, label_text, font_nr);
3098 (mode == MICROLABEL_LEVEL_NAME ? level.name :
3099 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
3100 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
3101 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
3102 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
3103 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
3104 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
3105 max_len_label_text);
3106 label_text[max_len_label_text] = '\0';
3108 if (strlen(label_text) > 0)
3111 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3113 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3114 int lypos = MICROLABEL2_YPOS;
3116 DrawText(lxpos, lypos, label_text, font_nr);
3120 redraw_mask |= REDRAW_MICROLEVEL;
3123 static void DrawPreviewLevelExt(boolean restart)
3125 static unsigned int scroll_delay = 0;
3126 static unsigned int label_delay = 0;
3127 static int from_x, from_y, scroll_direction;
3128 static int label_state, label_counter;
3129 unsigned int scroll_delay_value = preview.step_delay;
3130 boolean show_level_border = (BorderElement != EL_EMPTY);
3131 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3132 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3133 int last_game_status = game_status; /* save current game status */
3136 /* force PREVIEW font on preview level */
3137 game_status = GAME_MODE_PSEUDO_PREVIEW;
3145 if (preview.anim_mode == ANIM_CENTERED)
3147 if (level_xsize > preview.xsize)
3148 from_x = (level_xsize - preview.xsize) / 2;
3149 if (level_ysize > preview.ysize)
3150 from_y = (level_ysize - preview.ysize) / 2;
3153 from_x += preview.xoffset;
3154 from_y += preview.yoffset;
3156 scroll_direction = MV_RIGHT;
3160 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3161 DrawPreviewLevelLabelExt(label_state);
3163 /* initialize delay counters */
3164 DelayReached(&scroll_delay, 0);
3165 DelayReached(&label_delay, 0);
3167 if (leveldir_current->name)
3169 struct TextPosInfo *pos = &menu.main.text.level_info_1;
3170 char label_text[MAX_OUTPUT_LINESIZE + 1];
3172 int font_nr = pos->font;
3174 int font_nr = FONT_TEXT_1;
3177 int max_len_label_text = getMaxTextLength(pos, font_nr);
3179 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
3187 if (pos->size != -1)
3188 max_len_label_text = pos->size;
3191 strncpy(label_text, leveldir_current->name, max_len_label_text);
3192 label_text[max_len_label_text] = '\0';
3195 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3197 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3198 lypos = SY + MICROLABEL1_YPOS;
3200 DrawText(lxpos, lypos, label_text, font_nr);
3204 game_status = last_game_status; /* restore current game status */
3209 /* scroll preview level, if needed */
3210 if (preview.anim_mode != ANIM_NONE &&
3211 (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
3212 DelayReached(&scroll_delay, scroll_delay_value))
3214 switch (scroll_direction)
3219 from_x -= preview.step_offset;
3220 from_x = (from_x < 0 ? 0 : from_x);
3223 scroll_direction = MV_UP;
3227 if (from_x < level_xsize - preview.xsize)
3229 from_x += preview.step_offset;
3230 from_x = (from_x > level_xsize - preview.xsize ?
3231 level_xsize - preview.xsize : from_x);
3234 scroll_direction = MV_DOWN;
3240 from_y -= preview.step_offset;
3241 from_y = (from_y < 0 ? 0 : from_y);
3244 scroll_direction = MV_RIGHT;
3248 if (from_y < level_ysize - preview.ysize)
3250 from_y += preview.step_offset;
3251 from_y = (from_y > level_ysize - preview.ysize ?
3252 level_ysize - preview.ysize : from_y);
3255 scroll_direction = MV_LEFT;
3262 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3265 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
3266 /* redraw micro level label, if needed */
3267 if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
3268 !strEqual(level.author, ANONYMOUS_NAME) &&
3269 !strEqual(level.author, leveldir_current->name) &&
3270 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
3272 int max_label_counter = 23;
3274 if (leveldir_current->imported_from != NULL &&
3275 strlen(leveldir_current->imported_from) > 0)
3276 max_label_counter += 14;
3277 if (leveldir_current->imported_by != NULL &&
3278 strlen(leveldir_current->imported_by) > 0)
3279 max_label_counter += 14;
3281 label_counter = (label_counter + 1) % max_label_counter;
3282 label_state = (label_counter >= 0 && label_counter <= 7 ?
3283 MICROLABEL_LEVEL_NAME :
3284 label_counter >= 9 && label_counter <= 12 ?
3285 MICROLABEL_LEVEL_AUTHOR_HEAD :
3286 label_counter >= 14 && label_counter <= 21 ?
3287 MICROLABEL_LEVEL_AUTHOR :
3288 label_counter >= 23 && label_counter <= 26 ?
3289 MICROLABEL_IMPORTED_FROM_HEAD :
3290 label_counter >= 28 && label_counter <= 35 ?
3291 MICROLABEL_IMPORTED_FROM :
3292 label_counter >= 37 && label_counter <= 40 ?
3293 MICROLABEL_IMPORTED_BY_HEAD :
3294 label_counter >= 42 && label_counter <= 49 ?
3295 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
3297 if (leveldir_current->imported_from == NULL &&
3298 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
3299 label_state == MICROLABEL_IMPORTED_FROM))
3300 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
3301 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
3303 DrawPreviewLevelLabelExt(label_state);
3306 game_status = last_game_status; /* restore current game status */
3309 void DrawPreviewLevelInitial()
3311 DrawPreviewLevelExt(TRUE);
3314 void DrawPreviewLevelAnimation()
3316 DrawPreviewLevelExt(FALSE);
3319 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3320 int graphic, int sync_frame, int mask_mode)
3322 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3324 if (mask_mode == USE_MASKING)
3325 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3327 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
3330 inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3331 int graphic, int sync_frame,
3334 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3336 if (mask_mode == USE_MASKING)
3337 DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3339 DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
3342 inline void DrawGraphicAnimation(int x, int y, int graphic)
3344 int lx = LEVELX(x), ly = LEVELY(y);
3346 if (!IN_SCR_FIELD(x, y))
3350 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
3351 graphic, GfxFrame[lx][ly], NO_MASKING);
3353 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3354 graphic, GfxFrame[lx][ly], NO_MASKING);
3356 MarkTileDirty(x, y);
3359 inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
3361 int lx = LEVELX(x), ly = LEVELY(y);
3363 if (!IN_SCR_FIELD(x, y))
3366 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3367 graphic, GfxFrame[lx][ly], NO_MASKING);
3368 MarkTileDirty(x, y);
3371 void DrawLevelGraphicAnimation(int x, int y, int graphic)
3373 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3376 void DrawLevelElementAnimation(int x, int y, int element)
3378 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3380 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3383 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
3385 int sx = SCREENX(x), sy = SCREENY(y);
3387 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3390 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3393 DrawGraphicAnimation(sx, sy, graphic);
3396 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
3397 DrawLevelFieldCrumbled(x, y);
3399 if (GFX_CRUMBLED(Feld[x][y]))
3400 DrawLevelFieldCrumbled(x, y);
3404 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
3406 int sx = SCREENX(x), sy = SCREENY(y);
3409 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3412 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3414 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3417 DrawGraphicAnimation(sx, sy, graphic);
3419 if (GFX_CRUMBLED(element))
3420 DrawLevelFieldCrumbled(x, y);
3423 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
3425 if (player->use_murphy)
3427 /* this works only because currently only one player can be "murphy" ... */
3428 static int last_horizontal_dir = MV_LEFT;
3429 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
3431 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3432 last_horizontal_dir = move_dir;
3434 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
3436 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
3438 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
3444 return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
3447 static boolean equalGraphics(int graphic1, int graphic2)
3449 struct GraphicInfo *g1 = &graphic_info[graphic1];
3450 struct GraphicInfo *g2 = &graphic_info[graphic2];
3452 return (g1->bitmap == g2->bitmap &&
3453 g1->src_x == g2->src_x &&
3454 g1->src_y == g2->src_y &&
3455 g1->anim_frames == g2->anim_frames &&
3456 g1->anim_delay == g2->anim_delay &&
3457 g1->anim_mode == g2->anim_mode);
3460 void DrawAllPlayers()
3464 for (i = 0; i < MAX_PLAYERS; i++)
3465 if (stored_player[i].active)
3466 DrawPlayer(&stored_player[i]);
3469 void DrawPlayerField(int x, int y)
3471 if (!IS_PLAYER(x, y))
3474 DrawPlayer(PLAYERINFO(x, y));
3477 #define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
3479 void DrawPlayer(struct PlayerInfo *player)
3481 int jx = player->jx;
3482 int jy = player->jy;
3483 int move_dir = player->MovDir;
3484 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
3485 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
3486 int last_jx = (player->is_moving ? jx - dx : jx);
3487 int last_jy = (player->is_moving ? jy - dy : jy);
3488 int next_jx = jx + dx;
3489 int next_jy = jy + dy;
3490 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
3491 boolean player_is_opaque = FALSE;
3492 int sx = SCREENX(jx), sy = SCREENY(jy);
3493 int sxx = 0, syy = 0;
3494 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
3496 int action = ACTION_DEFAULT;
3497 int last_player_graphic = getPlayerGraphic(player, move_dir);
3498 int last_player_frame = player->Frame;
3501 /* GfxElement[][] is set to the element the player is digging or collecting;
3502 remove also for off-screen player if the player is not moving anymore */
3503 if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
3504 GfxElement[jx][jy] = EL_UNDEFINED;
3506 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
3510 if (!IN_LEV_FIELD(jx, jy))
3512 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
3513 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
3514 printf("DrawPlayerField(): This should never happen!\n");
3519 if (element == EL_EXPLOSION)
3522 action = (player->is_pushing ? ACTION_PUSHING :
3523 player->is_digging ? ACTION_DIGGING :
3524 player->is_collecting ? ACTION_COLLECTING :
3525 player->is_moving ? ACTION_MOVING :
3526 player->is_snapping ? ACTION_SNAPPING :
3527 player->is_dropping ? ACTION_DROPPING :
3528 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
3530 if (player->is_waiting)
3531 move_dir = player->dir_waiting;
3533 InitPlayerGfxAnimation(player, action, move_dir);
3535 /* ----------------------------------------------------------------------- */
3536 /* draw things in the field the player is leaving, if needed */
3537 /* ----------------------------------------------------------------------- */
3539 if (player->is_moving)
3541 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
3543 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
3545 if (last_element == EL_DYNAMITE_ACTIVE ||
3546 last_element == EL_EM_DYNAMITE_ACTIVE ||
3547 last_element == EL_SP_DISK_RED_ACTIVE)
3548 DrawDynamite(last_jx, last_jy);
3550 DrawLevelFieldThruMask(last_jx, last_jy);
3552 else if (last_element == EL_DYNAMITE_ACTIVE ||
3553 last_element == EL_EM_DYNAMITE_ACTIVE ||
3554 last_element == EL_SP_DISK_RED_ACTIVE)
3555 DrawDynamite(last_jx, last_jy);
3557 /* !!! this is not enough to prevent flickering of players which are
3558 moving next to each others without a free tile between them -- this
3559 can only be solved by drawing all players layer by layer (first the
3560 background, then the foreground etc.) !!! => TODO */
3561 else if (!IS_PLAYER(last_jx, last_jy))
3562 DrawLevelField(last_jx, last_jy);
3565 DrawLevelField(last_jx, last_jy);
3568 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
3569 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
3572 if (!IN_SCR_FIELD(sx, sy))
3575 /* ----------------------------------------------------------------------- */
3576 /* draw things behind the player, if needed */
3577 /* ----------------------------------------------------------------------- */
3580 DrawLevelElement(jx, jy, Back[jx][jy]);
3581 else if (IS_ACTIVE_BOMB(element))
3582 DrawLevelElement(jx, jy, EL_EMPTY);
3585 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
3587 int old_element = GfxElement[jx][jy];
3588 int old_graphic = el_act_dir2img(old_element, action, move_dir);
3589 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
3591 if (GFX_CRUMBLED(old_element))
3592 DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
3594 DrawGraphic(sx, sy, old_graphic, frame);
3596 if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
3597 player_is_opaque = TRUE;
3601 GfxElement[jx][jy] = EL_UNDEFINED;
3603 /* make sure that pushed elements are drawn with correct frame rate */
3605 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
3607 if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
3608 GfxFrame[jx][jy] = player->StepFrame;
3610 if (player->is_pushing && player->is_moving)
3611 GfxFrame[jx][jy] = player->StepFrame;
3614 DrawLevelField(jx, jy);
3618 #if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
3619 /* ----------------------------------------------------------------------- */
3620 /* draw player himself */
3621 /* ----------------------------------------------------------------------- */
3623 graphic = getPlayerGraphic(player, move_dir);
3625 /* in the case of changed player action or direction, prevent the current
3626 animation frame from being restarted for identical animations */
3627 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
3628 player->Frame = last_player_frame;
3630 frame = getGraphicAnimationFrame(graphic, player->Frame);
3634 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3635 sxx = player->GfxPos;
3637 syy = player->GfxPos;
3640 if (!setup.soft_scrolling && ScreenMovPos)
3643 if (player_is_opaque)
3644 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
3646 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3648 if (SHIELD_ON(player))
3650 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
3651 IMG_SHIELD_NORMAL_ACTIVE);
3652 int frame = getGraphicAnimationFrame(graphic, -1);
3654 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3658 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
3661 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3662 sxx = player->GfxPos;
3664 syy = player->GfxPos;
3668 /* ----------------------------------------------------------------------- */
3669 /* draw things the player is pushing, if needed */
3670 /* ----------------------------------------------------------------------- */
3673 printf("::: %d, %d [%d, %d] [%d]\n",
3674 player->is_pushing, player_is_moving, player->GfxAction,
3675 player->is_moving, player_is_moving);
3679 if (player->is_pushing && player->is_moving)
3681 int px = SCREENX(jx), py = SCREENY(jy);
3682 int pxx = (TILEX - ABS(sxx)) * dx;
3683 int pyy = (TILEY - ABS(syy)) * dy;
3684 int gfx_frame = GfxFrame[jx][jy];
3690 if (!IS_MOVING(jx, jy)) /* push movement already finished */
3692 element = Feld[next_jx][next_jy];
3693 gfx_frame = GfxFrame[next_jx][next_jy];
3696 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
3699 sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
3700 frame = getGraphicAnimationFrame(graphic, sync_frame);
3702 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
3705 /* draw background element under pushed element (like the Sokoban field) */
3707 if (game.use_masked_pushing && IS_MOVING(jx, jy))
3709 /* this allows transparent pushing animation over non-black background */
3712 DrawLevelElement(jx, jy, Back[jx][jy]);
3714 DrawLevelElement(jx, jy, EL_EMPTY);
3716 if (Back[next_jx][next_jy])
3717 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
3719 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
3721 else if (Back[next_jx][next_jy])
3722 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
3724 if (Back[next_jx][next_jy])
3725 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
3729 printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
3730 jx, px, player->GfxPos, player->StepFrame,
3735 GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
3739 /* do not draw (EM style) pushing animation when pushing is finished */
3740 /* (two-tile animations usually do not contain start and end frame) */
3741 if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
3742 DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
3744 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
3746 /* masked drawing is needed for EMC style (double) movement graphics */
3747 /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
3748 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
3753 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
3754 /* ----------------------------------------------------------------------- */
3755 /* draw player himself */
3756 /* ----------------------------------------------------------------------- */
3758 graphic = getPlayerGraphic(player, move_dir);
3760 /* in the case of changed player action or direction, prevent the current
3761 animation frame from being restarted for identical animations */
3762 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
3763 player->Frame = last_player_frame;
3765 frame = getGraphicAnimationFrame(graphic, player->Frame);
3769 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3770 sxx = player->GfxPos;
3772 syy = player->GfxPos;
3775 if (!setup.soft_scrolling && ScreenMovPos)
3778 if (player_is_opaque)
3779 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
3781 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3783 if (SHIELD_ON(player))
3785 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
3786 IMG_SHIELD_NORMAL_ACTIVE);
3787 int frame = getGraphicAnimationFrame(graphic, -1);
3789 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3793 /* ----------------------------------------------------------------------- */
3794 /* draw things in front of player (active dynamite or dynabombs) */
3795 /* ----------------------------------------------------------------------- */
3797 if (IS_ACTIVE_BOMB(element))
3799 graphic = el2img(element);
3800 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
3802 if (game.emulation == EMU_SUPAPLEX)
3803 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
3805 DrawGraphicThruMask(sx, sy, graphic, frame);
3808 if (player_is_moving && last_element == EL_EXPLOSION)
3810 int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
3811 GfxElement[last_jx][last_jy] : EL_EMPTY);
3812 int graphic = el_act2img(element, ACTION_EXPLODING);
3813 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
3814 int phase = ExplodePhase[last_jx][last_jy] - 1;
3815 int frame = getGraphicAnimationFrame(graphic, phase - delay);
3818 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
3821 /* ----------------------------------------------------------------------- */
3822 /* draw elements the player is just walking/passing through/under */
3823 /* ----------------------------------------------------------------------- */
3825 if (player_is_moving)
3827 /* handle the field the player is leaving ... */
3828 if (IS_ACCESSIBLE_INSIDE(last_element))
3829 DrawLevelField(last_jx, last_jy);
3830 else if (IS_ACCESSIBLE_UNDER(last_element))
3831 DrawLevelFieldThruMask(last_jx, last_jy);
3834 /* do not redraw accessible elements if the player is just pushing them */
3835 if (!player_is_moving || !player->is_pushing)
3837 /* ... and the field the player is entering */
3838 if (IS_ACCESSIBLE_INSIDE(element))
3839 DrawLevelField(jx, jy);
3840 else if (IS_ACCESSIBLE_UNDER(element))
3841 DrawLevelFieldThruMask(jx, jy);
3844 MarkTileDirty(sx, sy);
3847 /* ------------------------------------------------------------------------- */
3849 void WaitForEventToContinue()
3851 boolean still_wait = TRUE;
3853 /* simulate releasing mouse button over last gadget, if still pressed */
3855 HandleGadgets(-1, -1, 0);
3857 button_status = MB_RELEASED;
3873 case EVENT_BUTTONPRESS:
3874 case EVENT_KEYPRESS:
3878 case EVENT_KEYRELEASE:
3879 ClearPlayerAction();
3883 HandleOtherEvents(&event);
3887 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
3894 /* don't eat all CPU time */
3899 #define MAX_REQUEST_LINES 13
3900 #define MAX_REQUEST_LINE_FONT1_LEN 7
3901 #define MAX_REQUEST_LINE_FONT2_LEN 10
3903 boolean Request(char *text, unsigned int req_state)
3905 int mx, my, ty, result = -1;
3906 unsigned int old_door_state;
3907 int last_game_status = game_status; /* save current game status */
3908 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
3909 int font_nr = FONT_TEXT_2;
3911 int max_word_len = 0;
3917 global.use_envelope_request = 1;
3921 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
3923 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
3924 font_nr = FONT_TEXT_1;
3927 for (text_ptr = text; *text_ptr; text_ptr++)
3929 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
3931 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
3933 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
3935 font_nr = FONT_TEXT_1;
3937 font_nr = FONT_LEVEL_NUMBER;
3945 if (game_status == GAME_MODE_PLAYING)
3947 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
3948 BlitScreenToBitmap_EM(backbuffer);
3949 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3950 BlitScreenToBitmap_SP(backbuffer);
3953 /* disable deactivated drawing when quick-loading level tape recording */
3954 if (tape.playing && tape.deactivate_display)
3955 TapeDeactivateDisplayOff(TRUE);
3957 SetMouseCursor(CURSOR_DEFAULT);
3959 #if defined(NETWORK_AVALIABLE)
3960 /* pause network game while waiting for request to answer */
3961 if (options.network &&
3962 game_status == GAME_MODE_PLAYING &&
3963 req_state & REQUEST_WAIT_FOR_INPUT)
3964 SendToServer_PausePlaying();
3967 old_door_state = GetDoorState();
3969 /* simulate releasing mouse button over last gadget, if still pressed */
3971 HandleGadgets(-1, -1, 0);
3975 /* draw released gadget before proceeding */
3979 if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request)
3981 if (old_door_state & DOOR_OPEN_1)
3985 if (!global.use_envelope_request)
3986 CloseDoor(DOOR_CLOSE_1);
3988 CloseDoor(DOOR_CLOSE_1);
3991 /* save old door content */
3992 BlitBitmap(bitmap_db_door, bitmap_db_door,
3993 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
3994 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
3998 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4001 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4003 /* clear door drawing field */
4004 DrawBackground(DX, DY, DXSIZE, DYSIZE);
4006 /* force DOOR font inside door area */
4007 game_status = GAME_MODE_PSEUDO_DOOR;
4009 /* write text for request */
4010 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
4012 char text_line[max_request_line_len + 1];
4018 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
4020 tc = *(text_ptr + tx);
4021 if (!tc || tc == ' ')
4032 strncpy(text_line, text_ptr, tl);
4035 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
4036 DY + 8 + ty * (getFontHeight(font_nr) + 2),
4037 text_line, font_nr);
4039 text_ptr += tl + (tc == ' ' ? 1 : 0);
4042 game_status = last_game_status; /* restore current game status */
4045 if (global.use_envelope_request)
4049 CreateToolButtons();
4053 if (req_state & REQ_ASK)
4055 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4056 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4058 else if (req_state & REQ_CONFIRM)
4060 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4062 else if (req_state & REQ_PLAYER)
4064 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4065 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4066 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4067 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4070 /* copy request gadgets to door backbuffer */
4071 BlitBitmap(drawto, bitmap_db_door,
4072 DX, DY, DXSIZE, DYSIZE,
4073 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4076 if (global.use_envelope_request)
4078 ShowEnvelopeRequest(text, ACTION_OPENING);
4080 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4082 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
4083 i == TOOL_CTRL_ID_NO)) ||
4084 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
4085 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
4086 i == TOOL_CTRL_ID_PLAYER_2 &&
4087 i == TOOL_CTRL_ID_PLAYER_3 &&
4088 i == TOOL_CTRL_ID_PLAYER_4)))
4090 int x = tool_gadget[i]->x + dDX;
4091 int y = tool_gadget[i]->y + dDY;
4093 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
4100 if (!global.use_envelope_request)
4101 OpenDoor(DOOR_OPEN_1);
4103 OpenDoor(DOOR_OPEN_1);
4106 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4108 if (game_status == GAME_MODE_PLAYING)
4110 SetPanelBackground();
4111 SetDrawBackgroundMask(REDRAW_DOOR_1);
4115 SetDrawBackgroundMask(REDRAW_FIELD);
4122 if (game_status != GAME_MODE_MAIN && !global.use_envelope_request)
4125 if (game_status != GAME_MODE_MAIN)
4129 button_status = MB_RELEASED;
4131 request_gadget_id = -1;
4133 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4145 case EVENT_BUTTONPRESS:
4146 case EVENT_BUTTONRELEASE:
4147 case EVENT_MOTIONNOTIFY:
4149 if (event.type == EVENT_MOTIONNOTIFY)
4151 if (!PointerInWindow(window))
4152 continue; /* window and pointer are on different screens */
4157 motion_status = TRUE;
4158 mx = ((MotionEvent *) &event)->x;
4159 my = ((MotionEvent *) &event)->y;
4163 motion_status = FALSE;
4164 mx = ((ButtonEvent *) &event)->x;
4165 my = ((ButtonEvent *) &event)->y;
4166 if (event.type == EVENT_BUTTONPRESS)
4167 button_status = ((ButtonEvent *) &event)->button;
4169 button_status = MB_RELEASED;
4172 /* this sets 'request_gadget_id' */
4173 HandleGadgets(mx, my, button_status);
4175 switch (request_gadget_id)
4177 case TOOL_CTRL_ID_YES:
4180 case TOOL_CTRL_ID_NO:
4183 case TOOL_CTRL_ID_CONFIRM:
4184 result = TRUE | FALSE;
4187 case TOOL_CTRL_ID_PLAYER_1:
4190 case TOOL_CTRL_ID_PLAYER_2:
4193 case TOOL_CTRL_ID_PLAYER_3:
4196 case TOOL_CTRL_ID_PLAYER_4:
4207 case EVENT_KEYPRESS:
4208 switch (GetEventKey((KeyEvent *)&event, TRUE))
4211 if (req_state & REQ_CONFIRM)
4220 #if defined(TARGET_SDL2)
4230 if (req_state & REQ_PLAYER)
4234 case EVENT_KEYRELEASE:
4235 ClearPlayerAction();
4239 HandleOtherEvents(&event);
4243 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4245 int joy = AnyJoystick();
4247 if (joy & JOY_BUTTON_1)
4249 else if (joy & JOY_BUTTON_2)
4255 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
4257 HandleGameActions();
4263 if (!PendingEvent()) /* delay only if no pending events */
4268 game_status = GAME_MODE_PSEUDO_DOOR;
4274 game_status = last_game_status; /* restore current game status */
4282 if (!PendingEvent()) /* delay only if no pending events */
4285 /* don't eat all CPU time */
4292 if (game_status != GAME_MODE_MAIN)
4298 if (global.use_envelope_request)
4299 ShowEnvelopeRequest(text, ACTION_CLOSING);
4303 if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request)
4305 if (!(req_state & REQ_STAY_OPEN))
4308 CloseDoor(DOOR_CLOSE_1);
4310 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
4311 (req_state & REQ_REOPEN))
4312 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
4317 if (game_status == GAME_MODE_PLAYING)
4319 SetPanelBackground();
4320 SetDrawBackgroundMask(REDRAW_DOOR_1);
4324 SetDrawBackgroundMask(REDRAW_FIELD);
4327 #if defined(NETWORK_AVALIABLE)
4328 /* continue network game after request */
4329 if (options.network &&
4330 game_status == GAME_MODE_PLAYING &&
4331 req_state & REQUEST_WAIT_FOR_INPUT)
4332 SendToServer_ContinuePlaying();
4335 /* restore deactivated drawing when quick-loading level tape recording */
4336 if (tape.playing && tape.deactivate_display)
4337 TapeDeactivateDisplayOn();
4342 unsigned int OpenDoor(unsigned int door_state)
4344 if (door_state & DOOR_COPY_BACK)
4346 if (door_state & DOOR_OPEN_1)
4347 BlitBitmap(bitmap_db_door, bitmap_db_door,
4348 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4349 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4351 if (door_state & DOOR_OPEN_2)
4352 BlitBitmap(bitmap_db_door, bitmap_db_door,
4353 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
4354 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
4356 door_state &= ~DOOR_COPY_BACK;
4359 return MoveDoor(door_state);
4362 unsigned int CloseDoor(unsigned int door_state)
4364 unsigned int old_door_state = GetDoorState();
4366 if (!(door_state & DOOR_NO_COPY_BACK))
4368 if (old_door_state & DOOR_OPEN_1)
4369 BlitBitmap(backbuffer, bitmap_db_door,
4370 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4372 if (old_door_state & DOOR_OPEN_2)
4373 BlitBitmap(backbuffer, bitmap_db_door,
4374 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
4376 door_state &= ~DOOR_NO_COPY_BACK;
4379 return MoveDoor(door_state);
4382 unsigned int GetDoorState()
4384 return MoveDoor(DOOR_GET_STATE);
4387 unsigned int SetDoorState(unsigned int door_state)
4389 return MoveDoor(door_state | DOOR_SET_STATE);
4392 unsigned int MoveDoor(unsigned int door_state)
4394 static int door1 = DOOR_OPEN_1;
4395 static int door2 = DOOR_CLOSE_2;
4396 unsigned int door_delay = 0;
4397 unsigned int door_delay_value;
4400 if (door_1.width < 0 || door_1.width > DXSIZE)
4401 door_1.width = DXSIZE;
4402 if (door_1.height < 0 || door_1.height > DYSIZE)
4403 door_1.height = DYSIZE;
4404 if (door_2.width < 0 || door_2.width > VXSIZE)
4405 door_2.width = VXSIZE;
4406 if (door_2.height < 0 || door_2.height > VYSIZE)
4407 door_2.height = VYSIZE;
4409 if (door_state == DOOR_GET_STATE)
4410 return (door1 | door2);
4412 if (door_state & DOOR_SET_STATE)
4414 if (door_state & DOOR_ACTION_1)
4415 door1 = door_state & DOOR_ACTION_1;
4416 if (door_state & DOOR_ACTION_2)
4417 door2 = door_state & DOOR_ACTION_2;
4419 return (door1 | door2);
4422 if (!(door_state & DOOR_FORCE_REDRAW))
4424 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
4425 door_state &= ~DOOR_OPEN_1;
4426 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
4427 door_state &= ~DOOR_CLOSE_1;
4428 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
4429 door_state &= ~DOOR_OPEN_2;
4430 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
4431 door_state &= ~DOOR_CLOSE_2;
4434 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
4437 if (setup.quick_doors)
4439 stepsize = 20; /* must be chosen to always draw last frame */
4440 door_delay_value = 0;
4443 if (global.autoplay_leveldir)
4445 door_state |= DOOR_NO_DELAY;
4446 door_state &= ~DOOR_CLOSE_ALL;
4450 if (game_status == GAME_MODE_EDITOR)
4451 door_state |= DOOR_NO_DELAY;
4454 if (door_state & DOOR_ACTION)
4456 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
4457 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
4458 boolean door_1_done = (!handle_door_1);
4459 boolean door_2_done = (!handle_door_2);
4460 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
4461 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
4462 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
4463 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
4464 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
4465 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
4466 int door_size = (handle_door_1 ? door_size_1 : door_size_2);
4467 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
4468 int door_skip = max_door_size - door_size;
4469 int end = door_size;
4470 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
4473 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
4475 /* opening door sound has priority over simultaneously closing door */
4476 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
4477 PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
4478 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
4479 PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
4482 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
4485 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
4486 GC gc = bitmap->stored_clip_gc;
4488 if (door_state & DOOR_ACTION_1)
4490 int a = MIN(x * door_1.step_offset, end);
4491 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
4492 int i = p + door_skip;
4494 if (door_1.anim_mode & ANIM_STATIC_PANEL)
4496 BlitBitmap(bitmap_db_door, drawto,
4497 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
4498 DXSIZE, DYSIZE, DX, DY);
4502 BlitBitmap(bitmap_db_door, drawto,
4503 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
4504 DXSIZE, DYSIZE - p / 2, DX, DY);
4506 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
4509 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
4511 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
4512 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
4513 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
4514 int dst2_x = DX, dst2_y = DY;
4515 int width = i, height = DYSIZE;
4517 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4518 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4521 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4522 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4525 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
4527 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
4528 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
4529 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
4530 int dst2_x = DX, dst2_y = DY;
4531 int width = DXSIZE, height = i;
4533 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4534 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4537 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4538 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4541 else if (x <= DXSIZE) /* ANIM_DEFAULT */
4543 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
4545 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
4546 BlitBitmapMasked(bitmap, drawto,
4547 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
4548 DX + DXSIZE - i, DY + j);
4549 BlitBitmapMasked(bitmap, drawto,
4550 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
4551 DX + DXSIZE - i, DY + 140 + j);
4552 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
4553 DY - (DOOR_GFX_PAGEY1 + j));
4554 BlitBitmapMasked(bitmap, drawto,
4555 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
4557 BlitBitmapMasked(bitmap, drawto,
4558 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
4561 BlitBitmapMasked(bitmap, drawto,
4562 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
4564 BlitBitmapMasked(bitmap, drawto,
4565 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
4567 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
4568 BlitBitmapMasked(bitmap, drawto,
4569 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
4570 DX + DXSIZE - i, DY + 77 + j);
4571 BlitBitmapMasked(bitmap, drawto,
4572 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
4573 DX + DXSIZE - i, DY + 203 + j);
4576 redraw_mask |= REDRAW_DOOR_1;
4577 door_1_done = (a == end);
4580 if (door_state & DOOR_ACTION_2)
4582 int a = MIN(x * door_2.step_offset, door_size);
4583 int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
4584 int i = p + door_skip;
4586 if (door_2.anim_mode & ANIM_STATIC_PANEL)
4588 BlitBitmap(bitmap_db_door, drawto,
4589 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
4590 VXSIZE, VYSIZE, VX, VY);
4592 else if (x <= VYSIZE)
4594 BlitBitmap(bitmap_db_door, drawto,
4595 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
4596 VXSIZE, VYSIZE - p / 2, VX, VY);
4598 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
4601 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
4603 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
4604 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
4605 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
4606 int dst2_x = VX, dst2_y = VY;
4607 int width = i, height = VYSIZE;
4609 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4610 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4613 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4614 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4617 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
4619 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
4620 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
4621 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
4622 int dst2_x = VX, dst2_y = VY;
4623 int width = VXSIZE, height = i;
4625 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4626 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4629 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4630 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4633 else if (x <= VXSIZE) /* ANIM_DEFAULT */
4635 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
4637 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
4638 BlitBitmapMasked(bitmap, drawto,
4639 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
4640 VX + VXSIZE - i, VY + j);
4641 SetClipOrigin(bitmap, gc,
4642 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
4643 BlitBitmapMasked(bitmap, drawto,
4644 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
4647 BlitBitmapMasked(bitmap, drawto,
4648 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
4649 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
4650 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
4651 BlitBitmapMasked(bitmap, drawto,
4652 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
4654 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
4657 redraw_mask |= REDRAW_DOOR_2;
4658 door_2_done = (a == VXSIZE);
4661 if (!(door_state & DOOR_NO_DELAY))
4665 if (game_status == GAME_MODE_MAIN)
4668 WaitUntilDelayReached(&door_delay, door_delay_value);
4673 if (door_state & DOOR_ACTION_1)
4674 door1 = door_state & DOOR_ACTION_1;
4675 if (door_state & DOOR_ACTION_2)
4676 door2 = door_state & DOOR_ACTION_2;
4678 return (door1 | door2);
4681 void DrawSpecialEditorDoor()
4683 /* draw bigger toolbox window */
4684 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
4685 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
4687 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
4688 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
4691 redraw_mask |= REDRAW_ALL;
4694 void UndrawSpecialEditorDoor()
4696 /* draw normal tape recorder window */
4697 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
4698 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
4701 redraw_mask |= REDRAW_ALL;
4705 /* ---------- new tool button stuff ---------------------------------------- */
4712 struct TextPosInfo *pos;
4715 } toolbutton_info[NUM_TOOL_BUTTONS] =
4718 IMG_REQUEST_BUTTON_GFX_YES, &request.button.yes,
4719 TOOL_CTRL_ID_YES, "yes"
4722 IMG_REQUEST_BUTTON_GFX_NO, &request.button.no,
4723 TOOL_CTRL_ID_NO, "no"
4726 IMG_REQUEST_BUTTON_GFX_CONFIRM, &request.button.confirm,
4727 TOOL_CTRL_ID_CONFIRM, "confirm"
4730 IMG_REQUEST_BUTTON_GFX_PLAYER_1, &request.button.player_1,
4731 TOOL_CTRL_ID_PLAYER_1, "player 1"
4734 IMG_REQUEST_BUTTON_GFX_PLAYER_2, &request.button.player_2,
4735 TOOL_CTRL_ID_PLAYER_2, "player 2"
4738 IMG_REQUEST_BUTTON_GFX_PLAYER_3, &request.button.player_3,
4739 TOOL_CTRL_ID_PLAYER_3, "player 3"
4742 IMG_REQUEST_BUTTON_GFX_PLAYER_4, &request.button.player_4,
4743 TOOL_CTRL_ID_PLAYER_4, "player 4"
4747 void CreateToolButtons()
4751 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4753 struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
4754 struct TextPosInfo *pos = toolbutton_info[i].pos;
4755 struct GadgetInfo *gi;
4756 Bitmap *deco_bitmap = None;
4757 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
4758 unsigned int event_mask = GD_EVENT_RELEASED;
4759 int gd_x = gfx->src_x;
4760 int gd_y = gfx->src_y;
4761 int gd_xp = gfx->src_x + gfx->pressed_xoffset;
4762 int gd_yp = gfx->src_y + gfx->pressed_yoffset;
4765 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
4767 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
4769 getSizedGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0,
4770 pos->size, &deco_bitmap, &deco_x, &deco_y);
4771 deco_xpos = (gfx->width - pos->size) / 2;
4772 deco_ypos = (gfx->height - pos->size) / 2;
4775 gi = CreateGadget(GDI_CUSTOM_ID, id,
4776 GDI_INFO_TEXT, toolbutton_info[i].infotext,
4779 GDI_WIDTH, gfx->width,
4780 GDI_HEIGHT, gfx->height,
4781 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
4782 GDI_STATE, GD_BUTTON_UNPRESSED,
4783 GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y,
4784 GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp,
4785 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
4786 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
4787 GDI_DECORATION_SIZE, pos->size, pos->size,
4788 GDI_DECORATION_SHIFTING, 1, 1,
4789 GDI_DIRECT_DRAW, FALSE,
4790 GDI_EVENT_MASK, event_mask,
4791 GDI_CALLBACK_ACTION, HandleToolButtons,
4795 Error(ERR_EXIT, "cannot create gadget");
4797 tool_gadget[id] = gi;
4803 /* graphic position values for tool buttons */
4804 #define TOOL_BUTTON_YES_XPOS 2
4805 #define TOOL_BUTTON_YES_YPOS 250
4806 #define TOOL_BUTTON_YES_GFX_YPOS 0
4807 #define TOOL_BUTTON_YES_XSIZE 46
4808 #define TOOL_BUTTON_YES_YSIZE 28
4809 #define TOOL_BUTTON_NO_XPOS 52
4810 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
4811 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
4812 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
4813 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
4814 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
4815 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
4816 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
4817 #define TOOL_BUTTON_CONFIRM_XSIZE 96
4818 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
4819 #define TOOL_BUTTON_PLAYER_XSIZE 30
4820 #define TOOL_BUTTON_PLAYER_YSIZE 30
4821 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
4822 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
4823 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
4824 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
4825 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4826 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
4827 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4828 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
4829 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4830 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
4831 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4832 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
4833 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4834 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
4835 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4836 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
4837 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4838 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
4839 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4840 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
4849 } toolbutton_info[NUM_TOOL_BUTTONS] =
4852 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
4853 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
4854 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
4859 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
4860 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
4861 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
4866 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
4867 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
4868 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
4869 TOOL_CTRL_ID_CONFIRM,
4873 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4874 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
4875 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4876 TOOL_CTRL_ID_PLAYER_1,
4880 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4881 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
4882 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4883 TOOL_CTRL_ID_PLAYER_2,
4887 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4888 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
4889 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4890 TOOL_CTRL_ID_PLAYER_3,
4894 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4895 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
4896 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4897 TOOL_CTRL_ID_PLAYER_4,
4902 void CreateToolButtons()
4906 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4908 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
4909 Bitmap *deco_bitmap = None;
4910 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
4911 struct GadgetInfo *gi;
4912 unsigned int event_mask;
4913 int gd_xoffset, gd_yoffset;
4914 int gd_x1, gd_x2, gd_y;
4917 event_mask = GD_EVENT_RELEASED;
4919 gd_xoffset = toolbutton_info[i].xpos;
4920 gd_yoffset = toolbutton_info[i].ypos;
4921 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
4922 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
4923 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
4925 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
4927 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
4929 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
4930 &deco_bitmap, &deco_x, &deco_y);
4931 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
4932 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
4935 gi = CreateGadget(GDI_CUSTOM_ID, id,
4936 GDI_INFO_TEXT, toolbutton_info[i].infotext,
4937 GDI_X, DX + toolbutton_info[i].x,
4938 GDI_Y, DY + toolbutton_info[i].y,
4939 GDI_WIDTH, toolbutton_info[i].width,
4940 GDI_HEIGHT, toolbutton_info[i].height,
4941 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
4942 GDI_STATE, GD_BUTTON_UNPRESSED,
4943 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
4944 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
4945 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
4946 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
4947 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
4948 GDI_DECORATION_SHIFTING, 1, 1,
4949 GDI_DIRECT_DRAW, FALSE,
4950 GDI_EVENT_MASK, event_mask,
4951 GDI_CALLBACK_ACTION, HandleToolButtons,
4955 Error(ERR_EXIT, "cannot create gadget");
4957 tool_gadget[id] = gi;
4963 void FreeToolButtons()
4967 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4968 FreeGadget(tool_gadget[i]);
4971 static void UnmapToolButtons()
4975 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4976 UnmapGadget(tool_gadget[i]);
4979 static void HandleToolButtons(struct GadgetInfo *gi)
4981 request_gadget_id = gi->custom_id;
4984 static struct Mapping_EM_to_RND_object
4987 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
4988 boolean is_backside; /* backside of moving element */
4994 em_object_mapping_list[] =
4997 Xblank, TRUE, FALSE,
5001 Yacid_splash_eB, FALSE, FALSE,
5002 EL_ACID_SPLASH_RIGHT, -1, -1
5005 Yacid_splash_wB, FALSE, FALSE,
5006 EL_ACID_SPLASH_LEFT, -1, -1
5009 #ifdef EM_ENGINE_BAD_ROLL
5011 Xstone_force_e, FALSE, FALSE,
5012 EL_ROCK, -1, MV_BIT_RIGHT
5015 Xstone_force_w, FALSE, FALSE,
5016 EL_ROCK, -1, MV_BIT_LEFT
5019 Xnut_force_e, FALSE, FALSE,
5020 EL_NUT, -1, MV_BIT_RIGHT
5023 Xnut_force_w, FALSE, FALSE,
5024 EL_NUT, -1, MV_BIT_LEFT
5027 Xspring_force_e, FALSE, FALSE,
5028 EL_SPRING, -1, MV_BIT_RIGHT
5031 Xspring_force_w, FALSE, FALSE,
5032 EL_SPRING, -1, MV_BIT_LEFT
5035 Xemerald_force_e, FALSE, FALSE,
5036 EL_EMERALD, -1, MV_BIT_RIGHT
5039 Xemerald_force_w, FALSE, FALSE,
5040 EL_EMERALD, -1, MV_BIT_LEFT
5043 Xdiamond_force_e, FALSE, FALSE,
5044 EL_DIAMOND, -1, MV_BIT_RIGHT
5047 Xdiamond_force_w, FALSE, FALSE,
5048 EL_DIAMOND, -1, MV_BIT_LEFT
5051 Xbomb_force_e, FALSE, FALSE,
5052 EL_BOMB, -1, MV_BIT_RIGHT
5055 Xbomb_force_w, FALSE, FALSE,
5056 EL_BOMB, -1, MV_BIT_LEFT
5058 #endif /* EM_ENGINE_BAD_ROLL */
5061 Xstone, TRUE, FALSE,
5065 Xstone_pause, FALSE, FALSE,
5069 Xstone_fall, FALSE, FALSE,
5073 Ystone_s, FALSE, FALSE,
5074 EL_ROCK, ACTION_FALLING, -1
5077 Ystone_sB, FALSE, TRUE,
5078 EL_ROCK, ACTION_FALLING, -1
5081 Ystone_e, FALSE, FALSE,
5082 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
5085 Ystone_eB, FALSE, TRUE,
5086 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
5089 Ystone_w, FALSE, FALSE,
5090 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
5093 Ystone_wB, FALSE, TRUE,
5094 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
5101 Xnut_pause, FALSE, FALSE,
5105 Xnut_fall, FALSE, FALSE,
5109 Ynut_s, FALSE, FALSE,
5110 EL_NUT, ACTION_FALLING, -1
5113 Ynut_sB, FALSE, TRUE,
5114 EL_NUT, ACTION_FALLING, -1
5117 Ynut_e, FALSE, FALSE,
5118 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
5121 Ynut_eB, FALSE, TRUE,
5122 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
5125 Ynut_w, FALSE, FALSE,
5126 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
5129 Ynut_wB, FALSE, TRUE,
5130 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
5133 Xbug_n, TRUE, FALSE,
5137 Xbug_e, TRUE, FALSE,
5138 EL_BUG_RIGHT, -1, -1
5141 Xbug_s, TRUE, FALSE,
5145 Xbug_w, TRUE, FALSE,
5149 Xbug_gon, FALSE, FALSE,
5153 Xbug_goe, FALSE, FALSE,
5154 EL_BUG_RIGHT, -1, -1
5157 Xbug_gos, FALSE, FALSE,
5161 Xbug_gow, FALSE, FALSE,
5165 Ybug_n, FALSE, FALSE,
5166 EL_BUG, ACTION_MOVING, MV_BIT_UP
5169 Ybug_nB, FALSE, TRUE,
5170 EL_BUG, ACTION_MOVING, MV_BIT_UP
5173 Ybug_e, FALSE, FALSE,
5174 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
5177 Ybug_eB, FALSE, TRUE,
5178 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
5181 Ybug_s, FALSE, FALSE,
5182 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
5185 Ybug_sB, FALSE, TRUE,
5186 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
5189 Ybug_w, FALSE, FALSE,
5190 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
5193 Ybug_wB, FALSE, TRUE,
5194 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
5197 Ybug_w_n, FALSE, FALSE,
5198 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
5201 Ybug_n_e, FALSE, FALSE,
5202 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
5205 Ybug_e_s, FALSE, FALSE,
5206 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
5209 Ybug_s_w, FALSE, FALSE,
5210 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
5213 Ybug_e_n, FALSE, FALSE,
5214 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
5217 Ybug_s_e, FALSE, FALSE,
5218 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
5221 Ybug_w_s, FALSE, FALSE,
5222 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
5225 Ybug_n_w, FALSE, FALSE,
5226 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
5229 Ybug_stone, FALSE, FALSE,
5230 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
5233 Ybug_spring, FALSE, FALSE,
5234 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
5237 Xtank_n, TRUE, FALSE,
5238 EL_SPACESHIP_UP, -1, -1
5241 Xtank_e, TRUE, FALSE,
5242 EL_SPACESHIP_RIGHT, -1, -1
5245 Xtank_s, TRUE, FALSE,
5246 EL_SPACESHIP_DOWN, -1, -1
5249 Xtank_w, TRUE, FALSE,
5250 EL_SPACESHIP_LEFT, -1, -1
5253 Xtank_gon, FALSE, FALSE,
5254 EL_SPACESHIP_UP, -1, -1
5257 Xtank_goe, FALSE, FALSE,
5258 EL_SPACESHIP_RIGHT, -1, -1
5261 Xtank_gos, FALSE, FALSE,
5262 EL_SPACESHIP_DOWN, -1, -1
5265 Xtank_gow, FALSE, FALSE,
5266 EL_SPACESHIP_LEFT, -1, -1
5269 Ytank_n, FALSE, FALSE,
5270 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
5273 Ytank_nB, FALSE, TRUE,
5274 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
5277 Ytank_e, FALSE, FALSE,
5278 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
5281 Ytank_eB, FALSE, TRUE,
5282 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
5285 Ytank_s, FALSE, FALSE,
5286 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
5289 Ytank_sB, FALSE, TRUE,
5290 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
5293 Ytank_w, FALSE, FALSE,
5294 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
5297 Ytank_wB, FALSE, TRUE,
5298 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
5301 Ytank_w_n, FALSE, FALSE,
5302 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
5305 Ytank_n_e, FALSE, FALSE,
5306 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
5309 Ytank_e_s, FALSE, FALSE,
5310 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
5313 Ytank_s_w, FALSE, FALSE,
5314 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
5317 Ytank_e_n, FALSE, FALSE,
5318 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
5321 Ytank_s_e, FALSE, FALSE,
5322 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
5325 Ytank_w_s, FALSE, FALSE,
5326 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
5329 Ytank_n_w, FALSE, FALSE,
5330 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
5333 Ytank_stone, FALSE, FALSE,
5334 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
5337 Ytank_spring, FALSE, FALSE,
5338 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
5341 Xandroid, TRUE, FALSE,
5342 EL_EMC_ANDROID, ACTION_ACTIVE, -1
5345 Xandroid_1_n, FALSE, FALSE,
5346 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
5349 Xandroid_2_n, FALSE, FALSE,
5350 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
5353 Xandroid_1_e, FALSE, FALSE,
5354 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
5357 Xandroid_2_e, FALSE, FALSE,
5358 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
5361 Xandroid_1_w, FALSE, FALSE,
5362 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
5365 Xandroid_2_w, FALSE, FALSE,
5366 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
5369 Xandroid_1_s, FALSE, FALSE,
5370 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
5373 Xandroid_2_s, FALSE, FALSE,
5374 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
5377 Yandroid_n, FALSE, FALSE,
5378 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
5381 Yandroid_nB, FALSE, TRUE,
5382 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
5385 Yandroid_ne, FALSE, FALSE,
5386 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
5389 Yandroid_neB, FALSE, TRUE,
5390 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
5393 Yandroid_e, FALSE, FALSE,
5394 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
5397 Yandroid_eB, FALSE, TRUE,
5398 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
5401 Yandroid_se, FALSE, FALSE,
5402 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
5405 Yandroid_seB, FALSE, TRUE,
5406 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
5409 Yandroid_s, FALSE, FALSE,
5410 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
5413 Yandroid_sB, FALSE, TRUE,
5414 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
5417 Yandroid_sw, FALSE, FALSE,
5418 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
5421 Yandroid_swB, FALSE, TRUE,
5422 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
5425 Yandroid_w, FALSE, FALSE,
5426 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
5429 Yandroid_wB, FALSE, TRUE,
5430 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
5433 Yandroid_nw, FALSE, FALSE,
5434 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
5437 Yandroid_nwB, FALSE, TRUE,
5438 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
5441 Xspring, TRUE, FALSE,
5445 Xspring_pause, FALSE, FALSE,
5449 Xspring_e, FALSE, FALSE,
5453 Xspring_w, FALSE, FALSE,
5457 Xspring_fall, FALSE, FALSE,
5461 Yspring_s, FALSE, FALSE,
5462 EL_SPRING, ACTION_FALLING, -1
5465 Yspring_sB, FALSE, TRUE,
5466 EL_SPRING, ACTION_FALLING, -1
5469 Yspring_e, FALSE, FALSE,
5470 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
5473 Yspring_eB, FALSE, TRUE,
5474 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
5477 Yspring_w, FALSE, FALSE,
5478 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
5481 Yspring_wB, FALSE, TRUE,
5482 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
5485 Yspring_kill_e, FALSE, FALSE,
5486 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
5489 Yspring_kill_eB, FALSE, TRUE,
5490 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
5493 Yspring_kill_w, FALSE, FALSE,
5494 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
5497 Yspring_kill_wB, FALSE, TRUE,
5498 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
5501 Xeater_n, TRUE, FALSE,
5502 EL_YAMYAM_UP, -1, -1
5505 Xeater_e, TRUE, FALSE,
5506 EL_YAMYAM_RIGHT, -1, -1
5509 Xeater_w, TRUE, FALSE,
5510 EL_YAMYAM_LEFT, -1, -1
5513 Xeater_s, TRUE, FALSE,
5514 EL_YAMYAM_DOWN, -1, -1
5517 Yeater_n, FALSE, FALSE,
5518 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
5521 Yeater_nB, FALSE, TRUE,
5522 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
5525 Yeater_e, FALSE, FALSE,
5526 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
5529 Yeater_eB, FALSE, TRUE,
5530 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
5533 Yeater_s, FALSE, FALSE,
5534 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
5537 Yeater_sB, FALSE, TRUE,
5538 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
5541 Yeater_w, FALSE, FALSE,
5542 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
5545 Yeater_wB, FALSE, TRUE,
5546 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
5549 Yeater_stone, FALSE, FALSE,
5550 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
5553 Yeater_spring, FALSE, FALSE,
5554 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
5557 Xalien, TRUE, FALSE,
5561 Xalien_pause, FALSE, FALSE,
5565 Yalien_n, FALSE, FALSE,
5566 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
5569 Yalien_nB, FALSE, TRUE,
5570 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
5573 Yalien_e, FALSE, FALSE,
5574 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
5577 Yalien_eB, FALSE, TRUE,
5578 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
5581 Yalien_s, FALSE, FALSE,
5582 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
5585 Yalien_sB, FALSE, TRUE,
5586 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
5589 Yalien_w, FALSE, FALSE,
5590 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
5593 Yalien_wB, FALSE, TRUE,
5594 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
5597 Yalien_stone, FALSE, FALSE,
5598 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
5601 Yalien_spring, FALSE, FALSE,
5602 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
5605 Xemerald, TRUE, FALSE,
5609 Xemerald_pause, FALSE, FALSE,
5613 Xemerald_fall, FALSE, FALSE,
5617 Xemerald_shine, FALSE, FALSE,
5618 EL_EMERALD, ACTION_TWINKLING, -1
5621 Yemerald_s, FALSE, FALSE,
5622 EL_EMERALD, ACTION_FALLING, -1
5625 Yemerald_sB, FALSE, TRUE,
5626 EL_EMERALD, ACTION_FALLING, -1
5629 Yemerald_e, FALSE, FALSE,
5630 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
5633 Yemerald_eB, FALSE, TRUE,
5634 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
5637 Yemerald_w, FALSE, FALSE,
5638 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
5641 Yemerald_wB, FALSE, TRUE,
5642 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
5645 Yemerald_eat, FALSE, FALSE,
5646 EL_EMERALD, ACTION_COLLECTING, -1
5649 Yemerald_stone, FALSE, FALSE,
5650 EL_NUT, ACTION_BREAKING, -1
5653 Xdiamond, TRUE, FALSE,
5657 Xdiamond_pause, FALSE, FALSE,
5661 Xdiamond_fall, FALSE, FALSE,
5665 Xdiamond_shine, FALSE, FALSE,
5666 EL_DIAMOND, ACTION_TWINKLING, -1
5669 Ydiamond_s, FALSE, FALSE,
5670 EL_DIAMOND, ACTION_FALLING, -1
5673 Ydiamond_sB, FALSE, TRUE,
5674 EL_DIAMOND, ACTION_FALLING, -1
5677 Ydiamond_e, FALSE, FALSE,
5678 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
5681 Ydiamond_eB, FALSE, TRUE,
5682 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
5685 Ydiamond_w, FALSE, FALSE,
5686 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
5689 Ydiamond_wB, FALSE, TRUE,
5690 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
5693 Ydiamond_eat, FALSE, FALSE,
5694 EL_DIAMOND, ACTION_COLLECTING, -1
5697 Ydiamond_stone, FALSE, FALSE,
5698 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
5701 Xdrip_fall, TRUE, FALSE,
5702 EL_AMOEBA_DROP, -1, -1
5705 Xdrip_stretch, FALSE, FALSE,
5706 EL_AMOEBA_DROP, ACTION_FALLING, -1
5709 Xdrip_stretchB, FALSE, TRUE,
5710 EL_AMOEBA_DROP, ACTION_FALLING, -1
5713 Xdrip_eat, FALSE, FALSE,
5714 EL_AMOEBA_DROP, ACTION_GROWING, -1
5717 Ydrip_s1, FALSE, FALSE,
5718 EL_AMOEBA_DROP, ACTION_FALLING, -1
5721 Ydrip_s1B, FALSE, TRUE,
5722 EL_AMOEBA_DROP, ACTION_FALLING, -1
5725 Ydrip_s2, FALSE, FALSE,
5726 EL_AMOEBA_DROP, ACTION_FALLING, -1
5729 Ydrip_s2B, FALSE, TRUE,
5730 EL_AMOEBA_DROP, ACTION_FALLING, -1
5737 Xbomb_pause, FALSE, FALSE,
5741 Xbomb_fall, FALSE, FALSE,
5745 Ybomb_s, FALSE, FALSE,
5746 EL_BOMB, ACTION_FALLING, -1
5749 Ybomb_sB, FALSE, TRUE,
5750 EL_BOMB, ACTION_FALLING, -1
5753 Ybomb_e, FALSE, FALSE,
5754 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
5757 Ybomb_eB, FALSE, TRUE,
5758 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
5761 Ybomb_w, FALSE, FALSE,
5762 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
5765 Ybomb_wB, FALSE, TRUE,
5766 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
5769 Ybomb_eat, FALSE, FALSE,
5770 EL_BOMB, ACTION_ACTIVATING, -1
5773 Xballoon, TRUE, FALSE,
5777 Yballoon_n, FALSE, FALSE,
5778 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
5781 Yballoon_nB, FALSE, TRUE,
5782 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
5785 Yballoon_e, FALSE, FALSE,
5786 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
5789 Yballoon_eB, FALSE, TRUE,
5790 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
5793 Yballoon_s, FALSE, FALSE,
5794 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
5797 Yballoon_sB, FALSE, TRUE,
5798 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
5801 Yballoon_w, FALSE, FALSE,
5802 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
5805 Yballoon_wB, FALSE, TRUE,
5806 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
5809 Xgrass, TRUE, FALSE,
5810 EL_EMC_GRASS, -1, -1
5813 Ygrass_nB, FALSE, FALSE,
5814 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
5817 Ygrass_eB, FALSE, FALSE,
5818 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
5821 Ygrass_sB, FALSE, FALSE,
5822 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
5825 Ygrass_wB, FALSE, FALSE,
5826 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
5833 Ydirt_nB, FALSE, FALSE,
5834 EL_SAND, ACTION_DIGGING, MV_BIT_UP
5837 Ydirt_eB, FALSE, FALSE,
5838 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
5841 Ydirt_sB, FALSE, FALSE,
5842 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
5845 Ydirt_wB, FALSE, FALSE,
5846 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
5849 Xacid_ne, TRUE, FALSE,
5850 EL_ACID_POOL_TOPRIGHT, -1, -1
5853 Xacid_se, TRUE, FALSE,
5854 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
5857 Xacid_s, TRUE, FALSE,
5858 EL_ACID_POOL_BOTTOM, -1, -1
5861 Xacid_sw, TRUE, FALSE,
5862 EL_ACID_POOL_BOTTOMLEFT, -1, -1
5865 Xacid_nw, TRUE, FALSE,
5866 EL_ACID_POOL_TOPLEFT, -1, -1
5869 Xacid_1, TRUE, FALSE,
5873 Xacid_2, FALSE, FALSE,
5877 Xacid_3, FALSE, FALSE,
5881 Xacid_4, FALSE, FALSE,
5885 Xacid_5, FALSE, FALSE,
5889 Xacid_6, FALSE, FALSE,
5893 Xacid_7, FALSE, FALSE,
5897 Xacid_8, FALSE, FALSE,
5901 Xball_1, TRUE, FALSE,
5902 EL_EMC_MAGIC_BALL, -1, -1
5905 Xball_1B, FALSE, FALSE,
5906 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
5909 Xball_2, FALSE, FALSE,
5910 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
5913 Xball_2B, FALSE, FALSE,
5914 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
5917 Yball_eat, FALSE, FALSE,
5918 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
5921 Ykey_1_eat, FALSE, FALSE,
5922 EL_EM_KEY_1, ACTION_COLLECTING, -1
5925 Ykey_2_eat, FALSE, FALSE,
5926 EL_EM_KEY_2, ACTION_COLLECTING, -1
5929 Ykey_3_eat, FALSE, FALSE,
5930 EL_EM_KEY_3, ACTION_COLLECTING, -1
5933 Ykey_4_eat, FALSE, FALSE,
5934 EL_EM_KEY_4, ACTION_COLLECTING, -1
5937 Ykey_5_eat, FALSE, FALSE,
5938 EL_EMC_KEY_5, ACTION_COLLECTING, -1
5941 Ykey_6_eat, FALSE, FALSE,
5942 EL_EMC_KEY_6, ACTION_COLLECTING, -1
5945 Ykey_7_eat, FALSE, FALSE,
5946 EL_EMC_KEY_7, ACTION_COLLECTING, -1
5949 Ykey_8_eat, FALSE, FALSE,
5950 EL_EMC_KEY_8, ACTION_COLLECTING, -1
5953 Ylenses_eat, FALSE, FALSE,
5954 EL_EMC_LENSES, ACTION_COLLECTING, -1
5957 Ymagnify_eat, FALSE, FALSE,
5958 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
5961 Ygrass_eat, FALSE, FALSE,
5962 EL_EMC_GRASS, ACTION_SNAPPING, -1
5965 Ydirt_eat, FALSE, FALSE,
5966 EL_SAND, ACTION_SNAPPING, -1
5969 Xgrow_ns, TRUE, FALSE,
5970 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
5973 Ygrow_ns_eat, FALSE, FALSE,
5974 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
5977 Xgrow_ew, TRUE, FALSE,
5978 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
5981 Ygrow_ew_eat, FALSE, FALSE,
5982 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
5985 Xwonderwall, TRUE, FALSE,
5986 EL_MAGIC_WALL, -1, -1
5989 XwonderwallB, FALSE, FALSE,
5990 EL_MAGIC_WALL, ACTION_ACTIVE, -1
5993 Xamoeba_1, TRUE, FALSE,
5994 EL_AMOEBA_DRY, ACTION_OTHER, -1
5997 Xamoeba_2, FALSE, FALSE,
5998 EL_AMOEBA_DRY, ACTION_OTHER, -1
6001 Xamoeba_3, FALSE, FALSE,
6002 EL_AMOEBA_DRY, ACTION_OTHER, -1
6005 Xamoeba_4, FALSE, FALSE,
6006 EL_AMOEBA_DRY, ACTION_OTHER, -1
6009 Xamoeba_5, TRUE, FALSE,
6010 EL_AMOEBA_WET, ACTION_OTHER, -1
6013 Xamoeba_6, FALSE, FALSE,
6014 EL_AMOEBA_WET, ACTION_OTHER, -1
6017 Xamoeba_7, FALSE, FALSE,
6018 EL_AMOEBA_WET, ACTION_OTHER, -1
6021 Xamoeba_8, FALSE, FALSE,
6022 EL_AMOEBA_WET, ACTION_OTHER, -1
6025 Xdoor_1, TRUE, FALSE,
6026 EL_EM_GATE_1, -1, -1
6029 Xdoor_2, TRUE, FALSE,
6030 EL_EM_GATE_2, -1, -1
6033 Xdoor_3, TRUE, FALSE,
6034 EL_EM_GATE_3, -1, -1
6037 Xdoor_4, TRUE, FALSE,
6038 EL_EM_GATE_4, -1, -1
6041 Xdoor_5, TRUE, FALSE,
6042 EL_EMC_GATE_5, -1, -1
6045 Xdoor_6, TRUE, FALSE,
6046 EL_EMC_GATE_6, -1, -1
6049 Xdoor_7, TRUE, FALSE,
6050 EL_EMC_GATE_7, -1, -1
6053 Xdoor_8, TRUE, FALSE,
6054 EL_EMC_GATE_8, -1, -1
6057 Xkey_1, TRUE, FALSE,
6061 Xkey_2, TRUE, FALSE,
6065 Xkey_3, TRUE, FALSE,
6069 Xkey_4, TRUE, FALSE,
6073 Xkey_5, TRUE, FALSE,
6074 EL_EMC_KEY_5, -1, -1
6077 Xkey_6, TRUE, FALSE,
6078 EL_EMC_KEY_6, -1, -1
6081 Xkey_7, TRUE, FALSE,
6082 EL_EMC_KEY_7, -1, -1
6085 Xkey_8, TRUE, FALSE,
6086 EL_EMC_KEY_8, -1, -1
6089 Xwind_n, TRUE, FALSE,
6090 EL_BALLOON_SWITCH_UP, -1, -1
6093 Xwind_e, TRUE, FALSE,
6094 EL_BALLOON_SWITCH_RIGHT, -1, -1
6097 Xwind_s, TRUE, FALSE,
6098 EL_BALLOON_SWITCH_DOWN, -1, -1
6101 Xwind_w, TRUE, FALSE,
6102 EL_BALLOON_SWITCH_LEFT, -1, -1
6105 Xwind_nesw, TRUE, FALSE,
6106 EL_BALLOON_SWITCH_ANY, -1, -1
6109 Xwind_stop, TRUE, FALSE,
6110 EL_BALLOON_SWITCH_NONE, -1, -1
6114 EL_EM_EXIT_CLOSED, -1, -1
6117 Xexit_1, TRUE, FALSE,
6118 EL_EM_EXIT_OPEN, -1, -1
6121 Xexit_2, FALSE, FALSE,
6122 EL_EM_EXIT_OPEN, -1, -1
6125 Xexit_3, FALSE, FALSE,
6126 EL_EM_EXIT_OPEN, -1, -1
6129 Xdynamite, TRUE, FALSE,
6130 EL_EM_DYNAMITE, -1, -1
6133 Ydynamite_eat, FALSE, FALSE,
6134 EL_EM_DYNAMITE, ACTION_COLLECTING, -1
6137 Xdynamite_1, TRUE, FALSE,
6138 EL_EM_DYNAMITE_ACTIVE, -1, -1
6141 Xdynamite_2, FALSE, FALSE,
6142 EL_EM_DYNAMITE_ACTIVE, -1, -1
6145 Xdynamite_3, FALSE, FALSE,
6146 EL_EM_DYNAMITE_ACTIVE, -1, -1
6149 Xdynamite_4, FALSE, FALSE,
6150 EL_EM_DYNAMITE_ACTIVE, -1, -1
6153 Xbumper, TRUE, FALSE,
6154 EL_EMC_SPRING_BUMPER, -1, -1
6157 XbumperB, FALSE, FALSE,
6158 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
6161 Xwheel, TRUE, FALSE,
6162 EL_ROBOT_WHEEL, -1, -1
6165 XwheelB, FALSE, FALSE,
6166 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
6169 Xswitch, TRUE, FALSE,
6170 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
6173 XswitchB, FALSE, FALSE,
6174 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
6178 EL_QUICKSAND_EMPTY, -1, -1
6181 Xsand_stone, TRUE, FALSE,
6182 EL_QUICKSAND_FULL, -1, -1
6185 Xsand_stonein_1, FALSE, TRUE,
6186 EL_ROCK, ACTION_FILLING, -1
6189 Xsand_stonein_2, FALSE, TRUE,
6190 EL_ROCK, ACTION_FILLING, -1
6193 Xsand_stonein_3, FALSE, TRUE,
6194 EL_ROCK, ACTION_FILLING, -1
6197 Xsand_stonein_4, FALSE, TRUE,
6198 EL_ROCK, ACTION_FILLING, -1
6202 Xsand_stonesand_1, FALSE, FALSE,
6203 EL_QUICKSAND_EMPTYING, -1, -1
6206 Xsand_stonesand_2, FALSE, FALSE,
6207 EL_QUICKSAND_EMPTYING, -1, -1
6210 Xsand_stonesand_3, FALSE, FALSE,
6211 EL_QUICKSAND_EMPTYING, -1, -1
6214 Xsand_stonesand_4, FALSE, FALSE,
6215 EL_QUICKSAND_EMPTYING, -1, -1
6218 Xsand_stonesand_quickout_1, FALSE, FALSE,
6219 EL_QUICKSAND_EMPTYING, -1, -1
6222 Xsand_stonesand_quickout_2, FALSE, FALSE,
6223 EL_QUICKSAND_EMPTYING, -1, -1
6227 Xsand_stonesand_1, FALSE, FALSE,
6228 EL_QUICKSAND_FULL, -1, -1
6231 Xsand_stonesand_2, FALSE, FALSE,
6232 EL_QUICKSAND_FULL, -1, -1
6235 Xsand_stonesand_3, FALSE, FALSE,
6236 EL_QUICKSAND_FULL, -1, -1
6239 Xsand_stonesand_4, FALSE, FALSE,
6240 EL_QUICKSAND_FULL, -1, -1
6244 Xsand_stoneout_1, FALSE, FALSE,
6245 EL_ROCK, ACTION_EMPTYING, -1
6248 Xsand_stoneout_2, FALSE, FALSE,
6249 EL_ROCK, ACTION_EMPTYING, -1
6253 Xsand_sandstone_1, FALSE, FALSE,
6254 EL_QUICKSAND_FILLING, -1, -1
6257 Xsand_sandstone_2, FALSE, FALSE,
6258 EL_QUICKSAND_FILLING, -1, -1
6261 Xsand_sandstone_3, FALSE, FALSE,
6262 EL_QUICKSAND_FILLING, -1, -1
6265 Xsand_sandstone_4, FALSE, FALSE,
6266 EL_QUICKSAND_FILLING, -1, -1
6270 Xsand_sandstone_1, FALSE, FALSE,
6271 EL_QUICKSAND_FULL, -1, -1
6274 Xsand_sandstone_2, FALSE, FALSE,
6275 EL_QUICKSAND_FULL, -1, -1
6278 Xsand_sandstone_3, FALSE, FALSE,
6279 EL_QUICKSAND_FULL, -1, -1
6282 Xsand_sandstone_4, FALSE, FALSE,
6283 EL_QUICKSAND_FULL, -1, -1
6287 Xplant, TRUE, FALSE,
6288 EL_EMC_PLANT, -1, -1
6291 Yplant, FALSE, FALSE,
6292 EL_EMC_PLANT, -1, -1
6295 Xlenses, TRUE, FALSE,
6296 EL_EMC_LENSES, -1, -1
6299 Xmagnify, TRUE, FALSE,
6300 EL_EMC_MAGNIFIER, -1, -1
6303 Xdripper, TRUE, FALSE,
6304 EL_EMC_DRIPPER, -1, -1
6307 XdripperB, FALSE, FALSE,
6308 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
6311 Xfake_blank, TRUE, FALSE,
6312 EL_INVISIBLE_WALL, -1, -1
6315 Xfake_blankB, FALSE, FALSE,
6316 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
6319 Xfake_grass, TRUE, FALSE,
6320 EL_EMC_FAKE_GRASS, -1, -1
6323 Xfake_grassB, FALSE, FALSE,
6324 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
6327 Xfake_door_1, TRUE, FALSE,
6328 EL_EM_GATE_1_GRAY, -1, -1
6331 Xfake_door_2, TRUE, FALSE,
6332 EL_EM_GATE_2_GRAY, -1, -1
6335 Xfake_door_3, TRUE, FALSE,
6336 EL_EM_GATE_3_GRAY, -1, -1
6339 Xfake_door_4, TRUE, FALSE,
6340 EL_EM_GATE_4_GRAY, -1, -1
6343 Xfake_door_5, TRUE, FALSE,
6344 EL_EMC_GATE_5_GRAY, -1, -1
6347 Xfake_door_6, TRUE, FALSE,
6348 EL_EMC_GATE_6_GRAY, -1, -1
6351 Xfake_door_7, TRUE, FALSE,
6352 EL_EMC_GATE_7_GRAY, -1, -1
6355 Xfake_door_8, TRUE, FALSE,
6356 EL_EMC_GATE_8_GRAY, -1, -1
6359 Xfake_acid_1, TRUE, FALSE,
6360 EL_EMC_FAKE_ACID, -1, -1
6363 Xfake_acid_2, FALSE, FALSE,
6364 EL_EMC_FAKE_ACID, -1, -1
6367 Xfake_acid_3, FALSE, FALSE,
6368 EL_EMC_FAKE_ACID, -1, -1
6371 Xfake_acid_4, FALSE, FALSE,
6372 EL_EMC_FAKE_ACID, -1, -1
6375 Xfake_acid_5, FALSE, FALSE,
6376 EL_EMC_FAKE_ACID, -1, -1
6379 Xfake_acid_6, FALSE, FALSE,
6380 EL_EMC_FAKE_ACID, -1, -1
6383 Xfake_acid_7, FALSE, FALSE,
6384 EL_EMC_FAKE_ACID, -1, -1
6387 Xfake_acid_8, FALSE, FALSE,
6388 EL_EMC_FAKE_ACID, -1, -1
6391 Xsteel_1, TRUE, FALSE,
6392 EL_STEELWALL, -1, -1
6395 Xsteel_2, TRUE, FALSE,
6396 EL_EMC_STEELWALL_2, -1, -1
6399 Xsteel_3, TRUE, FALSE,
6400 EL_EMC_STEELWALL_3, -1, -1
6403 Xsteel_4, TRUE, FALSE,
6404 EL_EMC_STEELWALL_4, -1, -1
6407 Xwall_1, TRUE, FALSE,
6411 Xwall_2, TRUE, FALSE,
6412 EL_EMC_WALL_14, -1, -1
6415 Xwall_3, TRUE, FALSE,
6416 EL_EMC_WALL_15, -1, -1
6419 Xwall_4, TRUE, FALSE,
6420 EL_EMC_WALL_16, -1, -1
6423 Xround_wall_1, TRUE, FALSE,
6424 EL_WALL_SLIPPERY, -1, -1
6427 Xround_wall_2, TRUE, FALSE,
6428 EL_EMC_WALL_SLIPPERY_2, -1, -1
6431 Xround_wall_3, TRUE, FALSE,
6432 EL_EMC_WALL_SLIPPERY_3, -1, -1
6435 Xround_wall_4, TRUE, FALSE,
6436 EL_EMC_WALL_SLIPPERY_4, -1, -1
6439 Xdecor_1, TRUE, FALSE,
6440 EL_EMC_WALL_8, -1, -1
6443 Xdecor_2, TRUE, FALSE,
6444 EL_EMC_WALL_6, -1, -1
6447 Xdecor_3, TRUE, FALSE,
6448 EL_EMC_WALL_4, -1, -1
6451 Xdecor_4, TRUE, FALSE,
6452 EL_EMC_WALL_7, -1, -1
6455 Xdecor_5, TRUE, FALSE,
6456 EL_EMC_WALL_5, -1, -1
6459 Xdecor_6, TRUE, FALSE,
6460 EL_EMC_WALL_9, -1, -1
6463 Xdecor_7, TRUE, FALSE,
6464 EL_EMC_WALL_10, -1, -1
6467 Xdecor_8, TRUE, FALSE,
6468 EL_EMC_WALL_1, -1, -1
6471 Xdecor_9, TRUE, FALSE,
6472 EL_EMC_WALL_2, -1, -1
6475 Xdecor_10, TRUE, FALSE,
6476 EL_EMC_WALL_3, -1, -1
6479 Xdecor_11, TRUE, FALSE,
6480 EL_EMC_WALL_11, -1, -1
6483 Xdecor_12, TRUE, FALSE,
6484 EL_EMC_WALL_12, -1, -1
6487 Xalpha_0, TRUE, FALSE,
6488 EL_CHAR('0'), -1, -1
6491 Xalpha_1, TRUE, FALSE,
6492 EL_CHAR('1'), -1, -1
6495 Xalpha_2, TRUE, FALSE,
6496 EL_CHAR('2'), -1, -1
6499 Xalpha_3, TRUE, FALSE,
6500 EL_CHAR('3'), -1, -1
6503 Xalpha_4, TRUE, FALSE,
6504 EL_CHAR('4'), -1, -1
6507 Xalpha_5, TRUE, FALSE,
6508 EL_CHAR('5'), -1, -1
6511 Xalpha_6, TRUE, FALSE,
6512 EL_CHAR('6'), -1, -1
6515 Xalpha_7, TRUE, FALSE,
6516 EL_CHAR('7'), -1, -1
6519 Xalpha_8, TRUE, FALSE,
6520 EL_CHAR('8'), -1, -1
6523 Xalpha_9, TRUE, FALSE,
6524 EL_CHAR('9'), -1, -1
6527 Xalpha_excla, TRUE, FALSE,
6528 EL_CHAR('!'), -1, -1
6531 Xalpha_quote, TRUE, FALSE,
6532 EL_CHAR('"'), -1, -1
6535 Xalpha_comma, TRUE, FALSE,
6536 EL_CHAR(','), -1, -1
6539 Xalpha_minus, TRUE, FALSE,
6540 EL_CHAR('-'), -1, -1
6543 Xalpha_perio, TRUE, FALSE,
6544 EL_CHAR('.'), -1, -1
6547 Xalpha_colon, TRUE, FALSE,
6548 EL_CHAR(':'), -1, -1
6551 Xalpha_quest, TRUE, FALSE,
6552 EL_CHAR('?'), -1, -1
6555 Xalpha_a, TRUE, FALSE,
6556 EL_CHAR('A'), -1, -1
6559 Xalpha_b, TRUE, FALSE,
6560 EL_CHAR('B'), -1, -1
6563 Xalpha_c, TRUE, FALSE,
6564 EL_CHAR('C'), -1, -1
6567 Xalpha_d, TRUE, FALSE,
6568 EL_CHAR('D'), -1, -1
6571 Xalpha_e, TRUE, FALSE,
6572 EL_CHAR('E'), -1, -1
6575 Xalpha_f, TRUE, FALSE,
6576 EL_CHAR('F'), -1, -1
6579 Xalpha_g, TRUE, FALSE,
6580 EL_CHAR('G'), -1, -1
6583 Xalpha_h, TRUE, FALSE,
6584 EL_CHAR('H'), -1, -1
6587 Xalpha_i, TRUE, FALSE,
6588 EL_CHAR('I'), -1, -1
6591 Xalpha_j, TRUE, FALSE,
6592 EL_CHAR('J'), -1, -1
6595 Xalpha_k, TRUE, FALSE,
6596 EL_CHAR('K'), -1, -1
6599 Xalpha_l, TRUE, FALSE,
6600 EL_CHAR('L'), -1, -1
6603 Xalpha_m, TRUE, FALSE,
6604 EL_CHAR('M'), -1, -1
6607 Xalpha_n, TRUE, FALSE,
6608 EL_CHAR('N'), -1, -1
6611 Xalpha_o, TRUE, FALSE,
6612 EL_CHAR('O'), -1, -1
6615 Xalpha_p, TRUE, FALSE,
6616 EL_CHAR('P'), -1, -1
6619 Xalpha_q, TRUE, FALSE,
6620 EL_CHAR('Q'), -1, -1
6623 Xalpha_r, TRUE, FALSE,
6624 EL_CHAR('R'), -1, -1
6627 Xalpha_s, TRUE, FALSE,
6628 EL_CHAR('S'), -1, -1
6631 Xalpha_t, TRUE, FALSE,
6632 EL_CHAR('T'), -1, -1
6635 Xalpha_u, TRUE, FALSE,
6636 EL_CHAR('U'), -1, -1
6639 Xalpha_v, TRUE, FALSE,
6640 EL_CHAR('V'), -1, -1
6643 Xalpha_w, TRUE, FALSE,
6644 EL_CHAR('W'), -1, -1
6647 Xalpha_x, TRUE, FALSE,
6648 EL_CHAR('X'), -1, -1
6651 Xalpha_y, TRUE, FALSE,
6652 EL_CHAR('Y'), -1, -1
6655 Xalpha_z, TRUE, FALSE,
6656 EL_CHAR('Z'), -1, -1
6659 Xalpha_arrow_e, TRUE, FALSE,
6660 EL_CHAR('>'), -1, -1
6663 Xalpha_arrow_w, TRUE, FALSE,
6664 EL_CHAR('<'), -1, -1
6667 Xalpha_copyr, TRUE, FALSE,
6668 EL_CHAR('©'), -1, -1
6672 Xboom_bug, FALSE, FALSE,
6673 EL_BUG, ACTION_EXPLODING, -1
6676 Xboom_bomb, FALSE, FALSE,
6677 EL_BOMB, ACTION_EXPLODING, -1
6680 Xboom_android, FALSE, FALSE,
6681 EL_EMC_ANDROID, ACTION_OTHER, -1
6684 Xboom_1, FALSE, FALSE,
6685 EL_DEFAULT, ACTION_EXPLODING, -1
6688 Xboom_2, FALSE, FALSE,
6689 EL_DEFAULT, ACTION_EXPLODING, -1
6692 Znormal, FALSE, FALSE,
6696 Zdynamite, FALSE, FALSE,
6700 Zplayer, FALSE, FALSE,
6704 ZBORDER, FALSE, FALSE,
6714 static struct Mapping_EM_to_RND_player
6723 em_player_mapping_list[] =
6727 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
6731 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
6735 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
6739 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
6743 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
6747 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
6751 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
6755 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
6759 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
6763 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
6767 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
6771 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
6775 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
6779 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
6783 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
6787 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
6791 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
6795 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
6799 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
6803 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
6807 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
6811 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
6815 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
6819 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
6823 EL_PLAYER_1, ACTION_DEFAULT, -1,
6827 EL_PLAYER_2, ACTION_DEFAULT, -1,
6831 EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
6835 EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
6839 EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
6843 EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
6847 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
6851 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
6855 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
6859 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
6863 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
6867 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
6871 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
6875 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
6879 EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
6883 EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
6887 EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
6891 EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
6895 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
6899 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
6903 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
6907 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
6911 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
6915 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
6919 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
6923 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
6927 EL_PLAYER_3, ACTION_DEFAULT, -1,
6931 EL_PLAYER_4, ACTION_DEFAULT, -1,
6940 int map_element_RND_to_EM(int element_rnd)
6942 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
6943 static boolean mapping_initialized = FALSE;
6945 if (!mapping_initialized)
6949 /* return "Xalpha_quest" for all undefined elements in mapping array */
6950 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
6951 mapping_RND_to_EM[i] = Xalpha_quest;
6953 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
6954 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
6955 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
6956 em_object_mapping_list[i].element_em;
6958 mapping_initialized = TRUE;
6961 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
6962 return mapping_RND_to_EM[element_rnd];
6964 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
6969 int map_element_EM_to_RND(int element_em)
6971 static unsigned short mapping_EM_to_RND[TILE_MAX];
6972 static boolean mapping_initialized = FALSE;
6974 if (!mapping_initialized)
6978 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
6979 for (i = 0; i < TILE_MAX; i++)
6980 mapping_EM_to_RND[i] = EL_UNKNOWN;
6982 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
6983 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
6984 em_object_mapping_list[i].element_rnd;
6986 mapping_initialized = TRUE;
6989 if (element_em >= 0 && element_em < TILE_MAX)
6990 return mapping_EM_to_RND[element_em];
6992 Error(ERR_WARN, "invalid EM level element %d", element_em);
6997 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
6999 struct LevelInfo_EM *level_em = level->native_em_level;
7000 struct LEVEL *lev = level_em->lev;
7003 for (i = 0; i < TILE_MAX; i++)
7004 lev->android_array[i] = Xblank;
7006 for (i = 0; i < level->num_android_clone_elements; i++)
7008 int element_rnd = level->android_clone_element[i];
7009 int element_em = map_element_RND_to_EM(element_rnd);
7011 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
7012 if (em_object_mapping_list[j].element_rnd == element_rnd)
7013 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
7017 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
7019 struct LevelInfo_EM *level_em = level->native_em_level;
7020 struct LEVEL *lev = level_em->lev;
7023 level->num_android_clone_elements = 0;
7025 for (i = 0; i < TILE_MAX; i++)
7027 int element_em = lev->android_array[i];
7029 boolean element_found = FALSE;
7031 if (element_em == Xblank)
7034 element_rnd = map_element_EM_to_RND(element_em);
7036 for (j = 0; j < level->num_android_clone_elements; j++)
7037 if (level->android_clone_element[j] == element_rnd)
7038 element_found = TRUE;
7042 level->android_clone_element[level->num_android_clone_elements++] =
7045 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
7050 if (level->num_android_clone_elements == 0)
7052 level->num_android_clone_elements = 1;
7053 level->android_clone_element[0] = EL_EMPTY;
7057 int map_direction_RND_to_EM(int direction)
7059 return (direction == MV_UP ? 0 :
7060 direction == MV_RIGHT ? 1 :
7061 direction == MV_DOWN ? 2 :
7062 direction == MV_LEFT ? 3 :
7066 int map_direction_EM_to_RND(int direction)
7068 return (direction == 0 ? MV_UP :
7069 direction == 1 ? MV_RIGHT :
7070 direction == 2 ? MV_DOWN :
7071 direction == 3 ? MV_LEFT :
7075 int map_element_RND_to_SP(int element_rnd)
7077 int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
7079 if (element_rnd >= EL_SP_START &&
7080 element_rnd <= EL_SP_END)
7081 element_sp = element_rnd - EL_SP_START;
7082 else if (element_rnd == EL_EMPTY_SPACE)
7084 else if (element_rnd == EL_INVISIBLE_WALL)
7090 int map_element_SP_to_RND(int element_sp)
7092 int element_rnd = EL_UNKNOWN;
7094 if (element_sp >= 0x00 &&
7096 element_rnd = EL_SP_START + element_sp;
7097 else if (element_sp == 0x28)
7098 element_rnd = EL_INVISIBLE_WALL;
7103 int map_action_SP_to_RND(int action_sp)
7107 case actActive: return ACTION_ACTIVE;
7108 case actImpact: return ACTION_IMPACT;
7109 case actExploding: return ACTION_EXPLODING;
7110 case actDigging: return ACTION_DIGGING;
7111 case actSnapping: return ACTION_SNAPPING;
7112 case actCollecting: return ACTION_COLLECTING;
7113 case actPassing: return ACTION_PASSING;
7114 case actPushing: return ACTION_PUSHING;
7115 case actDropping: return ACTION_DROPPING;
7117 default: return ACTION_DEFAULT;
7121 int get_next_element(int element)
7125 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
7126 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
7127 case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL;
7128 case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY;
7129 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
7130 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
7131 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
7132 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
7133 case EL_DC_MAGIC_WALL_FILLING: return EL_DC_MAGIC_WALL_FULL;
7134 case EL_DC_MAGIC_WALL_EMPTYING: return EL_DC_MAGIC_WALL_ACTIVE;
7135 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
7137 default: return element;
7142 int el_act_dir2img(int element, int action, int direction)
7144 element = GFX_ELEMENT(element);
7146 if (direction == MV_NONE)
7147 return element_info[element].graphic[action];
7149 direction = MV_DIR_TO_BIT(direction);
7151 return element_info[element].direction_graphic[action][direction];
7154 int el_act_dir2img(int element, int action, int direction)
7156 element = GFX_ELEMENT(element);
7157 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
7159 /* direction_graphic[][] == graphic[] for undefined direction graphics */
7160 return element_info[element].direction_graphic[action][direction];
7165 static int el_act_dir2crm(int element, int action, int direction)
7167 element = GFX_ELEMENT(element);
7169 if (direction == MV_NONE)
7170 return element_info[element].crumbled[action];
7172 direction = MV_DIR_TO_BIT(direction);
7174 return element_info[element].direction_crumbled[action][direction];
7177 static int el_act_dir2crm(int element, int action, int direction)
7179 element = GFX_ELEMENT(element);
7180 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
7182 /* direction_graphic[][] == graphic[] for undefined direction graphics */
7183 return element_info[element].direction_crumbled[action][direction];
7187 int el_act2img(int element, int action)
7189 element = GFX_ELEMENT(element);
7191 return element_info[element].graphic[action];
7194 int el_act2crm(int element, int action)
7196 element = GFX_ELEMENT(element);
7198 return element_info[element].crumbled[action];
7201 int el_dir2img(int element, int direction)
7203 element = GFX_ELEMENT(element);
7205 return el_act_dir2img(element, ACTION_DEFAULT, direction);
7208 int el2baseimg(int element)
7210 return element_info[element].graphic[ACTION_DEFAULT];
7213 int el2img(int element)
7215 element = GFX_ELEMENT(element);
7217 return element_info[element].graphic[ACTION_DEFAULT];
7220 int el2edimg(int element)
7222 element = GFX_ELEMENT(element);
7224 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
7227 int el2preimg(int element)
7229 element = GFX_ELEMENT(element);
7231 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
7234 int el2panelimg(int element)
7236 element = GFX_ELEMENT(element);
7238 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PANEL];
7241 int font2baseimg(int font_nr)
7243 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
7246 int getBeltNrFromBeltElement(int element)
7248 return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 :
7249 element < EL_CONVEYOR_BELT_3_LEFT ? 1 :
7250 element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3);
7253 int getBeltNrFromBeltActiveElement(int element)
7255 return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 :
7256 element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 :
7257 element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3);
7260 int getBeltNrFromBeltSwitchElement(int element)
7262 return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 :
7263 element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 :
7264 element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3);
7267 int getBeltDirNrFromBeltElement(int element)
7269 static int belt_base_element[4] =
7271 EL_CONVEYOR_BELT_1_LEFT,
7272 EL_CONVEYOR_BELT_2_LEFT,
7273 EL_CONVEYOR_BELT_3_LEFT,
7274 EL_CONVEYOR_BELT_4_LEFT
7277 int belt_nr = getBeltNrFromBeltElement(element);
7278 int belt_dir_nr = element - belt_base_element[belt_nr];
7280 return (belt_dir_nr % 3);
7283 int getBeltDirNrFromBeltSwitchElement(int element)
7285 static int belt_base_element[4] =
7287 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
7288 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
7289 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
7290 EL_CONVEYOR_BELT_4_SWITCH_LEFT
7293 int belt_nr = getBeltNrFromBeltSwitchElement(element);
7294 int belt_dir_nr = element - belt_base_element[belt_nr];
7296 return (belt_dir_nr % 3);
7299 int getBeltDirFromBeltElement(int element)
7301 static int belt_move_dir[3] =
7308 int belt_dir_nr = getBeltDirNrFromBeltElement(element);
7310 return belt_move_dir[belt_dir_nr];
7313 int getBeltDirFromBeltSwitchElement(int element)
7315 static int belt_move_dir[3] =
7322 int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(element);
7324 return belt_move_dir[belt_dir_nr];
7327 int getBeltElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
7329 static int belt_base_element[4] =
7331 EL_CONVEYOR_BELT_1_LEFT,
7332 EL_CONVEYOR_BELT_2_LEFT,
7333 EL_CONVEYOR_BELT_3_LEFT,
7334 EL_CONVEYOR_BELT_4_LEFT
7337 return belt_base_element[belt_nr] + belt_dir_nr;
7340 int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
7342 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
7344 return getBeltElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
7347 int getBeltSwitchElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
7349 static int belt_base_element[4] =
7351 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
7352 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
7353 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
7354 EL_CONVEYOR_BELT_4_SWITCH_LEFT
7357 return belt_base_element[belt_nr] + belt_dir_nr;
7360 int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
7362 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
7364 return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
7367 int getNumActivePlayers_EM()
7369 int num_players = 0;
7375 for (i = 0; i < MAX_PLAYERS; i++)
7376 if (tape.player_participates[i])
7382 int getGameFrameDelay_EM(int native_em_game_frame_delay)
7384 int game_frame_delay_value;
7386 game_frame_delay_value =
7387 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
7388 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
7391 if (tape.playing && tape.warp_forward && !tape.pausing)
7392 game_frame_delay_value = 0;
7394 return game_frame_delay_value;
7397 unsigned int InitRND(int seed)
7399 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
7400 return InitEngineRandom_EM(seed);
7401 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
7402 return InitEngineRandom_SP(seed);
7404 return InitEngineRandom_RND(seed);
7408 static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
7409 static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
7412 inline static int get_effective_element_EM(int tile, int frame_em)
7414 int element = object_mapping[tile].element_rnd;
7415 int action = object_mapping[tile].action;
7416 boolean is_backside = object_mapping[tile].is_backside;
7417 boolean action_removing = (action == ACTION_DIGGING ||
7418 action == ACTION_SNAPPING ||
7419 action == ACTION_COLLECTING);
7425 case Yacid_splash_eB:
7426 case Yacid_splash_wB:
7427 return (frame_em > 5 ? EL_EMPTY : element);
7431 case Ydiamond_stone:
7432 // if (!game.use_native_emc_graphics_engine)
7440 else /* frame_em == 7 */
7444 case Yacid_splash_eB:
7445 case Yacid_splash_wB:
7448 case Yemerald_stone:
7451 case Ydiamond_stone:
7455 case Xdrip_stretchB:
7474 case Xsand_stonein_1:
7475 case Xsand_stonein_2:
7476 case Xsand_stonein_3:
7477 case Xsand_stonein_4:
7481 return (is_backside || action_removing ? EL_EMPTY : element);
7486 inline static boolean check_linear_animation_EM(int tile)
7490 case Xsand_stonesand_1:
7491 case Xsand_stonesand_quickout_1:
7492 case Xsand_sandstone_1:
7493 case Xsand_stonein_1:
7494 case Xsand_stoneout_1:
7514 case Yacid_splash_eB:
7515 case Yacid_splash_wB:
7516 case Yemerald_stone:
7524 inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
7525 boolean has_crumbled_graphics,
7526 int crumbled, int sync_frame)
7528 /* if element can be crumbled, but certain action graphics are just empty
7529 space (like instantly snapping sand to empty space in 1 frame), do not
7530 treat these empty space graphics as crumbled graphics in EMC engine */
7531 if (crumbled == IMG_EMPTY_SPACE)
7532 has_crumbled_graphics = FALSE;
7534 if (has_crumbled_graphics)
7536 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
7537 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
7538 g_crumbled->anim_delay,
7539 g_crumbled->anim_mode,
7540 g_crumbled->anim_start_frame,
7543 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
7544 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
7546 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
7548 g_em->has_crumbled_graphics = TRUE;
7552 g_em->crumbled_bitmap = NULL;
7553 g_em->crumbled_src_x = 0;
7554 g_em->crumbled_src_y = 0;
7555 g_em->crumbled_border_size = 0;
7557 g_em->has_crumbled_graphics = FALSE;
7561 void ResetGfxAnimation_EM(int x, int y, int tile)
7566 void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
7567 int tile, int frame_em, int x, int y)
7569 int action = object_mapping[tile].action;
7571 int direction = object_mapping[tile].direction;
7572 int effective_element = get_effective_element_EM(tile, frame_em);
7573 int graphic = (direction == MV_NONE ?
7574 el_act2img(effective_element, action) :
7575 el_act_dir2img(effective_element, action, direction));
7576 struct GraphicInfo *g = &graphic_info[graphic];
7579 boolean action_removing = (action == ACTION_DIGGING ||
7580 action == ACTION_SNAPPING ||
7581 action == ACTION_COLLECTING);
7582 boolean action_moving = (action == ACTION_FALLING ||
7583 action == ACTION_MOVING ||
7584 action == ACTION_PUSHING ||
7585 action == ACTION_EATING ||
7586 action == ACTION_FILLING ||
7587 action == ACTION_EMPTYING);
7588 boolean action_falling = (action == ACTION_FALLING ||
7589 action == ACTION_FILLING ||
7590 action == ACTION_EMPTYING);
7592 /* special case: graphic uses "2nd movement tile" and has defined
7593 7 frames for movement animation (or less) => use default graphic
7594 for last (8th) frame which ends the movement animation */
7595 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
7597 action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
7598 graphic = (direction == MV_NONE ?
7599 el_act2img(effective_element, action) :
7600 el_act_dir2img(effective_element, action, direction));
7602 g = &graphic_info[graphic];
7606 if (tile == Xsand_stonesand_1 ||
7607 tile == Xsand_stonesand_2 ||
7608 tile == Xsand_stonesand_3 ||
7609 tile == Xsand_stonesand_4)
7610 printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
7614 if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
7618 // printf("::: resetting... [%d]\n", tile);
7621 if (action_removing || check_linear_animation_EM(tile))
7623 GfxFrame[x][y] = frame_em;
7625 // printf("::: resetting... [%d]\n", tile);
7628 else if (action_moving)
7630 boolean is_backside = object_mapping[tile].is_backside;
7634 int direction = object_mapping[tile].direction;
7635 int move_dir = (action_falling ? MV_DOWN : direction);
7640 /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
7641 if (g->double_movement && frame_em == 0)
7645 // printf("::: resetting... [%d]\n", tile);
7649 if (move_dir == MV_LEFT)
7650 GfxFrame[x - 1][y] = GfxFrame[x][y];
7651 else if (move_dir == MV_RIGHT)
7652 GfxFrame[x + 1][y] = GfxFrame[x][y];
7653 else if (move_dir == MV_UP)
7654 GfxFrame[x][y - 1] = GfxFrame[x][y];
7655 else if (move_dir == MV_DOWN)
7656 GfxFrame[x][y + 1] = GfxFrame[x][y];
7663 /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
7664 if (tile == Xsand_stonesand_quickout_1 ||
7665 tile == Xsand_stonesand_quickout_2)
7670 if (tile == Xsand_stonesand_1 ||
7671 tile == Xsand_stonesand_2 ||
7672 tile == Xsand_stonesand_3 ||
7673 tile == Xsand_stonesand_4)
7674 printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
7678 if (graphic_info[graphic].anim_global_sync)
7679 sync_frame = FrameCounter;
7680 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
7681 sync_frame = GfxFrame[x][y];
7683 sync_frame = 0; /* playfield border (pseudo steel) */
7685 SetRandomAnimationValue(x, y);
7687 int frame = getAnimationFrame(g->anim_frames,
7690 g->anim_start_frame,
7693 g_em->unique_identifier =
7694 (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
7698 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
7699 int tile, int frame_em, int x, int y)
7701 int action = object_mapping[tile].action;
7702 int direction = object_mapping[tile].direction;
7703 boolean is_backside = object_mapping[tile].is_backside;
7704 int effective_element = get_effective_element_EM(tile, frame_em);
7706 int effective_action = action;
7708 int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
7710 int graphic = (direction == MV_NONE ?
7711 el_act2img(effective_element, effective_action) :
7712 el_act_dir2img(effective_element, effective_action,
7714 int crumbled = (direction == MV_NONE ?
7715 el_act2crm(effective_element, effective_action) :
7716 el_act_dir2crm(effective_element, effective_action,
7718 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
7719 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
7720 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
7721 struct GraphicInfo *g = &graphic_info[graphic];
7723 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
7727 /* special case: graphic uses "2nd movement tile" and has defined
7728 7 frames for movement animation (or less) => use default graphic
7729 for last (8th) frame which ends the movement animation */
7730 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
7732 effective_action = ACTION_DEFAULT;
7733 graphic = (direction == MV_NONE ?
7734 el_act2img(effective_element, effective_action) :
7735 el_act_dir2img(effective_element, effective_action,
7737 crumbled = (direction == MV_NONE ?
7738 el_act2crm(effective_element, effective_action) :
7739 el_act_dir2crm(effective_element, effective_action,
7742 g = &graphic_info[graphic];
7752 if (frame_em == 0) /* reset animation frame for certain elements */
7754 if (check_linear_animation_EM(tile))
7759 if (graphic_info[graphic].anim_global_sync)
7760 sync_frame = FrameCounter;
7761 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
7762 sync_frame = GfxFrame[x][y];
7764 sync_frame = 0; /* playfield border (pseudo steel) */
7766 SetRandomAnimationValue(x, y);
7771 int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
7772 i == Xdrip_stretchB ? 7 :
7773 i == Ydrip_s2 ? j + 8 :
7774 i == Ydrip_s2B ? j + 8 :
7783 i == Xfake_acid_1 ? 0 :
7784 i == Xfake_acid_2 ? 10 :
7785 i == Xfake_acid_3 ? 20 :
7786 i == Xfake_acid_4 ? 30 :
7787 i == Xfake_acid_5 ? 40 :
7788 i == Xfake_acid_6 ? 50 :
7789 i == Xfake_acid_7 ? 60 :
7790 i == Xfake_acid_8 ? 70 :
7792 i == Xball_2B ? j + 8 :
7793 i == Yball_eat ? j + 1 :
7794 i == Ykey_1_eat ? j + 1 :
7795 i == Ykey_2_eat ? j + 1 :
7796 i == Ykey_3_eat ? j + 1 :
7797 i == Ykey_4_eat ? j + 1 :
7798 i == Ykey_5_eat ? j + 1 :
7799 i == Ykey_6_eat ? j + 1 :
7800 i == Ykey_7_eat ? j + 1 :
7801 i == Ykey_8_eat ? j + 1 :
7802 i == Ylenses_eat ? j + 1 :
7803 i == Ymagnify_eat ? j + 1 :
7804 i == Ygrass_eat ? j + 1 :
7805 i == Ydirt_eat ? j + 1 :
7806 i == Xamoeba_1 ? 0 :
7807 i == Xamoeba_2 ? 1 :
7808 i == Xamoeba_3 ? 2 :
7809 i == Xamoeba_4 ? 3 :
7810 i == Xamoeba_5 ? 0 :
7811 i == Xamoeba_6 ? 1 :
7812 i == Xamoeba_7 ? 2 :
7813 i == Xamoeba_8 ? 3 :
7814 i == Xexit_2 ? j + 8 :
7815 i == Xexit_3 ? j + 16 :
7816 i == Xdynamite_1 ? 0 :
7817 i == Xdynamite_2 ? 8 :
7818 i == Xdynamite_3 ? 16 :
7819 i == Xdynamite_4 ? 24 :
7820 i == Xsand_stonein_1 ? j + 1 :
7821 i == Xsand_stonein_2 ? j + 9 :
7822 i == Xsand_stonein_3 ? j + 17 :
7823 i == Xsand_stonein_4 ? j + 25 :
7824 i == Xsand_stoneout_1 && j == 0 ? 0 :
7825 i == Xsand_stoneout_1 && j == 1 ? 0 :
7826 i == Xsand_stoneout_1 && j == 2 ? 1 :
7827 i == Xsand_stoneout_1 && j == 3 ? 2 :
7828 i == Xsand_stoneout_1 && j == 4 ? 2 :
7829 i == Xsand_stoneout_1 && j == 5 ? 3 :
7830 i == Xsand_stoneout_1 && j == 6 ? 4 :
7831 i == Xsand_stoneout_1 && j == 7 ? 4 :
7832 i == Xsand_stoneout_2 && j == 0 ? 5 :
7833 i == Xsand_stoneout_2 && j == 1 ? 6 :
7834 i == Xsand_stoneout_2 && j == 2 ? 7 :
7835 i == Xsand_stoneout_2 && j == 3 ? 8 :
7836 i == Xsand_stoneout_2 && j == 4 ? 9 :
7837 i == Xsand_stoneout_2 && j == 5 ? 11 :
7838 i == Xsand_stoneout_2 && j == 6 ? 13 :
7839 i == Xsand_stoneout_2 && j == 7 ? 15 :
7840 i == Xboom_bug && j == 1 ? 2 :
7841 i == Xboom_bug && j == 2 ? 2 :
7842 i == Xboom_bug && j == 3 ? 4 :
7843 i == Xboom_bug && j == 4 ? 4 :
7844 i == Xboom_bug && j == 5 ? 2 :
7845 i == Xboom_bug && j == 6 ? 2 :
7846 i == Xboom_bug && j == 7 ? 0 :
7847 i == Xboom_bomb && j == 1 ? 2 :
7848 i == Xboom_bomb && j == 2 ? 2 :
7849 i == Xboom_bomb && j == 3 ? 4 :
7850 i == Xboom_bomb && j == 4 ? 4 :
7851 i == Xboom_bomb && j == 5 ? 2 :
7852 i == Xboom_bomb && j == 6 ? 2 :
7853 i == Xboom_bomb && j == 7 ? 0 :
7854 i == Xboom_android && j == 7 ? 6 :
7855 i == Xboom_1 && j == 1 ? 2 :
7856 i == Xboom_1 && j == 2 ? 2 :
7857 i == Xboom_1 && j == 3 ? 4 :
7858 i == Xboom_1 && j == 4 ? 4 :
7859 i == Xboom_1 && j == 5 ? 6 :
7860 i == Xboom_1 && j == 6 ? 6 :
7861 i == Xboom_1 && j == 7 ? 8 :
7862 i == Xboom_2 && j == 0 ? 8 :
7863 i == Xboom_2 && j == 1 ? 8 :
7864 i == Xboom_2 && j == 2 ? 10 :
7865 i == Xboom_2 && j == 3 ? 10 :
7866 i == Xboom_2 && j == 4 ? 10 :
7867 i == Xboom_2 && j == 5 ? 12 :
7868 i == Xboom_2 && j == 6 ? 12 :
7869 i == Xboom_2 && j == 7 ? 12 :
7871 special_animation && j == 4 ? 3 :
7872 effective_action != action ? 0 :
7878 int xxx_effective_action;
7879 int xxx_has_action_graphics;
7882 int element = object_mapping[i].element_rnd;
7883 int action = object_mapping[i].action;
7884 int direction = object_mapping[i].direction;
7885 boolean is_backside = object_mapping[i].is_backside;
7887 boolean action_removing = (action == ACTION_DIGGING ||
7888 action == ACTION_SNAPPING ||
7889 action == ACTION_COLLECTING);
7891 boolean action_exploding = ((action == ACTION_EXPLODING ||
7892 action == ACTION_SMASHED_BY_ROCK ||
7893 action == ACTION_SMASHED_BY_SPRING) &&
7894 element != EL_DIAMOND);
7895 boolean action_active = (action == ACTION_ACTIVE);
7896 boolean action_other = (action == ACTION_OTHER);
7900 int effective_element = get_effective_element_EM(i, j);
7902 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
7903 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
7905 i == Xdrip_stretch ? element :
7906 i == Xdrip_stretchB ? element :
7907 i == Ydrip_s1 ? element :
7908 i == Ydrip_s1B ? element :
7909 i == Xball_1B ? element :
7910 i == Xball_2 ? element :
7911 i == Xball_2B ? element :
7912 i == Yball_eat ? element :
7913 i == Ykey_1_eat ? element :
7914 i == Ykey_2_eat ? element :
7915 i == Ykey_3_eat ? element :
7916 i == Ykey_4_eat ? element :
7917 i == Ykey_5_eat ? element :
7918 i == Ykey_6_eat ? element :
7919 i == Ykey_7_eat ? element :
7920 i == Ykey_8_eat ? element :
7921 i == Ylenses_eat ? element :
7922 i == Ymagnify_eat ? element :
7923 i == Ygrass_eat ? element :
7924 i == Ydirt_eat ? element :
7925 i == Yemerald_stone ? EL_EMERALD :
7926 i == Ydiamond_stone ? EL_ROCK :
7927 i == Xsand_stonein_1 ? element :
7928 i == Xsand_stonein_2 ? element :
7929 i == Xsand_stonein_3 ? element :
7930 i == Xsand_stonein_4 ? element :
7931 is_backside ? EL_EMPTY :
7932 action_removing ? EL_EMPTY :
7935 int effective_action = (j < 7 ? action :
7936 i == Xdrip_stretch ? action :
7937 i == Xdrip_stretchB ? action :
7938 i == Ydrip_s1 ? action :
7939 i == Ydrip_s1B ? action :
7940 i == Xball_1B ? action :
7941 i == Xball_2 ? action :
7942 i == Xball_2B ? action :
7943 i == Yball_eat ? action :
7944 i == Ykey_1_eat ? action :
7945 i == Ykey_2_eat ? action :
7946 i == Ykey_3_eat ? action :
7947 i == Ykey_4_eat ? action :
7948 i == Ykey_5_eat ? action :
7949 i == Ykey_6_eat ? action :
7950 i == Ykey_7_eat ? action :
7951 i == Ykey_8_eat ? action :
7952 i == Ylenses_eat ? action :
7953 i == Ymagnify_eat ? action :
7954 i == Ygrass_eat ? action :
7955 i == Ydirt_eat ? action :
7956 i == Xsand_stonein_1 ? action :
7957 i == Xsand_stonein_2 ? action :
7958 i == Xsand_stonein_3 ? action :
7959 i == Xsand_stonein_4 ? action :
7960 i == Xsand_stoneout_1 ? action :
7961 i == Xsand_stoneout_2 ? action :
7962 i == Xboom_android ? ACTION_EXPLODING :
7963 action_exploding ? ACTION_EXPLODING :
7964 action_active ? action :
7965 action_other ? action :
7967 int graphic = (el_act_dir2img(effective_element, effective_action,
7969 int crumbled = (el_act_dir2crm(effective_element, effective_action,
7971 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
7972 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
7973 boolean has_action_graphics = (graphic != base_graphic);
7974 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
7975 struct GraphicInfo *g = &graphic_info[graphic];
7977 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
7979 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
7982 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
7983 boolean special_animation = (action != ACTION_DEFAULT &&
7984 g->anim_frames == 3 &&
7985 g->anim_delay == 2 &&
7986 g->anim_mode & ANIM_LINEAR);
7987 xxx_sync_frame = (i == Xdrip_stretch ? 7 :
7988 i == Xdrip_stretchB ? 7 :
7989 i == Ydrip_s2 ? j + 8 :
7990 i == Ydrip_s2B ? j + 8 :
7999 i == Xfake_acid_1 ? 0 :
8000 i == Xfake_acid_2 ? 10 :
8001 i == Xfake_acid_3 ? 20 :
8002 i == Xfake_acid_4 ? 30 :
8003 i == Xfake_acid_5 ? 40 :
8004 i == Xfake_acid_6 ? 50 :
8005 i == Xfake_acid_7 ? 60 :
8006 i == Xfake_acid_8 ? 70 :
8008 i == Xball_2B ? j + 8 :
8009 i == Yball_eat ? j + 1 :
8010 i == Ykey_1_eat ? j + 1 :
8011 i == Ykey_2_eat ? j + 1 :
8012 i == Ykey_3_eat ? j + 1 :
8013 i == Ykey_4_eat ? j + 1 :
8014 i == Ykey_5_eat ? j + 1 :
8015 i == Ykey_6_eat ? j + 1 :
8016 i == Ykey_7_eat ? j + 1 :
8017 i == Ykey_8_eat ? j + 1 :
8018 i == Ylenses_eat ? j + 1 :
8019 i == Ymagnify_eat ? j + 1 :
8020 i == Ygrass_eat ? j + 1 :
8021 i == Ydirt_eat ? j + 1 :
8022 i == Xamoeba_1 ? 0 :
8023 i == Xamoeba_2 ? 1 :
8024 i == Xamoeba_3 ? 2 :
8025 i == Xamoeba_4 ? 3 :
8026 i == Xamoeba_5 ? 0 :
8027 i == Xamoeba_6 ? 1 :
8028 i == Xamoeba_7 ? 2 :
8029 i == Xamoeba_8 ? 3 :
8030 i == Xexit_2 ? j + 8 :
8031 i == Xexit_3 ? j + 16 :
8032 i == Xdynamite_1 ? 0 :
8033 i == Xdynamite_2 ? 8 :
8034 i == Xdynamite_3 ? 16 :
8035 i == Xdynamite_4 ? 24 :
8036 i == Xsand_stonein_1 ? j + 1 :
8037 i == Xsand_stonein_2 ? j + 9 :
8038 i == Xsand_stonein_3 ? j + 17 :
8039 i == Xsand_stonein_4 ? j + 25 :
8040 i == Xsand_stoneout_1 && j == 0 ? 0 :
8041 i == Xsand_stoneout_1 && j == 1 ? 0 :
8042 i == Xsand_stoneout_1 && j == 2 ? 1 :
8043 i == Xsand_stoneout_1 && j == 3 ? 2 :
8044 i == Xsand_stoneout_1 && j == 4 ? 2 :
8045 i == Xsand_stoneout_1 && j == 5 ? 3 :
8046 i == Xsand_stoneout_1 && j == 6 ? 4 :
8047 i == Xsand_stoneout_1 && j == 7 ? 4 :
8048 i == Xsand_stoneout_2 && j == 0 ? 5 :
8049 i == Xsand_stoneout_2 && j == 1 ? 6 :
8050 i == Xsand_stoneout_2 && j == 2 ? 7 :
8051 i == Xsand_stoneout_2 && j == 3 ? 8 :
8052 i == Xsand_stoneout_2 && j == 4 ? 9 :
8053 i == Xsand_stoneout_2 && j == 5 ? 11 :
8054 i == Xsand_stoneout_2 && j == 6 ? 13 :
8055 i == Xsand_stoneout_2 && j == 7 ? 15 :
8056 i == Xboom_bug && j == 1 ? 2 :
8057 i == Xboom_bug && j == 2 ? 2 :
8058 i == Xboom_bug && j == 3 ? 4 :
8059 i == Xboom_bug && j == 4 ? 4 :
8060 i == Xboom_bug && j == 5 ? 2 :
8061 i == Xboom_bug && j == 6 ? 2 :
8062 i == Xboom_bug && j == 7 ? 0 :
8063 i == Xboom_bomb && j == 1 ? 2 :
8064 i == Xboom_bomb && j == 2 ? 2 :
8065 i == Xboom_bomb && j == 3 ? 4 :
8066 i == Xboom_bomb && j == 4 ? 4 :
8067 i == Xboom_bomb && j == 5 ? 2 :
8068 i == Xboom_bomb && j == 6 ? 2 :
8069 i == Xboom_bomb && j == 7 ? 0 :
8070 i == Xboom_android && j == 7 ? 6 :
8071 i == Xboom_1 && j == 1 ? 2 :
8072 i == Xboom_1 && j == 2 ? 2 :
8073 i == Xboom_1 && j == 3 ? 4 :
8074 i == Xboom_1 && j == 4 ? 4 :
8075 i == Xboom_1 && j == 5 ? 6 :
8076 i == Xboom_1 && j == 6 ? 6 :
8077 i == Xboom_1 && j == 7 ? 8 :
8078 i == Xboom_2 && j == 0 ? 8 :
8079 i == Xboom_2 && j == 1 ? 8 :
8080 i == Xboom_2 && j == 2 ? 10 :
8081 i == Xboom_2 && j == 3 ? 10 :
8082 i == Xboom_2 && j == 4 ? 10 :
8083 i == Xboom_2 && j == 5 ? 12 :
8084 i == Xboom_2 && j == 6 ? 12 :
8085 i == Xboom_2 && j == 7 ? 12 :
8086 special_animation && j == 4 ? 3 :
8087 effective_action != action ? 0 :
8090 xxx_effective_action = effective_action;
8091 xxx_has_action_graphics = has_action_graphics;
8096 int frame = getAnimationFrame(g->anim_frames,
8099 g->anim_start_frame,
8113 int old_src_x = g_em->src_x;
8114 int old_src_y = g_em->src_y;
8118 getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
8119 g->double_movement && is_backside);
8121 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
8122 &g_em->src_x, &g_em->src_y, FALSE);
8127 if (tile == Ydiamond_stone)
8128 printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n",
8133 g->anim_start_frame,
8136 g_em->src_x, g_em->src_y,
8137 g_em->src_offset_x, g_em->src_offset_y,
8138 g_em->dst_offset_x, g_em->dst_offset_y,
8150 if (graphic == IMG_BUG_MOVING_RIGHT)
8151 printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
8152 g->double_movement, is_backside,
8153 old_src_x, old_src_y, g_em->src_x, g_em->src_y);
8161 g_em->src_offset_x = 0;
8162 g_em->src_offset_y = 0;
8163 g_em->dst_offset_x = 0;
8164 g_em->dst_offset_y = 0;
8165 g_em->width = TILEX;
8166 g_em->height = TILEY;
8168 g_em->preserve_background = FALSE;
8171 /* (updating the "crumbled" graphic definitions is probably not really needed,
8172 as animations for crumbled graphics can't be longer than one EMC cycle) */
8174 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
8179 g_em->crumbled_bitmap = NULL;
8180 g_em->crumbled_src_x = 0;
8181 g_em->crumbled_src_y = 0;
8183 g_em->has_crumbled_graphics = FALSE;
8185 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
8187 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
8188 g_crumbled->anim_delay,
8189 g_crumbled->anim_mode,
8190 g_crumbled->anim_start_frame,
8193 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
8194 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
8196 g_em->has_crumbled_graphics = TRUE;
8202 int effective_action = xxx_effective_action;
8203 int has_action_graphics = xxx_has_action_graphics;
8205 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
8206 effective_action == ACTION_MOVING ||
8207 effective_action == ACTION_PUSHING ||
8208 effective_action == ACTION_EATING)) ||
8209 (!has_action_graphics && (effective_action == ACTION_FILLING ||
8210 effective_action == ACTION_EMPTYING)))
8213 (effective_action == ACTION_FALLING ||
8214 effective_action == ACTION_FILLING ||
8215 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
8216 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
8217 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
8218 int num_steps = (i == Ydrip_s1 ? 16 :
8219 i == Ydrip_s1B ? 16 :
8220 i == Ydrip_s2 ? 16 :
8221 i == Ydrip_s2B ? 16 :
8222 i == Xsand_stonein_1 ? 32 :
8223 i == Xsand_stonein_2 ? 32 :
8224 i == Xsand_stonein_3 ? 32 :
8225 i == Xsand_stonein_4 ? 32 :
8226 i == Xsand_stoneout_1 ? 16 :
8227 i == Xsand_stoneout_2 ? 16 : 8);
8228 int cx = ABS(dx) * (TILEX / num_steps);
8229 int cy = ABS(dy) * (TILEY / num_steps);
8230 int step_frame = (i == Ydrip_s2 ? j + 8 :
8231 i == Ydrip_s2B ? j + 8 :
8232 i == Xsand_stonein_2 ? j + 8 :
8233 i == Xsand_stonein_3 ? j + 16 :
8234 i == Xsand_stonein_4 ? j + 24 :
8235 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
8236 int step = (is_backside ? step_frame : num_steps - step_frame);
8238 if (is_backside) /* tile where movement starts */
8240 if (dx < 0 || dy < 0)
8242 g_em->src_offset_x = cx * step;
8243 g_em->src_offset_y = cy * step;
8247 g_em->dst_offset_x = cx * step;
8248 g_em->dst_offset_y = cy * step;
8251 else /* tile where movement ends */
8253 if (dx < 0 || dy < 0)
8255 g_em->dst_offset_x = cx * step;
8256 g_em->dst_offset_y = cy * step;
8260 g_em->src_offset_x = cx * step;
8261 g_em->src_offset_y = cy * step;
8265 g_em->width = TILEX - cx * step;
8266 g_em->height = TILEY - cy * step;
8269 /* create unique graphic identifier to decide if tile must be redrawn */
8270 /* bit 31 - 16 (16 bit): EM style graphic
8271 bit 15 - 12 ( 4 bit): EM style frame
8272 bit 11 - 6 ( 6 bit): graphic width
8273 bit 5 - 0 ( 6 bit): graphic height */
8274 g_em->unique_identifier =
8275 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
8281 void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
8282 int player_nr, int anim, int frame_em)
8284 int element = player_mapping[player_nr][anim].element_rnd;
8285 int action = player_mapping[player_nr][anim].action;
8286 int direction = player_mapping[player_nr][anim].direction;
8287 int graphic = (direction == MV_NONE ?
8288 el_act2img(element, action) :
8289 el_act_dir2img(element, action, direction));
8290 struct GraphicInfo *g = &graphic_info[graphic];
8293 InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
8295 stored_player[player_nr].StepFrame = frame_em;
8297 sync_frame = stored_player[player_nr].Frame;
8299 int frame = getAnimationFrame(g->anim_frames,
8302 g->anim_start_frame,
8305 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
8306 &g_em->src_x, &g_em->src_y, FALSE);
8309 printf("::: %d: %d, %d [%d]\n",
8311 stored_player[player_nr].Frame,
8312 stored_player[player_nr].StepFrame,
8317 void InitGraphicInfo_EM(void)
8320 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
8321 struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
8326 int num_em_gfx_errors = 0;
8328 if (graphic_info_em_object[0][0].bitmap == NULL)
8330 /* EM graphics not yet initialized in em_open_all() */
8335 printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
8338 /* always start with reliable default values */
8339 for (i = 0; i < TILE_MAX; i++)
8341 object_mapping[i].element_rnd = EL_UNKNOWN;
8342 object_mapping[i].is_backside = FALSE;
8343 object_mapping[i].action = ACTION_DEFAULT;
8344 object_mapping[i].direction = MV_NONE;
8347 /* always start with reliable default values */
8348 for (p = 0; p < MAX_PLAYERS; p++)
8350 for (i = 0; i < SPR_MAX; i++)
8352 player_mapping[p][i].element_rnd = EL_UNKNOWN;
8353 player_mapping[p][i].action = ACTION_DEFAULT;
8354 player_mapping[p][i].direction = MV_NONE;
8358 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
8360 int e = em_object_mapping_list[i].element_em;
8362 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
8363 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
8365 if (em_object_mapping_list[i].action != -1)
8366 object_mapping[e].action = em_object_mapping_list[i].action;
8368 if (em_object_mapping_list[i].direction != -1)
8369 object_mapping[e].direction =
8370 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
8373 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
8375 int a = em_player_mapping_list[i].action_em;
8376 int p = em_player_mapping_list[i].player_nr;
8378 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
8380 if (em_player_mapping_list[i].action != -1)
8381 player_mapping[p][a].action = em_player_mapping_list[i].action;
8383 if (em_player_mapping_list[i].direction != -1)
8384 player_mapping[p][a].direction =
8385 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
8388 for (i = 0; i < TILE_MAX; i++)
8390 int element = object_mapping[i].element_rnd;
8391 int action = object_mapping[i].action;
8392 int direction = object_mapping[i].direction;
8393 boolean is_backside = object_mapping[i].is_backside;
8395 boolean action_removing = (action == ACTION_DIGGING ||
8396 action == ACTION_SNAPPING ||
8397 action == ACTION_COLLECTING);
8399 boolean action_exploding = ((action == ACTION_EXPLODING ||
8400 action == ACTION_SMASHED_BY_ROCK ||
8401 action == ACTION_SMASHED_BY_SPRING) &&
8402 element != EL_DIAMOND);
8403 boolean action_active = (action == ACTION_ACTIVE);
8404 boolean action_other = (action == ACTION_OTHER);
8406 for (j = 0; j < 8; j++)
8409 int effective_element = get_effective_element_EM(i, j);
8411 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
8412 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
8414 i == Xdrip_stretch ? element :
8415 i == Xdrip_stretchB ? element :
8416 i == Ydrip_s1 ? element :
8417 i == Ydrip_s1B ? element :
8418 i == Xball_1B ? element :
8419 i == Xball_2 ? element :
8420 i == Xball_2B ? element :
8421 i == Yball_eat ? element :
8422 i == Ykey_1_eat ? element :
8423 i == Ykey_2_eat ? element :
8424 i == Ykey_3_eat ? element :
8425 i == Ykey_4_eat ? element :
8426 i == Ykey_5_eat ? element :
8427 i == Ykey_6_eat ? element :
8428 i == Ykey_7_eat ? element :
8429 i == Ykey_8_eat ? element :
8430 i == Ylenses_eat ? element :
8431 i == Ymagnify_eat ? element :
8432 i == Ygrass_eat ? element :
8433 i == Ydirt_eat ? element :
8434 i == Yemerald_stone ? EL_EMERALD :
8435 i == Ydiamond_stone ? EL_ROCK :
8436 i == Xsand_stonein_1 ? element :
8437 i == Xsand_stonein_2 ? element :
8438 i == Xsand_stonein_3 ? element :
8439 i == Xsand_stonein_4 ? element :
8440 is_backside ? EL_EMPTY :
8441 action_removing ? EL_EMPTY :
8444 int effective_action = (j < 7 ? action :
8445 i == Xdrip_stretch ? action :
8446 i == Xdrip_stretchB ? action :
8447 i == Ydrip_s1 ? action :
8448 i == Ydrip_s1B ? action :
8449 i == Xball_1B ? action :
8450 i == Xball_2 ? action :
8451 i == Xball_2B ? action :
8452 i == Yball_eat ? action :
8453 i == Ykey_1_eat ? action :
8454 i == Ykey_2_eat ? action :
8455 i == Ykey_3_eat ? action :
8456 i == Ykey_4_eat ? action :
8457 i == Ykey_5_eat ? action :
8458 i == Ykey_6_eat ? action :
8459 i == Ykey_7_eat ? action :
8460 i == Ykey_8_eat ? action :
8461 i == Ylenses_eat ? action :
8462 i == Ymagnify_eat ? action :
8463 i == Ygrass_eat ? action :
8464 i == Ydirt_eat ? action :
8465 i == Xsand_stonein_1 ? action :
8466 i == Xsand_stonein_2 ? action :
8467 i == Xsand_stonein_3 ? action :
8468 i == Xsand_stonein_4 ? action :
8469 i == Xsand_stoneout_1 ? action :
8470 i == Xsand_stoneout_2 ? action :
8471 i == Xboom_android ? ACTION_EXPLODING :
8472 action_exploding ? ACTION_EXPLODING :
8473 action_active ? action :
8474 action_other ? action :
8476 int graphic = (el_act_dir2img(effective_element, effective_action,
8478 int crumbled = (el_act_dir2crm(effective_element, effective_action,
8480 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
8481 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
8482 boolean has_action_graphics = (graphic != base_graphic);
8483 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
8484 struct GraphicInfo *g = &graphic_info[graphic];
8486 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
8488 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
8491 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
8492 boolean special_animation = (action != ACTION_DEFAULT &&
8493 g->anim_frames == 3 &&
8494 g->anim_delay == 2 &&
8495 g->anim_mode & ANIM_LINEAR);
8496 int sync_frame = (i == Xdrip_stretch ? 7 :
8497 i == Xdrip_stretchB ? 7 :
8498 i == Ydrip_s2 ? j + 8 :
8499 i == Ydrip_s2B ? j + 8 :
8508 i == Xfake_acid_1 ? 0 :
8509 i == Xfake_acid_2 ? 10 :
8510 i == Xfake_acid_3 ? 20 :
8511 i == Xfake_acid_4 ? 30 :
8512 i == Xfake_acid_5 ? 40 :
8513 i == Xfake_acid_6 ? 50 :
8514 i == Xfake_acid_7 ? 60 :
8515 i == Xfake_acid_8 ? 70 :
8517 i == Xball_2B ? j + 8 :
8518 i == Yball_eat ? j + 1 :
8519 i == Ykey_1_eat ? j + 1 :
8520 i == Ykey_2_eat ? j + 1 :
8521 i == Ykey_3_eat ? j + 1 :
8522 i == Ykey_4_eat ? j + 1 :
8523 i == Ykey_5_eat ? j + 1 :
8524 i == Ykey_6_eat ? j + 1 :
8525 i == Ykey_7_eat ? j + 1 :
8526 i == Ykey_8_eat ? j + 1 :
8527 i == Ylenses_eat ? j + 1 :
8528 i == Ymagnify_eat ? j + 1 :
8529 i == Ygrass_eat ? j + 1 :
8530 i == Ydirt_eat ? j + 1 :
8531 i == Xamoeba_1 ? 0 :
8532 i == Xamoeba_2 ? 1 :
8533 i == Xamoeba_3 ? 2 :
8534 i == Xamoeba_4 ? 3 :
8535 i == Xamoeba_5 ? 0 :
8536 i == Xamoeba_6 ? 1 :
8537 i == Xamoeba_7 ? 2 :
8538 i == Xamoeba_8 ? 3 :
8539 i == Xexit_2 ? j + 8 :
8540 i == Xexit_3 ? j + 16 :
8541 i == Xdynamite_1 ? 0 :
8542 i == Xdynamite_2 ? 8 :
8543 i == Xdynamite_3 ? 16 :
8544 i == Xdynamite_4 ? 24 :
8545 i == Xsand_stonein_1 ? j + 1 :
8546 i == Xsand_stonein_2 ? j + 9 :
8547 i == Xsand_stonein_3 ? j + 17 :
8548 i == Xsand_stonein_4 ? j + 25 :
8549 i == Xsand_stoneout_1 && j == 0 ? 0 :
8550 i == Xsand_stoneout_1 && j == 1 ? 0 :
8551 i == Xsand_stoneout_1 && j == 2 ? 1 :
8552 i == Xsand_stoneout_1 && j == 3 ? 2 :
8553 i == Xsand_stoneout_1 && j == 4 ? 2 :
8554 i == Xsand_stoneout_1 && j == 5 ? 3 :
8555 i == Xsand_stoneout_1 && j == 6 ? 4 :
8556 i == Xsand_stoneout_1 && j == 7 ? 4 :
8557 i == Xsand_stoneout_2 && j == 0 ? 5 :
8558 i == Xsand_stoneout_2 && j == 1 ? 6 :
8559 i == Xsand_stoneout_2 && j == 2 ? 7 :
8560 i == Xsand_stoneout_2 && j == 3 ? 8 :
8561 i == Xsand_stoneout_2 && j == 4 ? 9 :
8562 i == Xsand_stoneout_2 && j == 5 ? 11 :
8563 i == Xsand_stoneout_2 && j == 6 ? 13 :
8564 i == Xsand_stoneout_2 && j == 7 ? 15 :
8565 i == Xboom_bug && j == 1 ? 2 :
8566 i == Xboom_bug && j == 2 ? 2 :
8567 i == Xboom_bug && j == 3 ? 4 :
8568 i == Xboom_bug && j == 4 ? 4 :
8569 i == Xboom_bug && j == 5 ? 2 :
8570 i == Xboom_bug && j == 6 ? 2 :
8571 i == Xboom_bug && j == 7 ? 0 :
8572 i == Xboom_bomb && j == 1 ? 2 :
8573 i == Xboom_bomb && j == 2 ? 2 :
8574 i == Xboom_bomb && j == 3 ? 4 :
8575 i == Xboom_bomb && j == 4 ? 4 :
8576 i == Xboom_bomb && j == 5 ? 2 :
8577 i == Xboom_bomb && j == 6 ? 2 :
8578 i == Xboom_bomb && j == 7 ? 0 :
8579 i == Xboom_android && j == 7 ? 6 :
8580 i == Xboom_1 && j == 1 ? 2 :
8581 i == Xboom_1 && j == 2 ? 2 :
8582 i == Xboom_1 && j == 3 ? 4 :
8583 i == Xboom_1 && j == 4 ? 4 :
8584 i == Xboom_1 && j == 5 ? 6 :
8585 i == Xboom_1 && j == 6 ? 6 :
8586 i == Xboom_1 && j == 7 ? 8 :
8587 i == Xboom_2 && j == 0 ? 8 :
8588 i == Xboom_2 && j == 1 ? 8 :
8589 i == Xboom_2 && j == 2 ? 10 :
8590 i == Xboom_2 && j == 3 ? 10 :
8591 i == Xboom_2 && j == 4 ? 10 :
8592 i == Xboom_2 && j == 5 ? 12 :
8593 i == Xboom_2 && j == 6 ? 12 :
8594 i == Xboom_2 && j == 7 ? 12 :
8595 special_animation && j == 4 ? 3 :
8596 effective_action != action ? 0 :
8600 Bitmap *debug_bitmap = g_em->bitmap;
8601 int debug_src_x = g_em->src_x;
8602 int debug_src_y = g_em->src_y;
8605 int frame = getAnimationFrame(g->anim_frames,
8608 g->anim_start_frame,
8611 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
8612 g->double_movement && is_backside);
8614 g_em->bitmap = src_bitmap;
8615 g_em->src_x = src_x;
8616 g_em->src_y = src_y;
8617 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 g_em->width = TILEX;
8622 g_em->height = TILEY;
8624 g_em->preserve_background = FALSE;
8627 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
8632 g_em->crumbled_bitmap = NULL;
8633 g_em->crumbled_src_x = 0;
8634 g_em->crumbled_src_y = 0;
8635 g_em->crumbled_border_size = 0;
8637 g_em->has_crumbled_graphics = FALSE;
8640 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
8641 printf("::: empty crumbled: %d [%s], %d, %d\n",
8642 effective_element, element_info[effective_element].token_name,
8643 effective_action, direction);
8646 /* if element can be crumbled, but certain action graphics are just empty
8647 space (like instantly snapping sand to empty space in 1 frame), do not
8648 treat these empty space graphics as crumbled graphics in EMC engine */
8649 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
8651 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
8652 g_crumbled->anim_delay,
8653 g_crumbled->anim_mode,
8654 g_crumbled->anim_start_frame,
8657 getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
8659 g_em->has_crumbled_graphics = TRUE;
8660 g_em->crumbled_bitmap = src_bitmap;
8661 g_em->crumbled_src_x = src_x;
8662 g_em->crumbled_src_y = src_y;
8663 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
8667 if (g_em == &graphic_info_em_object[207][0])
8668 printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
8669 graphic_info_em_object[207][0].crumbled_src_x,
8670 graphic_info_em_object[207][0].crumbled_src_y,
8672 crumbled, frame, src_x, src_y,
8677 g->anim_start_frame,
8679 gfx.anim_random_frame,
8684 printf("::: EMC tile %d is crumbled\n", i);
8690 if (element == EL_ROCK &&
8691 effective_action == ACTION_FILLING)
8692 printf("::: has_action_graphics == %d\n", has_action_graphics);
8695 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
8696 effective_action == ACTION_MOVING ||
8697 effective_action == ACTION_PUSHING ||
8698 effective_action == ACTION_EATING)) ||
8699 (!has_action_graphics && (effective_action == ACTION_FILLING ||
8700 effective_action == ACTION_EMPTYING)))
8703 (effective_action == ACTION_FALLING ||
8704 effective_action == ACTION_FILLING ||
8705 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
8706 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
8707 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
8708 int num_steps = (i == Ydrip_s1 ? 16 :
8709 i == Ydrip_s1B ? 16 :
8710 i == Ydrip_s2 ? 16 :
8711 i == Ydrip_s2B ? 16 :
8712 i == Xsand_stonein_1 ? 32 :
8713 i == Xsand_stonein_2 ? 32 :
8714 i == Xsand_stonein_3 ? 32 :
8715 i == Xsand_stonein_4 ? 32 :
8716 i == Xsand_stoneout_1 ? 16 :
8717 i == Xsand_stoneout_2 ? 16 : 8);
8718 int cx = ABS(dx) * (TILEX / num_steps);
8719 int cy = ABS(dy) * (TILEY / num_steps);
8720 int step_frame = (i == Ydrip_s2 ? j + 8 :
8721 i == Ydrip_s2B ? j + 8 :
8722 i == Xsand_stonein_2 ? j + 8 :
8723 i == Xsand_stonein_3 ? j + 16 :
8724 i == Xsand_stonein_4 ? j + 24 :
8725 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
8726 int step = (is_backside ? step_frame : num_steps - step_frame);
8728 if (is_backside) /* tile where movement starts */
8730 if (dx < 0 || dy < 0)
8732 g_em->src_offset_x = cx * step;
8733 g_em->src_offset_y = cy * step;
8737 g_em->dst_offset_x = cx * step;
8738 g_em->dst_offset_y = cy * step;
8741 else /* tile where movement ends */
8743 if (dx < 0 || dy < 0)
8745 g_em->dst_offset_x = cx * step;
8746 g_em->dst_offset_y = cy * step;
8750 g_em->src_offset_x = cx * step;
8751 g_em->src_offset_y = cy * step;
8755 g_em->width = TILEX - cx * step;
8756 g_em->height = TILEY - cy * step;
8759 /* create unique graphic identifier to decide if tile must be redrawn */
8760 /* bit 31 - 16 (16 bit): EM style graphic
8761 bit 15 - 12 ( 4 bit): EM style frame
8762 bit 11 - 6 ( 6 bit): graphic width
8763 bit 5 - 0 ( 6 bit): graphic height */
8764 g_em->unique_identifier =
8765 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
8769 /* skip check for EMC elements not contained in original EMC artwork */
8770 if (element == EL_EMC_FAKE_ACID)
8773 if (g_em->bitmap != debug_bitmap ||
8774 g_em->src_x != debug_src_x ||
8775 g_em->src_y != debug_src_y ||
8776 g_em->src_offset_x != 0 ||
8777 g_em->src_offset_y != 0 ||
8778 g_em->dst_offset_x != 0 ||
8779 g_em->dst_offset_y != 0 ||
8780 g_em->width != TILEX ||
8781 g_em->height != TILEY)
8783 static int last_i = -1;
8791 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
8792 i, element, element_info[element].token_name,
8793 element_action_info[effective_action].suffix, direction);
8795 if (element != effective_element)
8796 printf(" [%d ('%s')]",
8798 element_info[effective_element].token_name);
8802 if (g_em->bitmap != debug_bitmap)
8803 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
8804 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
8806 if (g_em->src_x != debug_src_x ||
8807 g_em->src_y != debug_src_y)
8808 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
8809 j, (is_backside ? 'B' : 'F'),
8810 g_em->src_x, g_em->src_y,
8811 g_em->src_x / 32, g_em->src_y / 32,
8812 debug_src_x, debug_src_y,
8813 debug_src_x / 32, debug_src_y / 32);
8815 if (g_em->src_offset_x != 0 ||
8816 g_em->src_offset_y != 0 ||
8817 g_em->dst_offset_x != 0 ||
8818 g_em->dst_offset_y != 0)
8819 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
8821 g_em->src_offset_x, g_em->src_offset_y,
8822 g_em->dst_offset_x, g_em->dst_offset_y);
8824 if (g_em->width != TILEX ||
8825 g_em->height != TILEY)
8826 printf(" %d (%d): size %d,%d should be %d,%d\n",
8828 g_em->width, g_em->height, TILEX, TILEY);
8830 num_em_gfx_errors++;
8837 for (i = 0; i < TILE_MAX; i++)
8839 for (j = 0; j < 8; j++)
8841 int element = object_mapping[i].element_rnd;
8842 int action = object_mapping[i].action;
8843 int direction = object_mapping[i].direction;
8844 boolean is_backside = object_mapping[i].is_backside;
8845 int graphic_action = el_act_dir2img(element, action, direction);
8846 int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
8848 if ((action == ACTION_SMASHED_BY_ROCK ||
8849 action == ACTION_SMASHED_BY_SPRING ||
8850 action == ACTION_EATING) &&
8851 graphic_action == graphic_default)
8853 int e = (action == ACTION_SMASHED_BY_ROCK ? Ystone_s :
8854 action == ACTION_SMASHED_BY_SPRING ? Yspring_s :
8855 direction == MV_LEFT ? (is_backside? Yspring_wB: Yspring_w) :
8856 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
8859 /* no separate animation for "smashed by rock" -- use rock instead */
8860 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
8861 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
8863 g_em->bitmap = g_xx->bitmap;
8864 g_em->src_x = g_xx->src_x;
8865 g_em->src_y = g_xx->src_y;
8866 g_em->src_offset_x = g_xx->src_offset_x;
8867 g_em->src_offset_y = g_xx->src_offset_y;
8868 g_em->dst_offset_x = g_xx->dst_offset_x;
8869 g_em->dst_offset_y = g_xx->dst_offset_y;
8870 g_em->width = g_xx->width;
8871 g_em->height = g_xx->height;
8872 g_em->unique_identifier = g_xx->unique_identifier;
8875 g_em->preserve_background = TRUE;
8880 for (p = 0; p < MAX_PLAYERS; p++)
8882 for (i = 0; i < SPR_MAX; i++)
8884 int element = player_mapping[p][i].element_rnd;
8885 int action = player_mapping[p][i].action;
8886 int direction = player_mapping[p][i].direction;
8888 for (j = 0; j < 8; j++)
8890 int effective_element = element;
8891 int effective_action = action;
8892 int graphic = (direction == MV_NONE ?
8893 el_act2img(effective_element, effective_action) :
8894 el_act_dir2img(effective_element, effective_action,
8896 struct GraphicInfo *g = &graphic_info[graphic];
8897 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
8903 Bitmap *debug_bitmap = g_em->bitmap;
8904 int debug_src_x = g_em->src_x;
8905 int debug_src_y = g_em->src_y;
8908 int frame = getAnimationFrame(g->anim_frames,
8911 g->anim_start_frame,
8914 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
8916 g_em->bitmap = src_bitmap;
8917 g_em->src_x = src_x;
8918 g_em->src_y = src_y;
8919 g_em->src_offset_x = 0;
8920 g_em->src_offset_y = 0;
8921 g_em->dst_offset_x = 0;
8922 g_em->dst_offset_y = 0;
8923 g_em->width = TILEX;
8924 g_em->height = TILEY;
8928 /* skip check for EMC elements not contained in original EMC artwork */
8929 if (element == EL_PLAYER_3 ||
8930 element == EL_PLAYER_4)
8933 if (g_em->bitmap != debug_bitmap ||
8934 g_em->src_x != debug_src_x ||
8935 g_em->src_y != debug_src_y)
8937 static int last_i = -1;
8945 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
8946 p, i, element, element_info[element].token_name,
8947 element_action_info[effective_action].suffix, direction);
8949 if (element != effective_element)
8950 printf(" [%d ('%s')]",
8952 element_info[effective_element].token_name);
8956 if (g_em->bitmap != debug_bitmap)
8957 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
8958 j, (int)(g_em->bitmap), (int)(debug_bitmap));
8960 if (g_em->src_x != debug_src_x ||
8961 g_em->src_y != debug_src_y)
8962 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
8964 g_em->src_x, g_em->src_y,
8965 g_em->src_x / 32, g_em->src_y / 32,
8966 debug_src_x, debug_src_y,
8967 debug_src_x / 32, debug_src_y / 32);
8969 num_em_gfx_errors++;
8979 printf("::: [%d errors found]\n", num_em_gfx_errors);
8985 void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
8986 boolean any_player_moving,
8987 boolean player_is_dropping)
8989 if (tape.single_step && tape.recording && !tape.pausing)
8992 boolean active_players = FALSE;
8995 for (i = 0; i < MAX_PLAYERS; i++)
8996 if (action[i] != JOY_NO_ACTION)
8997 active_players = TRUE;
9001 if (frame == 0 && !player_is_dropping)
9002 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
9006 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
9007 boolean murphy_is_dropping)
9010 printf("::: waiting: %d, dropping: %d\n",
9011 murphy_is_waiting, murphy_is_dropping);
9014 if (tape.single_step && tape.recording && !tape.pausing)
9016 // if (murphy_is_waiting || murphy_is_dropping)
9017 if (murphy_is_waiting)
9020 printf("::: murphy is waiting -> pause mode\n");
9023 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
9028 void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
9029 int graphic, int sync_frame, int x, int y)
9031 int frame = getGraphicAnimationFrame(graphic, sync_frame);
9033 getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
9036 boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
9038 return (IS_NEXT_FRAME(sync_frame, graphic));
9041 int getGraphicInfo_Delay(int graphic)
9043 return graphic_info[graphic].anim_delay;
9046 void PlayMenuSoundExt(int sound)
9048 if (sound == SND_UNDEFINED)
9051 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
9052 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
9055 if (IS_LOOP_SOUND(sound))
9056 PlaySoundLoop(sound);
9061 void PlayMenuSound()
9063 PlayMenuSoundExt(menu.sound[game_status]);
9066 void PlayMenuSoundStereo(int sound, int stereo_position)
9068 if (sound == SND_UNDEFINED)
9071 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
9072 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
9075 if (IS_LOOP_SOUND(sound))
9076 PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP);
9078 PlaySoundStereo(sound, stereo_position);
9081 void PlayMenuSoundIfLoopExt(int sound)
9083 if (sound == SND_UNDEFINED)
9086 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
9087 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
9090 if (IS_LOOP_SOUND(sound))
9091 PlaySoundLoop(sound);
9094 void PlayMenuSoundIfLoop()
9096 PlayMenuSoundIfLoopExt(menu.sound[game_status]);
9099 void PlayMenuMusicExt(int music)
9101 if (music == MUS_UNDEFINED)
9104 if (!setup.sound_music)
9110 void PlayMenuMusic()
9112 PlayMenuMusicExt(menu.music[game_status]);
9115 void PlaySoundActivating()
9118 PlaySound(SND_MENU_ITEM_ACTIVATING);
9122 void PlaySoundSelecting()
9125 PlaySound(SND_MENU_ITEM_SELECTING);
9129 void ToggleFullscreenOrChangeWindowScalingIfNeeded()
9131 boolean change_fullscreen = (setup.fullscreen !=
9132 video.fullscreen_enabled);
9133 boolean change_fullscreen_mode = (video.fullscreen_enabled &&
9134 !strEqual(setup.fullscreen_mode,
9135 video.fullscreen_mode_current));
9136 boolean change_window_scaling_percent = (!video.fullscreen_enabled &&
9137 setup.window_scaling_percent !=
9138 video.window_scaling_percent);
9140 if (change_window_scaling_percent && video.fullscreen_enabled)
9143 if (!change_window_scaling_percent && !video.fullscreen_available)
9146 #if defined(TARGET_SDL2)
9147 if (change_window_scaling_percent)
9149 SDLSetWindowScaling(setup.window_scaling_percent);
9153 else if (change_fullscreen)
9155 SDLSetWindowFullscreen(setup.fullscreen);
9157 /* set setup value according to successfully changed fullscreen mode */
9158 setup.fullscreen = video.fullscreen_enabled;
9164 if (change_fullscreen ||
9165 change_fullscreen_mode ||
9166 change_window_scaling_percent)
9168 Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
9170 /* save backbuffer content which gets lost when toggling fullscreen mode */
9171 BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
9173 if (change_fullscreen_mode)
9175 /* keep fullscreen, but change fullscreen mode (screen resolution) */
9176 video.fullscreen_enabled = FALSE; /* force new fullscreen mode */
9179 if (change_window_scaling_percent)
9181 /* keep window mode, but change window scaling */
9182 video.fullscreen_enabled = TRUE; /* force new window scaling */
9185 /* toggle fullscreen */
9186 ChangeVideoModeIfNeeded(setup.fullscreen);
9188 /* set setup value according to successfully changed fullscreen mode */
9189 setup.fullscreen = video.fullscreen_enabled;
9191 /* restore backbuffer content from temporary backbuffer backup bitmap */
9192 BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
9194 FreeBitmap(tmp_backbuffer);
9197 /* update visible window/screen */
9198 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
9200 redraw_mask = REDRAW_ALL;
9205 void ChangeViewportPropertiesIfNeeded()
9207 int *door_1_x = &DX;
9208 int *door_1_y = &DY;
9209 int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
9210 int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
9211 int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
9212 game_status == GAME_MODE_EDITOR ? game_status :
9214 struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
9215 struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
9216 struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode];
9217 int border_size = vp_playfield->border_size;
9218 int new_sx = vp_playfield->x + border_size;
9219 int new_sy = vp_playfield->y + border_size;
9220 int new_sxsize = vp_playfield->width - 2 * border_size;
9221 int new_sysize = vp_playfield->height - 2 * border_size;
9222 int new_real_sx = vp_playfield->x;
9223 int new_real_sy = vp_playfield->y;
9224 int new_full_sxsize = vp_playfield->width;
9225 int new_full_sysize = vp_playfield->height;
9227 int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
9228 int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
9229 gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
9230 int new_scr_fieldx = new_sxsize / tilesize;
9231 int new_scr_fieldy = new_sysize / tilesize;
9232 int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var;
9233 int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
9235 int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE;
9236 int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE;
9238 boolean init_gfx_buffers = FALSE;
9239 boolean init_video_buffer = FALSE;
9240 boolean init_gadgets_and_toons = FALSE;
9243 /* !!! TEST ONLY !!! */
9244 // InitGfxBuffers();
9248 if (viewport.window.width != WIN_XSIZE ||
9249 viewport.window.height != WIN_YSIZE)
9251 WIN_XSIZE = viewport.window.width;
9252 WIN_YSIZE = viewport.window.height;
9255 init_video_buffer = TRUE;
9256 init_gfx_buffers = TRUE;
9258 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
9262 SetDrawDeactivationMask(REDRAW_NONE);
9263 SetDrawBackgroundMask(REDRAW_FIELD);
9265 // RedrawBackground();
9269 // printf("::: video: init_video_buffer, init_gfx_buffers\n");
9272 if (new_scr_fieldx != SCR_FIELDX ||
9273 new_scr_fieldy != SCR_FIELDY)
9275 /* this always toggles between MAIN and GAME when using small tile size */
9277 SCR_FIELDX = new_scr_fieldx;
9278 SCR_FIELDY = new_scr_fieldy;
9280 // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
9284 if (new_tilesize_var != TILESIZE_VAR &&
9285 gfx_game_mode == GAME_MODE_PLAYING)
9287 /* doing this outside GAME_MODE_PLAYING would give wrong playfield size */
9289 TILESIZE_VAR = new_tilesize_var;
9291 init_gfx_buffers = TRUE;
9293 // printf("::: tilesize: init_gfx_buffers\n");
9299 new_sxsize != SXSIZE ||
9300 new_sysize != SYSIZE ||
9301 new_real_sx != REAL_SX ||
9302 new_real_sy != REAL_SY ||
9303 new_full_sxsize != FULL_SXSIZE ||
9304 new_full_sysize != FULL_SYSIZE ||
9305 new_tilesize_var != TILESIZE_VAR ||
9306 vp_door_1->x != *door_1_x ||
9307 vp_door_1->y != *door_1_y ||
9308 vp_door_2->x != *door_2_x ||
9309 vp_door_2->y != *door_2_y)
9313 SXSIZE = new_sxsize;
9314 SYSIZE = new_sysize;
9315 REAL_SX = new_real_sx;
9316 REAL_SY = new_real_sy;
9317 FULL_SXSIZE = new_full_sxsize;
9318 FULL_SYSIZE = new_full_sysize;
9319 TILESIZE_VAR = new_tilesize_var;
9322 printf("::: %d, %d, %d [%d]\n",
9323 SCR_FIELDX, SCR_FIELDY, TILESIZE_VAR,
9324 setup.small_game_graphics);
9327 *door_1_x = vp_door_1->x;
9328 *door_1_y = vp_door_1->y;
9329 *door_2_x = vp_door_2->x;
9330 *door_2_y = vp_door_2->y;
9333 init_gfx_buffers = TRUE;
9335 // printf("::: viewports: init_gfx_buffers\n");
9340 if (gfx_game_mode == GAME_MODE_MAIN)
9343 init_gadgets_and_toons = TRUE;
9345 // printf("::: viewports: init_gadgets_and_toons\n");
9353 if (init_gfx_buffers)
9355 // printf("::: init_gfx_buffers\n");
9357 SCR_FIELDX = new_scr_fieldx_buffers;
9358 SCR_FIELDY = new_scr_fieldy_buffers;
9362 SCR_FIELDX = new_scr_fieldx;
9363 SCR_FIELDY = new_scr_fieldy;
9366 if (init_video_buffer)
9368 // printf("::: init_video_buffer\n");
9370 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
9372 SetDrawDeactivationMask(REDRAW_NONE);
9373 SetDrawBackgroundMask(REDRAW_FIELD);
9376 if (init_gadgets_and_toons)
9378 // printf("::: init_gadgets_and_toons\n");
9385 printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status);