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 /* !!! TEST ONLY !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1 */
400 /* (force full redraw) */
401 if (game_status == GAME_MODE_PLAYING)
402 redraw_mask |= REDRAW_FIELD;
405 if (redraw_mask & REDRAW_FIELD)
406 redraw_mask &= ~REDRAW_TILES;
408 if (redraw_mask == REDRAW_NONE)
411 if (redraw_mask & REDRAW_TILES &&
412 game_status == GAME_MODE_PLAYING &&
413 border.draw_masked[GAME_MODE_PLAYING])
414 redraw_mask |= REDRAW_FIELD;
416 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
418 static boolean last_frame_skipped = FALSE;
419 boolean skip_even_when_not_scrolling = TRUE;
420 boolean just_scrolling = (ScreenMovDir != 0);
421 boolean verbose = FALSE;
423 if (global.fps_slowdown_factor > 1 &&
424 (FrameCounter % global.fps_slowdown_factor) &&
425 (just_scrolling || skip_even_when_not_scrolling))
427 redraw_mask &= ~REDRAW_MAIN;
429 last_frame_skipped = TRUE;
432 printf("FRAME SKIPPED\n");
436 if (last_frame_skipped)
437 redraw_mask |= REDRAW_FIELD;
439 last_frame_skipped = FALSE;
442 printf("frame not skipped\n");
446 /* synchronize X11 graphics at this point; if we would synchronize the
447 display immediately after the buffer switching (after the XFlush),
448 this could mean that we have to wait for the graphics to complete,
449 although we could go on doing calculations for the next frame */
453 /* never draw masked border to backbuffer when using playfield buffer */
454 if (game_status != GAME_MODE_PLAYING ||
455 redraw_mask & REDRAW_FROM_BACKBUFFER ||
456 buffer == backbuffer)
457 DrawMaskedBorder(redraw_mask);
459 DrawMaskedBorder(redraw_mask & REDRAW_DOORS);
461 if (redraw_mask & REDRAW_ALL)
463 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
465 redraw_mask = REDRAW_NONE;
468 if (redraw_mask & REDRAW_FIELD)
471 printf("::: REDRAW_FIELD\n");
474 if (game_status != GAME_MODE_PLAYING ||
475 redraw_mask & REDRAW_FROM_BACKBUFFER)
477 BlitBitmap(backbuffer, window,
478 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
483 BlitScreenToBitmap(window);
485 int fx = FX, fy = FY;
488 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
489 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
490 int dx_var = dx * TILESIZE_VAR / TILESIZE;
491 int dy_var = dy * TILESIZE_VAR / TILESIZE;
494 // fx += dx * TILESIZE_VAR / TILESIZE;
495 // fy += dy * TILESIZE_VAR / TILESIZE;
497 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
498 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
501 /* !!! THIS WORKS !!! */
503 printf("::: %d, %d\n", scroll_x, scroll_y);
505 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
506 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
508 if (EVEN(SCR_FIELDX))
510 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
511 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
513 fx += (dx > 0 ? TILEX_VAR : 0);
520 if (EVEN(SCR_FIELDY))
522 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
523 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
525 fy += (dy > 0 ? TILEY_VAR : 0);
532 if (border.draw_masked[GAME_MODE_PLAYING])
534 if (buffer != backbuffer)
536 /* copy playfield buffer to backbuffer to add masked border */
537 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
538 DrawMaskedBorder(REDRAW_FIELD);
541 BlitBitmap(backbuffer, window,
542 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
547 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
553 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
555 (setup.soft_scrolling ?
556 "setup.soft_scrolling" :
557 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
558 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
559 ABS(ScreenGfxPos) == ScrollStepSize ?
560 "ABS(ScreenGfxPos) == ScrollStepSize" :
561 "redraw_tiles > REDRAWTILES_THRESHOLD"));
566 redraw_mask &= ~REDRAW_MAIN;
569 if (redraw_mask & REDRAW_DOORS)
571 if (redraw_mask & REDRAW_DOOR_1)
572 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
574 if (redraw_mask & REDRAW_DOOR_2)
575 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
577 if (redraw_mask & REDRAW_DOOR_3)
578 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
580 redraw_mask &= ~REDRAW_DOORS;
583 if (redraw_mask & REDRAW_MICROLEVEL)
585 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
586 SX, SY + 10 * TILEY);
588 redraw_mask &= ~REDRAW_MICROLEVEL;
591 if (redraw_mask & REDRAW_TILES)
594 printf("::: REDRAW_TILES\n");
600 InitGfxClipRegion(TRUE, SX, SY, SXSIZE, SYSIZE);
603 int sx = SX; // - (EVEN(SCR_FIELDX) ? TILEX_VAR / 2 : 0);
604 int sy = SY; // + (EVEN(SCR_FIELDY) ? TILEY_VAR / 2 : 0);
607 int dx_var = dx * TILESIZE_VAR / TILESIZE;
608 int dy_var = dy * TILESIZE_VAR / TILESIZE;
610 int fx = FX, fy = FY;
612 int scr_fieldx = SCR_FIELDX + (EVEN(SCR_FIELDX) ? 2 : 0);
613 int scr_fieldy = SCR_FIELDY + (EVEN(SCR_FIELDY) ? 2 : 0);
615 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
616 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
618 if (EVEN(SCR_FIELDX))
620 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
622 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
631 fx += (dx_var > 0 ? TILEX_VAR : 0);
635 if (EVEN(SCR_FIELDY))
637 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
639 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
648 fy += (dy_var > 0 ? TILEY_VAR : 0);
653 printf("::: %d, %d, %d, %d\n", sx, sy, SCR_FIELDX, SCR_FIELDY);
656 for (x = 0; x < scr_fieldx; x++)
657 for (y = 0 ; y < scr_fieldy; y++)
658 if (redraw[redraw_x1 + x][redraw_y1 + y])
659 BlitBitmap(buffer, window,
660 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
661 TILEX_VAR, TILEY_VAR,
662 sx + x * TILEX_VAR, sy + y * TILEY_VAR);
665 InitGfxClipRegion(FALSE, -1, -1, -1, -1);
667 for (x = 0; x < SCR_FIELDX; x++)
668 for (y = 0 ; y < SCR_FIELDY; y++)
669 if (redraw[redraw_x1 + x][redraw_y1 + y])
670 BlitBitmap(buffer, window,
671 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
672 TILEX_VAR, TILEY_VAR,
673 SX + x * TILEX_VAR, SY + y * TILEY_VAR);
677 for (x = 0; x < SCR_FIELDX; x++)
678 for (y = 0 ; y < SCR_FIELDY; y++)
679 if (redraw[redraw_x1 + x][redraw_y1 + y])
680 BlitBitmap(buffer, window,
681 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
682 SX + x * TILEX, SY + y * TILEY);
686 if (redraw_mask & REDRAW_FPS) /* display frames per second */
691 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
692 if (!global.fps_slowdown)
695 sprintf(text, "%04.1f fps%s", global.frames_per_second, info1);
697 DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE);
699 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
705 for (x = 0; x < MAX_BUF_XSIZE; x++)
706 for (y = 0; y < MAX_BUF_YSIZE; y++)
709 redraw_mask = REDRAW_NONE;
712 static void FadeCrossSaveBackbuffer()
714 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
717 static void FadeExt(int fade_mask, int fade_mode, int fade_type)
719 static int fade_type_skip = FADE_TYPE_NONE;
720 void (*draw_border_function)(void) = NULL;
721 Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL);
722 int x, y, width, height;
723 int fade_delay, post_delay;
725 if (fade_type == FADE_TYPE_FADE_OUT)
727 if (fade_type_skip != FADE_TYPE_NONE)
730 printf("::: skipping %d ... [%d] (X)\n", fade_mode, fade_type_skip);
733 /* skip all fade operations until specified fade operation */
734 if (fade_type & fade_type_skip)
735 fade_type_skip = FADE_TYPE_NONE;
740 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
742 FadeCrossSaveBackbuffer();
748 redraw_mask |= fade_mask;
750 if (fade_type == FADE_TYPE_SKIP)
753 printf("::: will skip %d ... [%d]\n", fade_mode, fade_type_skip);
756 fade_type_skip = fade_mode;
762 printf("::: !!! FADING %d ... [%d] [%d]\n", fade_mode, fade_type,
767 fade_delay = fading.fade_delay;
768 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
771 if (fade_type_skip != FADE_TYPE_NONE)
774 printf("::: skipping %d ... [%d]\n", fade_mode, fade_type_skip);
777 /* skip all fade operations until specified fade operation */
778 if (fade_type & fade_type_skip)
779 fade_type_skip = FADE_TYPE_NONE;
789 if (global.autoplay_leveldir)
791 // fading.fade_mode = FADE_MODE_NONE;
798 if (fading.fade_mode == FADE_MODE_NONE)
806 /* !!! what about fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */
809 printf("::: NOW FADING %d ... [%d]\n", fade_mode, fade_type);
813 if (fade_mask == REDRAW_NONE)
814 fade_mask = REDRAW_FIELD;
817 // if (fade_mask & REDRAW_FIELD)
818 if (fade_mask == REDRAW_FIELD)
823 height = FULL_SYSIZE;
826 fade_delay = fading.fade_delay;
827 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
830 if (border.draw_masked_when_fading)
831 draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */
833 DrawMaskedBorder_FIELD(); /* draw once */
835 else /* REDRAW_ALL */
843 fade_delay = fading.fade_delay;
844 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
849 if (!setup.fade_screens ||
851 fading.fade_mode == FADE_MODE_NONE)
853 if (!setup.fade_screens || fade_delay == 0)
856 if (fade_mode == FADE_MODE_FADE_OUT)
860 if (fade_mode == FADE_MODE_FADE_OUT &&
861 fading.fade_mode != FADE_MODE_NONE)
862 ClearRectangle(backbuffer, x, y, width, height);
866 BlitBitmap(backbuffer, window, x, y, width, height, x, y);
867 redraw_mask = REDRAW_NONE;
875 FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay,
876 draw_border_function);
878 redraw_mask &= ~fade_mask;
881 void FadeIn(int fade_mask)
883 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
884 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN);
886 FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN);
889 void FadeOut(int fade_mask)
891 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
892 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_OUT);
894 FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT);
896 global.border_status = game_status;
899 static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set)
901 static struct TitleFadingInfo fading_leave_stored;
904 fading_leave_stored = fading_leave;
906 fading = fading_leave_stored;
909 void FadeSetEnterMenu()
911 fading = menu.enter_menu;
914 printf("::: storing enter_menu\n");
917 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
920 void FadeSetLeaveMenu()
922 fading = menu.leave_menu;
925 printf("::: storing leave_menu\n");
928 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
931 void FadeSetEnterScreen()
933 fading = menu.enter_screen[game_status];
936 printf("::: storing leave_screen[%d]\n", game_status);
939 FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */
942 void FadeSetNextScreen()
944 fading = menu.next_screen;
947 printf("::: storing next_screen\n");
950 // (do not overwrite fade mode set by FadeSetEnterScreen)
951 // FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
954 void FadeSetLeaveScreen()
957 printf("::: recalling last stored value\n");
960 FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */
963 void FadeSetFromType(int type)
965 if (type & TYPE_ENTER_SCREEN)
966 FadeSetEnterScreen();
967 else if (type & TYPE_ENTER)
969 else if (type & TYPE_LEAVE)
973 void FadeSetDisabled()
975 static struct TitleFadingInfo fading_none = { FADE_MODE_NONE, -1, -1, -1 };
977 fading = fading_none;
980 void FadeSkipNextFadeIn()
982 FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP);
985 void FadeSkipNextFadeOut()
987 FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
990 void SetWindowBackgroundImageIfDefined(int graphic)
992 if (graphic_info[graphic].bitmap)
993 SetWindowBackgroundBitmap(graphic_info[graphic].bitmap);
996 void SetMainBackgroundImageIfDefined(int graphic)
998 if (graphic_info[graphic].bitmap)
999 SetMainBackgroundBitmap(graphic_info[graphic].bitmap);
1002 void SetDoorBackgroundImageIfDefined(int graphic)
1004 if (graphic_info[graphic].bitmap)
1005 SetDoorBackgroundBitmap(graphic_info[graphic].bitmap);
1008 void SetWindowBackgroundImage(int graphic)
1010 SetWindowBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1011 graphic_info[graphic].bitmap ?
1012 graphic_info[graphic].bitmap :
1013 graphic_info[IMG_BACKGROUND].bitmap);
1016 void SetMainBackgroundImage(int graphic)
1018 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1019 graphic_info[graphic].bitmap ?
1020 graphic_info[graphic].bitmap :
1021 graphic_info[IMG_BACKGROUND].bitmap);
1024 void SetDoorBackgroundImage(int graphic)
1026 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1027 graphic_info[graphic].bitmap ?
1028 graphic_info[graphic].bitmap :
1029 graphic_info[IMG_BACKGROUND].bitmap);
1032 void SetPanelBackground()
1035 struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL];
1038 BlitBitmapTiled(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1039 gfx->width, gfx->height, 0, 0, DXSIZE, DYSIZE);
1041 /* (ClearRectangle() only needed if panel bitmap is smaller than panel) */
1042 ClearRectangle(bitmap_db_panel, DX, DY, DXSIZE, DYSIZE);
1043 BlitBitmap(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1044 MIN(gfx->width, DXSIZE), MIN(gfx->height, DYSIZE), 0, 0);
1047 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, bitmap_db_panel,
1048 DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, 0, 0);
1051 SetDoorBackgroundBitmap(bitmap_db_panel);
1054 void DrawBackground(int x, int y, int width, int height)
1056 /* !!! "drawto" might still point to playfield buffer here (see below) !!! */
1057 /* (when entering hall of fame after playing) */
1059 ClearRectangleOnBackground(drawto, x, y, width, height);
1061 ClearRectangleOnBackground(backbuffer, x, y, width, height);
1064 redraw_mask |= REDRAW_FIELD;
1067 void DrawBackgroundForFont(int x, int y, int width, int height, int font_nr)
1069 struct FontBitmapInfo *font = getFontBitmapInfo(font_nr);
1071 if (font->bitmap == NULL)
1074 DrawBackground(x, y, width, height);
1077 void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic)
1079 struct GraphicInfo *g = &graphic_info[graphic];
1081 if (g->bitmap == NULL)
1084 DrawBackground(x, y, width, height);
1089 /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
1090 /* (when entering hall of fame after playing) */
1091 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
1093 /* !!! maybe this should be done before clearing the background !!! */
1094 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
1096 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
1097 SetDrawtoField(DRAW_BUFFERED);
1100 SetDrawtoField(DRAW_BACKBUFFER);
1103 void MarkTileDirty(int x, int y)
1105 int xx = redraw_x1 + x;
1106 int yy = redraw_y1 + y;
1108 if (!redraw[xx][yy])
1111 redraw[xx][yy] = TRUE;
1112 redraw_mask |= REDRAW_TILES;
1115 void SetBorderElement()
1119 BorderElement = EL_EMPTY;
1121 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
1123 for (x = 0; x < lev_fieldx; x++)
1125 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
1126 BorderElement = EL_STEELWALL;
1128 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
1134 void FloodFillLevel(int from_x, int from_y, int fill_element,
1135 short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
1136 int max_fieldx, int max_fieldy)
1140 static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
1141 static int safety = 0;
1143 /* check if starting field still has the desired content */
1144 if (field[from_x][from_y] == fill_element)
1149 if (safety > max_fieldx * max_fieldy)
1150 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
1152 old_element = field[from_x][from_y];
1153 field[from_x][from_y] = fill_element;
1155 for (i = 0; i < 4; i++)
1157 x = from_x + check[i][0];
1158 y = from_y + check[i][1];
1160 if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
1161 FloodFillLevel(x, y, fill_element, field, max_fieldx, max_fieldy);
1167 void SetRandomAnimationValue(int x, int y)
1169 gfx.anim_random_frame = GfxRandom[x][y];
1172 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
1174 /* animation synchronized with global frame counter, not move position */
1175 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
1176 sync_frame = FrameCounter;
1178 return getAnimationFrame(graphic_info[graphic].anim_frames,
1179 graphic_info[graphic].anim_delay,
1180 graphic_info[graphic].anim_mode,
1181 graphic_info[graphic].anim_start_frame,
1185 void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw,
1186 Bitmap **bitmap, int *x, int *y,
1187 boolean get_backside)
1191 int width_mult, width_div;
1192 int height_mult, height_div;
1196 { 15, 16, 2, 3 }, /* 1 x 1 */
1197 { 7, 8, 2, 3 }, /* 2 x 2 */
1198 { 3, 4, 2, 3 }, /* 4 x 4 */
1199 { 1, 2, 2, 3 }, /* 8 x 8 */
1200 { 0, 1, 2, 3 }, /* 16 x 16 */
1201 { 0, 1, 0, 1 }, /* 32 x 32 */
1203 struct GraphicInfo *g = &graphic_info[graphic];
1204 Bitmap *src_bitmap = g->bitmap;
1205 int tilesize = MIN(MAX(1, tilesize_raw), TILESIZE);
1206 int offset_calc_pos = log_2(tilesize);
1207 int width_mult = offset_calc[offset_calc_pos].width_mult;
1208 int width_div = offset_calc[offset_calc_pos].width_div;
1209 int height_mult = offset_calc[offset_calc_pos].height_mult;
1210 int height_div = offset_calc[offset_calc_pos].height_div;
1211 int startx = src_bitmap->width * width_mult / width_div;
1212 int starty = src_bitmap->height * height_mult / height_div;
1214 int src_x = (g->src_x + (get_backside ? g->offset2_x : 0)) *
1215 tilesize / TILESIZE;
1216 int src_y = (g->src_y + (get_backside ? g->offset2_y : 0)) *
1217 tilesize / TILESIZE;
1219 int src_x = g->src_x * tilesize / TILESIZE;
1220 int src_y = g->src_y * tilesize / TILESIZE;
1222 int width = g->width * tilesize / TILESIZE;
1223 int height = g->height * tilesize / TILESIZE;
1224 int offset_x = g->offset_x * tilesize / TILESIZE;
1225 int offset_y = g->offset_y * tilesize / TILESIZE;
1227 if (g->offset_y == 0) /* frames are ordered horizontally */
1229 int max_width = g->anim_frames_per_line * width;
1230 int pos = (src_y / height) * max_width + src_x + frame * offset_x;
1232 src_x = pos % max_width;
1233 src_y = src_y % height + pos / max_width * height;
1235 else if (g->offset_x == 0) /* frames are ordered vertically */
1237 int max_height = g->anim_frames_per_line * height;
1238 int pos = (src_x / width) * max_height + src_y + frame * offset_y;
1240 src_x = src_x % width + pos / max_height * width;
1241 src_y = pos % max_height;
1243 else /* frames are ordered diagonally */
1245 src_x = src_x + frame * offset_x;
1246 src_y = src_y + frame * offset_y;
1249 *bitmap = src_bitmap;
1250 *x = startx + src_x;
1251 *y = starty + src_y;
1254 void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1255 int *x, int *y, boolean get_backside)
1257 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y,
1261 void getSizedGraphicSource(int graphic, int frame, int tilesize_raw,
1262 Bitmap **bitmap, int *x, int *y)
1264 getSizedGraphicSourceExt(graphic, frame, tilesize_raw, bitmap, x, y, FALSE);
1267 void getFixedGraphicSource(int graphic, int frame,
1268 Bitmap **bitmap, int *x, int *y)
1270 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y, FALSE);
1273 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1276 getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
1278 struct GraphicInfo *g = &graphic_info[graphic];
1279 int mini_startx = 0;
1280 int mini_starty = g->bitmap->height * 2 / 3;
1282 *bitmap = g->bitmap;
1283 *x = mini_startx + g->src_x / 2;
1284 *y = mini_starty + g->src_y / 2;
1288 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1289 int *x, int *y, boolean get_backside)
1291 struct GraphicInfo *g = &graphic_info[graphic];
1292 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
1293 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
1296 if (TILESIZE_VAR != TILESIZE)
1297 return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
1301 *bitmap = g->bitmap;
1303 if (g->offset_y == 0) /* frames are ordered horizontally */
1305 int max_width = g->anim_frames_per_line * g->width;
1306 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
1308 *x = pos % max_width;
1309 *y = src_y % g->height + pos / max_width * g->height;
1311 else if (g->offset_x == 0) /* frames are ordered vertically */
1313 int max_height = g->anim_frames_per_line * g->height;
1314 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
1316 *x = src_x % g->width + pos / max_height * g->width;
1317 *y = pos % max_height;
1319 else /* frames are ordered diagonally */
1321 *x = src_x + frame * g->offset_x;
1322 *y = src_y + frame * g->offset_y;
1326 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
1328 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
1331 void DrawGraphic(int x, int y, int graphic, int frame)
1334 if (!IN_SCR_FIELD(x, y))
1336 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1337 printf("DrawGraphic(): This should never happen!\n");
1343 DrawGraphicExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR, graphic,
1346 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
1348 MarkTileDirty(x, y);
1351 void DrawFixedGraphic(int x, int y, int graphic, int frame)
1354 if (!IN_SCR_FIELD(x, y))
1356 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1357 printf("DrawGraphic(): This should never happen!\n");
1362 DrawFixedGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1364 MarkTileDirty(x, y);
1367 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1373 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1375 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX_VAR, TILEY_VAR, x, y);
1377 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1381 void DrawFixedGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1387 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1388 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1391 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
1394 if (!IN_SCR_FIELD(x, y))
1396 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1397 printf("DrawGraphicThruMask(): This should never happen!\n");
1403 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
1406 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1409 MarkTileDirty(x, y);
1412 void DrawFixedGraphicThruMask(int x, int y, int graphic, int frame)
1415 if (!IN_SCR_FIELD(x, y))
1417 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1418 printf("DrawGraphicThruMask(): This should never happen!\n");
1423 DrawFixedGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1425 MarkTileDirty(x, y);
1428 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
1434 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1436 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1437 dst_x - src_x, dst_y - src_y);
1439 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX_VAR, TILEY_VAR,
1442 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1446 void DrawFixedGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y,
1447 int graphic, int frame)
1452 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1454 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1455 dst_x - src_x, dst_y - src_y);
1456 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1459 void DrawSizedGraphic(int x, int y, int graphic, int frame, int tilesize)
1461 DrawSizedGraphicExt(drawto, SX + x * tilesize, SY + y * tilesize, graphic,
1463 MarkTileDirty(x / tilesize, y / tilesize);
1466 void DrawSizedGraphicExt(DrawBuffer *d, int x, int y, int graphic, int frame,
1472 getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
1473 BlitBitmap(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
1476 void DrawMiniGraphic(int x, int y, int graphic)
1478 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1479 MarkTileDirty(x / 2, y / 2);
1482 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1487 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1488 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1491 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
1492 int graphic, int frame,
1493 int cut_mode, int mask_mode)
1498 int width = TILEX, height = TILEY;
1501 if (dx || dy) /* shifted graphic */
1503 if (x < BX1) /* object enters playfield from the left */
1510 else if (x > BX2) /* object enters playfield from the right */
1516 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1522 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1524 else if (dx) /* general horizontal movement */
1525 MarkTileDirty(x + SIGN(dx), y);
1527 if (y < BY1) /* object enters playfield from the top */
1529 if (cut_mode==CUT_BELOW) /* object completely above top border */
1537 else if (y > BY2) /* object enters playfield from the bottom */
1543 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1549 else if (dy > 0 && cut_mode == CUT_ABOVE)
1551 if (y == BY2) /* object completely above bottom border */
1557 MarkTileDirty(x, y + 1);
1558 } /* object leaves playfield to the bottom */
1559 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1561 else if (dy) /* general vertical movement */
1562 MarkTileDirty(x, y + SIGN(dy));
1566 if (!IN_SCR_FIELD(x, y))
1568 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1569 printf("DrawGraphicShifted(): This should never happen!\n");
1575 width = width * TILESIZE_VAR / TILESIZE;
1576 height = height * TILESIZE_VAR / TILESIZE;
1577 cx = cx * TILESIZE_VAR / TILESIZE;
1578 cy = cy * TILESIZE_VAR / TILESIZE;
1579 dx = dx * TILESIZE_VAR / TILESIZE;
1580 dy = dy * TILESIZE_VAR / TILESIZE;
1583 if (width > 0 && height > 0)
1585 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1591 dst_x = FX + x * TILEX_VAR + dx;
1592 dst_y = FY + y * TILEY_VAR + dy;
1594 dst_x = FX + x * TILEX + dx;
1595 dst_y = FY + y * TILEY + dy;
1598 if (mask_mode == USE_MASKING)
1600 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1601 dst_x - src_x, dst_y - src_y);
1602 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1606 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1609 MarkTileDirty(x, y);
1613 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
1614 int graphic, int frame,
1615 int cut_mode, int mask_mode)
1621 int width = TILEX_VAR, height = TILEY_VAR;
1623 int width = TILEX, height = TILEY;
1627 int x2 = x + SIGN(dx);
1628 int y2 = y + SIGN(dy);
1630 /* !!! DOES NOT WORK FOR SLOW MOVEMENT !!! */
1631 int sync_frame = GfxFrame[LEVELX(x)][LEVELY(y)];
1633 /* movement with two-tile animations must be sync'ed with movement position,
1634 not with current GfxFrame (which can be higher when using slow movement) */
1635 int anim_pos = (dx ? ABS(dx) : ABS(dy));
1636 int anim_frames = graphic_info[graphic].anim_frames;
1638 /* (we also need anim_delay here for movement animations with less frames) */
1639 int anim_delay = graphic_info[graphic].anim_delay;
1640 int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
1642 int sync_frame = anim_pos * anim_frames / TILESIZE;
1645 boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */
1646 boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */
1648 /* re-calculate animation frame for two-tile movement animation */
1649 frame = getGraphicAnimationFrame(graphic, sync_frame);
1653 printf("::: %d, %d, %d => %d [%d]\n",
1654 anim_pos, anim_frames, anim_delay, sync_frame, graphic);
1656 printf("::: %d, %d => %d\n",
1657 anim_pos, anim_frames, sync_frame);
1662 printf("::: %d [%d, %d] [%d] [%d]\n", frame, sync_frame, dy,
1663 GfxFrame[LEVELX(x)][LEVELY(y)], mask_mode);
1666 /* check if movement start graphic inside screen area and should be drawn */
1667 if (draw_start_tile && IN_SCR_FIELD(x1, y1))
1669 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
1672 dst_x = FX + x1 * TILEX_VAR;
1673 dst_y = FY + y1 * TILEY_VAR;
1675 dst_x = FX + x1 * TILEX;
1676 dst_y = FY + y1 * TILEY;
1679 if (mask_mode == USE_MASKING)
1681 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1682 dst_x - src_x, dst_y - src_y);
1683 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1687 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1690 MarkTileDirty(x1, y1);
1693 /* check if movement end graphic inside screen area and should be drawn */
1694 if (draw_end_tile && IN_SCR_FIELD(x2, y2))
1696 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
1699 dst_x = FX + x2 * TILEX_VAR;
1700 dst_y = FY + y2 * TILEY_VAR;
1702 dst_x = FX + x2 * TILEX;
1703 dst_y = FY + y2 * TILEY;
1706 if (mask_mode == USE_MASKING)
1708 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1709 dst_x - src_x, dst_y - src_y);
1710 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1714 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1717 MarkTileDirty(x2, y2);
1721 static void DrawGraphicShifted(int x, int y, int dx, int dy,
1722 int graphic, int frame,
1723 int cut_mode, int mask_mode)
1727 DrawGraphic(x, y, graphic, frame);
1732 if (graphic_info[graphic].double_movement) /* EM style movement images */
1733 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1735 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1738 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1739 int frame, int cut_mode)
1741 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1744 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1745 int cut_mode, int mask_mode)
1747 int lx = LEVELX(x), ly = LEVELY(y);
1751 if (IN_LEV_FIELD(lx, ly))
1753 SetRandomAnimationValue(lx, ly);
1755 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1756 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1758 /* do not use double (EM style) movement graphic when not moving */
1759 if (graphic_info[graphic].double_movement && !dx && !dy)
1761 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
1762 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1765 else /* border element */
1767 graphic = el2img(element);
1768 frame = getGraphicAnimationFrame(graphic, -1);
1771 if (element == EL_EXPANDABLE_WALL)
1773 boolean left_stopped = FALSE, right_stopped = FALSE;
1775 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1776 left_stopped = TRUE;
1777 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1778 right_stopped = TRUE;
1780 if (left_stopped && right_stopped)
1782 else if (left_stopped)
1784 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1785 frame = graphic_info[graphic].anim_frames - 1;
1787 else if (right_stopped)
1789 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1790 frame = graphic_info[graphic].anim_frames - 1;
1795 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1796 else if (mask_mode == USE_MASKING)
1797 DrawGraphicThruMask(x, y, graphic, frame);
1799 DrawGraphic(x, y, graphic, frame);
1802 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1803 int cut_mode, int mask_mode)
1805 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1806 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1807 cut_mode, mask_mode);
1810 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1813 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1816 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1819 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1822 void DrawLevelElementThruMask(int x, int y, int element)
1824 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1827 void DrawLevelFieldThruMask(int x, int y)
1829 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1832 /* !!! implementation of quicksand is totally broken !!! */
1833 #define IS_CRUMBLED_TILE(x, y, e) \
1834 (GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) || \
1835 !IS_MOVING(x, y) || \
1836 (e) == EL_QUICKSAND_EMPTYING || \
1837 (e) == EL_QUICKSAND_FAST_EMPTYING))
1839 static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
1844 int width, height, cx, cy;
1845 int sx = SCREENX(x), sy = SCREENY(y);
1846 int crumbled_border_size = graphic_info[graphic].border_size;
1849 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1851 for (i = 1; i < 4; i++)
1853 int dxx = (i & 1 ? dx : 0);
1854 int dyy = (i & 2 ? dy : 0);
1857 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1860 /* check if neighbour field is of same crumble type */
1861 boolean same = (IS_CRUMBLED_TILE(xx, yy, element) &&
1862 graphic_info[graphic].class ==
1863 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class);
1865 /* return if check prevents inner corner */
1866 if (same == (dxx == dx && dyy == dy))
1870 /* if we reach this point, we have an inner corner */
1872 getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
1875 width = crumbled_border_size * TILESIZE_VAR / TILESIZE;
1876 height = crumbled_border_size * TILESIZE_VAR / TILESIZE;
1877 cx = (dx > 0 ? TILEX - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
1878 cy = (dy > 0 ? TILEY - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
1880 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1881 width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
1883 width = crumbled_border_size;
1884 height = crumbled_border_size;
1885 cx = (dx > 0 ? TILEX - crumbled_border_size : 0);
1886 cy = (dy > 0 ? TILEY - crumbled_border_size : 0);
1888 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1889 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1893 static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
1898 int width, height, bx, by, cx, cy;
1899 int sx = SCREENX(x), sy = SCREENY(y);
1900 int crumbled_border_size = graphic_info[graphic].border_size;
1903 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1905 /* draw simple, sloppy, non-corner-accurate crumbled border */
1908 width = (dir == 1 || dir == 2 ? crumbled_border_size : TILEX);
1909 height = (dir == 0 || dir == 3 ? crumbled_border_size : TILEY);
1910 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
1911 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
1913 if (dir == 1 || dir == 2) /* left or right crumbled border */
1915 width = crumbled_border_size;
1917 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
1920 else /* top or bottom crumbled border */
1923 height = crumbled_border_size;
1925 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
1930 BlitBitmap(src_bitmap, drawto_field,
1931 src_x + cx * TILESIZE_VAR / TILESIZE,
1932 src_y + cy * TILESIZE_VAR / TILESIZE,
1933 width * TILESIZE_VAR / TILESIZE,
1934 height * TILESIZE_VAR / TILESIZE,
1935 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
1936 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
1938 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1939 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1942 /* (remaining middle border part must be at least as big as corner part) */
1943 if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
1944 crumbled_border_size >= TILESIZE / 3)
1947 /* correct corners of crumbled border, if needed */
1950 for (i = -1; i <= 1; i+=2)
1952 int xx = x + (dir == 0 || dir == 3 ? i : 0);
1953 int yy = y + (dir == 1 || dir == 2 ? i : 0);
1954 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1957 /* check if neighbour field is of same crumble type */
1958 if (IS_CRUMBLED_TILE(xx, yy, element) &&
1959 graphic_info[graphic].class ==
1960 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
1962 /* no crumbled corner, but continued crumbled border */
1964 int c1 = (dir == 2 || dir == 3 ? TILESIZE - crumbled_border_size : 0);
1965 int c2 = (i == 1 ? TILESIZE - crumbled_border_size : 0);
1966 int b1 = (i == 1 ? crumbled_border_size :
1967 TILESIZE - 2 * crumbled_border_size);
1969 width = crumbled_border_size;
1970 height = crumbled_border_size;
1972 if (dir == 1 || dir == 2)
1988 BlitBitmap(src_bitmap, drawto_field,
1989 src_x + bx * TILESIZE_VAR / TILESIZE,
1990 src_y + by * TILESIZE_VAR / TILESIZE,
1991 width * TILESIZE_VAR / TILESIZE,
1992 height * TILESIZE_VAR / TILESIZE,
1993 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
1994 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
1996 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
1997 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2002 if (dir == 1 || dir == 2) /* left or right crumbled border */
2004 for (i = -1; i <= 1; i+=2)
2008 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2011 /* check if neighbour field is of same crumble type */
2012 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2013 graphic_info[graphic].class ==
2014 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2016 /* no crumbled corner, but continued crumbled border */
2018 width = crumbled_border_size;
2019 height = crumbled_border_size;
2020 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2021 cy = (i == 1 ? TILEY - crumbled_border_size : 0);
2023 by = (i == 1 ? crumbled_border_size :
2024 TILEY - 2 * crumbled_border_size);
2026 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2027 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2031 else /* top or bottom crumbled border */
2033 for (i = -1; i <= 1; i+=2)
2037 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2040 /* check if neighbour field is of same crumble type */
2041 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2042 graphic_info[graphic].class ==
2043 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2045 /* no crumbled corner, but continued crumbled border */
2047 width = crumbled_border_size;
2048 height = crumbled_border_size;
2049 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
2050 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2051 bx = (i == 1 ? crumbled_border_size :
2052 TILEX - 2 * crumbled_border_size);
2055 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2056 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2063 static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
2065 int sx = SCREENX(x), sy = SCREENY(y);
2068 static int xy[4][2] =
2076 if (!IN_LEV_FIELD(x, y))
2079 element = TILE_GFX_ELEMENT(x, y);
2081 /* crumble field itself */
2082 if (IS_CRUMBLED_TILE(x, y, element))
2084 if (!IN_SCR_FIELD(sx, sy))
2087 for (i = 0; i < 4; i++)
2089 int xx = x + xy[i][0];
2090 int yy = y + xy[i][1];
2092 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2095 /* check if neighbour field is of same crumble type */
2097 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2098 graphic_info[graphic].class ==
2099 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2102 if (IS_CRUMBLED_TILE(xx, yy, element))
2106 DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
2109 if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
2110 graphic_info[graphic].anim_frames == 2)
2112 for (i = 0; i < 4; i++)
2114 int dx = (i & 1 ? +1 : -1);
2115 int dy = (i & 2 ? +1 : -1);
2117 DrawLevelFieldCrumbledInnerCorners(x, y, dx, dy, graphic);
2121 MarkTileDirty(sx, sy);
2123 else /* center field not crumbled -- crumble neighbour fields */
2125 for (i = 0; i < 4; i++)
2127 int xx = x + xy[i][0];
2128 int yy = y + xy[i][1];
2129 int sxx = sx + xy[i][0];
2130 int syy = sy + xy[i][1];
2132 if (!IN_LEV_FIELD(xx, yy) ||
2133 !IN_SCR_FIELD(sxx, syy))
2136 if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
2139 element = TILE_GFX_ELEMENT(xx, yy);
2141 if (!IS_CRUMBLED_TILE(xx, yy, element))
2144 graphic = el_act2crm(element, ACTION_DEFAULT);
2146 DrawLevelFieldCrumbledBorders(xx, yy, graphic, 0, 3 - i);
2148 MarkTileDirty(sxx, syy);
2153 void DrawLevelFieldCrumbled(int x, int y)
2157 if (!IN_LEV_FIELD(x, y))
2161 /* !!! CHECK THIS !!! */
2164 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2165 GFX_CRUMBLED(GfxElement[x][y]))
2168 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2169 GfxElement[x][y] != EL_UNDEFINED &&
2170 GFX_CRUMBLED(GfxElement[x][y]))
2172 DrawLevelFieldCrumbledDigging(x, y, GfxDir[x][y], GfxFrame[x][y]);
2179 graphic = el_act2crm(TILE_GFX_ELEMENT(x, y), ACTION_DEFAULT);
2181 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
2184 DrawLevelFieldCrumbledExt(x, y, graphic, 0);
2187 void DrawLevelFieldCrumbledDigging(int x, int y, int direction,
2190 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
2191 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
2192 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
2193 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
2194 int sx = SCREENX(x), sy = SCREENY(y);
2196 DrawGraphic(sx, sy, graphic1, frame1);
2197 DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
2200 void DrawLevelFieldCrumbledNeighbours(int x, int y)
2202 int sx = SCREENX(x), sy = SCREENY(y);
2203 static int xy[4][2] =
2212 for (i = 0; i < 4; i++)
2214 int xx = x + xy[i][0];
2215 int yy = y + xy[i][1];
2216 int sxx = sx + xy[i][0];
2217 int syy = sy + xy[i][1];
2219 if (!IN_LEV_FIELD(xx, yy) ||
2220 !IN_SCR_FIELD(sxx, syy) ||
2221 !GFX_CRUMBLED(Feld[xx][yy]) ||
2225 DrawLevelField(xx, yy);
2229 static int getBorderElement(int x, int y)
2233 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
2234 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
2235 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
2236 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
2237 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
2238 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
2239 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
2241 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2242 int steel_position = (x == -1 && y == -1 ? 0 :
2243 x == lev_fieldx && y == -1 ? 1 :
2244 x == -1 && y == lev_fieldy ? 2 :
2245 x == lev_fieldx && y == lev_fieldy ? 3 :
2246 x == -1 || x == lev_fieldx ? 4 :
2247 y == -1 || y == lev_fieldy ? 5 : 6);
2249 return border[steel_position][steel_type];
2252 void DrawScreenElement(int x, int y, int element)
2254 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
2255 DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
2258 void DrawLevelElement(int x, int y, int element)
2260 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2261 DrawScreenElement(SCREENX(x), SCREENY(y), element);
2264 void DrawScreenField(int x, int y)
2266 int lx = LEVELX(x), ly = LEVELY(y);
2267 int element, content;
2269 if (!IN_LEV_FIELD(lx, ly))
2271 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
2274 element = getBorderElement(lx, ly);
2276 DrawScreenElement(x, y, element);
2281 element = Feld[lx][ly];
2282 content = Store[lx][ly];
2284 if (IS_MOVING(lx, ly))
2286 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
2287 boolean cut_mode = NO_CUTTING;
2289 if (element == EL_QUICKSAND_EMPTYING ||
2290 element == EL_QUICKSAND_FAST_EMPTYING ||
2291 element == EL_MAGIC_WALL_EMPTYING ||
2292 element == EL_BD_MAGIC_WALL_EMPTYING ||
2293 element == EL_DC_MAGIC_WALL_EMPTYING ||
2294 element == EL_AMOEBA_DROPPING)
2295 cut_mode = CUT_ABOVE;
2296 else if (element == EL_QUICKSAND_FILLING ||
2297 element == EL_QUICKSAND_FAST_FILLING ||
2298 element == EL_MAGIC_WALL_FILLING ||
2299 element == EL_BD_MAGIC_WALL_FILLING ||
2300 element == EL_DC_MAGIC_WALL_FILLING)
2301 cut_mode = CUT_BELOW;
2304 if (lx == 9 && ly == 1)
2305 printf("::: %s [%d] [%d, %d] [%d]\n",
2306 EL_NAME(TILE_GFX_ELEMENT(lx, ly)),
2307 el_act2crm(TILE_GFX_ELEMENT(lx, ly), ACTION_DEFAULT),
2308 element_info[EL_QUICKSAND_EMPTYING].graphic[ACTION_DEFAULT],
2309 element_info[EL_QUICKSAND_EMPTYING].crumbled[ACTION_DEFAULT],
2310 GFX_CRUMBLED(TILE_GFX_ELEMENT(lx, ly)));
2313 if (cut_mode == CUT_ABOVE)
2315 DrawScreenElement(x, y, element);
2317 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
2320 DrawScreenElement(x, y, EL_EMPTY);
2323 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
2324 else if (cut_mode == NO_CUTTING)
2325 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
2328 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
2331 if (cut_mode == CUT_BELOW &&
2332 IN_LEV_FIELD(lx, ly + 1) && IN_SCR_FIELD(x, y + 1))
2333 DrawLevelElement(lx, ly + 1, element);
2337 if (content == EL_ACID)
2339 int dir = MovDir[lx][ly];
2340 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
2341 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
2343 DrawLevelElementThruMask(newlx, newly, EL_ACID);
2346 else if (IS_BLOCKED(lx, ly))
2351 boolean cut_mode = NO_CUTTING;
2352 int element_old, content_old;
2354 Blocked2Moving(lx, ly, &oldx, &oldy);
2357 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
2358 MovDir[oldx][oldy] == MV_RIGHT);
2360 element_old = Feld[oldx][oldy];
2361 content_old = Store[oldx][oldy];
2363 if (element_old == EL_QUICKSAND_EMPTYING ||
2364 element_old == EL_QUICKSAND_FAST_EMPTYING ||
2365 element_old == EL_MAGIC_WALL_EMPTYING ||
2366 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2367 element_old == EL_DC_MAGIC_WALL_EMPTYING ||
2368 element_old == EL_AMOEBA_DROPPING)
2369 cut_mode = CUT_ABOVE;
2371 DrawScreenElement(x, y, EL_EMPTY);
2374 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2376 else if (cut_mode == NO_CUTTING)
2377 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2380 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2383 else if (IS_DRAWABLE(element))
2384 DrawScreenElement(x, y, element);
2386 DrawScreenElement(x, y, EL_EMPTY);
2389 void DrawLevelField(int x, int y)
2391 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2392 DrawScreenField(SCREENX(x), SCREENY(y));
2393 else if (IS_MOVING(x, y))
2397 Moving2Blocked(x, y, &newx, &newy);
2398 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2399 DrawScreenField(SCREENX(newx), SCREENY(newy));
2401 else if (IS_BLOCKED(x, y))
2405 Blocked2Moving(x, y, &oldx, &oldy);
2406 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2407 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2411 void DrawMiniElement(int x, int y, int element)
2415 graphic = el2edimg(element);
2416 DrawMiniGraphic(x, y, graphic);
2419 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2421 int x = sx + scroll_x, y = sy + scroll_y;
2423 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2424 DrawMiniElement(sx, sy, EL_EMPTY);
2425 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2426 DrawMiniElement(sx, sy, Feld[x][y]);
2428 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
2431 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
2432 int x, int y, int xsize, int ysize, int font_nr)
2434 int font_width = getFontWidth(font_nr);
2435 int font_height = getFontHeight(font_nr);
2436 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2439 int dst_x = SX + startx + x * font_width;
2440 int dst_y = SY + starty + y * font_height;
2441 int width = graphic_info[graphic].width;
2442 int height = graphic_info[graphic].height;
2443 int inner_width = MAX(width - 2 * font_width, font_width);
2444 int inner_height = MAX(height - 2 * font_height, font_height);
2445 int inner_sx = (width >= 3 * font_width ? font_width : 0);
2446 int inner_sy = (height >= 3 * font_height ? font_height : 0);
2447 boolean draw_masked = graphic_info[graphic].draw_masked;
2449 getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2451 if (src_bitmap == NULL || width < font_width || height < font_height)
2453 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
2457 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
2458 inner_sx + (x - 1) * font_width % inner_width);
2459 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
2460 inner_sy + (y - 1) * font_height % inner_height);
2464 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
2465 dst_x - src_x, dst_y - src_y);
2466 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
2470 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
2474 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
2476 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2477 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2478 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2479 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2480 boolean no_delay = (tape.warp_forward);
2481 unsigned int anim_delay = 0;
2482 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2483 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
2484 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2485 int font_width = getFontWidth(font_nr);
2486 int font_height = getFontHeight(font_nr);
2487 int max_xsize = level.envelope[envelope_nr].xsize;
2488 int max_ysize = level.envelope[envelope_nr].ysize;
2489 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2490 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2491 int xend = max_xsize;
2492 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2493 int xstep = (xstart < xend ? 1 : 0);
2494 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2497 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2499 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2500 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2501 int sx = (SXSIZE - xsize * font_width) / 2;
2502 int sy = (SYSIZE - ysize * font_height) / 2;
2505 SetDrawtoField(DRAW_BUFFERED);
2507 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2509 SetDrawtoField(DRAW_BACKBUFFER);
2511 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
2512 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
2515 DrawTextBuffer(SX + sx + font_width, SY + sy + font_height,
2516 level.envelope[envelope_nr].text, font_nr, max_xsize,
2517 xsize - 2, ysize - 2, 0, mask_mode,
2518 level.envelope[envelope_nr].autowrap,
2519 level.envelope[envelope_nr].centered, FALSE);
2521 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
2522 level.envelope[envelope_nr].text, font_nr, max_xsize,
2523 xsize - 2, ysize - 2, mask_mode);
2526 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2529 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2533 void AnimateEnvelopeDoor(char *text, int anim_mode, int action)
2536 int envelope_nr = 0;
2538 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2539 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2540 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2541 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2542 boolean no_delay = (tape.warp_forward);
2543 unsigned int anim_delay = 0;
2544 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2545 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
2547 int max_word_len = maxWordLengthInString(text);
2548 int font_nr = (max_word_len > 7 ? FONT_TEXT_1 : FONT_TEXT_2);
2550 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2552 int font_width = getFontWidth(font_nr);
2553 int font_height = getFontHeight(font_nr);
2557 int max_xsize = DXSIZE / font_width;
2558 int max_ysize = DYSIZE / font_height;
2560 int max_xsize = 7; /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
2561 int max_ysize = 13; /* tools.c: MAX_REQUEST_LINES == 13 */
2565 int max_xsize = level.envelope[envelope_nr].xsize;
2566 int max_ysize = level.envelope[envelope_nr].ysize;
2568 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2569 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2570 int xend = max_xsize;
2571 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2572 int xstep = (xstart < xend ? 1 : 0);
2573 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2578 char *text_copy = getStringCopy(text);
2581 font_nr = FONT_TEXT_2;
2583 if (maxWordLengthInString(text) > 7) /* MAX_REQUEST_LINE_FONT1_LEN == 7 */
2585 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
2586 font_nr = FONT_TEXT_1;
2589 int max_word_len = 0;
2591 char *text_copy = getStringCopy(text);
2593 font_nr = FONT_TEXT_2;
2595 for (text_ptr = text; *text_ptr; text_ptr++)
2597 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2599 if (max_word_len > 7) /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
2601 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
2602 font_nr = FONT_TEXT_1;
2611 for (text_ptr = text_copy; *text_ptr; text_ptr++)
2612 if (*text_ptr == ' ')
2617 dDX = SX + (SXSIZE - DXSIZE) / 2 - DX;
2618 dDY = SY + (SYSIZE - DYSIZE) / 2 - DY;
2620 dDX = SX + SXSIZE / 2 - max_xsize * font_width / 2 - DX;
2621 dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY;
2624 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2626 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2627 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2628 int sx = (SXSIZE - xsize * font_width) / 2;
2629 int sy = (SYSIZE - ysize * font_height) / 2;
2633 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2635 SetDrawtoField(DRAW_BUFFERED);
2637 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2639 SetDrawtoField(DRAW_BACKBUFFER);
2642 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
2643 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
2648 DrawTextBuffer(SX + sx + font_width, SY + sy + font_height + 8,
2649 text_copy, font_nr, max_xsize,
2650 xsize - 2, ysize - 2, 2, mask_mode,
2651 FALSE, TRUE, FALSE);
2653 DrawTextBuffer(SX + sx + font_width, SY + sy + font_height,
2654 level.envelope[envelope_nr].text, font_nr, max_xsize,
2655 xsize - 2, ysize - 2, 0, mask_mode,
2656 level.envelope[envelope_nr].autowrap,
2657 level.envelope[envelope_nr].centered, FALSE);
2661 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
2662 level.envelope[envelope_nr].text, font_nr, max_xsize,
2663 xsize - 2, ysize - 2, mask_mode);
2666 /* copy request gadgets to door backbuffer */
2668 if ((ysize - 2) > 13)
2669 BlitBitmap(bitmap_db_door, drawto,
2670 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
2671 DOOR_GFX_PAGEY1 + 13 * font_height,
2672 (xsize - 2) * font_width,
2673 (ysize - 2 - 13) * font_height,
2674 SX + sx + font_width,
2675 SY + sy + font_height * (1 + 13));
2677 if ((ysize - 2) > 13)
2678 BlitBitmap(bitmap_db_door, drawto,
2679 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
2680 DOOR_GFX_PAGEY1 + 13 * font_height,
2681 (xsize - 2) * font_width,
2682 (ysize - 2 - 13) * font_height,
2683 SX + sx + font_width,
2684 SY + sy + font_height * (1 + 13));
2688 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2689 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
2691 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2701 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2709 void ShowEnvelope(int envelope_nr)
2711 int element = EL_ENVELOPE_1 + envelope_nr;
2712 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2713 int sound_opening = element_info[element].sound[ACTION_OPENING];
2714 int sound_closing = element_info[element].sound[ACTION_CLOSING];
2715 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2716 boolean no_delay = (tape.warp_forward);
2717 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
2718 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
2719 int anim_mode = graphic_info[graphic].anim_mode;
2720 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
2721 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
2723 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
2725 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
2727 if (anim_mode == ANIM_DEFAULT)
2728 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
2730 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
2733 Delay(wait_delay_value);
2735 WaitForEventToContinue();
2737 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
2739 if (anim_mode != ANIM_NONE)
2740 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
2742 if (anim_mode == ANIM_DEFAULT)
2743 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
2745 game.envelope_active = FALSE;
2747 SetDrawtoField(DRAW_BUFFERED);
2749 redraw_mask |= REDRAW_FIELD;
2753 void ShowEnvelopeDoor(char *text, int action)
2756 int last_game_status = game_status; /* save current game status */
2757 // int last_draw_background_mask = gfx.draw_background_mask;
2758 int envelope_nr = 0;
2760 int element = EL_ENVELOPE_1 + envelope_nr;
2761 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2762 int sound_opening = element_info[element].sound[ACTION_OPENING];
2763 int sound_closing = element_info[element].sound[ACTION_CLOSING];
2765 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2766 boolean no_delay = (tape.warp_forward);
2767 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
2768 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
2770 int anim_mode = graphic_info[graphic].anim_mode;
2771 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
2772 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
2775 if (game_status == GAME_MODE_PLAYING)
2777 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2778 BlitScreenToBitmap_EM(backbuffer);
2779 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
2780 BlitScreenToBitmap_SP(backbuffer);
2783 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2787 SetDrawtoField(DRAW_BACKBUFFER);
2789 // SetDrawBackgroundMask(REDRAW_NONE);
2791 if (action == ACTION_OPENING)
2793 BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2795 if (game_status != GAME_MODE_MAIN)
2799 /* force DOOR font inside door area */
2800 game_status = GAME_MODE_PSEUDO_DOOR;
2803 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
2805 if (action == ACTION_OPENING)
2807 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
2809 if (anim_mode == ANIM_DEFAULT)
2810 AnimateEnvelopeDoor(text, ANIM_DEFAULT, ACTION_OPENING);
2812 AnimateEnvelopeDoor(text, main_anim_mode, ACTION_OPENING);
2816 Delay(wait_delay_value);
2818 WaitForEventToContinue();
2823 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
2825 if (anim_mode != ANIM_NONE)
2826 AnimateEnvelopeDoor(text, main_anim_mode, ACTION_CLOSING);
2828 if (anim_mode == ANIM_DEFAULT)
2829 AnimateEnvelopeDoor(text, ANIM_DEFAULT, ACTION_CLOSING);
2832 game.envelope_active = FALSE;
2835 // game_status = last_game_status; /* restore current game status */
2837 if (action == ACTION_CLOSING)
2839 if (game_status != GAME_MODE_MAIN)
2842 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2845 SetDrawtoField(DRAW_BUFFERED);
2848 // SetDrawBackgroundMask(last_draw_background_mask);
2851 redraw_mask = REDRAW_FIELD;
2852 // redraw_mask |= REDRAW_ALL;
2854 redraw_mask |= REDRAW_FIELD;
2858 if (game_status == GAME_MODE_MAIN)
2863 /* (important: after "BackToFront()", but before "SetDrawtoField()") */
2864 game_status = last_game_status; /* restore current game status */
2866 if (game_status == GAME_MODE_PLAYING &&
2867 level.game_engine_type == GAME_ENGINE_TYPE_RND)
2868 SetDrawtoField(DRAW_BUFFERED);
2874 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
2878 int graphic = el2preimg(element);
2880 getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
2881 BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
2889 SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
2890 SetDrawBackgroundMask(REDRAW_FIELD);
2892 SetDrawBackgroundMask(REDRAW_NONE);
2897 for (x = BX1; x <= BX2; x++)
2898 for (y = BY1; y <= BY2; y++)
2899 DrawScreenField(x, y);
2901 redraw_mask |= REDRAW_FIELD;
2904 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2908 for (x = 0; x < size_x; x++)
2909 for (y = 0; y < size_y; y++)
2910 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2912 redraw_mask |= REDRAW_FIELD;
2915 static void DrawPreviewLevelExt(int from_x, int from_y)
2917 boolean show_level_border = (BorderElement != EL_EMPTY);
2918 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
2919 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
2920 int tile_size = preview.tile_size;
2921 int preview_width = preview.xsize * tile_size;
2922 int preview_height = preview.ysize * tile_size;
2923 int real_preview_xsize = MIN(level_xsize, preview.xsize);
2924 int real_preview_ysize = MIN(level_ysize, preview.ysize);
2925 int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
2926 int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
2929 DrawBackground(dst_x, dst_y, preview_width, preview_height);
2931 dst_x += (preview_width - real_preview_xsize * tile_size) / 2;
2932 dst_y += (preview_height - real_preview_ysize * tile_size) / 2;
2934 for (x = 0; x < real_preview_xsize; x++)
2936 for (y = 0; y < real_preview_ysize; y++)
2938 int lx = from_x + x + (show_level_border ? -1 : 0);
2939 int ly = from_y + y + (show_level_border ? -1 : 0);
2940 int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
2941 getBorderElement(lx, ly));
2943 DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size,
2944 element, tile_size);
2948 redraw_mask |= REDRAW_MICROLEVEL;
2951 #define MICROLABEL_EMPTY 0
2952 #define MICROLABEL_LEVEL_NAME 1
2953 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
2954 #define MICROLABEL_LEVEL_AUTHOR 3
2955 #define MICROLABEL_IMPORTED_FROM_HEAD 4
2956 #define MICROLABEL_IMPORTED_FROM 5
2957 #define MICROLABEL_IMPORTED_BY_HEAD 6
2958 #define MICROLABEL_IMPORTED_BY 7
2960 static int getMaxTextLength(struct TextPosInfo *pos, int font_nr)
2962 int max_text_width = SXSIZE;
2963 int font_width = getFontWidth(font_nr);
2965 if (pos->align == ALIGN_CENTER)
2966 max_text_width = (pos->x < SXSIZE / 2 ? pos->x * 2 : (SXSIZE - pos->x) * 2);
2967 else if (pos->align == ALIGN_RIGHT)
2968 max_text_width = pos->x;
2970 max_text_width = SXSIZE - pos->x;
2972 return max_text_width / font_width;
2975 static void DrawPreviewLevelLabelExt(int mode)
2977 struct TextPosInfo *pos = &menu.main.text.level_info_2;
2978 char label_text[MAX_OUTPUT_LINESIZE + 1];
2979 int max_len_label_text;
2981 int font_nr = pos->font;
2984 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
2985 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
2986 mode == MICROLABEL_IMPORTED_BY_HEAD)
2987 font_nr = pos->font_alt;
2989 int font_nr = FONT_TEXT_2;
2992 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
2993 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
2994 mode == MICROLABEL_IMPORTED_BY_HEAD)
2995 font_nr = FONT_TEXT_3;
2999 max_len_label_text = getMaxTextLength(pos, font_nr);
3001 max_len_label_text = SXSIZE / getFontWidth(font_nr);
3005 if (pos->size != -1)
3006 max_len_label_text = pos->size;
3009 for (i = 0; i < max_len_label_text; i++)
3010 label_text[i] = ' ';
3011 label_text[max_len_label_text] = '\0';
3013 if (strlen(label_text) > 0)
3016 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3018 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3019 int lypos = MICROLABEL2_YPOS;
3021 DrawText(lxpos, lypos, label_text, font_nr);
3026 (mode == MICROLABEL_LEVEL_NAME ? level.name :
3027 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
3028 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
3029 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
3030 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
3031 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
3032 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
3033 max_len_label_text);
3034 label_text[max_len_label_text] = '\0';
3036 if (strlen(label_text) > 0)
3039 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3041 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3042 int lypos = MICROLABEL2_YPOS;
3044 DrawText(lxpos, lypos, label_text, font_nr);
3048 redraw_mask |= REDRAW_MICROLEVEL;
3051 void DrawPreviewLevel(boolean restart)
3053 static unsigned int scroll_delay = 0;
3054 static unsigned int label_delay = 0;
3055 static int from_x, from_y, scroll_direction;
3056 static int label_state, label_counter;
3057 unsigned int scroll_delay_value = preview.step_delay;
3058 boolean show_level_border = (BorderElement != EL_EMPTY);
3059 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3060 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3061 int last_game_status = game_status; /* save current game status */
3064 /* force PREVIEW font on preview level */
3065 game_status = GAME_MODE_PSEUDO_PREVIEW;
3073 if (preview.anim_mode == ANIM_CENTERED)
3075 if (level_xsize > preview.xsize)
3076 from_x = (level_xsize - preview.xsize) / 2;
3077 if (level_ysize > preview.ysize)
3078 from_y = (level_ysize - preview.ysize) / 2;
3081 from_x += preview.xoffset;
3082 from_y += preview.yoffset;
3084 scroll_direction = MV_RIGHT;
3088 DrawPreviewLevelExt(from_x, from_y);
3089 DrawPreviewLevelLabelExt(label_state);
3091 /* initialize delay counters */
3092 DelayReached(&scroll_delay, 0);
3093 DelayReached(&label_delay, 0);
3095 if (leveldir_current->name)
3097 struct TextPosInfo *pos = &menu.main.text.level_info_1;
3098 char label_text[MAX_OUTPUT_LINESIZE + 1];
3100 int font_nr = pos->font;
3102 int font_nr = FONT_TEXT_1;
3105 int max_len_label_text = getMaxTextLength(pos, font_nr);
3107 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
3115 if (pos->size != -1)
3116 max_len_label_text = pos->size;
3119 strncpy(label_text, leveldir_current->name, max_len_label_text);
3120 label_text[max_len_label_text] = '\0';
3123 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3125 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3126 lypos = SY + MICROLABEL1_YPOS;
3128 DrawText(lxpos, lypos, label_text, font_nr);
3132 game_status = last_game_status; /* restore current game status */
3137 /* scroll preview level, if needed */
3138 if (preview.anim_mode != ANIM_NONE &&
3139 (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
3140 DelayReached(&scroll_delay, scroll_delay_value))
3142 switch (scroll_direction)
3147 from_x -= preview.step_offset;
3148 from_x = (from_x < 0 ? 0 : from_x);
3151 scroll_direction = MV_UP;
3155 if (from_x < level_xsize - preview.xsize)
3157 from_x += preview.step_offset;
3158 from_x = (from_x > level_xsize - preview.xsize ?
3159 level_xsize - preview.xsize : from_x);
3162 scroll_direction = MV_DOWN;
3168 from_y -= preview.step_offset;
3169 from_y = (from_y < 0 ? 0 : from_y);
3172 scroll_direction = MV_RIGHT;
3176 if (from_y < level_ysize - preview.ysize)
3178 from_y += preview.step_offset;
3179 from_y = (from_y > level_ysize - preview.ysize ?
3180 level_ysize - preview.ysize : from_y);
3183 scroll_direction = MV_LEFT;
3190 DrawPreviewLevelExt(from_x, from_y);
3193 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
3194 /* redraw micro level label, if needed */
3195 if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
3196 !strEqual(level.author, ANONYMOUS_NAME) &&
3197 !strEqual(level.author, leveldir_current->name) &&
3198 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
3200 int max_label_counter = 23;
3202 if (leveldir_current->imported_from != NULL &&
3203 strlen(leveldir_current->imported_from) > 0)
3204 max_label_counter += 14;
3205 if (leveldir_current->imported_by != NULL &&
3206 strlen(leveldir_current->imported_by) > 0)
3207 max_label_counter += 14;
3209 label_counter = (label_counter + 1) % max_label_counter;
3210 label_state = (label_counter >= 0 && label_counter <= 7 ?
3211 MICROLABEL_LEVEL_NAME :
3212 label_counter >= 9 && label_counter <= 12 ?
3213 MICROLABEL_LEVEL_AUTHOR_HEAD :
3214 label_counter >= 14 && label_counter <= 21 ?
3215 MICROLABEL_LEVEL_AUTHOR :
3216 label_counter >= 23 && label_counter <= 26 ?
3217 MICROLABEL_IMPORTED_FROM_HEAD :
3218 label_counter >= 28 && label_counter <= 35 ?
3219 MICROLABEL_IMPORTED_FROM :
3220 label_counter >= 37 && label_counter <= 40 ?
3221 MICROLABEL_IMPORTED_BY_HEAD :
3222 label_counter >= 42 && label_counter <= 49 ?
3223 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
3225 if (leveldir_current->imported_from == NULL &&
3226 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
3227 label_state == MICROLABEL_IMPORTED_FROM))
3228 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
3229 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
3231 DrawPreviewLevelLabelExt(label_state);
3234 game_status = last_game_status; /* restore current game status */
3237 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3238 int graphic, int sync_frame, int mask_mode)
3240 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3242 if (mask_mode == USE_MASKING)
3243 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3245 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
3248 inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3249 int graphic, int sync_frame,
3252 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3254 if (mask_mode == USE_MASKING)
3255 DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3257 DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
3260 inline void DrawGraphicAnimation(int x, int y, int graphic)
3262 int lx = LEVELX(x), ly = LEVELY(y);
3264 if (!IN_SCR_FIELD(x, y))
3268 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
3269 graphic, GfxFrame[lx][ly], NO_MASKING);
3271 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3272 graphic, GfxFrame[lx][ly], NO_MASKING);
3274 MarkTileDirty(x, y);
3277 inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
3279 int lx = LEVELX(x), ly = LEVELY(y);
3281 if (!IN_SCR_FIELD(x, y))
3284 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3285 graphic, GfxFrame[lx][ly], NO_MASKING);
3286 MarkTileDirty(x, y);
3289 void DrawLevelGraphicAnimation(int x, int y, int graphic)
3291 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3294 void DrawLevelElementAnimation(int x, int y, int element)
3296 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3298 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3301 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
3303 int sx = SCREENX(x), sy = SCREENY(y);
3305 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3308 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3311 DrawGraphicAnimation(sx, sy, graphic);
3314 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
3315 DrawLevelFieldCrumbled(x, y);
3317 if (GFX_CRUMBLED(Feld[x][y]))
3318 DrawLevelFieldCrumbled(x, y);
3322 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
3324 int sx = SCREENX(x), sy = SCREENY(y);
3327 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3330 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3332 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3335 DrawGraphicAnimation(sx, sy, graphic);
3337 if (GFX_CRUMBLED(element))
3338 DrawLevelFieldCrumbled(x, y);
3341 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
3343 if (player->use_murphy)
3345 /* this works only because currently only one player can be "murphy" ... */
3346 static int last_horizontal_dir = MV_LEFT;
3347 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
3349 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3350 last_horizontal_dir = move_dir;
3352 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
3354 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
3356 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
3362 return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
3365 static boolean equalGraphics(int graphic1, int graphic2)
3367 struct GraphicInfo *g1 = &graphic_info[graphic1];
3368 struct GraphicInfo *g2 = &graphic_info[graphic2];
3370 return (g1->bitmap == g2->bitmap &&
3371 g1->src_x == g2->src_x &&
3372 g1->src_y == g2->src_y &&
3373 g1->anim_frames == g2->anim_frames &&
3374 g1->anim_delay == g2->anim_delay &&
3375 g1->anim_mode == g2->anim_mode);
3378 void DrawAllPlayers()
3382 for (i = 0; i < MAX_PLAYERS; i++)
3383 if (stored_player[i].active)
3384 DrawPlayer(&stored_player[i]);
3387 void DrawPlayerField(int x, int y)
3389 if (!IS_PLAYER(x, y))
3392 DrawPlayer(PLAYERINFO(x, y));
3395 #define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
3397 void DrawPlayer(struct PlayerInfo *player)
3399 int jx = player->jx;
3400 int jy = player->jy;
3401 int move_dir = player->MovDir;
3402 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
3403 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
3404 int last_jx = (player->is_moving ? jx - dx : jx);
3405 int last_jy = (player->is_moving ? jy - dy : jy);
3406 int next_jx = jx + dx;
3407 int next_jy = jy + dy;
3408 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
3409 boolean player_is_opaque = FALSE;
3410 int sx = SCREENX(jx), sy = SCREENY(jy);
3411 int sxx = 0, syy = 0;
3412 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
3414 int action = ACTION_DEFAULT;
3415 int last_player_graphic = getPlayerGraphic(player, move_dir);
3416 int last_player_frame = player->Frame;
3419 /* GfxElement[][] is set to the element the player is digging or collecting;
3420 remove also for off-screen player if the player is not moving anymore */
3421 if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
3422 GfxElement[jx][jy] = EL_UNDEFINED;
3424 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
3428 if (!IN_LEV_FIELD(jx, jy))
3430 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
3431 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
3432 printf("DrawPlayerField(): This should never happen!\n");
3437 if (element == EL_EXPLOSION)
3440 action = (player->is_pushing ? ACTION_PUSHING :
3441 player->is_digging ? ACTION_DIGGING :
3442 player->is_collecting ? ACTION_COLLECTING :
3443 player->is_moving ? ACTION_MOVING :
3444 player->is_snapping ? ACTION_SNAPPING :
3445 player->is_dropping ? ACTION_DROPPING :
3446 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
3448 if (player->is_waiting)
3449 move_dir = player->dir_waiting;
3451 InitPlayerGfxAnimation(player, action, move_dir);
3453 /* ----------------------------------------------------------------------- */
3454 /* draw things in the field the player is leaving, if needed */
3455 /* ----------------------------------------------------------------------- */
3457 if (player->is_moving)
3459 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
3461 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
3463 if (last_element == EL_DYNAMITE_ACTIVE ||
3464 last_element == EL_EM_DYNAMITE_ACTIVE ||
3465 last_element == EL_SP_DISK_RED_ACTIVE)
3466 DrawDynamite(last_jx, last_jy);
3468 DrawLevelFieldThruMask(last_jx, last_jy);
3470 else if (last_element == EL_DYNAMITE_ACTIVE ||
3471 last_element == EL_EM_DYNAMITE_ACTIVE ||
3472 last_element == EL_SP_DISK_RED_ACTIVE)
3473 DrawDynamite(last_jx, last_jy);
3475 /* !!! this is not enough to prevent flickering of players which are
3476 moving next to each others without a free tile between them -- this
3477 can only be solved by drawing all players layer by layer (first the
3478 background, then the foreground etc.) !!! => TODO */
3479 else if (!IS_PLAYER(last_jx, last_jy))
3480 DrawLevelField(last_jx, last_jy);
3483 DrawLevelField(last_jx, last_jy);
3486 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
3487 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
3490 if (!IN_SCR_FIELD(sx, sy))
3493 /* ----------------------------------------------------------------------- */
3494 /* draw things behind the player, if needed */
3495 /* ----------------------------------------------------------------------- */
3498 DrawLevelElement(jx, jy, Back[jx][jy]);
3499 else if (IS_ACTIVE_BOMB(element))
3500 DrawLevelElement(jx, jy, EL_EMPTY);
3503 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
3505 int old_element = GfxElement[jx][jy];
3506 int old_graphic = el_act_dir2img(old_element, action, move_dir);
3507 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
3509 if (GFX_CRUMBLED(old_element))
3510 DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
3512 DrawGraphic(sx, sy, old_graphic, frame);
3514 if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
3515 player_is_opaque = TRUE;
3519 GfxElement[jx][jy] = EL_UNDEFINED;
3521 /* make sure that pushed elements are drawn with correct frame rate */
3523 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
3525 if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
3526 GfxFrame[jx][jy] = player->StepFrame;
3528 if (player->is_pushing && player->is_moving)
3529 GfxFrame[jx][jy] = player->StepFrame;
3532 DrawLevelField(jx, jy);
3536 #if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
3537 /* ----------------------------------------------------------------------- */
3538 /* draw player himself */
3539 /* ----------------------------------------------------------------------- */
3541 graphic = getPlayerGraphic(player, move_dir);
3543 /* in the case of changed player action or direction, prevent the current
3544 animation frame from being restarted for identical animations */
3545 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
3546 player->Frame = last_player_frame;
3548 frame = getGraphicAnimationFrame(graphic, player->Frame);
3552 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3553 sxx = player->GfxPos;
3555 syy = player->GfxPos;
3558 if (!setup.soft_scrolling && ScreenMovPos)
3561 if (player_is_opaque)
3562 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
3564 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3566 if (SHIELD_ON(player))
3568 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
3569 IMG_SHIELD_NORMAL_ACTIVE);
3570 int frame = getGraphicAnimationFrame(graphic, -1);
3572 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3576 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
3579 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3580 sxx = player->GfxPos;
3582 syy = player->GfxPos;
3586 /* ----------------------------------------------------------------------- */
3587 /* draw things the player is pushing, if needed */
3588 /* ----------------------------------------------------------------------- */
3591 printf("::: %d, %d [%d, %d] [%d]\n",
3592 player->is_pushing, player_is_moving, player->GfxAction,
3593 player->is_moving, player_is_moving);
3597 if (player->is_pushing && player->is_moving)
3599 int px = SCREENX(jx), py = SCREENY(jy);
3600 int pxx = (TILEX - ABS(sxx)) * dx;
3601 int pyy = (TILEY - ABS(syy)) * dy;
3602 int gfx_frame = GfxFrame[jx][jy];
3608 if (!IS_MOVING(jx, jy)) /* push movement already finished */
3610 element = Feld[next_jx][next_jy];
3611 gfx_frame = GfxFrame[next_jx][next_jy];
3614 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
3617 sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
3618 frame = getGraphicAnimationFrame(graphic, sync_frame);
3620 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
3623 /* draw background element under pushed element (like the Sokoban field) */
3625 if (game.use_masked_pushing && IS_MOVING(jx, jy))
3627 /* this allows transparent pushing animation over non-black background */
3630 DrawLevelElement(jx, jy, Back[jx][jy]);
3632 DrawLevelElement(jx, jy, EL_EMPTY);
3634 if (Back[next_jx][next_jy])
3635 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
3637 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
3639 else if (Back[next_jx][next_jy])
3640 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
3642 if (Back[next_jx][next_jy])
3643 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
3647 printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
3648 jx, px, player->GfxPos, player->StepFrame,
3653 GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
3657 /* do not draw (EM style) pushing animation when pushing is finished */
3658 /* (two-tile animations usually do not contain start and end frame) */
3659 if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
3660 DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
3662 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
3664 /* masked drawing is needed for EMC style (double) movement graphics */
3665 /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
3666 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
3671 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
3672 /* ----------------------------------------------------------------------- */
3673 /* draw player himself */
3674 /* ----------------------------------------------------------------------- */
3676 graphic = getPlayerGraphic(player, move_dir);
3678 /* in the case of changed player action or direction, prevent the current
3679 animation frame from being restarted for identical animations */
3680 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
3681 player->Frame = last_player_frame;
3683 frame = getGraphicAnimationFrame(graphic, player->Frame);
3687 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3688 sxx = player->GfxPos;
3690 syy = player->GfxPos;
3693 if (!setup.soft_scrolling && ScreenMovPos)
3696 if (player_is_opaque)
3697 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
3699 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3701 if (SHIELD_ON(player))
3703 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
3704 IMG_SHIELD_NORMAL_ACTIVE);
3705 int frame = getGraphicAnimationFrame(graphic, -1);
3707 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3711 /* ----------------------------------------------------------------------- */
3712 /* draw things in front of player (active dynamite or dynabombs) */
3713 /* ----------------------------------------------------------------------- */
3715 if (IS_ACTIVE_BOMB(element))
3717 graphic = el2img(element);
3718 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
3720 if (game.emulation == EMU_SUPAPLEX)
3721 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
3723 DrawGraphicThruMask(sx, sy, graphic, frame);
3726 if (player_is_moving && last_element == EL_EXPLOSION)
3728 int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
3729 GfxElement[last_jx][last_jy] : EL_EMPTY);
3730 int graphic = el_act2img(element, ACTION_EXPLODING);
3731 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
3732 int phase = ExplodePhase[last_jx][last_jy] - 1;
3733 int frame = getGraphicAnimationFrame(graphic, phase - delay);
3736 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
3739 /* ----------------------------------------------------------------------- */
3740 /* draw elements the player is just walking/passing through/under */
3741 /* ----------------------------------------------------------------------- */
3743 if (player_is_moving)
3745 /* handle the field the player is leaving ... */
3746 if (IS_ACCESSIBLE_INSIDE(last_element))
3747 DrawLevelField(last_jx, last_jy);
3748 else if (IS_ACCESSIBLE_UNDER(last_element))
3749 DrawLevelFieldThruMask(last_jx, last_jy);
3752 /* do not redraw accessible elements if the player is just pushing them */
3753 if (!player_is_moving || !player->is_pushing)
3755 /* ... and the field the player is entering */
3756 if (IS_ACCESSIBLE_INSIDE(element))
3757 DrawLevelField(jx, jy);
3758 else if (IS_ACCESSIBLE_UNDER(element))
3759 DrawLevelFieldThruMask(jx, jy);
3762 MarkTileDirty(sx, sy);
3765 /* ------------------------------------------------------------------------- */
3767 void WaitForEventToContinue()
3769 boolean still_wait = TRUE;
3771 /* simulate releasing mouse button over last gadget, if still pressed */
3773 HandleGadgets(-1, -1, 0);
3775 button_status = MB_RELEASED;
3791 case EVENT_BUTTONPRESS:
3792 case EVENT_KEYPRESS:
3796 case EVENT_KEYRELEASE:
3797 ClearPlayerAction();
3801 HandleOtherEvents(&event);
3805 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
3812 /* don't eat all CPU time */
3817 #define MAX_REQUEST_LINES 13
3818 #define MAX_REQUEST_LINE_FONT1_LEN 7
3819 #define MAX_REQUEST_LINE_FONT2_LEN 10
3821 boolean Request(char *text, unsigned int req_state)
3823 int mx, my, ty, result = -1;
3824 unsigned int old_door_state;
3825 int last_game_status = game_status; /* save current game status */
3826 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
3827 int font_nr = FONT_TEXT_2;
3829 int max_word_len = 0;
3835 global.use_envelope_request = 0;
3839 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
3841 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
3842 font_nr = FONT_TEXT_1;
3845 for (text_ptr = text; *text_ptr; text_ptr++)
3847 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
3849 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
3851 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
3853 font_nr = FONT_TEXT_1;
3855 font_nr = FONT_LEVEL_NUMBER;
3863 if (game_status == GAME_MODE_PLAYING)
3865 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
3866 BlitScreenToBitmap_EM(backbuffer);
3867 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3868 BlitScreenToBitmap_SP(backbuffer);
3871 /* disable deactivated drawing when quick-loading level tape recording */
3872 if (tape.playing && tape.deactivate_display)
3873 TapeDeactivateDisplayOff(TRUE);
3875 SetMouseCursor(CURSOR_DEFAULT);
3877 #if defined(NETWORK_AVALIABLE)
3878 /* pause network game while waiting for request to answer */
3879 if (options.network &&
3880 game_status == GAME_MODE_PLAYING &&
3881 req_state & REQUEST_WAIT_FOR_INPUT)
3882 SendToServer_PausePlaying();
3885 old_door_state = GetDoorState();
3887 /* simulate releasing mouse button over last gadget, if still pressed */
3889 HandleGadgets(-1, -1, 0);
3893 /* draw released gadget before proceeding */
3897 if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request)
3899 if (old_door_state & DOOR_OPEN_1)
3903 if (!global.use_envelope_request)
3904 CloseDoor(DOOR_CLOSE_1);
3906 CloseDoor(DOOR_CLOSE_1);
3909 /* save old door content */
3910 BlitBitmap(bitmap_db_door, bitmap_db_door,
3911 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
3912 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
3916 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
3919 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
3921 /* clear door drawing field */
3922 DrawBackground(DX, DY, DXSIZE, DYSIZE);
3924 /* force DOOR font inside door area */
3925 game_status = GAME_MODE_PSEUDO_DOOR;
3927 /* write text for request */
3928 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
3930 char text_line[max_request_line_len + 1];
3936 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
3938 tc = *(text_ptr + tx);
3939 if (!tc || tc == ' ')
3950 strncpy(text_line, text_ptr, tl);
3953 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
3954 DY + 8 + ty * (getFontHeight(font_nr) + 2),
3955 text_line, font_nr);
3957 text_ptr += tl + (tc == ' ' ? 1 : 0);
3960 game_status = last_game_status; /* restore current game status */
3963 if (global.use_envelope_request)
3967 CreateToolButtons();
3971 if (req_state & REQ_ASK)
3973 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
3974 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
3976 else if (req_state & REQ_CONFIRM)
3978 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
3980 else if (req_state & REQ_PLAYER)
3982 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
3983 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
3984 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
3985 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
3988 /* copy request gadgets to door backbuffer */
3989 BlitBitmap(drawto, bitmap_db_door,
3990 DX, DY, DXSIZE, DYSIZE,
3991 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3994 if (global.use_envelope_request)
3996 ShowEnvelopeDoor(text, ACTION_OPENING);
3998 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4000 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
4001 i == TOOL_CTRL_ID_NO)) ||
4002 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
4003 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
4004 i == TOOL_CTRL_ID_PLAYER_2 &&
4005 i == TOOL_CTRL_ID_PLAYER_3 &&
4006 i == TOOL_CTRL_ID_PLAYER_4)))
4008 int x = tool_gadget[i]->x + dDX;
4009 int y = tool_gadget[i]->y + dDY;
4011 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
4018 if (!global.use_envelope_request)
4019 OpenDoor(DOOR_OPEN_1);
4021 OpenDoor(DOOR_OPEN_1);
4024 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4026 if (game_status == GAME_MODE_PLAYING)
4028 SetPanelBackground();
4029 SetDrawBackgroundMask(REDRAW_DOOR_1);
4033 SetDrawBackgroundMask(REDRAW_FIELD);
4040 if (game_status != GAME_MODE_MAIN && !global.use_envelope_request)
4043 if (game_status != GAME_MODE_MAIN)
4047 button_status = MB_RELEASED;
4049 request_gadget_id = -1;
4051 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4063 case EVENT_BUTTONPRESS:
4064 case EVENT_BUTTONRELEASE:
4065 case EVENT_MOTIONNOTIFY:
4067 if (event.type == EVENT_MOTIONNOTIFY)
4069 if (!PointerInWindow(window))
4070 continue; /* window and pointer are on different screens */
4075 motion_status = TRUE;
4076 mx = ((MotionEvent *) &event)->x;
4077 my = ((MotionEvent *) &event)->y;
4081 motion_status = FALSE;
4082 mx = ((ButtonEvent *) &event)->x;
4083 my = ((ButtonEvent *) &event)->y;
4084 if (event.type == EVENT_BUTTONPRESS)
4085 button_status = ((ButtonEvent *) &event)->button;
4087 button_status = MB_RELEASED;
4090 /* this sets 'request_gadget_id' */
4091 HandleGadgets(mx, my, button_status);
4093 switch (request_gadget_id)
4095 case TOOL_CTRL_ID_YES:
4098 case TOOL_CTRL_ID_NO:
4101 case TOOL_CTRL_ID_CONFIRM:
4102 result = TRUE | FALSE;
4105 case TOOL_CTRL_ID_PLAYER_1:
4108 case TOOL_CTRL_ID_PLAYER_2:
4111 case TOOL_CTRL_ID_PLAYER_3:
4114 case TOOL_CTRL_ID_PLAYER_4:
4125 case EVENT_KEYPRESS:
4126 switch (GetEventKey((KeyEvent *)&event, TRUE))
4129 if (req_state & REQ_CONFIRM)
4145 if (req_state & REQ_PLAYER)
4149 case EVENT_KEYRELEASE:
4150 ClearPlayerAction();
4154 HandleOtherEvents(&event);
4158 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4160 int joy = AnyJoystick();
4162 if (joy & JOY_BUTTON_1)
4164 else if (joy & JOY_BUTTON_2)
4170 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
4172 HandleGameActions();
4178 if (!PendingEvent()) /* delay only if no pending events */
4183 game_status = GAME_MODE_PSEUDO_DOOR;
4189 game_status = last_game_status; /* restore current game status */
4197 if (!PendingEvent()) /* delay only if no pending events */
4200 /* don't eat all CPU time */
4207 if (game_status != GAME_MODE_MAIN)
4213 if (global.use_envelope_request)
4214 ShowEnvelopeDoor(text, ACTION_CLOSING);
4218 if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request)
4220 if (!(req_state & REQ_STAY_OPEN))
4223 CloseDoor(DOOR_CLOSE_1);
4225 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
4226 (req_state & REQ_REOPEN))
4227 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
4232 if (game_status == GAME_MODE_PLAYING)
4234 SetPanelBackground();
4235 SetDrawBackgroundMask(REDRAW_DOOR_1);
4239 SetDrawBackgroundMask(REDRAW_FIELD);
4242 #if defined(NETWORK_AVALIABLE)
4243 /* continue network game after request */
4244 if (options.network &&
4245 game_status == GAME_MODE_PLAYING &&
4246 req_state & REQUEST_WAIT_FOR_INPUT)
4247 SendToServer_ContinuePlaying();
4250 /* restore deactivated drawing when quick-loading level tape recording */
4251 if (tape.playing && tape.deactivate_display)
4252 TapeDeactivateDisplayOn();
4257 unsigned int OpenDoor(unsigned int door_state)
4259 if (door_state & DOOR_COPY_BACK)
4261 if (door_state & DOOR_OPEN_1)
4262 BlitBitmap(bitmap_db_door, bitmap_db_door,
4263 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4264 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4266 if (door_state & DOOR_OPEN_2)
4267 BlitBitmap(bitmap_db_door, bitmap_db_door,
4268 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
4269 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
4271 door_state &= ~DOOR_COPY_BACK;
4274 return MoveDoor(door_state);
4277 unsigned int CloseDoor(unsigned int door_state)
4279 unsigned int old_door_state = GetDoorState();
4281 if (!(door_state & DOOR_NO_COPY_BACK))
4283 if (old_door_state & DOOR_OPEN_1)
4284 BlitBitmap(backbuffer, bitmap_db_door,
4285 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4287 if (old_door_state & DOOR_OPEN_2)
4288 BlitBitmap(backbuffer, bitmap_db_door,
4289 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
4291 door_state &= ~DOOR_NO_COPY_BACK;
4294 return MoveDoor(door_state);
4297 unsigned int GetDoorState()
4299 return MoveDoor(DOOR_GET_STATE);
4302 unsigned int SetDoorState(unsigned int door_state)
4304 return MoveDoor(door_state | DOOR_SET_STATE);
4307 unsigned int MoveDoor(unsigned int door_state)
4309 static int door1 = DOOR_OPEN_1;
4310 static int door2 = DOOR_CLOSE_2;
4311 unsigned int door_delay = 0;
4312 unsigned int door_delay_value;
4315 if (door_1.width < 0 || door_1.width > DXSIZE)
4316 door_1.width = DXSIZE;
4317 if (door_1.height < 0 || door_1.height > DYSIZE)
4318 door_1.height = DYSIZE;
4319 if (door_2.width < 0 || door_2.width > VXSIZE)
4320 door_2.width = VXSIZE;
4321 if (door_2.height < 0 || door_2.height > VYSIZE)
4322 door_2.height = VYSIZE;
4324 if (door_state == DOOR_GET_STATE)
4325 return (door1 | door2);
4327 if (door_state & DOOR_SET_STATE)
4329 if (door_state & DOOR_ACTION_1)
4330 door1 = door_state & DOOR_ACTION_1;
4331 if (door_state & DOOR_ACTION_2)
4332 door2 = door_state & DOOR_ACTION_2;
4334 return (door1 | door2);
4337 if (!(door_state & DOOR_FORCE_REDRAW))
4339 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
4340 door_state &= ~DOOR_OPEN_1;
4341 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
4342 door_state &= ~DOOR_CLOSE_1;
4343 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
4344 door_state &= ~DOOR_OPEN_2;
4345 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
4346 door_state &= ~DOOR_CLOSE_2;
4349 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
4352 if (setup.quick_doors)
4354 stepsize = 20; /* must be chosen to always draw last frame */
4355 door_delay_value = 0;
4358 if (global.autoplay_leveldir)
4360 door_state |= DOOR_NO_DELAY;
4361 door_state &= ~DOOR_CLOSE_ALL;
4365 if (game_status == GAME_MODE_EDITOR)
4366 door_state |= DOOR_NO_DELAY;
4369 if (door_state & DOOR_ACTION)
4371 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
4372 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
4373 boolean door_1_done = (!handle_door_1);
4374 boolean door_2_done = (!handle_door_2);
4375 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
4376 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
4377 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
4378 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
4379 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
4380 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
4381 int door_size = (handle_door_1 ? door_size_1 : door_size_2);
4382 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
4383 int door_skip = max_door_size - door_size;
4384 int end = door_size;
4385 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
4388 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
4390 /* opening door sound has priority over simultaneously closing door */
4391 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
4392 PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
4393 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
4394 PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
4397 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
4400 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
4401 GC gc = bitmap->stored_clip_gc;
4403 if (door_state & DOOR_ACTION_1)
4405 int a = MIN(x * door_1.step_offset, end);
4406 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
4407 int i = p + door_skip;
4409 if (door_1.anim_mode & ANIM_STATIC_PANEL)
4411 BlitBitmap(bitmap_db_door, drawto,
4412 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
4413 DXSIZE, DYSIZE, DX, DY);
4417 BlitBitmap(bitmap_db_door, drawto,
4418 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
4419 DXSIZE, DYSIZE - p / 2, DX, DY);
4421 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
4424 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
4426 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
4427 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
4428 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
4429 int dst2_x = DX, dst2_y = DY;
4430 int width = i, height = DYSIZE;
4432 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4433 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4436 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4437 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4440 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
4442 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
4443 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
4444 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
4445 int dst2_x = DX, dst2_y = DY;
4446 int width = DXSIZE, height = i;
4448 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4449 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4452 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4453 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4456 else if (x <= DXSIZE) /* ANIM_DEFAULT */
4458 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
4460 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
4461 BlitBitmapMasked(bitmap, drawto,
4462 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
4463 DX + DXSIZE - i, DY + j);
4464 BlitBitmapMasked(bitmap, drawto,
4465 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
4466 DX + DXSIZE - i, DY + 140 + j);
4467 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
4468 DY - (DOOR_GFX_PAGEY1 + j));
4469 BlitBitmapMasked(bitmap, drawto,
4470 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
4472 BlitBitmapMasked(bitmap, drawto,
4473 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
4476 BlitBitmapMasked(bitmap, drawto,
4477 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
4479 BlitBitmapMasked(bitmap, drawto,
4480 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
4482 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
4483 BlitBitmapMasked(bitmap, drawto,
4484 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
4485 DX + DXSIZE - i, DY + 77 + j);
4486 BlitBitmapMasked(bitmap, drawto,
4487 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
4488 DX + DXSIZE - i, DY + 203 + j);
4491 redraw_mask |= REDRAW_DOOR_1;
4492 door_1_done = (a == end);
4495 if (door_state & DOOR_ACTION_2)
4497 int a = MIN(x * door_2.step_offset, door_size);
4498 int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
4499 int i = p + door_skip;
4501 if (door_2.anim_mode & ANIM_STATIC_PANEL)
4503 BlitBitmap(bitmap_db_door, drawto,
4504 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
4505 VXSIZE, VYSIZE, VX, VY);
4507 else if (x <= VYSIZE)
4509 BlitBitmap(bitmap_db_door, drawto,
4510 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
4511 VXSIZE, VYSIZE - p / 2, VX, VY);
4513 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
4516 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
4518 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
4519 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
4520 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
4521 int dst2_x = VX, dst2_y = VY;
4522 int width = i, height = VYSIZE;
4524 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4525 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4528 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4529 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4532 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
4534 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
4535 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
4536 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
4537 int dst2_x = VX, dst2_y = VY;
4538 int width = VXSIZE, height = i;
4540 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4541 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4544 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4545 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4548 else if (x <= VXSIZE) /* ANIM_DEFAULT */
4550 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
4552 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
4553 BlitBitmapMasked(bitmap, drawto,
4554 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
4555 VX + VXSIZE - i, VY + j);
4556 SetClipOrigin(bitmap, gc,
4557 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
4558 BlitBitmapMasked(bitmap, drawto,
4559 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
4562 BlitBitmapMasked(bitmap, drawto,
4563 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
4564 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
4565 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
4566 BlitBitmapMasked(bitmap, drawto,
4567 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
4569 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
4572 redraw_mask |= REDRAW_DOOR_2;
4573 door_2_done = (a == VXSIZE);
4576 if (!(door_state & DOOR_NO_DELAY))
4580 if (game_status == GAME_MODE_MAIN)
4583 WaitUntilDelayReached(&door_delay, door_delay_value);
4588 if (door_state & DOOR_ACTION_1)
4589 door1 = door_state & DOOR_ACTION_1;
4590 if (door_state & DOOR_ACTION_2)
4591 door2 = door_state & DOOR_ACTION_2;
4593 return (door1 | door2);
4596 void DrawSpecialEditorDoor()
4598 /* draw bigger toolbox window */
4599 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
4600 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
4602 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
4603 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
4606 redraw_mask |= REDRAW_ALL;
4609 void UndrawSpecialEditorDoor()
4611 /* draw normal tape recorder window */
4612 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
4613 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
4616 redraw_mask |= REDRAW_ALL;
4620 /* ---------- new tool button stuff ---------------------------------------- */
4622 /* graphic position values for tool buttons */
4623 #define TOOL_BUTTON_YES_XPOS 2
4624 #define TOOL_BUTTON_YES_YPOS 250
4625 #define TOOL_BUTTON_YES_GFX_YPOS 0
4626 #define TOOL_BUTTON_YES_XSIZE 46
4627 #define TOOL_BUTTON_YES_YSIZE 28
4628 #define TOOL_BUTTON_NO_XPOS 52
4629 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
4630 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
4631 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
4632 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
4633 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
4634 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
4635 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
4636 #define TOOL_BUTTON_CONFIRM_XSIZE 96
4637 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
4638 #define TOOL_BUTTON_PLAYER_XSIZE 30
4639 #define TOOL_BUTTON_PLAYER_YSIZE 30
4640 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
4641 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
4642 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
4643 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
4644 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4645 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
4646 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4647 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
4648 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4649 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
4650 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4651 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
4652 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4653 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
4654 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4655 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
4656 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4657 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
4658 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4659 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
4668 } toolbutton_info[NUM_TOOL_BUTTONS] =
4671 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
4672 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
4673 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
4678 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
4679 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
4680 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
4685 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
4686 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
4687 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
4688 TOOL_CTRL_ID_CONFIRM,
4692 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4693 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
4694 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4695 TOOL_CTRL_ID_PLAYER_1,
4699 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4700 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
4701 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4702 TOOL_CTRL_ID_PLAYER_2,
4706 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4707 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
4708 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4709 TOOL_CTRL_ID_PLAYER_3,
4713 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4714 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
4715 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4716 TOOL_CTRL_ID_PLAYER_4,
4721 void CreateToolButtons()
4725 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4727 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
4728 Bitmap *deco_bitmap = None;
4729 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
4730 struct GadgetInfo *gi;
4731 unsigned int event_mask;
4732 int gd_xoffset, gd_yoffset;
4733 int gd_x1, gd_x2, gd_y;
4736 event_mask = GD_EVENT_RELEASED;
4738 gd_xoffset = toolbutton_info[i].xpos;
4739 gd_yoffset = toolbutton_info[i].ypos;
4740 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
4741 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
4742 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
4744 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
4746 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
4748 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
4749 &deco_bitmap, &deco_x, &deco_y);
4750 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
4751 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
4754 gi = CreateGadget(GDI_CUSTOM_ID, id,
4755 GDI_INFO_TEXT, toolbutton_info[i].infotext,
4756 GDI_X, DX + toolbutton_info[i].x,
4757 GDI_Y, DY + toolbutton_info[i].y,
4758 GDI_WIDTH, toolbutton_info[i].width,
4759 GDI_HEIGHT, toolbutton_info[i].height,
4760 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
4761 GDI_STATE, GD_BUTTON_UNPRESSED,
4762 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
4763 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
4764 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
4765 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
4766 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
4767 GDI_DECORATION_SHIFTING, 1, 1,
4768 GDI_DIRECT_DRAW, FALSE,
4769 GDI_EVENT_MASK, event_mask,
4770 GDI_CALLBACK_ACTION, HandleToolButtons,
4774 Error(ERR_EXIT, "cannot create gadget");
4776 tool_gadget[id] = gi;
4780 void FreeToolButtons()
4784 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4785 FreeGadget(tool_gadget[i]);
4788 static void UnmapToolButtons()
4792 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4793 UnmapGadget(tool_gadget[i]);
4796 static void HandleToolButtons(struct GadgetInfo *gi)
4798 request_gadget_id = gi->custom_id;
4801 static struct Mapping_EM_to_RND_object
4804 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
4805 boolean is_backside; /* backside of moving element */
4811 em_object_mapping_list[] =
4814 Xblank, TRUE, FALSE,
4818 Yacid_splash_eB, FALSE, FALSE,
4819 EL_ACID_SPLASH_RIGHT, -1, -1
4822 Yacid_splash_wB, FALSE, FALSE,
4823 EL_ACID_SPLASH_LEFT, -1, -1
4826 #ifdef EM_ENGINE_BAD_ROLL
4828 Xstone_force_e, FALSE, FALSE,
4829 EL_ROCK, -1, MV_BIT_RIGHT
4832 Xstone_force_w, FALSE, FALSE,
4833 EL_ROCK, -1, MV_BIT_LEFT
4836 Xnut_force_e, FALSE, FALSE,
4837 EL_NUT, -1, MV_BIT_RIGHT
4840 Xnut_force_w, FALSE, FALSE,
4841 EL_NUT, -1, MV_BIT_LEFT
4844 Xspring_force_e, FALSE, FALSE,
4845 EL_SPRING, -1, MV_BIT_RIGHT
4848 Xspring_force_w, FALSE, FALSE,
4849 EL_SPRING, -1, MV_BIT_LEFT
4852 Xemerald_force_e, FALSE, FALSE,
4853 EL_EMERALD, -1, MV_BIT_RIGHT
4856 Xemerald_force_w, FALSE, FALSE,
4857 EL_EMERALD, -1, MV_BIT_LEFT
4860 Xdiamond_force_e, FALSE, FALSE,
4861 EL_DIAMOND, -1, MV_BIT_RIGHT
4864 Xdiamond_force_w, FALSE, FALSE,
4865 EL_DIAMOND, -1, MV_BIT_LEFT
4868 Xbomb_force_e, FALSE, FALSE,
4869 EL_BOMB, -1, MV_BIT_RIGHT
4872 Xbomb_force_w, FALSE, FALSE,
4873 EL_BOMB, -1, MV_BIT_LEFT
4875 #endif /* EM_ENGINE_BAD_ROLL */
4878 Xstone, TRUE, FALSE,
4882 Xstone_pause, FALSE, FALSE,
4886 Xstone_fall, FALSE, FALSE,
4890 Ystone_s, FALSE, FALSE,
4891 EL_ROCK, ACTION_FALLING, -1
4894 Ystone_sB, FALSE, TRUE,
4895 EL_ROCK, ACTION_FALLING, -1
4898 Ystone_e, FALSE, FALSE,
4899 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
4902 Ystone_eB, FALSE, TRUE,
4903 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
4906 Ystone_w, FALSE, FALSE,
4907 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
4910 Ystone_wB, FALSE, TRUE,
4911 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
4918 Xnut_pause, FALSE, FALSE,
4922 Xnut_fall, FALSE, FALSE,
4926 Ynut_s, FALSE, FALSE,
4927 EL_NUT, ACTION_FALLING, -1
4930 Ynut_sB, FALSE, TRUE,
4931 EL_NUT, ACTION_FALLING, -1
4934 Ynut_e, FALSE, FALSE,
4935 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
4938 Ynut_eB, FALSE, TRUE,
4939 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
4942 Ynut_w, FALSE, FALSE,
4943 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
4946 Ynut_wB, FALSE, TRUE,
4947 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
4950 Xbug_n, TRUE, FALSE,
4954 Xbug_e, TRUE, FALSE,
4955 EL_BUG_RIGHT, -1, -1
4958 Xbug_s, TRUE, FALSE,
4962 Xbug_w, TRUE, FALSE,
4966 Xbug_gon, FALSE, FALSE,
4970 Xbug_goe, FALSE, FALSE,
4971 EL_BUG_RIGHT, -1, -1
4974 Xbug_gos, FALSE, FALSE,
4978 Xbug_gow, FALSE, FALSE,
4982 Ybug_n, FALSE, FALSE,
4983 EL_BUG, ACTION_MOVING, MV_BIT_UP
4986 Ybug_nB, FALSE, TRUE,
4987 EL_BUG, ACTION_MOVING, MV_BIT_UP
4990 Ybug_e, FALSE, FALSE,
4991 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
4994 Ybug_eB, FALSE, TRUE,
4995 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
4998 Ybug_s, FALSE, FALSE,
4999 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
5002 Ybug_sB, FALSE, TRUE,
5003 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
5006 Ybug_w, FALSE, FALSE,
5007 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
5010 Ybug_wB, FALSE, TRUE,
5011 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
5014 Ybug_w_n, FALSE, FALSE,
5015 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
5018 Ybug_n_e, FALSE, FALSE,
5019 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
5022 Ybug_e_s, FALSE, FALSE,
5023 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
5026 Ybug_s_w, FALSE, FALSE,
5027 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
5030 Ybug_e_n, FALSE, FALSE,
5031 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
5034 Ybug_s_e, FALSE, FALSE,
5035 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
5038 Ybug_w_s, FALSE, FALSE,
5039 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
5042 Ybug_n_w, FALSE, FALSE,
5043 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
5046 Ybug_stone, FALSE, FALSE,
5047 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
5050 Ybug_spring, FALSE, FALSE,
5051 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
5054 Xtank_n, TRUE, FALSE,
5055 EL_SPACESHIP_UP, -1, -1
5058 Xtank_e, TRUE, FALSE,
5059 EL_SPACESHIP_RIGHT, -1, -1
5062 Xtank_s, TRUE, FALSE,
5063 EL_SPACESHIP_DOWN, -1, -1
5066 Xtank_w, TRUE, FALSE,
5067 EL_SPACESHIP_LEFT, -1, -1
5070 Xtank_gon, FALSE, FALSE,
5071 EL_SPACESHIP_UP, -1, -1
5074 Xtank_goe, FALSE, FALSE,
5075 EL_SPACESHIP_RIGHT, -1, -1
5078 Xtank_gos, FALSE, FALSE,
5079 EL_SPACESHIP_DOWN, -1, -1
5082 Xtank_gow, FALSE, FALSE,
5083 EL_SPACESHIP_LEFT, -1, -1
5086 Ytank_n, FALSE, FALSE,
5087 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
5090 Ytank_nB, FALSE, TRUE,
5091 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
5094 Ytank_e, FALSE, FALSE,
5095 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
5098 Ytank_eB, FALSE, TRUE,
5099 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
5102 Ytank_s, FALSE, FALSE,
5103 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
5106 Ytank_sB, FALSE, TRUE,
5107 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
5110 Ytank_w, FALSE, FALSE,
5111 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
5114 Ytank_wB, FALSE, TRUE,
5115 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
5118 Ytank_w_n, FALSE, FALSE,
5119 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
5122 Ytank_n_e, FALSE, FALSE,
5123 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
5126 Ytank_e_s, FALSE, FALSE,
5127 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
5130 Ytank_s_w, FALSE, FALSE,
5131 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
5134 Ytank_e_n, FALSE, FALSE,
5135 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
5138 Ytank_s_e, FALSE, FALSE,
5139 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
5142 Ytank_w_s, FALSE, FALSE,
5143 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
5146 Ytank_n_w, FALSE, FALSE,
5147 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
5150 Ytank_stone, FALSE, FALSE,
5151 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
5154 Ytank_spring, FALSE, FALSE,
5155 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
5158 Xandroid, TRUE, FALSE,
5159 EL_EMC_ANDROID, ACTION_ACTIVE, -1
5162 Xandroid_1_n, FALSE, FALSE,
5163 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
5166 Xandroid_2_n, FALSE, FALSE,
5167 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
5170 Xandroid_1_e, FALSE, FALSE,
5171 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
5174 Xandroid_2_e, FALSE, FALSE,
5175 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
5178 Xandroid_1_w, FALSE, FALSE,
5179 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
5182 Xandroid_2_w, FALSE, FALSE,
5183 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
5186 Xandroid_1_s, FALSE, FALSE,
5187 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
5190 Xandroid_2_s, FALSE, FALSE,
5191 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
5194 Yandroid_n, FALSE, FALSE,
5195 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
5198 Yandroid_nB, FALSE, TRUE,
5199 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
5202 Yandroid_ne, FALSE, FALSE,
5203 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
5206 Yandroid_neB, FALSE, TRUE,
5207 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
5210 Yandroid_e, FALSE, FALSE,
5211 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
5214 Yandroid_eB, FALSE, TRUE,
5215 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
5218 Yandroid_se, FALSE, FALSE,
5219 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
5222 Yandroid_seB, FALSE, TRUE,
5223 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
5226 Yandroid_s, FALSE, FALSE,
5227 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
5230 Yandroid_sB, FALSE, TRUE,
5231 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
5234 Yandroid_sw, FALSE, FALSE,
5235 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
5238 Yandroid_swB, FALSE, TRUE,
5239 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
5242 Yandroid_w, FALSE, FALSE,
5243 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
5246 Yandroid_wB, FALSE, TRUE,
5247 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
5250 Yandroid_nw, FALSE, FALSE,
5251 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
5254 Yandroid_nwB, FALSE, TRUE,
5255 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
5258 Xspring, TRUE, FALSE,
5262 Xspring_pause, FALSE, FALSE,
5266 Xspring_e, FALSE, FALSE,
5270 Xspring_w, FALSE, FALSE,
5274 Xspring_fall, FALSE, FALSE,
5278 Yspring_s, FALSE, FALSE,
5279 EL_SPRING, ACTION_FALLING, -1
5282 Yspring_sB, FALSE, TRUE,
5283 EL_SPRING, ACTION_FALLING, -1
5286 Yspring_e, FALSE, FALSE,
5287 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
5290 Yspring_eB, FALSE, TRUE,
5291 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
5294 Yspring_w, FALSE, FALSE,
5295 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
5298 Yspring_wB, FALSE, TRUE,
5299 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
5302 Yspring_kill_e, FALSE, FALSE,
5303 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
5306 Yspring_kill_eB, FALSE, TRUE,
5307 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
5310 Yspring_kill_w, FALSE, FALSE,
5311 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
5314 Yspring_kill_wB, FALSE, TRUE,
5315 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
5318 Xeater_n, TRUE, FALSE,
5319 EL_YAMYAM_UP, -1, -1
5322 Xeater_e, TRUE, FALSE,
5323 EL_YAMYAM_RIGHT, -1, -1
5326 Xeater_w, TRUE, FALSE,
5327 EL_YAMYAM_LEFT, -1, -1
5330 Xeater_s, TRUE, FALSE,
5331 EL_YAMYAM_DOWN, -1, -1
5334 Yeater_n, FALSE, FALSE,
5335 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
5338 Yeater_nB, FALSE, TRUE,
5339 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
5342 Yeater_e, FALSE, FALSE,
5343 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
5346 Yeater_eB, FALSE, TRUE,
5347 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
5350 Yeater_s, FALSE, FALSE,
5351 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
5354 Yeater_sB, FALSE, TRUE,
5355 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
5358 Yeater_w, FALSE, FALSE,
5359 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
5362 Yeater_wB, FALSE, TRUE,
5363 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
5366 Yeater_stone, FALSE, FALSE,
5367 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
5370 Yeater_spring, FALSE, FALSE,
5371 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
5374 Xalien, TRUE, FALSE,
5378 Xalien_pause, FALSE, FALSE,
5382 Yalien_n, FALSE, FALSE,
5383 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
5386 Yalien_nB, FALSE, TRUE,
5387 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
5390 Yalien_e, FALSE, FALSE,
5391 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
5394 Yalien_eB, FALSE, TRUE,
5395 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
5398 Yalien_s, FALSE, FALSE,
5399 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
5402 Yalien_sB, FALSE, TRUE,
5403 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
5406 Yalien_w, FALSE, FALSE,
5407 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
5410 Yalien_wB, FALSE, TRUE,
5411 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
5414 Yalien_stone, FALSE, FALSE,
5415 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
5418 Yalien_spring, FALSE, FALSE,
5419 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
5422 Xemerald, TRUE, FALSE,
5426 Xemerald_pause, FALSE, FALSE,
5430 Xemerald_fall, FALSE, FALSE,
5434 Xemerald_shine, FALSE, FALSE,
5435 EL_EMERALD, ACTION_TWINKLING, -1
5438 Yemerald_s, FALSE, FALSE,
5439 EL_EMERALD, ACTION_FALLING, -1
5442 Yemerald_sB, FALSE, TRUE,
5443 EL_EMERALD, ACTION_FALLING, -1
5446 Yemerald_e, FALSE, FALSE,
5447 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
5450 Yemerald_eB, FALSE, TRUE,
5451 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
5454 Yemerald_w, FALSE, FALSE,
5455 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
5458 Yemerald_wB, FALSE, TRUE,
5459 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
5462 Yemerald_eat, FALSE, FALSE,
5463 EL_EMERALD, ACTION_COLLECTING, -1
5466 Yemerald_stone, FALSE, FALSE,
5467 EL_NUT, ACTION_BREAKING, -1
5470 Xdiamond, TRUE, FALSE,
5474 Xdiamond_pause, FALSE, FALSE,
5478 Xdiamond_fall, FALSE, FALSE,
5482 Xdiamond_shine, FALSE, FALSE,
5483 EL_DIAMOND, ACTION_TWINKLING, -1
5486 Ydiamond_s, FALSE, FALSE,
5487 EL_DIAMOND, ACTION_FALLING, -1
5490 Ydiamond_sB, FALSE, TRUE,
5491 EL_DIAMOND, ACTION_FALLING, -1
5494 Ydiamond_e, FALSE, FALSE,
5495 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
5498 Ydiamond_eB, FALSE, TRUE,
5499 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
5502 Ydiamond_w, FALSE, FALSE,
5503 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
5506 Ydiamond_wB, FALSE, TRUE,
5507 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
5510 Ydiamond_eat, FALSE, FALSE,
5511 EL_DIAMOND, ACTION_COLLECTING, -1
5514 Ydiamond_stone, FALSE, FALSE,
5515 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
5518 Xdrip_fall, TRUE, FALSE,
5519 EL_AMOEBA_DROP, -1, -1
5522 Xdrip_stretch, FALSE, FALSE,
5523 EL_AMOEBA_DROP, ACTION_FALLING, -1
5526 Xdrip_stretchB, FALSE, TRUE,
5527 EL_AMOEBA_DROP, ACTION_FALLING, -1
5530 Xdrip_eat, FALSE, FALSE,
5531 EL_AMOEBA_DROP, ACTION_GROWING, -1
5534 Ydrip_s1, FALSE, FALSE,
5535 EL_AMOEBA_DROP, ACTION_FALLING, -1
5538 Ydrip_s1B, FALSE, TRUE,
5539 EL_AMOEBA_DROP, ACTION_FALLING, -1
5542 Ydrip_s2, FALSE, FALSE,
5543 EL_AMOEBA_DROP, ACTION_FALLING, -1
5546 Ydrip_s2B, FALSE, TRUE,
5547 EL_AMOEBA_DROP, ACTION_FALLING, -1
5554 Xbomb_pause, FALSE, FALSE,
5558 Xbomb_fall, FALSE, FALSE,
5562 Ybomb_s, FALSE, FALSE,
5563 EL_BOMB, ACTION_FALLING, -1
5566 Ybomb_sB, FALSE, TRUE,
5567 EL_BOMB, ACTION_FALLING, -1
5570 Ybomb_e, FALSE, FALSE,
5571 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
5574 Ybomb_eB, FALSE, TRUE,
5575 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
5578 Ybomb_w, FALSE, FALSE,
5579 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
5582 Ybomb_wB, FALSE, TRUE,
5583 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
5586 Ybomb_eat, FALSE, FALSE,
5587 EL_BOMB, ACTION_ACTIVATING, -1
5590 Xballoon, TRUE, FALSE,
5594 Yballoon_n, FALSE, FALSE,
5595 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
5598 Yballoon_nB, FALSE, TRUE,
5599 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
5602 Yballoon_e, FALSE, FALSE,
5603 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
5606 Yballoon_eB, FALSE, TRUE,
5607 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
5610 Yballoon_s, FALSE, FALSE,
5611 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
5614 Yballoon_sB, FALSE, TRUE,
5615 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
5618 Yballoon_w, FALSE, FALSE,
5619 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
5622 Yballoon_wB, FALSE, TRUE,
5623 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
5626 Xgrass, TRUE, FALSE,
5627 EL_EMC_GRASS, -1, -1
5630 Ygrass_nB, FALSE, FALSE,
5631 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
5634 Ygrass_eB, FALSE, FALSE,
5635 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
5638 Ygrass_sB, FALSE, FALSE,
5639 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
5642 Ygrass_wB, FALSE, FALSE,
5643 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
5650 Ydirt_nB, FALSE, FALSE,
5651 EL_SAND, ACTION_DIGGING, MV_BIT_UP
5654 Ydirt_eB, FALSE, FALSE,
5655 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
5658 Ydirt_sB, FALSE, FALSE,
5659 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
5662 Ydirt_wB, FALSE, FALSE,
5663 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
5666 Xacid_ne, TRUE, FALSE,
5667 EL_ACID_POOL_TOPRIGHT, -1, -1
5670 Xacid_se, TRUE, FALSE,
5671 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
5674 Xacid_s, TRUE, FALSE,
5675 EL_ACID_POOL_BOTTOM, -1, -1
5678 Xacid_sw, TRUE, FALSE,
5679 EL_ACID_POOL_BOTTOMLEFT, -1, -1
5682 Xacid_nw, TRUE, FALSE,
5683 EL_ACID_POOL_TOPLEFT, -1, -1
5686 Xacid_1, TRUE, FALSE,
5690 Xacid_2, FALSE, FALSE,
5694 Xacid_3, FALSE, FALSE,
5698 Xacid_4, FALSE, FALSE,
5702 Xacid_5, FALSE, FALSE,
5706 Xacid_6, FALSE, FALSE,
5710 Xacid_7, FALSE, FALSE,
5714 Xacid_8, FALSE, FALSE,
5718 Xball_1, TRUE, FALSE,
5719 EL_EMC_MAGIC_BALL, -1, -1
5722 Xball_1B, FALSE, FALSE,
5723 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
5726 Xball_2, FALSE, FALSE,
5727 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
5730 Xball_2B, FALSE, FALSE,
5731 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
5734 Yball_eat, FALSE, FALSE,
5735 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
5738 Ykey_1_eat, FALSE, FALSE,
5739 EL_EM_KEY_1, ACTION_COLLECTING, -1
5742 Ykey_2_eat, FALSE, FALSE,
5743 EL_EM_KEY_2, ACTION_COLLECTING, -1
5746 Ykey_3_eat, FALSE, FALSE,
5747 EL_EM_KEY_3, ACTION_COLLECTING, -1
5750 Ykey_4_eat, FALSE, FALSE,
5751 EL_EM_KEY_4, ACTION_COLLECTING, -1
5754 Ykey_5_eat, FALSE, FALSE,
5755 EL_EMC_KEY_5, ACTION_COLLECTING, -1
5758 Ykey_6_eat, FALSE, FALSE,
5759 EL_EMC_KEY_6, ACTION_COLLECTING, -1
5762 Ykey_7_eat, FALSE, FALSE,
5763 EL_EMC_KEY_7, ACTION_COLLECTING, -1
5766 Ykey_8_eat, FALSE, FALSE,
5767 EL_EMC_KEY_8, ACTION_COLLECTING, -1
5770 Ylenses_eat, FALSE, FALSE,
5771 EL_EMC_LENSES, ACTION_COLLECTING, -1
5774 Ymagnify_eat, FALSE, FALSE,
5775 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
5778 Ygrass_eat, FALSE, FALSE,
5779 EL_EMC_GRASS, ACTION_SNAPPING, -1
5782 Ydirt_eat, FALSE, FALSE,
5783 EL_SAND, ACTION_SNAPPING, -1
5786 Xgrow_ns, TRUE, FALSE,
5787 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
5790 Ygrow_ns_eat, FALSE, FALSE,
5791 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
5794 Xgrow_ew, TRUE, FALSE,
5795 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
5798 Ygrow_ew_eat, FALSE, FALSE,
5799 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
5802 Xwonderwall, TRUE, FALSE,
5803 EL_MAGIC_WALL, -1, -1
5806 XwonderwallB, FALSE, FALSE,
5807 EL_MAGIC_WALL, ACTION_ACTIVE, -1
5810 Xamoeba_1, TRUE, FALSE,
5811 EL_AMOEBA_DRY, ACTION_OTHER, -1
5814 Xamoeba_2, FALSE, FALSE,
5815 EL_AMOEBA_DRY, ACTION_OTHER, -1
5818 Xamoeba_3, FALSE, FALSE,
5819 EL_AMOEBA_DRY, ACTION_OTHER, -1
5822 Xamoeba_4, FALSE, FALSE,
5823 EL_AMOEBA_DRY, ACTION_OTHER, -1
5826 Xamoeba_5, TRUE, FALSE,
5827 EL_AMOEBA_WET, ACTION_OTHER, -1
5830 Xamoeba_6, FALSE, FALSE,
5831 EL_AMOEBA_WET, ACTION_OTHER, -1
5834 Xamoeba_7, FALSE, FALSE,
5835 EL_AMOEBA_WET, ACTION_OTHER, -1
5838 Xamoeba_8, FALSE, FALSE,
5839 EL_AMOEBA_WET, ACTION_OTHER, -1
5842 Xdoor_1, TRUE, FALSE,
5843 EL_EM_GATE_1, -1, -1
5846 Xdoor_2, TRUE, FALSE,
5847 EL_EM_GATE_2, -1, -1
5850 Xdoor_3, TRUE, FALSE,
5851 EL_EM_GATE_3, -1, -1
5854 Xdoor_4, TRUE, FALSE,
5855 EL_EM_GATE_4, -1, -1
5858 Xdoor_5, TRUE, FALSE,
5859 EL_EMC_GATE_5, -1, -1
5862 Xdoor_6, TRUE, FALSE,
5863 EL_EMC_GATE_6, -1, -1
5866 Xdoor_7, TRUE, FALSE,
5867 EL_EMC_GATE_7, -1, -1
5870 Xdoor_8, TRUE, FALSE,
5871 EL_EMC_GATE_8, -1, -1
5874 Xkey_1, TRUE, FALSE,
5878 Xkey_2, TRUE, FALSE,
5882 Xkey_3, TRUE, FALSE,
5886 Xkey_4, TRUE, FALSE,
5890 Xkey_5, TRUE, FALSE,
5891 EL_EMC_KEY_5, -1, -1
5894 Xkey_6, TRUE, FALSE,
5895 EL_EMC_KEY_6, -1, -1
5898 Xkey_7, TRUE, FALSE,
5899 EL_EMC_KEY_7, -1, -1
5902 Xkey_8, TRUE, FALSE,
5903 EL_EMC_KEY_8, -1, -1
5906 Xwind_n, TRUE, FALSE,
5907 EL_BALLOON_SWITCH_UP, -1, -1
5910 Xwind_e, TRUE, FALSE,
5911 EL_BALLOON_SWITCH_RIGHT, -1, -1
5914 Xwind_s, TRUE, FALSE,
5915 EL_BALLOON_SWITCH_DOWN, -1, -1
5918 Xwind_w, TRUE, FALSE,
5919 EL_BALLOON_SWITCH_LEFT, -1, -1
5922 Xwind_nesw, TRUE, FALSE,
5923 EL_BALLOON_SWITCH_ANY, -1, -1
5926 Xwind_stop, TRUE, FALSE,
5927 EL_BALLOON_SWITCH_NONE, -1, -1
5931 EL_EM_EXIT_CLOSED, -1, -1
5934 Xexit_1, TRUE, FALSE,
5935 EL_EM_EXIT_OPEN, -1, -1
5938 Xexit_2, FALSE, FALSE,
5939 EL_EM_EXIT_OPEN, -1, -1
5942 Xexit_3, FALSE, FALSE,
5943 EL_EM_EXIT_OPEN, -1, -1
5946 Xdynamite, TRUE, FALSE,
5947 EL_EM_DYNAMITE, -1, -1
5950 Ydynamite_eat, FALSE, FALSE,
5951 EL_EM_DYNAMITE, ACTION_COLLECTING, -1
5954 Xdynamite_1, TRUE, FALSE,
5955 EL_EM_DYNAMITE_ACTIVE, -1, -1
5958 Xdynamite_2, FALSE, FALSE,
5959 EL_EM_DYNAMITE_ACTIVE, -1, -1
5962 Xdynamite_3, FALSE, FALSE,
5963 EL_EM_DYNAMITE_ACTIVE, -1, -1
5966 Xdynamite_4, FALSE, FALSE,
5967 EL_EM_DYNAMITE_ACTIVE, -1, -1
5970 Xbumper, TRUE, FALSE,
5971 EL_EMC_SPRING_BUMPER, -1, -1
5974 XbumperB, FALSE, FALSE,
5975 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
5978 Xwheel, TRUE, FALSE,
5979 EL_ROBOT_WHEEL, -1, -1
5982 XwheelB, FALSE, FALSE,
5983 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
5986 Xswitch, TRUE, FALSE,
5987 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
5990 XswitchB, FALSE, FALSE,
5991 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
5995 EL_QUICKSAND_EMPTY, -1, -1
5998 Xsand_stone, TRUE, FALSE,
5999 EL_QUICKSAND_FULL, -1, -1
6002 Xsand_stonein_1, FALSE, TRUE,
6003 EL_ROCK, ACTION_FILLING, -1
6006 Xsand_stonein_2, FALSE, TRUE,
6007 EL_ROCK, ACTION_FILLING, -1
6010 Xsand_stonein_3, FALSE, TRUE,
6011 EL_ROCK, ACTION_FILLING, -1
6014 Xsand_stonein_4, FALSE, TRUE,
6015 EL_ROCK, ACTION_FILLING, -1
6019 Xsand_stonesand_1, FALSE, FALSE,
6020 EL_QUICKSAND_EMPTYING, -1, -1
6023 Xsand_stonesand_2, FALSE, FALSE,
6024 EL_QUICKSAND_EMPTYING, -1, -1
6027 Xsand_stonesand_3, FALSE, FALSE,
6028 EL_QUICKSAND_EMPTYING, -1, -1
6031 Xsand_stonesand_4, FALSE, FALSE,
6032 EL_QUICKSAND_EMPTYING, -1, -1
6035 Xsand_stonesand_quickout_1, FALSE, FALSE,
6036 EL_QUICKSAND_EMPTYING, -1, -1
6039 Xsand_stonesand_quickout_2, FALSE, FALSE,
6040 EL_QUICKSAND_EMPTYING, -1, -1
6044 Xsand_stonesand_1, FALSE, FALSE,
6045 EL_QUICKSAND_FULL, -1, -1
6048 Xsand_stonesand_2, FALSE, FALSE,
6049 EL_QUICKSAND_FULL, -1, -1
6052 Xsand_stonesand_3, FALSE, FALSE,
6053 EL_QUICKSAND_FULL, -1, -1
6056 Xsand_stonesand_4, FALSE, FALSE,
6057 EL_QUICKSAND_FULL, -1, -1
6061 Xsand_stoneout_1, FALSE, FALSE,
6062 EL_ROCK, ACTION_EMPTYING, -1
6065 Xsand_stoneout_2, FALSE, FALSE,
6066 EL_ROCK, ACTION_EMPTYING, -1
6070 Xsand_sandstone_1, FALSE, FALSE,
6071 EL_QUICKSAND_FILLING, -1, -1
6074 Xsand_sandstone_2, FALSE, FALSE,
6075 EL_QUICKSAND_FILLING, -1, -1
6078 Xsand_sandstone_3, FALSE, FALSE,
6079 EL_QUICKSAND_FILLING, -1, -1
6082 Xsand_sandstone_4, FALSE, FALSE,
6083 EL_QUICKSAND_FILLING, -1, -1
6087 Xsand_sandstone_1, FALSE, FALSE,
6088 EL_QUICKSAND_FULL, -1, -1
6091 Xsand_sandstone_2, FALSE, FALSE,
6092 EL_QUICKSAND_FULL, -1, -1
6095 Xsand_sandstone_3, FALSE, FALSE,
6096 EL_QUICKSAND_FULL, -1, -1
6099 Xsand_sandstone_4, FALSE, FALSE,
6100 EL_QUICKSAND_FULL, -1, -1
6104 Xplant, TRUE, FALSE,
6105 EL_EMC_PLANT, -1, -1
6108 Yplant, FALSE, FALSE,
6109 EL_EMC_PLANT, -1, -1
6112 Xlenses, TRUE, FALSE,
6113 EL_EMC_LENSES, -1, -1
6116 Xmagnify, TRUE, FALSE,
6117 EL_EMC_MAGNIFIER, -1, -1
6120 Xdripper, TRUE, FALSE,
6121 EL_EMC_DRIPPER, -1, -1
6124 XdripperB, FALSE, FALSE,
6125 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
6128 Xfake_blank, TRUE, FALSE,
6129 EL_INVISIBLE_WALL, -1, -1
6132 Xfake_blankB, FALSE, FALSE,
6133 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
6136 Xfake_grass, TRUE, FALSE,
6137 EL_EMC_FAKE_GRASS, -1, -1
6140 Xfake_grassB, FALSE, FALSE,
6141 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
6144 Xfake_door_1, TRUE, FALSE,
6145 EL_EM_GATE_1_GRAY, -1, -1
6148 Xfake_door_2, TRUE, FALSE,
6149 EL_EM_GATE_2_GRAY, -1, -1
6152 Xfake_door_3, TRUE, FALSE,
6153 EL_EM_GATE_3_GRAY, -1, -1
6156 Xfake_door_4, TRUE, FALSE,
6157 EL_EM_GATE_4_GRAY, -1, -1
6160 Xfake_door_5, TRUE, FALSE,
6161 EL_EMC_GATE_5_GRAY, -1, -1
6164 Xfake_door_6, TRUE, FALSE,
6165 EL_EMC_GATE_6_GRAY, -1, -1
6168 Xfake_door_7, TRUE, FALSE,
6169 EL_EMC_GATE_7_GRAY, -1, -1
6172 Xfake_door_8, TRUE, FALSE,
6173 EL_EMC_GATE_8_GRAY, -1, -1
6176 Xfake_acid_1, TRUE, FALSE,
6177 EL_EMC_FAKE_ACID, -1, -1
6180 Xfake_acid_2, FALSE, FALSE,
6181 EL_EMC_FAKE_ACID, -1, -1
6184 Xfake_acid_3, FALSE, FALSE,
6185 EL_EMC_FAKE_ACID, -1, -1
6188 Xfake_acid_4, FALSE, FALSE,
6189 EL_EMC_FAKE_ACID, -1, -1
6192 Xfake_acid_5, FALSE, FALSE,
6193 EL_EMC_FAKE_ACID, -1, -1
6196 Xfake_acid_6, FALSE, FALSE,
6197 EL_EMC_FAKE_ACID, -1, -1
6200 Xfake_acid_7, FALSE, FALSE,
6201 EL_EMC_FAKE_ACID, -1, -1
6204 Xfake_acid_8, FALSE, FALSE,
6205 EL_EMC_FAKE_ACID, -1, -1
6208 Xsteel_1, TRUE, FALSE,
6209 EL_STEELWALL, -1, -1
6212 Xsteel_2, TRUE, FALSE,
6213 EL_EMC_STEELWALL_2, -1, -1
6216 Xsteel_3, TRUE, FALSE,
6217 EL_EMC_STEELWALL_3, -1, -1
6220 Xsteel_4, TRUE, FALSE,
6221 EL_EMC_STEELWALL_4, -1, -1
6224 Xwall_1, TRUE, FALSE,
6228 Xwall_2, TRUE, FALSE,
6229 EL_EMC_WALL_14, -1, -1
6232 Xwall_3, TRUE, FALSE,
6233 EL_EMC_WALL_15, -1, -1
6236 Xwall_4, TRUE, FALSE,
6237 EL_EMC_WALL_16, -1, -1
6240 Xround_wall_1, TRUE, FALSE,
6241 EL_WALL_SLIPPERY, -1, -1
6244 Xround_wall_2, TRUE, FALSE,
6245 EL_EMC_WALL_SLIPPERY_2, -1, -1
6248 Xround_wall_3, TRUE, FALSE,
6249 EL_EMC_WALL_SLIPPERY_3, -1, -1
6252 Xround_wall_4, TRUE, FALSE,
6253 EL_EMC_WALL_SLIPPERY_4, -1, -1
6256 Xdecor_1, TRUE, FALSE,
6257 EL_EMC_WALL_8, -1, -1
6260 Xdecor_2, TRUE, FALSE,
6261 EL_EMC_WALL_6, -1, -1
6264 Xdecor_3, TRUE, FALSE,
6265 EL_EMC_WALL_4, -1, -1
6268 Xdecor_4, TRUE, FALSE,
6269 EL_EMC_WALL_7, -1, -1
6272 Xdecor_5, TRUE, FALSE,
6273 EL_EMC_WALL_5, -1, -1
6276 Xdecor_6, TRUE, FALSE,
6277 EL_EMC_WALL_9, -1, -1
6280 Xdecor_7, TRUE, FALSE,
6281 EL_EMC_WALL_10, -1, -1
6284 Xdecor_8, TRUE, FALSE,
6285 EL_EMC_WALL_1, -1, -1
6288 Xdecor_9, TRUE, FALSE,
6289 EL_EMC_WALL_2, -1, -1
6292 Xdecor_10, TRUE, FALSE,
6293 EL_EMC_WALL_3, -1, -1
6296 Xdecor_11, TRUE, FALSE,
6297 EL_EMC_WALL_11, -1, -1
6300 Xdecor_12, TRUE, FALSE,
6301 EL_EMC_WALL_12, -1, -1
6304 Xalpha_0, TRUE, FALSE,
6305 EL_CHAR('0'), -1, -1
6308 Xalpha_1, TRUE, FALSE,
6309 EL_CHAR('1'), -1, -1
6312 Xalpha_2, TRUE, FALSE,
6313 EL_CHAR('2'), -1, -1
6316 Xalpha_3, TRUE, FALSE,
6317 EL_CHAR('3'), -1, -1
6320 Xalpha_4, TRUE, FALSE,
6321 EL_CHAR('4'), -1, -1
6324 Xalpha_5, TRUE, FALSE,
6325 EL_CHAR('5'), -1, -1
6328 Xalpha_6, TRUE, FALSE,
6329 EL_CHAR('6'), -1, -1
6332 Xalpha_7, TRUE, FALSE,
6333 EL_CHAR('7'), -1, -1
6336 Xalpha_8, TRUE, FALSE,
6337 EL_CHAR('8'), -1, -1
6340 Xalpha_9, TRUE, FALSE,
6341 EL_CHAR('9'), -1, -1
6344 Xalpha_excla, TRUE, FALSE,
6345 EL_CHAR('!'), -1, -1
6348 Xalpha_quote, TRUE, FALSE,
6349 EL_CHAR('"'), -1, -1
6352 Xalpha_comma, TRUE, FALSE,
6353 EL_CHAR(','), -1, -1
6356 Xalpha_minus, TRUE, FALSE,
6357 EL_CHAR('-'), -1, -1
6360 Xalpha_perio, TRUE, FALSE,
6361 EL_CHAR('.'), -1, -1
6364 Xalpha_colon, TRUE, FALSE,
6365 EL_CHAR(':'), -1, -1
6368 Xalpha_quest, TRUE, FALSE,
6369 EL_CHAR('?'), -1, -1
6372 Xalpha_a, TRUE, FALSE,
6373 EL_CHAR('A'), -1, -1
6376 Xalpha_b, TRUE, FALSE,
6377 EL_CHAR('B'), -1, -1
6380 Xalpha_c, TRUE, FALSE,
6381 EL_CHAR('C'), -1, -1
6384 Xalpha_d, TRUE, FALSE,
6385 EL_CHAR('D'), -1, -1
6388 Xalpha_e, TRUE, FALSE,
6389 EL_CHAR('E'), -1, -1
6392 Xalpha_f, TRUE, FALSE,
6393 EL_CHAR('F'), -1, -1
6396 Xalpha_g, TRUE, FALSE,
6397 EL_CHAR('G'), -1, -1
6400 Xalpha_h, TRUE, FALSE,
6401 EL_CHAR('H'), -1, -1
6404 Xalpha_i, TRUE, FALSE,
6405 EL_CHAR('I'), -1, -1
6408 Xalpha_j, TRUE, FALSE,
6409 EL_CHAR('J'), -1, -1
6412 Xalpha_k, TRUE, FALSE,
6413 EL_CHAR('K'), -1, -1
6416 Xalpha_l, TRUE, FALSE,
6417 EL_CHAR('L'), -1, -1
6420 Xalpha_m, TRUE, FALSE,
6421 EL_CHAR('M'), -1, -1
6424 Xalpha_n, TRUE, FALSE,
6425 EL_CHAR('N'), -1, -1
6428 Xalpha_o, TRUE, FALSE,
6429 EL_CHAR('O'), -1, -1
6432 Xalpha_p, TRUE, FALSE,
6433 EL_CHAR('P'), -1, -1
6436 Xalpha_q, TRUE, FALSE,
6437 EL_CHAR('Q'), -1, -1
6440 Xalpha_r, TRUE, FALSE,
6441 EL_CHAR('R'), -1, -1
6444 Xalpha_s, TRUE, FALSE,
6445 EL_CHAR('S'), -1, -1
6448 Xalpha_t, TRUE, FALSE,
6449 EL_CHAR('T'), -1, -1
6452 Xalpha_u, TRUE, FALSE,
6453 EL_CHAR('U'), -1, -1
6456 Xalpha_v, TRUE, FALSE,
6457 EL_CHAR('V'), -1, -1
6460 Xalpha_w, TRUE, FALSE,
6461 EL_CHAR('W'), -1, -1
6464 Xalpha_x, TRUE, FALSE,
6465 EL_CHAR('X'), -1, -1
6468 Xalpha_y, TRUE, FALSE,
6469 EL_CHAR('Y'), -1, -1
6472 Xalpha_z, TRUE, FALSE,
6473 EL_CHAR('Z'), -1, -1
6476 Xalpha_arrow_e, TRUE, FALSE,
6477 EL_CHAR('>'), -1, -1
6480 Xalpha_arrow_w, TRUE, FALSE,
6481 EL_CHAR('<'), -1, -1
6484 Xalpha_copyr, TRUE, FALSE,
6485 EL_CHAR('©'), -1, -1
6489 Xboom_bug, FALSE, FALSE,
6490 EL_BUG, ACTION_EXPLODING, -1
6493 Xboom_bomb, FALSE, FALSE,
6494 EL_BOMB, ACTION_EXPLODING, -1
6497 Xboom_android, FALSE, FALSE,
6498 EL_EMC_ANDROID, ACTION_OTHER, -1
6501 Xboom_1, FALSE, FALSE,
6502 EL_DEFAULT, ACTION_EXPLODING, -1
6505 Xboom_2, FALSE, FALSE,
6506 EL_DEFAULT, ACTION_EXPLODING, -1
6509 Znormal, FALSE, FALSE,
6513 Zdynamite, FALSE, FALSE,
6517 Zplayer, FALSE, FALSE,
6521 ZBORDER, FALSE, FALSE,
6531 static struct Mapping_EM_to_RND_player
6540 em_player_mapping_list[] =
6544 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
6548 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
6552 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
6556 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
6560 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
6564 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
6568 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
6572 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
6576 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
6580 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
6584 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
6588 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
6592 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
6596 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
6600 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
6604 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
6608 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
6612 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
6616 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
6620 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
6624 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
6628 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
6632 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
6636 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
6640 EL_PLAYER_1, ACTION_DEFAULT, -1,
6644 EL_PLAYER_2, ACTION_DEFAULT, -1,
6648 EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
6652 EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
6656 EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
6660 EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
6664 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
6668 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
6672 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
6676 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
6680 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
6684 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
6688 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
6692 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
6696 EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
6700 EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
6704 EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
6708 EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
6712 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
6716 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
6720 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
6724 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
6728 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
6732 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
6736 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
6740 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
6744 EL_PLAYER_3, ACTION_DEFAULT, -1,
6748 EL_PLAYER_4, ACTION_DEFAULT, -1,
6757 int map_element_RND_to_EM(int element_rnd)
6759 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
6760 static boolean mapping_initialized = FALSE;
6762 if (!mapping_initialized)
6766 /* return "Xalpha_quest" for all undefined elements in mapping array */
6767 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
6768 mapping_RND_to_EM[i] = Xalpha_quest;
6770 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
6771 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
6772 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
6773 em_object_mapping_list[i].element_em;
6775 mapping_initialized = TRUE;
6778 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
6779 return mapping_RND_to_EM[element_rnd];
6781 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
6786 int map_element_EM_to_RND(int element_em)
6788 static unsigned short mapping_EM_to_RND[TILE_MAX];
6789 static boolean mapping_initialized = FALSE;
6791 if (!mapping_initialized)
6795 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
6796 for (i = 0; i < TILE_MAX; i++)
6797 mapping_EM_to_RND[i] = EL_UNKNOWN;
6799 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
6800 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
6801 em_object_mapping_list[i].element_rnd;
6803 mapping_initialized = TRUE;
6806 if (element_em >= 0 && element_em < TILE_MAX)
6807 return mapping_EM_to_RND[element_em];
6809 Error(ERR_WARN, "invalid EM level element %d", element_em);
6814 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
6816 struct LevelInfo_EM *level_em = level->native_em_level;
6817 struct LEVEL *lev = level_em->lev;
6820 for (i = 0; i < TILE_MAX; i++)
6821 lev->android_array[i] = Xblank;
6823 for (i = 0; i < level->num_android_clone_elements; i++)
6825 int element_rnd = level->android_clone_element[i];
6826 int element_em = map_element_RND_to_EM(element_rnd);
6828 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
6829 if (em_object_mapping_list[j].element_rnd == element_rnd)
6830 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
6834 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
6836 struct LevelInfo_EM *level_em = level->native_em_level;
6837 struct LEVEL *lev = level_em->lev;
6840 level->num_android_clone_elements = 0;
6842 for (i = 0; i < TILE_MAX; i++)
6844 int element_em = lev->android_array[i];
6846 boolean element_found = FALSE;
6848 if (element_em == Xblank)
6851 element_rnd = map_element_EM_to_RND(element_em);
6853 for (j = 0; j < level->num_android_clone_elements; j++)
6854 if (level->android_clone_element[j] == element_rnd)
6855 element_found = TRUE;
6859 level->android_clone_element[level->num_android_clone_elements++] =
6862 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
6867 if (level->num_android_clone_elements == 0)
6869 level->num_android_clone_elements = 1;
6870 level->android_clone_element[0] = EL_EMPTY;
6874 int map_direction_RND_to_EM(int direction)
6876 return (direction == MV_UP ? 0 :
6877 direction == MV_RIGHT ? 1 :
6878 direction == MV_DOWN ? 2 :
6879 direction == MV_LEFT ? 3 :
6883 int map_direction_EM_to_RND(int direction)
6885 return (direction == 0 ? MV_UP :
6886 direction == 1 ? MV_RIGHT :
6887 direction == 2 ? MV_DOWN :
6888 direction == 3 ? MV_LEFT :
6892 int map_element_RND_to_SP(int element_rnd)
6894 int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
6896 if (element_rnd >= EL_SP_START &&
6897 element_rnd <= EL_SP_END)
6898 element_sp = element_rnd - EL_SP_START;
6899 else if (element_rnd == EL_EMPTY_SPACE)
6901 else if (element_rnd == EL_INVISIBLE_WALL)
6907 int map_element_SP_to_RND(int element_sp)
6909 int element_rnd = EL_UNKNOWN;
6911 if (element_sp >= 0x00 &&
6913 element_rnd = EL_SP_START + element_sp;
6914 else if (element_sp == 0x28)
6915 element_rnd = EL_INVISIBLE_WALL;
6920 int map_action_SP_to_RND(int action_sp)
6924 case actActive: return ACTION_ACTIVE;
6925 case actImpact: return ACTION_IMPACT;
6926 case actExploding: return ACTION_EXPLODING;
6927 case actDigging: return ACTION_DIGGING;
6928 case actSnapping: return ACTION_SNAPPING;
6929 case actCollecting: return ACTION_COLLECTING;
6930 case actPassing: return ACTION_PASSING;
6931 case actPushing: return ACTION_PUSHING;
6932 case actDropping: return ACTION_DROPPING;
6934 default: return ACTION_DEFAULT;
6938 int get_next_element(int element)
6942 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
6943 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
6944 case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL;
6945 case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY;
6946 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
6947 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
6948 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
6949 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
6950 case EL_DC_MAGIC_WALL_FILLING: return EL_DC_MAGIC_WALL_FULL;
6951 case EL_DC_MAGIC_WALL_EMPTYING: return EL_DC_MAGIC_WALL_ACTIVE;
6952 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
6954 default: return element;
6959 int el_act_dir2img(int element, int action, int direction)
6961 element = GFX_ELEMENT(element);
6963 if (direction == MV_NONE)
6964 return element_info[element].graphic[action];
6966 direction = MV_DIR_TO_BIT(direction);
6968 return element_info[element].direction_graphic[action][direction];
6971 int el_act_dir2img(int element, int action, int direction)
6973 element = GFX_ELEMENT(element);
6974 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
6976 /* direction_graphic[][] == graphic[] for undefined direction graphics */
6977 return element_info[element].direction_graphic[action][direction];
6982 static int el_act_dir2crm(int element, int action, int direction)
6984 element = GFX_ELEMENT(element);
6986 if (direction == MV_NONE)
6987 return element_info[element].crumbled[action];
6989 direction = MV_DIR_TO_BIT(direction);
6991 return element_info[element].direction_crumbled[action][direction];
6994 static int el_act_dir2crm(int element, int action, int direction)
6996 element = GFX_ELEMENT(element);
6997 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
6999 /* direction_graphic[][] == graphic[] for undefined direction graphics */
7000 return element_info[element].direction_crumbled[action][direction];
7004 int el_act2img(int element, int action)
7006 element = GFX_ELEMENT(element);
7008 return element_info[element].graphic[action];
7011 int el_act2crm(int element, int action)
7013 element = GFX_ELEMENT(element);
7015 return element_info[element].crumbled[action];
7018 int el_dir2img(int element, int direction)
7020 element = GFX_ELEMENT(element);
7022 return el_act_dir2img(element, ACTION_DEFAULT, direction);
7025 int el2baseimg(int element)
7027 return element_info[element].graphic[ACTION_DEFAULT];
7030 int el2img(int element)
7032 element = GFX_ELEMENT(element);
7034 return element_info[element].graphic[ACTION_DEFAULT];
7037 int el2edimg(int element)
7039 element = GFX_ELEMENT(element);
7041 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
7044 int el2preimg(int element)
7046 element = GFX_ELEMENT(element);
7048 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
7051 int el2panelimg(int element)
7053 element = GFX_ELEMENT(element);
7055 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PANEL];
7058 int font2baseimg(int font_nr)
7060 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
7063 int getBeltNrFromBeltElement(int element)
7065 return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 :
7066 element < EL_CONVEYOR_BELT_3_LEFT ? 1 :
7067 element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3);
7070 int getBeltNrFromBeltActiveElement(int element)
7072 return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 :
7073 element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 :
7074 element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3);
7077 int getBeltNrFromBeltSwitchElement(int element)
7079 return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 :
7080 element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 :
7081 element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3);
7084 int getBeltDirNrFromBeltElement(int element)
7086 static int belt_base_element[4] =
7088 EL_CONVEYOR_BELT_1_LEFT,
7089 EL_CONVEYOR_BELT_2_LEFT,
7090 EL_CONVEYOR_BELT_3_LEFT,
7091 EL_CONVEYOR_BELT_4_LEFT
7094 int belt_nr = getBeltNrFromBeltElement(element);
7095 int belt_dir_nr = element - belt_base_element[belt_nr];
7097 return (belt_dir_nr % 3);
7100 int getBeltDirNrFromBeltSwitchElement(int element)
7102 static int belt_base_element[4] =
7104 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
7105 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
7106 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
7107 EL_CONVEYOR_BELT_4_SWITCH_LEFT
7110 int belt_nr = getBeltNrFromBeltSwitchElement(element);
7111 int belt_dir_nr = element - belt_base_element[belt_nr];
7113 return (belt_dir_nr % 3);
7116 int getBeltDirFromBeltElement(int element)
7118 static int belt_move_dir[3] =
7125 int belt_dir_nr = getBeltDirNrFromBeltElement(element);
7127 return belt_move_dir[belt_dir_nr];
7130 int getBeltDirFromBeltSwitchElement(int element)
7132 static int belt_move_dir[3] =
7139 int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(element);
7141 return belt_move_dir[belt_dir_nr];
7144 int getBeltElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
7146 static int belt_base_element[4] =
7148 EL_CONVEYOR_BELT_1_LEFT,
7149 EL_CONVEYOR_BELT_2_LEFT,
7150 EL_CONVEYOR_BELT_3_LEFT,
7151 EL_CONVEYOR_BELT_4_LEFT
7154 return belt_base_element[belt_nr] + belt_dir_nr;
7157 int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
7159 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
7161 return getBeltElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
7164 int getBeltSwitchElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
7166 static int belt_base_element[4] =
7168 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
7169 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
7170 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
7171 EL_CONVEYOR_BELT_4_SWITCH_LEFT
7174 return belt_base_element[belt_nr] + belt_dir_nr;
7177 int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
7179 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
7181 return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
7184 int getNumActivePlayers_EM()
7186 int num_players = 0;
7192 for (i = 0; i < MAX_PLAYERS; i++)
7193 if (tape.player_participates[i])
7199 int getGameFrameDelay_EM(int native_em_game_frame_delay)
7201 int game_frame_delay_value;
7203 game_frame_delay_value =
7204 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
7205 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
7208 if (tape.playing && tape.warp_forward && !tape.pausing)
7209 game_frame_delay_value = 0;
7211 return game_frame_delay_value;
7214 unsigned int InitRND(int seed)
7216 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
7217 return InitEngineRandom_EM(seed);
7218 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
7219 return InitEngineRandom_SP(seed);
7221 return InitEngineRandom_RND(seed);
7225 static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
7226 static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
7229 inline static int get_effective_element_EM(int tile, int frame_em)
7231 int element = object_mapping[tile].element_rnd;
7232 int action = object_mapping[tile].action;
7233 boolean is_backside = object_mapping[tile].is_backside;
7234 boolean action_removing = (action == ACTION_DIGGING ||
7235 action == ACTION_SNAPPING ||
7236 action == ACTION_COLLECTING);
7242 case Yacid_splash_eB:
7243 case Yacid_splash_wB:
7244 return (frame_em > 5 ? EL_EMPTY : element);
7248 case Ydiamond_stone:
7249 // if (!game.use_native_emc_graphics_engine)
7257 else /* frame_em == 7 */
7261 case Yacid_splash_eB:
7262 case Yacid_splash_wB:
7265 case Yemerald_stone:
7268 case Ydiamond_stone:
7272 case Xdrip_stretchB:
7291 case Xsand_stonein_1:
7292 case Xsand_stonein_2:
7293 case Xsand_stonein_3:
7294 case Xsand_stonein_4:
7298 return (is_backside || action_removing ? EL_EMPTY : element);
7303 inline static boolean check_linear_animation_EM(int tile)
7307 case Xsand_stonesand_1:
7308 case Xsand_stonesand_quickout_1:
7309 case Xsand_sandstone_1:
7310 case Xsand_stonein_1:
7311 case Xsand_stoneout_1:
7331 case Yacid_splash_eB:
7332 case Yacid_splash_wB:
7333 case Yemerald_stone:
7341 inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
7342 boolean has_crumbled_graphics,
7343 int crumbled, int sync_frame)
7345 /* if element can be crumbled, but certain action graphics are just empty
7346 space (like instantly snapping sand to empty space in 1 frame), do not
7347 treat these empty space graphics as crumbled graphics in EMC engine */
7348 if (crumbled == IMG_EMPTY_SPACE)
7349 has_crumbled_graphics = FALSE;
7351 if (has_crumbled_graphics)
7353 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
7354 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
7355 g_crumbled->anim_delay,
7356 g_crumbled->anim_mode,
7357 g_crumbled->anim_start_frame,
7360 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
7361 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
7363 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
7365 g_em->has_crumbled_graphics = TRUE;
7369 g_em->crumbled_bitmap = NULL;
7370 g_em->crumbled_src_x = 0;
7371 g_em->crumbled_src_y = 0;
7372 g_em->crumbled_border_size = 0;
7374 g_em->has_crumbled_graphics = FALSE;
7378 void ResetGfxAnimation_EM(int x, int y, int tile)
7383 void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
7384 int tile, int frame_em, int x, int y)
7386 int action = object_mapping[tile].action;
7388 int direction = object_mapping[tile].direction;
7389 int effective_element = get_effective_element_EM(tile, frame_em);
7390 int graphic = (direction == MV_NONE ?
7391 el_act2img(effective_element, action) :
7392 el_act_dir2img(effective_element, action, direction));
7393 struct GraphicInfo *g = &graphic_info[graphic];
7396 boolean action_removing = (action == ACTION_DIGGING ||
7397 action == ACTION_SNAPPING ||
7398 action == ACTION_COLLECTING);
7399 boolean action_moving = (action == ACTION_FALLING ||
7400 action == ACTION_MOVING ||
7401 action == ACTION_PUSHING ||
7402 action == ACTION_EATING ||
7403 action == ACTION_FILLING ||
7404 action == ACTION_EMPTYING);
7405 boolean action_falling = (action == ACTION_FALLING ||
7406 action == ACTION_FILLING ||
7407 action == ACTION_EMPTYING);
7409 /* special case: graphic uses "2nd movement tile" and has defined
7410 7 frames for movement animation (or less) => use default graphic
7411 for last (8th) frame which ends the movement animation */
7412 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
7414 action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
7415 graphic = (direction == MV_NONE ?
7416 el_act2img(effective_element, action) :
7417 el_act_dir2img(effective_element, action, direction));
7419 g = &graphic_info[graphic];
7423 if (tile == Xsand_stonesand_1 ||
7424 tile == Xsand_stonesand_2 ||
7425 tile == Xsand_stonesand_3 ||
7426 tile == Xsand_stonesand_4)
7427 printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
7431 if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
7435 // printf("::: resetting... [%d]\n", tile);
7438 if (action_removing || check_linear_animation_EM(tile))
7440 GfxFrame[x][y] = frame_em;
7442 // printf("::: resetting... [%d]\n", tile);
7445 else if (action_moving)
7447 boolean is_backside = object_mapping[tile].is_backside;
7451 int direction = object_mapping[tile].direction;
7452 int move_dir = (action_falling ? MV_DOWN : direction);
7457 /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
7458 if (g->double_movement && frame_em == 0)
7462 // printf("::: resetting... [%d]\n", tile);
7466 if (move_dir == MV_LEFT)
7467 GfxFrame[x - 1][y] = GfxFrame[x][y];
7468 else if (move_dir == MV_RIGHT)
7469 GfxFrame[x + 1][y] = GfxFrame[x][y];
7470 else if (move_dir == MV_UP)
7471 GfxFrame[x][y - 1] = GfxFrame[x][y];
7472 else if (move_dir == MV_DOWN)
7473 GfxFrame[x][y + 1] = GfxFrame[x][y];
7480 /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
7481 if (tile == Xsand_stonesand_quickout_1 ||
7482 tile == Xsand_stonesand_quickout_2)
7487 if (tile == Xsand_stonesand_1 ||
7488 tile == Xsand_stonesand_2 ||
7489 tile == Xsand_stonesand_3 ||
7490 tile == Xsand_stonesand_4)
7491 printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
7495 if (graphic_info[graphic].anim_global_sync)
7496 sync_frame = FrameCounter;
7497 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
7498 sync_frame = GfxFrame[x][y];
7500 sync_frame = 0; /* playfield border (pseudo steel) */
7502 SetRandomAnimationValue(x, y);
7504 int frame = getAnimationFrame(g->anim_frames,
7507 g->anim_start_frame,
7510 g_em->unique_identifier =
7511 (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
7515 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
7516 int tile, int frame_em, int x, int y)
7518 int action = object_mapping[tile].action;
7519 int direction = object_mapping[tile].direction;
7520 boolean is_backside = object_mapping[tile].is_backside;
7521 int effective_element = get_effective_element_EM(tile, frame_em);
7523 int effective_action = action;
7525 int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
7527 int graphic = (direction == MV_NONE ?
7528 el_act2img(effective_element, effective_action) :
7529 el_act_dir2img(effective_element, effective_action,
7531 int crumbled = (direction == MV_NONE ?
7532 el_act2crm(effective_element, effective_action) :
7533 el_act_dir2crm(effective_element, effective_action,
7535 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
7536 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
7537 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
7538 struct GraphicInfo *g = &graphic_info[graphic];
7540 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
7544 /* special case: graphic uses "2nd movement tile" and has defined
7545 7 frames for movement animation (or less) => use default graphic
7546 for last (8th) frame which ends the movement animation */
7547 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
7549 effective_action = ACTION_DEFAULT;
7550 graphic = (direction == MV_NONE ?
7551 el_act2img(effective_element, effective_action) :
7552 el_act_dir2img(effective_element, effective_action,
7554 crumbled = (direction == MV_NONE ?
7555 el_act2crm(effective_element, effective_action) :
7556 el_act_dir2crm(effective_element, effective_action,
7559 g = &graphic_info[graphic];
7569 if (frame_em == 0) /* reset animation frame for certain elements */
7571 if (check_linear_animation_EM(tile))
7576 if (graphic_info[graphic].anim_global_sync)
7577 sync_frame = FrameCounter;
7578 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
7579 sync_frame = GfxFrame[x][y];
7581 sync_frame = 0; /* playfield border (pseudo steel) */
7583 SetRandomAnimationValue(x, y);
7588 int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
7589 i == Xdrip_stretchB ? 7 :
7590 i == Ydrip_s2 ? j + 8 :
7591 i == Ydrip_s2B ? j + 8 :
7600 i == Xfake_acid_1 ? 0 :
7601 i == Xfake_acid_2 ? 10 :
7602 i == Xfake_acid_3 ? 20 :
7603 i == Xfake_acid_4 ? 30 :
7604 i == Xfake_acid_5 ? 40 :
7605 i == Xfake_acid_6 ? 50 :
7606 i == Xfake_acid_7 ? 60 :
7607 i == Xfake_acid_8 ? 70 :
7609 i == Xball_2B ? j + 8 :
7610 i == Yball_eat ? j + 1 :
7611 i == Ykey_1_eat ? j + 1 :
7612 i == Ykey_2_eat ? j + 1 :
7613 i == Ykey_3_eat ? j + 1 :
7614 i == Ykey_4_eat ? j + 1 :
7615 i == Ykey_5_eat ? j + 1 :
7616 i == Ykey_6_eat ? j + 1 :
7617 i == Ykey_7_eat ? j + 1 :
7618 i == Ykey_8_eat ? j + 1 :
7619 i == Ylenses_eat ? j + 1 :
7620 i == Ymagnify_eat ? j + 1 :
7621 i == Ygrass_eat ? j + 1 :
7622 i == Ydirt_eat ? j + 1 :
7623 i == Xamoeba_1 ? 0 :
7624 i == Xamoeba_2 ? 1 :
7625 i == Xamoeba_3 ? 2 :
7626 i == Xamoeba_4 ? 3 :
7627 i == Xamoeba_5 ? 0 :
7628 i == Xamoeba_6 ? 1 :
7629 i == Xamoeba_7 ? 2 :
7630 i == Xamoeba_8 ? 3 :
7631 i == Xexit_2 ? j + 8 :
7632 i == Xexit_3 ? j + 16 :
7633 i == Xdynamite_1 ? 0 :
7634 i == Xdynamite_2 ? 8 :
7635 i == Xdynamite_3 ? 16 :
7636 i == Xdynamite_4 ? 24 :
7637 i == Xsand_stonein_1 ? j + 1 :
7638 i == Xsand_stonein_2 ? j + 9 :
7639 i == Xsand_stonein_3 ? j + 17 :
7640 i == Xsand_stonein_4 ? j + 25 :
7641 i == Xsand_stoneout_1 && j == 0 ? 0 :
7642 i == Xsand_stoneout_1 && j == 1 ? 0 :
7643 i == Xsand_stoneout_1 && j == 2 ? 1 :
7644 i == Xsand_stoneout_1 && j == 3 ? 2 :
7645 i == Xsand_stoneout_1 && j == 4 ? 2 :
7646 i == Xsand_stoneout_1 && j == 5 ? 3 :
7647 i == Xsand_stoneout_1 && j == 6 ? 4 :
7648 i == Xsand_stoneout_1 && j == 7 ? 4 :
7649 i == Xsand_stoneout_2 && j == 0 ? 5 :
7650 i == Xsand_stoneout_2 && j == 1 ? 6 :
7651 i == Xsand_stoneout_2 && j == 2 ? 7 :
7652 i == Xsand_stoneout_2 && j == 3 ? 8 :
7653 i == Xsand_stoneout_2 && j == 4 ? 9 :
7654 i == Xsand_stoneout_2 && j == 5 ? 11 :
7655 i == Xsand_stoneout_2 && j == 6 ? 13 :
7656 i == Xsand_stoneout_2 && j == 7 ? 15 :
7657 i == Xboom_bug && j == 1 ? 2 :
7658 i == Xboom_bug && j == 2 ? 2 :
7659 i == Xboom_bug && j == 3 ? 4 :
7660 i == Xboom_bug && j == 4 ? 4 :
7661 i == Xboom_bug && j == 5 ? 2 :
7662 i == Xboom_bug && j == 6 ? 2 :
7663 i == Xboom_bug && j == 7 ? 0 :
7664 i == Xboom_bomb && j == 1 ? 2 :
7665 i == Xboom_bomb && j == 2 ? 2 :
7666 i == Xboom_bomb && j == 3 ? 4 :
7667 i == Xboom_bomb && j == 4 ? 4 :
7668 i == Xboom_bomb && j == 5 ? 2 :
7669 i == Xboom_bomb && j == 6 ? 2 :
7670 i == Xboom_bomb && j == 7 ? 0 :
7671 i == Xboom_android && j == 7 ? 6 :
7672 i == Xboom_1 && j == 1 ? 2 :
7673 i == Xboom_1 && j == 2 ? 2 :
7674 i == Xboom_1 && j == 3 ? 4 :
7675 i == Xboom_1 && j == 4 ? 4 :
7676 i == Xboom_1 && j == 5 ? 6 :
7677 i == Xboom_1 && j == 6 ? 6 :
7678 i == Xboom_1 && j == 7 ? 8 :
7679 i == Xboom_2 && j == 0 ? 8 :
7680 i == Xboom_2 && j == 1 ? 8 :
7681 i == Xboom_2 && j == 2 ? 10 :
7682 i == Xboom_2 && j == 3 ? 10 :
7683 i == Xboom_2 && j == 4 ? 10 :
7684 i == Xboom_2 && j == 5 ? 12 :
7685 i == Xboom_2 && j == 6 ? 12 :
7686 i == Xboom_2 && j == 7 ? 12 :
7688 special_animation && j == 4 ? 3 :
7689 effective_action != action ? 0 :
7695 int xxx_effective_action;
7696 int xxx_has_action_graphics;
7699 int element = object_mapping[i].element_rnd;
7700 int action = object_mapping[i].action;
7701 int direction = object_mapping[i].direction;
7702 boolean is_backside = object_mapping[i].is_backside;
7704 boolean action_removing = (action == ACTION_DIGGING ||
7705 action == ACTION_SNAPPING ||
7706 action == ACTION_COLLECTING);
7708 boolean action_exploding = ((action == ACTION_EXPLODING ||
7709 action == ACTION_SMASHED_BY_ROCK ||
7710 action == ACTION_SMASHED_BY_SPRING) &&
7711 element != EL_DIAMOND);
7712 boolean action_active = (action == ACTION_ACTIVE);
7713 boolean action_other = (action == ACTION_OTHER);
7717 int effective_element = get_effective_element_EM(i, j);
7719 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
7720 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
7722 i == Xdrip_stretch ? element :
7723 i == Xdrip_stretchB ? element :
7724 i == Ydrip_s1 ? element :
7725 i == Ydrip_s1B ? element :
7726 i == Xball_1B ? element :
7727 i == Xball_2 ? element :
7728 i == Xball_2B ? element :
7729 i == Yball_eat ? element :
7730 i == Ykey_1_eat ? element :
7731 i == Ykey_2_eat ? element :
7732 i == Ykey_3_eat ? element :
7733 i == Ykey_4_eat ? element :
7734 i == Ykey_5_eat ? element :
7735 i == Ykey_6_eat ? element :
7736 i == Ykey_7_eat ? element :
7737 i == Ykey_8_eat ? element :
7738 i == Ylenses_eat ? element :
7739 i == Ymagnify_eat ? element :
7740 i == Ygrass_eat ? element :
7741 i == Ydirt_eat ? element :
7742 i == Yemerald_stone ? EL_EMERALD :
7743 i == Ydiamond_stone ? EL_ROCK :
7744 i == Xsand_stonein_1 ? element :
7745 i == Xsand_stonein_2 ? element :
7746 i == Xsand_stonein_3 ? element :
7747 i == Xsand_stonein_4 ? element :
7748 is_backside ? EL_EMPTY :
7749 action_removing ? EL_EMPTY :
7752 int effective_action = (j < 7 ? action :
7753 i == Xdrip_stretch ? action :
7754 i == Xdrip_stretchB ? action :
7755 i == Ydrip_s1 ? action :
7756 i == Ydrip_s1B ? action :
7757 i == Xball_1B ? action :
7758 i == Xball_2 ? action :
7759 i == Xball_2B ? action :
7760 i == Yball_eat ? action :
7761 i == Ykey_1_eat ? action :
7762 i == Ykey_2_eat ? action :
7763 i == Ykey_3_eat ? action :
7764 i == Ykey_4_eat ? action :
7765 i == Ykey_5_eat ? action :
7766 i == Ykey_6_eat ? action :
7767 i == Ykey_7_eat ? action :
7768 i == Ykey_8_eat ? action :
7769 i == Ylenses_eat ? action :
7770 i == Ymagnify_eat ? action :
7771 i == Ygrass_eat ? action :
7772 i == Ydirt_eat ? action :
7773 i == Xsand_stonein_1 ? action :
7774 i == Xsand_stonein_2 ? action :
7775 i == Xsand_stonein_3 ? action :
7776 i == Xsand_stonein_4 ? action :
7777 i == Xsand_stoneout_1 ? action :
7778 i == Xsand_stoneout_2 ? action :
7779 i == Xboom_android ? ACTION_EXPLODING :
7780 action_exploding ? ACTION_EXPLODING :
7781 action_active ? action :
7782 action_other ? action :
7784 int graphic = (el_act_dir2img(effective_element, effective_action,
7786 int crumbled = (el_act_dir2crm(effective_element, effective_action,
7788 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
7789 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
7790 boolean has_action_graphics = (graphic != base_graphic);
7791 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
7792 struct GraphicInfo *g = &graphic_info[graphic];
7794 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
7796 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
7799 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
7800 boolean special_animation = (action != ACTION_DEFAULT &&
7801 g->anim_frames == 3 &&
7802 g->anim_delay == 2 &&
7803 g->anim_mode & ANIM_LINEAR);
7804 xxx_sync_frame = (i == Xdrip_stretch ? 7 :
7805 i == Xdrip_stretchB ? 7 :
7806 i == Ydrip_s2 ? j + 8 :
7807 i == Ydrip_s2B ? j + 8 :
7816 i == Xfake_acid_1 ? 0 :
7817 i == Xfake_acid_2 ? 10 :
7818 i == Xfake_acid_3 ? 20 :
7819 i == Xfake_acid_4 ? 30 :
7820 i == Xfake_acid_5 ? 40 :
7821 i == Xfake_acid_6 ? 50 :
7822 i == Xfake_acid_7 ? 60 :
7823 i == Xfake_acid_8 ? 70 :
7825 i == Xball_2B ? j + 8 :
7826 i == Yball_eat ? j + 1 :
7827 i == Ykey_1_eat ? j + 1 :
7828 i == Ykey_2_eat ? j + 1 :
7829 i == Ykey_3_eat ? j + 1 :
7830 i == Ykey_4_eat ? j + 1 :
7831 i == Ykey_5_eat ? j + 1 :
7832 i == Ykey_6_eat ? j + 1 :
7833 i == Ykey_7_eat ? j + 1 :
7834 i == Ykey_8_eat ? j + 1 :
7835 i == Ylenses_eat ? j + 1 :
7836 i == Ymagnify_eat ? j + 1 :
7837 i == Ygrass_eat ? j + 1 :
7838 i == Ydirt_eat ? j + 1 :
7839 i == Xamoeba_1 ? 0 :
7840 i == Xamoeba_2 ? 1 :
7841 i == Xamoeba_3 ? 2 :
7842 i == Xamoeba_4 ? 3 :
7843 i == Xamoeba_5 ? 0 :
7844 i == Xamoeba_6 ? 1 :
7845 i == Xamoeba_7 ? 2 :
7846 i == Xamoeba_8 ? 3 :
7847 i == Xexit_2 ? j + 8 :
7848 i == Xexit_3 ? j + 16 :
7849 i == Xdynamite_1 ? 0 :
7850 i == Xdynamite_2 ? 8 :
7851 i == Xdynamite_3 ? 16 :
7852 i == Xdynamite_4 ? 24 :
7853 i == Xsand_stonein_1 ? j + 1 :
7854 i == Xsand_stonein_2 ? j + 9 :
7855 i == Xsand_stonein_3 ? j + 17 :
7856 i == Xsand_stonein_4 ? j + 25 :
7857 i == Xsand_stoneout_1 && j == 0 ? 0 :
7858 i == Xsand_stoneout_1 && j == 1 ? 0 :
7859 i == Xsand_stoneout_1 && j == 2 ? 1 :
7860 i == Xsand_stoneout_1 && j == 3 ? 2 :
7861 i == Xsand_stoneout_1 && j == 4 ? 2 :
7862 i == Xsand_stoneout_1 && j == 5 ? 3 :
7863 i == Xsand_stoneout_1 && j == 6 ? 4 :
7864 i == Xsand_stoneout_1 && j == 7 ? 4 :
7865 i == Xsand_stoneout_2 && j == 0 ? 5 :
7866 i == Xsand_stoneout_2 && j == 1 ? 6 :
7867 i == Xsand_stoneout_2 && j == 2 ? 7 :
7868 i == Xsand_stoneout_2 && j == 3 ? 8 :
7869 i == Xsand_stoneout_2 && j == 4 ? 9 :
7870 i == Xsand_stoneout_2 && j == 5 ? 11 :
7871 i == Xsand_stoneout_2 && j == 6 ? 13 :
7872 i == Xsand_stoneout_2 && j == 7 ? 15 :
7873 i == Xboom_bug && j == 1 ? 2 :
7874 i == Xboom_bug && j == 2 ? 2 :
7875 i == Xboom_bug && j == 3 ? 4 :
7876 i == Xboom_bug && j == 4 ? 4 :
7877 i == Xboom_bug && j == 5 ? 2 :
7878 i == Xboom_bug && j == 6 ? 2 :
7879 i == Xboom_bug && j == 7 ? 0 :
7880 i == Xboom_bomb && j == 1 ? 2 :
7881 i == Xboom_bomb && j == 2 ? 2 :
7882 i == Xboom_bomb && j == 3 ? 4 :
7883 i == Xboom_bomb && j == 4 ? 4 :
7884 i == Xboom_bomb && j == 5 ? 2 :
7885 i == Xboom_bomb && j == 6 ? 2 :
7886 i == Xboom_bomb && j == 7 ? 0 :
7887 i == Xboom_android && j == 7 ? 6 :
7888 i == Xboom_1 && j == 1 ? 2 :
7889 i == Xboom_1 && j == 2 ? 2 :
7890 i == Xboom_1 && j == 3 ? 4 :
7891 i == Xboom_1 && j == 4 ? 4 :
7892 i == Xboom_1 && j == 5 ? 6 :
7893 i == Xboom_1 && j == 6 ? 6 :
7894 i == Xboom_1 && j == 7 ? 8 :
7895 i == Xboom_2 && j == 0 ? 8 :
7896 i == Xboom_2 && j == 1 ? 8 :
7897 i == Xboom_2 && j == 2 ? 10 :
7898 i == Xboom_2 && j == 3 ? 10 :
7899 i == Xboom_2 && j == 4 ? 10 :
7900 i == Xboom_2 && j == 5 ? 12 :
7901 i == Xboom_2 && j == 6 ? 12 :
7902 i == Xboom_2 && j == 7 ? 12 :
7903 special_animation && j == 4 ? 3 :
7904 effective_action != action ? 0 :
7907 xxx_effective_action = effective_action;
7908 xxx_has_action_graphics = has_action_graphics;
7913 int frame = getAnimationFrame(g->anim_frames,
7916 g->anim_start_frame,
7930 int old_src_x = g_em->src_x;
7931 int old_src_y = g_em->src_y;
7935 getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
7936 g->double_movement && is_backside);
7938 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
7939 &g_em->src_x, &g_em->src_y, FALSE);
7944 if (tile == Ydiamond_stone)
7945 printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n",
7950 g->anim_start_frame,
7953 g_em->src_x, g_em->src_y,
7954 g_em->src_offset_x, g_em->src_offset_y,
7955 g_em->dst_offset_x, g_em->dst_offset_y,
7967 if (graphic == IMG_BUG_MOVING_RIGHT)
7968 printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
7969 g->double_movement, is_backside,
7970 old_src_x, old_src_y, g_em->src_x, g_em->src_y);
7978 g_em->src_offset_x = 0;
7979 g_em->src_offset_y = 0;
7980 g_em->dst_offset_x = 0;
7981 g_em->dst_offset_y = 0;
7982 g_em->width = TILEX;
7983 g_em->height = TILEY;
7985 g_em->preserve_background = FALSE;
7988 /* (updating the "crumbled" graphic definitions is probably not really needed,
7989 as animations for crumbled graphics can't be longer than one EMC cycle) */
7991 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
7996 g_em->crumbled_bitmap = NULL;
7997 g_em->crumbled_src_x = 0;
7998 g_em->crumbled_src_y = 0;
8000 g_em->has_crumbled_graphics = FALSE;
8002 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
8004 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
8005 g_crumbled->anim_delay,
8006 g_crumbled->anim_mode,
8007 g_crumbled->anim_start_frame,
8010 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
8011 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
8013 g_em->has_crumbled_graphics = TRUE;
8019 int effective_action = xxx_effective_action;
8020 int has_action_graphics = xxx_has_action_graphics;
8022 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
8023 effective_action == ACTION_MOVING ||
8024 effective_action == ACTION_PUSHING ||
8025 effective_action == ACTION_EATING)) ||
8026 (!has_action_graphics && (effective_action == ACTION_FILLING ||
8027 effective_action == ACTION_EMPTYING)))
8030 (effective_action == ACTION_FALLING ||
8031 effective_action == ACTION_FILLING ||
8032 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
8033 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
8034 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
8035 int num_steps = (i == Ydrip_s1 ? 16 :
8036 i == Ydrip_s1B ? 16 :
8037 i == Ydrip_s2 ? 16 :
8038 i == Ydrip_s2B ? 16 :
8039 i == Xsand_stonein_1 ? 32 :
8040 i == Xsand_stonein_2 ? 32 :
8041 i == Xsand_stonein_3 ? 32 :
8042 i == Xsand_stonein_4 ? 32 :
8043 i == Xsand_stoneout_1 ? 16 :
8044 i == Xsand_stoneout_2 ? 16 : 8);
8045 int cx = ABS(dx) * (TILEX / num_steps);
8046 int cy = ABS(dy) * (TILEY / num_steps);
8047 int step_frame = (i == Ydrip_s2 ? j + 8 :
8048 i == Ydrip_s2B ? j + 8 :
8049 i == Xsand_stonein_2 ? j + 8 :
8050 i == Xsand_stonein_3 ? j + 16 :
8051 i == Xsand_stonein_4 ? j + 24 :
8052 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
8053 int step = (is_backside ? step_frame : num_steps - step_frame);
8055 if (is_backside) /* tile where movement starts */
8057 if (dx < 0 || dy < 0)
8059 g_em->src_offset_x = cx * step;
8060 g_em->src_offset_y = cy * step;
8064 g_em->dst_offset_x = cx * step;
8065 g_em->dst_offset_y = cy * step;
8068 else /* tile where movement ends */
8070 if (dx < 0 || dy < 0)
8072 g_em->dst_offset_x = cx * step;
8073 g_em->dst_offset_y = cy * step;
8077 g_em->src_offset_x = cx * step;
8078 g_em->src_offset_y = cy * step;
8082 g_em->width = TILEX - cx * step;
8083 g_em->height = TILEY - cy * step;
8086 /* create unique graphic identifier to decide if tile must be redrawn */
8087 /* bit 31 - 16 (16 bit): EM style graphic
8088 bit 15 - 12 ( 4 bit): EM style frame
8089 bit 11 - 6 ( 6 bit): graphic width
8090 bit 5 - 0 ( 6 bit): graphic height */
8091 g_em->unique_identifier =
8092 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
8098 void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
8099 int player_nr, int anim, int frame_em)
8101 int element = player_mapping[player_nr][anim].element_rnd;
8102 int action = player_mapping[player_nr][anim].action;
8103 int direction = player_mapping[player_nr][anim].direction;
8104 int graphic = (direction == MV_NONE ?
8105 el_act2img(element, action) :
8106 el_act_dir2img(element, action, direction));
8107 struct GraphicInfo *g = &graphic_info[graphic];
8110 InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
8112 stored_player[player_nr].StepFrame = frame_em;
8114 sync_frame = stored_player[player_nr].Frame;
8116 int frame = getAnimationFrame(g->anim_frames,
8119 g->anim_start_frame,
8122 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
8123 &g_em->src_x, &g_em->src_y, FALSE);
8126 printf("::: %d: %d, %d [%d]\n",
8128 stored_player[player_nr].Frame,
8129 stored_player[player_nr].StepFrame,
8134 void InitGraphicInfo_EM(void)
8137 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
8138 struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
8143 int num_em_gfx_errors = 0;
8145 if (graphic_info_em_object[0][0].bitmap == NULL)
8147 /* EM graphics not yet initialized in em_open_all() */
8152 printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
8155 /* always start with reliable default values */
8156 for (i = 0; i < TILE_MAX; i++)
8158 object_mapping[i].element_rnd = EL_UNKNOWN;
8159 object_mapping[i].is_backside = FALSE;
8160 object_mapping[i].action = ACTION_DEFAULT;
8161 object_mapping[i].direction = MV_NONE;
8164 /* always start with reliable default values */
8165 for (p = 0; p < MAX_PLAYERS; p++)
8167 for (i = 0; i < SPR_MAX; i++)
8169 player_mapping[p][i].element_rnd = EL_UNKNOWN;
8170 player_mapping[p][i].action = ACTION_DEFAULT;
8171 player_mapping[p][i].direction = MV_NONE;
8175 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
8177 int e = em_object_mapping_list[i].element_em;
8179 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
8180 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
8182 if (em_object_mapping_list[i].action != -1)
8183 object_mapping[e].action = em_object_mapping_list[i].action;
8185 if (em_object_mapping_list[i].direction != -1)
8186 object_mapping[e].direction =
8187 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
8190 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
8192 int a = em_player_mapping_list[i].action_em;
8193 int p = em_player_mapping_list[i].player_nr;
8195 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
8197 if (em_player_mapping_list[i].action != -1)
8198 player_mapping[p][a].action = em_player_mapping_list[i].action;
8200 if (em_player_mapping_list[i].direction != -1)
8201 player_mapping[p][a].direction =
8202 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
8205 for (i = 0; i < TILE_MAX; i++)
8207 int element = object_mapping[i].element_rnd;
8208 int action = object_mapping[i].action;
8209 int direction = object_mapping[i].direction;
8210 boolean is_backside = object_mapping[i].is_backside;
8212 boolean action_removing = (action == ACTION_DIGGING ||
8213 action == ACTION_SNAPPING ||
8214 action == ACTION_COLLECTING);
8216 boolean action_exploding = ((action == ACTION_EXPLODING ||
8217 action == ACTION_SMASHED_BY_ROCK ||
8218 action == ACTION_SMASHED_BY_SPRING) &&
8219 element != EL_DIAMOND);
8220 boolean action_active = (action == ACTION_ACTIVE);
8221 boolean action_other = (action == ACTION_OTHER);
8223 for (j = 0; j < 8; j++)
8226 int effective_element = get_effective_element_EM(i, j);
8228 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
8229 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
8231 i == Xdrip_stretch ? element :
8232 i == Xdrip_stretchB ? element :
8233 i == Ydrip_s1 ? element :
8234 i == Ydrip_s1B ? element :
8235 i == Xball_1B ? element :
8236 i == Xball_2 ? element :
8237 i == Xball_2B ? element :
8238 i == Yball_eat ? element :
8239 i == Ykey_1_eat ? element :
8240 i == Ykey_2_eat ? element :
8241 i == Ykey_3_eat ? element :
8242 i == Ykey_4_eat ? element :
8243 i == Ykey_5_eat ? element :
8244 i == Ykey_6_eat ? element :
8245 i == Ykey_7_eat ? element :
8246 i == Ykey_8_eat ? element :
8247 i == Ylenses_eat ? element :
8248 i == Ymagnify_eat ? element :
8249 i == Ygrass_eat ? element :
8250 i == Ydirt_eat ? element :
8251 i == Yemerald_stone ? EL_EMERALD :
8252 i == Ydiamond_stone ? EL_ROCK :
8253 i == Xsand_stonein_1 ? element :
8254 i == Xsand_stonein_2 ? element :
8255 i == Xsand_stonein_3 ? element :
8256 i == Xsand_stonein_4 ? element :
8257 is_backside ? EL_EMPTY :
8258 action_removing ? EL_EMPTY :
8261 int effective_action = (j < 7 ? action :
8262 i == Xdrip_stretch ? action :
8263 i == Xdrip_stretchB ? action :
8264 i == Ydrip_s1 ? action :
8265 i == Ydrip_s1B ? action :
8266 i == Xball_1B ? action :
8267 i == Xball_2 ? action :
8268 i == Xball_2B ? action :
8269 i == Yball_eat ? action :
8270 i == Ykey_1_eat ? action :
8271 i == Ykey_2_eat ? action :
8272 i == Ykey_3_eat ? action :
8273 i == Ykey_4_eat ? action :
8274 i == Ykey_5_eat ? action :
8275 i == Ykey_6_eat ? action :
8276 i == Ykey_7_eat ? action :
8277 i == Ykey_8_eat ? action :
8278 i == Ylenses_eat ? action :
8279 i == Ymagnify_eat ? action :
8280 i == Ygrass_eat ? action :
8281 i == Ydirt_eat ? action :
8282 i == Xsand_stonein_1 ? action :
8283 i == Xsand_stonein_2 ? action :
8284 i == Xsand_stonein_3 ? action :
8285 i == Xsand_stonein_4 ? action :
8286 i == Xsand_stoneout_1 ? action :
8287 i == Xsand_stoneout_2 ? action :
8288 i == Xboom_android ? ACTION_EXPLODING :
8289 action_exploding ? ACTION_EXPLODING :
8290 action_active ? action :
8291 action_other ? action :
8293 int graphic = (el_act_dir2img(effective_element, effective_action,
8295 int crumbled = (el_act_dir2crm(effective_element, effective_action,
8297 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
8298 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
8299 boolean has_action_graphics = (graphic != base_graphic);
8300 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
8301 struct GraphicInfo *g = &graphic_info[graphic];
8303 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
8305 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
8308 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
8309 boolean special_animation = (action != ACTION_DEFAULT &&
8310 g->anim_frames == 3 &&
8311 g->anim_delay == 2 &&
8312 g->anim_mode & ANIM_LINEAR);
8313 int sync_frame = (i == Xdrip_stretch ? 7 :
8314 i == Xdrip_stretchB ? 7 :
8315 i == Ydrip_s2 ? j + 8 :
8316 i == Ydrip_s2B ? j + 8 :
8325 i == Xfake_acid_1 ? 0 :
8326 i == Xfake_acid_2 ? 10 :
8327 i == Xfake_acid_3 ? 20 :
8328 i == Xfake_acid_4 ? 30 :
8329 i == Xfake_acid_5 ? 40 :
8330 i == Xfake_acid_6 ? 50 :
8331 i == Xfake_acid_7 ? 60 :
8332 i == Xfake_acid_8 ? 70 :
8334 i == Xball_2B ? j + 8 :
8335 i == Yball_eat ? j + 1 :
8336 i == Ykey_1_eat ? j + 1 :
8337 i == Ykey_2_eat ? j + 1 :
8338 i == Ykey_3_eat ? j + 1 :
8339 i == Ykey_4_eat ? j + 1 :
8340 i == Ykey_5_eat ? j + 1 :
8341 i == Ykey_6_eat ? j + 1 :
8342 i == Ykey_7_eat ? j + 1 :
8343 i == Ykey_8_eat ? j + 1 :
8344 i == Ylenses_eat ? j + 1 :
8345 i == Ymagnify_eat ? j + 1 :
8346 i == Ygrass_eat ? j + 1 :
8347 i == Ydirt_eat ? j + 1 :
8348 i == Xamoeba_1 ? 0 :
8349 i == Xamoeba_2 ? 1 :
8350 i == Xamoeba_3 ? 2 :
8351 i == Xamoeba_4 ? 3 :
8352 i == Xamoeba_5 ? 0 :
8353 i == Xamoeba_6 ? 1 :
8354 i == Xamoeba_7 ? 2 :
8355 i == Xamoeba_8 ? 3 :
8356 i == Xexit_2 ? j + 8 :
8357 i == Xexit_3 ? j + 16 :
8358 i == Xdynamite_1 ? 0 :
8359 i == Xdynamite_2 ? 8 :
8360 i == Xdynamite_3 ? 16 :
8361 i == Xdynamite_4 ? 24 :
8362 i == Xsand_stonein_1 ? j + 1 :
8363 i == Xsand_stonein_2 ? j + 9 :
8364 i == Xsand_stonein_3 ? j + 17 :
8365 i == Xsand_stonein_4 ? j + 25 :
8366 i == Xsand_stoneout_1 && j == 0 ? 0 :
8367 i == Xsand_stoneout_1 && j == 1 ? 0 :
8368 i == Xsand_stoneout_1 && j == 2 ? 1 :
8369 i == Xsand_stoneout_1 && j == 3 ? 2 :
8370 i == Xsand_stoneout_1 && j == 4 ? 2 :
8371 i == Xsand_stoneout_1 && j == 5 ? 3 :
8372 i == Xsand_stoneout_1 && j == 6 ? 4 :
8373 i == Xsand_stoneout_1 && j == 7 ? 4 :
8374 i == Xsand_stoneout_2 && j == 0 ? 5 :
8375 i == Xsand_stoneout_2 && j == 1 ? 6 :
8376 i == Xsand_stoneout_2 && j == 2 ? 7 :
8377 i == Xsand_stoneout_2 && j == 3 ? 8 :
8378 i == Xsand_stoneout_2 && j == 4 ? 9 :
8379 i == Xsand_stoneout_2 && j == 5 ? 11 :
8380 i == Xsand_stoneout_2 && j == 6 ? 13 :
8381 i == Xsand_stoneout_2 && j == 7 ? 15 :
8382 i == Xboom_bug && j == 1 ? 2 :
8383 i == Xboom_bug && j == 2 ? 2 :
8384 i == Xboom_bug && j == 3 ? 4 :
8385 i == Xboom_bug && j == 4 ? 4 :
8386 i == Xboom_bug && j == 5 ? 2 :
8387 i == Xboom_bug && j == 6 ? 2 :
8388 i == Xboom_bug && j == 7 ? 0 :
8389 i == Xboom_bomb && j == 1 ? 2 :
8390 i == Xboom_bomb && j == 2 ? 2 :
8391 i == Xboom_bomb && j == 3 ? 4 :
8392 i == Xboom_bomb && j == 4 ? 4 :
8393 i == Xboom_bomb && j == 5 ? 2 :
8394 i == Xboom_bomb && j == 6 ? 2 :
8395 i == Xboom_bomb && j == 7 ? 0 :
8396 i == Xboom_android && j == 7 ? 6 :
8397 i == Xboom_1 && j == 1 ? 2 :
8398 i == Xboom_1 && j == 2 ? 2 :
8399 i == Xboom_1 && j == 3 ? 4 :
8400 i == Xboom_1 && j == 4 ? 4 :
8401 i == Xboom_1 && j == 5 ? 6 :
8402 i == Xboom_1 && j == 6 ? 6 :
8403 i == Xboom_1 && j == 7 ? 8 :
8404 i == Xboom_2 && j == 0 ? 8 :
8405 i == Xboom_2 && j == 1 ? 8 :
8406 i == Xboom_2 && j == 2 ? 10 :
8407 i == Xboom_2 && j == 3 ? 10 :
8408 i == Xboom_2 && j == 4 ? 10 :
8409 i == Xboom_2 && j == 5 ? 12 :
8410 i == Xboom_2 && j == 6 ? 12 :
8411 i == Xboom_2 && j == 7 ? 12 :
8412 special_animation && j == 4 ? 3 :
8413 effective_action != action ? 0 :
8417 Bitmap *debug_bitmap = g_em->bitmap;
8418 int debug_src_x = g_em->src_x;
8419 int debug_src_y = g_em->src_y;
8422 int frame = getAnimationFrame(g->anim_frames,
8425 g->anim_start_frame,
8428 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
8429 g->double_movement && is_backside);
8431 g_em->bitmap = src_bitmap;
8432 g_em->src_x = src_x;
8433 g_em->src_y = src_y;
8434 g_em->src_offset_x = 0;
8435 g_em->src_offset_y = 0;
8436 g_em->dst_offset_x = 0;
8437 g_em->dst_offset_y = 0;
8438 g_em->width = TILEX;
8439 g_em->height = TILEY;
8441 g_em->preserve_background = FALSE;
8444 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
8449 g_em->crumbled_bitmap = NULL;
8450 g_em->crumbled_src_x = 0;
8451 g_em->crumbled_src_y = 0;
8452 g_em->crumbled_border_size = 0;
8454 g_em->has_crumbled_graphics = FALSE;
8457 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
8458 printf("::: empty crumbled: %d [%s], %d, %d\n",
8459 effective_element, element_info[effective_element].token_name,
8460 effective_action, direction);
8463 /* if element can be crumbled, but certain action graphics are just empty
8464 space (like instantly snapping sand to empty space in 1 frame), do not
8465 treat these empty space graphics as crumbled graphics in EMC engine */
8466 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
8468 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
8469 g_crumbled->anim_delay,
8470 g_crumbled->anim_mode,
8471 g_crumbled->anim_start_frame,
8474 getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
8476 g_em->has_crumbled_graphics = TRUE;
8477 g_em->crumbled_bitmap = src_bitmap;
8478 g_em->crumbled_src_x = src_x;
8479 g_em->crumbled_src_y = src_y;
8480 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
8484 if (g_em == &graphic_info_em_object[207][0])
8485 printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
8486 graphic_info_em_object[207][0].crumbled_src_x,
8487 graphic_info_em_object[207][0].crumbled_src_y,
8489 crumbled, frame, src_x, src_y,
8494 g->anim_start_frame,
8496 gfx.anim_random_frame,
8501 printf("::: EMC tile %d is crumbled\n", i);
8507 if (element == EL_ROCK &&
8508 effective_action == ACTION_FILLING)
8509 printf("::: has_action_graphics == %d\n", has_action_graphics);
8512 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
8513 effective_action == ACTION_MOVING ||
8514 effective_action == ACTION_PUSHING ||
8515 effective_action == ACTION_EATING)) ||
8516 (!has_action_graphics && (effective_action == ACTION_FILLING ||
8517 effective_action == ACTION_EMPTYING)))
8520 (effective_action == ACTION_FALLING ||
8521 effective_action == ACTION_FILLING ||
8522 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
8523 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
8524 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
8525 int num_steps = (i == Ydrip_s1 ? 16 :
8526 i == Ydrip_s1B ? 16 :
8527 i == Ydrip_s2 ? 16 :
8528 i == Ydrip_s2B ? 16 :
8529 i == Xsand_stonein_1 ? 32 :
8530 i == Xsand_stonein_2 ? 32 :
8531 i == Xsand_stonein_3 ? 32 :
8532 i == Xsand_stonein_4 ? 32 :
8533 i == Xsand_stoneout_1 ? 16 :
8534 i == Xsand_stoneout_2 ? 16 : 8);
8535 int cx = ABS(dx) * (TILEX / num_steps);
8536 int cy = ABS(dy) * (TILEY / num_steps);
8537 int step_frame = (i == Ydrip_s2 ? j + 8 :
8538 i == Ydrip_s2B ? j + 8 :
8539 i == Xsand_stonein_2 ? j + 8 :
8540 i == Xsand_stonein_3 ? j + 16 :
8541 i == Xsand_stonein_4 ? j + 24 :
8542 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
8543 int step = (is_backside ? step_frame : num_steps - step_frame);
8545 if (is_backside) /* tile where movement starts */
8547 if (dx < 0 || dy < 0)
8549 g_em->src_offset_x = cx * step;
8550 g_em->src_offset_y = cy * step;
8554 g_em->dst_offset_x = cx * step;
8555 g_em->dst_offset_y = cy * step;
8558 else /* tile where movement ends */
8560 if (dx < 0 || dy < 0)
8562 g_em->dst_offset_x = cx * step;
8563 g_em->dst_offset_y = cy * step;
8567 g_em->src_offset_x = cx * step;
8568 g_em->src_offset_y = cy * step;
8572 g_em->width = TILEX - cx * step;
8573 g_em->height = TILEY - cy * step;
8576 /* create unique graphic identifier to decide if tile must be redrawn */
8577 /* bit 31 - 16 (16 bit): EM style graphic
8578 bit 15 - 12 ( 4 bit): EM style frame
8579 bit 11 - 6 ( 6 bit): graphic width
8580 bit 5 - 0 ( 6 bit): graphic height */
8581 g_em->unique_identifier =
8582 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
8586 /* skip check for EMC elements not contained in original EMC artwork */
8587 if (element == EL_EMC_FAKE_ACID)
8590 if (g_em->bitmap != debug_bitmap ||
8591 g_em->src_x != debug_src_x ||
8592 g_em->src_y != debug_src_y ||
8593 g_em->src_offset_x != 0 ||
8594 g_em->src_offset_y != 0 ||
8595 g_em->dst_offset_x != 0 ||
8596 g_em->dst_offset_y != 0 ||
8597 g_em->width != TILEX ||
8598 g_em->height != TILEY)
8600 static int last_i = -1;
8608 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
8609 i, element, element_info[element].token_name,
8610 element_action_info[effective_action].suffix, direction);
8612 if (element != effective_element)
8613 printf(" [%d ('%s')]",
8615 element_info[effective_element].token_name);
8619 if (g_em->bitmap != debug_bitmap)
8620 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
8621 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
8623 if (g_em->src_x != debug_src_x ||
8624 g_em->src_y != debug_src_y)
8625 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
8626 j, (is_backside ? 'B' : 'F'),
8627 g_em->src_x, g_em->src_y,
8628 g_em->src_x / 32, g_em->src_y / 32,
8629 debug_src_x, debug_src_y,
8630 debug_src_x / 32, debug_src_y / 32);
8632 if (g_em->src_offset_x != 0 ||
8633 g_em->src_offset_y != 0 ||
8634 g_em->dst_offset_x != 0 ||
8635 g_em->dst_offset_y != 0)
8636 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
8638 g_em->src_offset_x, g_em->src_offset_y,
8639 g_em->dst_offset_x, g_em->dst_offset_y);
8641 if (g_em->width != TILEX ||
8642 g_em->height != TILEY)
8643 printf(" %d (%d): size %d,%d should be %d,%d\n",
8645 g_em->width, g_em->height, TILEX, TILEY);
8647 num_em_gfx_errors++;
8654 for (i = 0; i < TILE_MAX; i++)
8656 for (j = 0; j < 8; j++)
8658 int element = object_mapping[i].element_rnd;
8659 int action = object_mapping[i].action;
8660 int direction = object_mapping[i].direction;
8661 boolean is_backside = object_mapping[i].is_backside;
8662 int graphic_action = el_act_dir2img(element, action, direction);
8663 int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
8665 if ((action == ACTION_SMASHED_BY_ROCK ||
8666 action == ACTION_SMASHED_BY_SPRING ||
8667 action == ACTION_EATING) &&
8668 graphic_action == graphic_default)
8670 int e = (action == ACTION_SMASHED_BY_ROCK ? Ystone_s :
8671 action == ACTION_SMASHED_BY_SPRING ? Yspring_s :
8672 direction == MV_LEFT ? (is_backside? Yspring_wB: Yspring_w) :
8673 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
8676 /* no separate animation for "smashed by rock" -- use rock instead */
8677 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
8678 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
8680 g_em->bitmap = g_xx->bitmap;
8681 g_em->src_x = g_xx->src_x;
8682 g_em->src_y = g_xx->src_y;
8683 g_em->src_offset_x = g_xx->src_offset_x;
8684 g_em->src_offset_y = g_xx->src_offset_y;
8685 g_em->dst_offset_x = g_xx->dst_offset_x;
8686 g_em->dst_offset_y = g_xx->dst_offset_y;
8687 g_em->width = g_xx->width;
8688 g_em->height = g_xx->height;
8689 g_em->unique_identifier = g_xx->unique_identifier;
8692 g_em->preserve_background = TRUE;
8697 for (p = 0; p < MAX_PLAYERS; p++)
8699 for (i = 0; i < SPR_MAX; i++)
8701 int element = player_mapping[p][i].element_rnd;
8702 int action = player_mapping[p][i].action;
8703 int direction = player_mapping[p][i].direction;
8705 for (j = 0; j < 8; j++)
8707 int effective_element = element;
8708 int effective_action = action;
8709 int graphic = (direction == MV_NONE ?
8710 el_act2img(effective_element, effective_action) :
8711 el_act_dir2img(effective_element, effective_action,
8713 struct GraphicInfo *g = &graphic_info[graphic];
8714 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
8720 Bitmap *debug_bitmap = g_em->bitmap;
8721 int debug_src_x = g_em->src_x;
8722 int debug_src_y = g_em->src_y;
8725 int frame = getAnimationFrame(g->anim_frames,
8728 g->anim_start_frame,
8731 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
8733 g_em->bitmap = src_bitmap;
8734 g_em->src_x = src_x;
8735 g_em->src_y = src_y;
8736 g_em->src_offset_x = 0;
8737 g_em->src_offset_y = 0;
8738 g_em->dst_offset_x = 0;
8739 g_em->dst_offset_y = 0;
8740 g_em->width = TILEX;
8741 g_em->height = TILEY;
8745 /* skip check for EMC elements not contained in original EMC artwork */
8746 if (element == EL_PLAYER_3 ||
8747 element == EL_PLAYER_4)
8750 if (g_em->bitmap != debug_bitmap ||
8751 g_em->src_x != debug_src_x ||
8752 g_em->src_y != debug_src_y)
8754 static int last_i = -1;
8762 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
8763 p, i, element, element_info[element].token_name,
8764 element_action_info[effective_action].suffix, direction);
8766 if (element != effective_element)
8767 printf(" [%d ('%s')]",
8769 element_info[effective_element].token_name);
8773 if (g_em->bitmap != debug_bitmap)
8774 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
8775 j, (int)(g_em->bitmap), (int)(debug_bitmap));
8777 if (g_em->src_x != debug_src_x ||
8778 g_em->src_y != debug_src_y)
8779 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
8781 g_em->src_x, g_em->src_y,
8782 g_em->src_x / 32, g_em->src_y / 32,
8783 debug_src_x, debug_src_y,
8784 debug_src_x / 32, debug_src_y / 32);
8786 num_em_gfx_errors++;
8796 printf("::: [%d errors found]\n", num_em_gfx_errors);
8802 void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
8803 boolean any_player_moving,
8804 boolean player_is_dropping)
8808 if (tape.single_step && tape.recording && !tape.pausing)
8810 boolean active_players = FALSE;
8812 for (i = 0; i < MAX_PLAYERS; i++)
8813 if (action[i] != JOY_NO_ACTION)
8814 active_players = TRUE;
8817 if (frame == 0 && !player_is_dropping)
8818 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
8822 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
8823 boolean murphy_is_dropping)
8826 printf("::: waiting: %d, dropping: %d\n",
8827 murphy_is_waiting, murphy_is_dropping);
8830 if (tape.single_step && tape.recording && !tape.pausing)
8832 // if (murphy_is_waiting || murphy_is_dropping)
8833 if (murphy_is_waiting)
8836 printf("::: murphy is waiting -> pause mode\n");
8839 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
8844 void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
8845 int graphic, int sync_frame, int x, int y)
8847 int frame = getGraphicAnimationFrame(graphic, sync_frame);
8849 getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
8852 boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
8854 return (IS_NEXT_FRAME(sync_frame, graphic));
8857 int getGraphicInfo_Delay(int graphic)
8859 return graphic_info[graphic].anim_delay;
8862 void PlayMenuSoundExt(int sound)
8864 if (sound == SND_UNDEFINED)
8867 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
8868 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
8871 if (IS_LOOP_SOUND(sound))
8872 PlaySoundLoop(sound);
8877 void PlayMenuSound()
8879 PlayMenuSoundExt(menu.sound[game_status]);
8882 void PlayMenuSoundStereo(int sound, int stereo_position)
8884 if (sound == SND_UNDEFINED)
8887 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
8888 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
8891 if (IS_LOOP_SOUND(sound))
8892 PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP);
8894 PlaySoundStereo(sound, stereo_position);
8897 void PlayMenuSoundIfLoopExt(int sound)
8899 if (sound == SND_UNDEFINED)
8902 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
8903 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
8906 if (IS_LOOP_SOUND(sound))
8907 PlaySoundLoop(sound);
8910 void PlayMenuSoundIfLoop()
8912 PlayMenuSoundIfLoopExt(menu.sound[game_status]);
8915 void PlayMenuMusicExt(int music)
8917 if (music == MUS_UNDEFINED)
8920 if (!setup.sound_music)
8926 void PlayMenuMusic()
8928 PlayMenuMusicExt(menu.music[game_status]);
8931 void PlaySoundActivating()
8934 PlaySound(SND_MENU_ITEM_ACTIVATING);
8938 void PlaySoundSelecting()
8941 PlaySound(SND_MENU_ITEM_SELECTING);
8945 void ToggleFullscreenIfNeeded()
8947 boolean change_fullscreen = (setup.fullscreen !=
8948 video.fullscreen_enabled);
8949 boolean change_fullscreen_mode = (video.fullscreen_enabled &&
8950 !strEqual(setup.fullscreen_mode,
8951 video.fullscreen_mode_current));
8953 if (!video.fullscreen_available)
8956 if (change_fullscreen || change_fullscreen_mode)
8958 Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
8960 /* save backbuffer content which gets lost when toggling fullscreen mode */
8961 BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
8963 if (change_fullscreen_mode)
8965 /* keep fullscreen, but change fullscreen mode (screen resolution) */
8966 video.fullscreen_enabled = FALSE; /* force new fullscreen mode */
8969 /* toggle fullscreen */
8970 ChangeVideoModeIfNeeded(setup.fullscreen);
8972 setup.fullscreen = video.fullscreen_enabled;
8974 /* restore backbuffer content from temporary backbuffer backup bitmap */
8975 BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
8977 FreeBitmap(tmp_backbuffer);
8980 /* update visible window/screen */
8981 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
8983 redraw_mask = REDRAW_ALL;
8988 void ChangeViewportPropertiesIfNeeded()
8990 int *door_1_x = &DX;
8991 int *door_1_y = &DY;
8992 int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
8993 int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
8994 int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
8995 game_status == GAME_MODE_EDITOR ? game_status :
8997 struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
8998 struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
8999 struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode];
9000 int border_size = vp_playfield->border_size;
9001 int new_sx = vp_playfield->x + border_size;
9002 int new_sy = vp_playfield->y + border_size;
9003 int new_sxsize = vp_playfield->width - 2 * border_size;
9004 int new_sysize = vp_playfield->height - 2 * border_size;
9005 int new_real_sx = vp_playfield->x;
9006 int new_real_sy = vp_playfield->y;
9007 int new_full_sxsize = vp_playfield->width;
9008 int new_full_sysize = vp_playfield->height;
9010 int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
9011 int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
9012 gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
9013 int new_scr_fieldx = new_sxsize / tilesize;
9014 int new_scr_fieldy = new_sysize / tilesize;
9015 int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var;
9016 int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
9018 int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE;
9019 int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE;
9021 boolean init_gfx_buffers = FALSE;
9022 boolean init_video_buffer = FALSE;
9023 boolean init_gadgets_and_toons = FALSE;
9026 /* !!! TEST ONLY !!! */
9027 // InitGfxBuffers();
9031 if (viewport.window.width != WIN_XSIZE ||
9032 viewport.window.height != WIN_YSIZE)
9034 WIN_XSIZE = viewport.window.width;
9035 WIN_YSIZE = viewport.window.height;
9038 init_video_buffer = TRUE;
9039 init_gfx_buffers = TRUE;
9041 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
9045 SetDrawDeactivationMask(REDRAW_NONE);
9046 SetDrawBackgroundMask(REDRAW_FIELD);
9048 // RedrawBackground();
9052 // printf("::: video: init_video_buffer, init_gfx_buffers\n");
9055 if (new_scr_fieldx != SCR_FIELDX ||
9056 new_scr_fieldy != SCR_FIELDY)
9058 /* this always toggles between MAIN and GAME when using small tile size */
9060 SCR_FIELDX = new_scr_fieldx;
9061 SCR_FIELDY = new_scr_fieldy;
9063 // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
9067 if (new_tilesize_var != TILESIZE_VAR &&
9068 gfx_game_mode == GAME_MODE_PLAYING)
9070 /* doing this outside GAME_MODE_PLAYING would give wrong playfield size */
9072 TILESIZE_VAR = new_tilesize_var;
9074 init_gfx_buffers = TRUE;
9076 // printf("::: tilesize: init_gfx_buffers\n");
9082 new_sxsize != SXSIZE ||
9083 new_sysize != SYSIZE ||
9084 new_real_sx != REAL_SX ||
9085 new_real_sy != REAL_SY ||
9086 new_full_sxsize != FULL_SXSIZE ||
9087 new_full_sysize != FULL_SYSIZE ||
9088 new_tilesize_var != TILESIZE_VAR ||
9089 vp_door_1->x != *door_1_x ||
9090 vp_door_1->y != *door_1_y ||
9091 vp_door_2->x != *door_2_x ||
9092 vp_door_2->y != *door_2_y)
9096 SXSIZE = new_sxsize;
9097 SYSIZE = new_sysize;
9098 REAL_SX = new_real_sx;
9099 REAL_SY = new_real_sy;
9100 FULL_SXSIZE = new_full_sxsize;
9101 FULL_SYSIZE = new_full_sysize;
9102 TILESIZE_VAR = new_tilesize_var;
9105 printf("::: %d, %d, %d [%d]\n",
9106 SCR_FIELDX, SCR_FIELDY, TILESIZE_VAR,
9107 setup.small_game_graphics);
9110 *door_1_x = vp_door_1->x;
9111 *door_1_y = vp_door_1->y;
9112 *door_2_x = vp_door_2->x;
9113 *door_2_y = vp_door_2->y;
9116 init_gfx_buffers = TRUE;
9118 // printf("::: viewports: init_gfx_buffers\n");
9123 if (gfx_game_mode == GAME_MODE_MAIN)
9126 init_gadgets_and_toons = TRUE;
9128 // printf("::: viewports: init_gadgets_and_toons\n");
9136 if (init_gfx_buffers)
9138 // printf("::: init_gfx_buffers\n");
9140 SCR_FIELDX = new_scr_fieldx_buffers;
9141 SCR_FIELDY = new_scr_fieldy_buffers;
9145 SCR_FIELDX = new_scr_fieldx;
9146 SCR_FIELDY = new_scr_fieldy;
9149 if (init_video_buffer)
9151 // printf("::: init_video_buffer\n");
9153 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
9155 SetDrawDeactivationMask(REDRAW_NONE);
9156 SetDrawBackgroundMask(REDRAW_FIELD);
9159 if (init_gadgets_and_toons)
9161 // printf("::: init_gadgets_and_toons\n");
9168 printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status);