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();
310 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
313 printf("::: TILES TO REFRESH: %d\n", redraw_tiles);
314 for (x = 0; x < SCR_FIELDX; x++)
315 for (y = 0 ; y < SCR_FIELDY; y++)
316 if (redraw[redraw_x1 + x][redraw_y1 + y])
317 printf("::: - %d, %d [%s]\n",
318 LEVELX(x), LEVELY(y),
319 EL_NAME(Feld[LEVELX(x)][LEVELY(y)]));
322 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
323 redraw_mask |= REDRAW_FIELD;
325 if (redraw_mask & REDRAW_FIELD)
326 redraw_mask &= ~REDRAW_TILES;
328 if (redraw_mask == REDRAW_NONE)
331 if (redraw_mask & REDRAW_TILES &&
332 game_status == GAME_MODE_PLAYING &&
333 border.draw_masked[GAME_MODE_PLAYING])
334 redraw_mask |= REDRAW_FIELD;
336 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
338 static boolean last_frame_skipped = FALSE;
339 boolean skip_even_when_not_scrolling = TRUE;
340 boolean just_scrolling = (ScreenMovDir != 0);
341 boolean verbose = FALSE;
343 if (global.fps_slowdown_factor > 1 &&
344 (FrameCounter % global.fps_slowdown_factor) &&
345 (just_scrolling || skip_even_when_not_scrolling))
347 redraw_mask &= ~REDRAW_MAIN;
349 last_frame_skipped = TRUE;
352 printf("FRAME SKIPPED\n");
356 if (last_frame_skipped)
357 redraw_mask |= REDRAW_FIELD;
359 last_frame_skipped = FALSE;
362 printf("frame not skipped\n");
366 /* synchronize X11 graphics at this point; if we would synchronize the
367 display immediately after the buffer switching (after the XFlush),
368 this could mean that we have to wait for the graphics to complete,
369 although we could go on doing calculations for the next frame */
373 /* never draw masked border to backbuffer when using playfield buffer */
374 if (game_status != GAME_MODE_PLAYING ||
375 redraw_mask & REDRAW_FROM_BACKBUFFER ||
376 buffer == backbuffer)
377 DrawMaskedBorder(redraw_mask);
379 DrawMaskedBorder(redraw_mask & REDRAW_DOORS);
381 if (redraw_mask & REDRAW_ALL)
383 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
385 redraw_mask = REDRAW_NONE;
388 if (redraw_mask & REDRAW_FIELD)
391 printf("::: REDRAW_FIELD\n");
394 if (game_status != GAME_MODE_PLAYING ||
395 redraw_mask & REDRAW_FROM_BACKBUFFER)
397 BlitBitmap(backbuffer, window,
398 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
402 int fx = FX, fy = FY;
404 if (setup.soft_scrolling)
407 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
408 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
410 int bx1, bx2, ffx, ffy;
412 // fx += dx * TILESIZE_VAR / TILESIZE;
413 // fy += dy * TILESIZE_VAR / TILESIZE;
415 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
416 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
422 bx1 = SBX_Left * TILEX_VAR + TILEX_VAR / 2;
423 // bx1 = SBX_Left * TILEX_VAR;
424 bx2 = SBX_Right * TILEX_VAR - TILEX_VAR / 2;
425 ffx = scroll_x * TILEX_VAR + dx * TILESIZE_VAR / TILESIZE;
427 if (ffx > bx1) // && ffx < bx2)
428 fx += dx * TILESIZE_VAR / TILESIZE;
430 // fx += TILEX_VAR - (ffx - bx1) % TILEX_VAR;
432 printf("::: %d (%d, %d) (%d)\n", ffx, bx1, bx2, dx);
435 if (ffx > SBX_Left * TILEX_VAR)
436 fx -= MIN(ffx, TILEX_VAR / 2);
437 if (ffx > SBX_Left * TILEX_VAR && ffx < (SBX_Right + 1) * TILEX_VAR)
438 fx -= MIN(ffx, TILEX_VAR / 2);
444 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx * TILESIZE_VAR / TILESIZE;
446 if (EVEN(SCR_FIELDX))
448 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2)
449 fx = fx + dx * TILESIZE_VAR / TILESIZE - MIN(ffx, TILEX_VAR / 2);
451 fx = fx - (dx <= 0 ? TILEX_VAR : 0);
453 printf("::: %d (%d, %d) [%d] [%d] => %d\n",
454 ffx, SBX_Left * TILEX_VAR, SBX_Right * TILEX_VAR, dx, FX, fx);
459 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx * TILESIZE_VAR / TILESIZE;
461 if (EVEN(SCR_FIELDX))
463 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + 0 * TILEX_VAR / 2)
465 fx = fx + dx * TILESIZE_VAR / TILESIZE - MIN(ffx, TILEX_VAR / 2) +
470 fx = fx - (dx <= 0 ? TILEX_VAR : 0) + 1 * TILEX_VAR;
472 printf("::: STOPPED\n");
475 printf("::: %d (%d, %d) [%d] [%d] => %d\n",
476 ffx, SBX_Left * TILEX_VAR, SBX_Right * TILEX_VAR, dx, FX, fx);
479 /* !!! THIS WORKS !!! */
481 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx * TILESIZE_VAR / TILESIZE;
483 if (EVEN(SCR_FIELDX))
485 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + 2 * TILEX_VAR / 2)
487 fx = fx + dx * TILESIZE_VAR / TILESIZE - MIN(ffx, TILEX_VAR / 2) +
492 fx = fx - (dx <= 0 ? TILEX_VAR : 0) + 1 * TILEX_VAR;
494 printf("::: STOPPED\n");
497 printf("::: %d (%d, %d) [%d] [%d] => %d\n",
498 ffx, SBX_Left * TILEX_VAR, SBX_Right * TILEX_VAR, dx, FX, fx);
507 printf("::: %d, %d [%d, %d] [%d, %d] [%d, %d] [%d] [%d, %d]\n",
508 fx, fy, FX, FY, ScreenMovDir, ScreenGfxPos,
511 SBX_Left, SBX_Right);
518 fx = fx * TILESIZE_VAR / TILESIZE;
519 fy = fy * TILESIZE_VAR / TILESIZE;
524 if (setup.soft_scrolling ||
525 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
526 ABS(ScreenMovPos) == ScrollStepSize ||
527 redraw_tiles > REDRAWTILES_THRESHOLD)
529 if (border.draw_masked[GAME_MODE_PLAYING])
531 if (buffer != backbuffer)
533 /* copy playfield buffer to backbuffer to add masked border */
534 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
535 DrawMaskedBorder(REDRAW_FIELD);
538 BlitBitmap(backbuffer, window,
539 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
544 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
549 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
551 (setup.soft_scrolling ?
552 "setup.soft_scrolling" :
553 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
554 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
555 ABS(ScreenGfxPos) == ScrollStepSize ?
556 "ABS(ScreenGfxPos) == ScrollStepSize" :
557 "redraw_tiles > REDRAWTILES_THRESHOLD"));
563 redraw_mask &= ~REDRAW_MAIN;
566 if (redraw_mask & REDRAW_DOORS)
568 if (redraw_mask & REDRAW_DOOR_1)
569 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
571 if (redraw_mask & REDRAW_DOOR_2)
572 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
574 if (redraw_mask & REDRAW_DOOR_3)
575 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
577 redraw_mask &= ~REDRAW_DOORS;
580 if (redraw_mask & REDRAW_MICROLEVEL)
582 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
583 SX, SY + 10 * TILEY);
585 redraw_mask &= ~REDRAW_MICROLEVEL;
588 if (redraw_mask & REDRAW_TILES)
591 printf("::: REDRAW_TILES\n");
595 for (x = 0; x < SCR_FIELDX; x++)
596 for (y = 0 ; y < SCR_FIELDY; y++)
597 if (redraw[redraw_x1 + x][redraw_y1 + y])
598 BlitBitmap(buffer, window,
599 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
600 TILEX_VAR, TILEY_VAR,
601 SX + x * TILEX_VAR, SY + y * TILEY_VAR);
603 for (x = 0; x < SCR_FIELDX; x++)
604 for (y = 0 ; y < SCR_FIELDY; y++)
605 if (redraw[redraw_x1 + x][redraw_y1 + y])
606 BlitBitmap(buffer, window,
607 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
608 SX + x * TILEX, SY + y * TILEY);
612 if (redraw_mask & REDRAW_FPS) /* display frames per second */
617 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
618 if (!global.fps_slowdown)
621 sprintf(text, "%04.1f fps%s", global.frames_per_second, info1);
623 DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE);
625 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
631 for (x = 0; x < MAX_BUF_XSIZE; x++)
632 for (y = 0; y < MAX_BUF_YSIZE; y++)
635 redraw_mask = REDRAW_NONE;
638 static void FadeCrossSaveBackbuffer()
640 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
643 static void FadeExt(int fade_mask, int fade_mode, int fade_type)
645 static int fade_type_skip = FADE_TYPE_NONE;
646 void (*draw_border_function)(void) = NULL;
647 Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL);
648 int x, y, width, height;
649 int fade_delay, post_delay;
651 if (fade_type == FADE_TYPE_FADE_OUT)
653 if (fade_type_skip != FADE_TYPE_NONE)
656 printf("::: skipping %d ... [%d] (X)\n", fade_mode, fade_type_skip);
659 /* skip all fade operations until specified fade operation */
660 if (fade_type & fade_type_skip)
661 fade_type_skip = FADE_TYPE_NONE;
666 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
668 FadeCrossSaveBackbuffer();
674 redraw_mask |= fade_mask;
676 if (fade_type == FADE_TYPE_SKIP)
679 printf("::: will skip %d ... [%d]\n", fade_mode, fade_type_skip);
682 fade_type_skip = fade_mode;
688 printf("::: !!! FADING %d ... [%d] [%d]\n", fade_mode, fade_type,
693 fade_delay = fading.fade_delay;
694 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
697 if (fade_type_skip != FADE_TYPE_NONE)
700 printf("::: skipping %d ... [%d]\n", fade_mode, fade_type_skip);
703 /* skip all fade operations until specified fade operation */
704 if (fade_type & fade_type_skip)
705 fade_type_skip = FADE_TYPE_NONE;
715 if (global.autoplay_leveldir)
717 // fading.fade_mode = FADE_MODE_NONE;
724 if (fading.fade_mode == FADE_MODE_NONE)
732 /* !!! what about fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */
735 printf("::: NOW FADING %d ... [%d]\n", fade_mode, fade_type);
739 if (fade_mask == REDRAW_NONE)
740 fade_mask = REDRAW_FIELD;
743 // if (fade_mask & REDRAW_FIELD)
744 if (fade_mask == REDRAW_FIELD)
749 height = FULL_SYSIZE;
752 fade_delay = fading.fade_delay;
753 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
756 if (border.draw_masked_when_fading)
757 draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */
759 DrawMaskedBorder_FIELD(); /* draw once */
761 else /* REDRAW_ALL */
769 fade_delay = fading.fade_delay;
770 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
775 if (!setup.fade_screens ||
777 fading.fade_mode == FADE_MODE_NONE)
779 if (!setup.fade_screens || fade_delay == 0)
782 if (fade_mode == FADE_MODE_FADE_OUT)
786 if (fade_mode == FADE_MODE_FADE_OUT &&
787 fading.fade_mode != FADE_MODE_NONE)
788 ClearRectangle(backbuffer, x, y, width, height);
792 BlitBitmap(backbuffer, window, x, y, width, height, x, y);
793 redraw_mask = REDRAW_NONE;
801 FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay,
802 draw_border_function);
804 redraw_mask &= ~fade_mask;
807 void FadeIn(int fade_mask)
809 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
810 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN);
812 FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN);
815 void FadeOut(int fade_mask)
817 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
818 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_OUT);
820 FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT);
822 global.border_status = game_status;
825 static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set)
827 static struct TitleFadingInfo fading_leave_stored;
830 fading_leave_stored = fading_leave;
832 fading = fading_leave_stored;
835 void FadeSetEnterMenu()
837 fading = menu.enter_menu;
840 printf("::: storing enter_menu\n");
843 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
846 void FadeSetLeaveMenu()
848 fading = menu.leave_menu;
851 printf("::: storing leave_menu\n");
854 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
857 void FadeSetEnterScreen()
859 fading = menu.enter_screen[game_status];
862 printf("::: storing leave_screen[%d]\n", game_status);
865 FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */
868 void FadeSetNextScreen()
870 fading = menu.next_screen;
873 printf("::: storing next_screen\n");
876 // (do not overwrite fade mode set by FadeSetEnterScreen)
877 // FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
880 void FadeSetLeaveScreen()
883 printf("::: recalling last stored value\n");
886 FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */
889 void FadeSetFromType(int type)
891 if (type & TYPE_ENTER_SCREEN)
892 FadeSetEnterScreen();
893 else if (type & TYPE_ENTER)
895 else if (type & TYPE_LEAVE)
899 void FadeSetDisabled()
901 static struct TitleFadingInfo fading_none = { FADE_MODE_NONE, -1, -1, -1 };
903 fading = fading_none;
906 void FadeSkipNextFadeIn()
908 FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP);
911 void FadeSkipNextFadeOut()
913 FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
916 void SetWindowBackgroundImageIfDefined(int graphic)
918 if (graphic_info[graphic].bitmap)
919 SetWindowBackgroundBitmap(graphic_info[graphic].bitmap);
922 void SetMainBackgroundImageIfDefined(int graphic)
924 if (graphic_info[graphic].bitmap)
925 SetMainBackgroundBitmap(graphic_info[graphic].bitmap);
928 void SetDoorBackgroundImageIfDefined(int graphic)
930 if (graphic_info[graphic].bitmap)
931 SetDoorBackgroundBitmap(graphic_info[graphic].bitmap);
934 void SetWindowBackgroundImage(int graphic)
936 SetWindowBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
937 graphic_info[graphic].bitmap ?
938 graphic_info[graphic].bitmap :
939 graphic_info[IMG_BACKGROUND].bitmap);
942 void SetMainBackgroundImage(int graphic)
944 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
945 graphic_info[graphic].bitmap ?
946 graphic_info[graphic].bitmap :
947 graphic_info[IMG_BACKGROUND].bitmap);
950 void SetDoorBackgroundImage(int graphic)
952 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
953 graphic_info[graphic].bitmap ?
954 graphic_info[graphic].bitmap :
955 graphic_info[IMG_BACKGROUND].bitmap);
958 void SetPanelBackground()
961 struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL];
964 BlitBitmapTiled(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
965 gfx->width, gfx->height, 0, 0, DXSIZE, DYSIZE);
967 /* (ClearRectangle() only needed if panel bitmap is smaller than panel) */
968 ClearRectangle(bitmap_db_panel, DX, DY, DXSIZE, DYSIZE);
969 BlitBitmap(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
970 MIN(gfx->width, DXSIZE), MIN(gfx->height, DYSIZE), 0, 0);
973 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, bitmap_db_panel,
974 DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, 0, 0);
977 SetDoorBackgroundBitmap(bitmap_db_panel);
980 void DrawBackground(int x, int y, int width, int height)
982 /* !!! "drawto" might still point to playfield buffer here (see below) !!! */
983 /* (when entering hall of fame after playing) */
985 ClearRectangleOnBackground(drawto, x, y, width, height);
987 ClearRectangleOnBackground(backbuffer, x, y, width, height);
990 redraw_mask |= REDRAW_FIELD;
993 void DrawBackgroundForFont(int x, int y, int width, int height, int font_nr)
995 struct FontBitmapInfo *font = getFontBitmapInfo(font_nr);
997 if (font->bitmap == NULL)
1000 DrawBackground(x, y, width, height);
1003 void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic)
1005 struct GraphicInfo *g = &graphic_info[graphic];
1007 if (g->bitmap == NULL)
1010 DrawBackground(x, y, width, height);
1015 /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
1016 /* (when entering hall of fame after playing) */
1017 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
1019 /* !!! maybe this should be done before clearing the background !!! */
1020 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
1022 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
1023 SetDrawtoField(DRAW_BUFFERED);
1026 SetDrawtoField(DRAW_BACKBUFFER);
1029 void MarkTileDirty(int x, int y)
1031 int xx = redraw_x1 + x;
1032 int yy = redraw_y1 + y;
1034 if (!redraw[xx][yy])
1037 redraw[xx][yy] = TRUE;
1038 redraw_mask |= REDRAW_TILES;
1041 void SetBorderElement()
1045 BorderElement = EL_EMPTY;
1047 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
1049 for (x = 0; x < lev_fieldx; x++)
1051 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
1052 BorderElement = EL_STEELWALL;
1054 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
1060 void FloodFillLevel(int from_x, int from_y, int fill_element,
1061 short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
1062 int max_fieldx, int max_fieldy)
1066 static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
1067 static int safety = 0;
1069 /* check if starting field still has the desired content */
1070 if (field[from_x][from_y] == fill_element)
1075 if (safety > max_fieldx * max_fieldy)
1076 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
1078 old_element = field[from_x][from_y];
1079 field[from_x][from_y] = fill_element;
1081 for (i = 0; i < 4; i++)
1083 x = from_x + check[i][0];
1084 y = from_y + check[i][1];
1086 if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
1087 FloodFillLevel(x, y, fill_element, field, max_fieldx, max_fieldy);
1093 void SetRandomAnimationValue(int x, int y)
1095 gfx.anim_random_frame = GfxRandom[x][y];
1098 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
1100 /* animation synchronized with global frame counter, not move position */
1101 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
1102 sync_frame = FrameCounter;
1104 return getAnimationFrame(graphic_info[graphic].anim_frames,
1105 graphic_info[graphic].anim_delay,
1106 graphic_info[graphic].anim_mode,
1107 graphic_info[graphic].anim_start_frame,
1111 void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw,
1112 Bitmap **bitmap, int *x, int *y,
1113 boolean get_backside)
1117 int width_mult, width_div;
1118 int height_mult, height_div;
1122 { 15, 16, 2, 3 }, /* 1 x 1 */
1123 { 7, 8, 2, 3 }, /* 2 x 2 */
1124 { 3, 4, 2, 3 }, /* 4 x 4 */
1125 { 1, 2, 2, 3 }, /* 8 x 8 */
1126 { 0, 1, 2, 3 }, /* 16 x 16 */
1127 { 0, 1, 0, 1 }, /* 32 x 32 */
1129 struct GraphicInfo *g = &graphic_info[graphic];
1130 Bitmap *src_bitmap = g->bitmap;
1131 int tilesize = MIN(MAX(1, tilesize_raw), TILESIZE);
1132 int offset_calc_pos = log_2(tilesize);
1133 int width_mult = offset_calc[offset_calc_pos].width_mult;
1134 int width_div = offset_calc[offset_calc_pos].width_div;
1135 int height_mult = offset_calc[offset_calc_pos].height_mult;
1136 int height_div = offset_calc[offset_calc_pos].height_div;
1137 int startx = src_bitmap->width * width_mult / width_div;
1138 int starty = src_bitmap->height * height_mult / height_div;
1140 int src_x = (g->src_x + (get_backside ? g->offset2_x : 0)) *
1141 tilesize / TILESIZE;
1142 int src_y = (g->src_y + (get_backside ? g->offset2_y : 0)) *
1143 tilesize / TILESIZE;
1145 int src_x = g->src_x * tilesize / TILESIZE;
1146 int src_y = g->src_y * tilesize / TILESIZE;
1148 int width = g->width * tilesize / TILESIZE;
1149 int height = g->height * tilesize / TILESIZE;
1150 int offset_x = g->offset_x * tilesize / TILESIZE;
1151 int offset_y = g->offset_y * tilesize / TILESIZE;
1153 if (g->offset_y == 0) /* frames are ordered horizontally */
1155 int max_width = g->anim_frames_per_line * width;
1156 int pos = (src_y / height) * max_width + src_x + frame * offset_x;
1158 src_x = pos % max_width;
1159 src_y = src_y % height + pos / max_width * height;
1161 else if (g->offset_x == 0) /* frames are ordered vertically */
1163 int max_height = g->anim_frames_per_line * height;
1164 int pos = (src_x / width) * max_height + src_y + frame * offset_y;
1166 src_x = src_x % width + pos / max_height * width;
1167 src_y = pos % max_height;
1169 else /* frames are ordered diagonally */
1171 src_x = src_x + frame * offset_x;
1172 src_y = src_y + frame * offset_y;
1175 *bitmap = src_bitmap;
1176 *x = startx + src_x;
1177 *y = starty + src_y;
1180 void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1181 int *x, int *y, boolean get_backside)
1183 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y,
1187 void getSizedGraphicSource(int graphic, int frame, int tilesize_raw,
1188 Bitmap **bitmap, int *x, int *y)
1190 getSizedGraphicSourceExt(graphic, frame, tilesize_raw, bitmap, x, y, FALSE);
1193 void getFixedGraphicSource(int graphic, int frame,
1194 Bitmap **bitmap, int *x, int *y)
1196 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y, FALSE);
1199 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1202 getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
1204 struct GraphicInfo *g = &graphic_info[graphic];
1205 int mini_startx = 0;
1206 int mini_starty = g->bitmap->height * 2 / 3;
1208 *bitmap = g->bitmap;
1209 *x = mini_startx + g->src_x / 2;
1210 *y = mini_starty + g->src_y / 2;
1214 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1215 int *x, int *y, boolean get_backside)
1217 struct GraphicInfo *g = &graphic_info[graphic];
1218 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
1219 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
1222 if (TILESIZE_VAR != TILESIZE)
1223 return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
1227 *bitmap = g->bitmap;
1229 if (g->offset_y == 0) /* frames are ordered horizontally */
1231 int max_width = g->anim_frames_per_line * g->width;
1232 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
1234 *x = pos % max_width;
1235 *y = src_y % g->height + pos / max_width * g->height;
1237 else if (g->offset_x == 0) /* frames are ordered vertically */
1239 int max_height = g->anim_frames_per_line * g->height;
1240 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
1242 *x = src_x % g->width + pos / max_height * g->width;
1243 *y = pos % max_height;
1245 else /* frames are ordered diagonally */
1247 *x = src_x + frame * g->offset_x;
1248 *y = src_y + frame * g->offset_y;
1252 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
1254 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
1257 void DrawGraphic(int x, int y, int graphic, int frame)
1260 if (!IN_SCR_FIELD(x, y))
1262 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1263 printf("DrawGraphic(): This should never happen!\n");
1269 DrawGraphicExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR, graphic,
1272 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
1274 MarkTileDirty(x, y);
1277 void DrawFixedGraphic(int x, int y, int graphic, int frame)
1280 if (!IN_SCR_FIELD(x, y))
1282 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1283 printf("DrawGraphic(): This should never happen!\n");
1288 DrawFixedGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1290 MarkTileDirty(x, y);
1293 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1299 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1301 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX_VAR, TILEY_VAR, x, y);
1303 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1307 void DrawFixedGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1313 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1314 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1317 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
1320 if (!IN_SCR_FIELD(x, y))
1322 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1323 printf("DrawGraphicThruMask(): This should never happen!\n");
1329 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
1332 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1335 MarkTileDirty(x, y);
1338 void DrawFixedGraphicThruMask(int x, int y, int graphic, int frame)
1341 if (!IN_SCR_FIELD(x, y))
1343 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1344 printf("DrawGraphicThruMask(): This should never happen!\n");
1349 DrawFixedGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1351 MarkTileDirty(x, y);
1354 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
1360 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1362 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1363 dst_x - src_x, dst_y - src_y);
1365 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX_VAR, TILEY_VAR,
1368 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1372 void DrawFixedGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y,
1373 int graphic, int frame)
1378 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1380 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1381 dst_x - src_x, dst_y - src_y);
1382 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1385 void DrawSizedGraphic(int x, int y, int graphic, int frame, int tilesize)
1387 DrawSizedGraphicExt(drawto, SX + x * tilesize, SY + y * tilesize, graphic,
1389 MarkTileDirty(x / tilesize, y / tilesize);
1392 void DrawSizedGraphicExt(DrawBuffer *d, int x, int y, int graphic, int frame,
1398 getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
1399 BlitBitmap(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
1402 void DrawMiniGraphic(int x, int y, int graphic)
1404 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1405 MarkTileDirty(x / 2, y / 2);
1408 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1413 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1414 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1417 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
1418 int graphic, int frame,
1419 int cut_mode, int mask_mode)
1424 int width = TILEX, height = TILEY;
1427 if (dx || dy) /* shifted graphic */
1429 if (x < BX1) /* object enters playfield from the left */
1436 else if (x > BX2) /* object enters playfield from the right */
1442 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1448 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1450 else if (dx) /* general horizontal movement */
1451 MarkTileDirty(x + SIGN(dx), y);
1453 if (y < BY1) /* object enters playfield from the top */
1455 if (cut_mode==CUT_BELOW) /* object completely above top border */
1463 else if (y > BY2) /* object enters playfield from the bottom */
1469 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1475 else if (dy > 0 && cut_mode == CUT_ABOVE)
1477 if (y == BY2) /* object completely above bottom border */
1483 MarkTileDirty(x, y + 1);
1484 } /* object leaves playfield to the bottom */
1485 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1487 else if (dy) /* general vertical movement */
1488 MarkTileDirty(x, y + SIGN(dy));
1492 if (!IN_SCR_FIELD(x, y))
1494 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1495 printf("DrawGraphicShifted(): This should never happen!\n");
1501 width = width * TILESIZE_VAR / TILESIZE;
1502 height = height * TILESIZE_VAR / TILESIZE;
1503 cx = cx * TILESIZE_VAR / TILESIZE;
1504 cy = cy * TILESIZE_VAR / TILESIZE;
1505 dx = dx * TILESIZE_VAR / TILESIZE;
1506 dy = dy * TILESIZE_VAR / TILESIZE;
1509 if (width > 0 && height > 0)
1511 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1517 dst_x = FX + x * TILEX_VAR + dx;
1518 dst_y = FY + y * TILEY_VAR + dy;
1520 dst_x = FX + x * TILEX + dx;
1521 dst_y = FY + y * TILEY + dy;
1524 if (mask_mode == USE_MASKING)
1526 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1527 dst_x - src_x, dst_y - src_y);
1528 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1532 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1535 MarkTileDirty(x, y);
1539 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
1540 int graphic, int frame,
1541 int cut_mode, int mask_mode)
1547 int width = TILEX_VAR, height = TILEY_VAR;
1549 int width = TILEX, height = TILEY;
1553 int x2 = x + SIGN(dx);
1554 int y2 = y + SIGN(dy);
1556 /* !!! DOES NOT WORK FOR SLOW MOVEMENT !!! */
1557 int sync_frame = GfxFrame[LEVELX(x)][LEVELY(y)];
1559 /* movement with two-tile animations must be sync'ed with movement position,
1560 not with current GfxFrame (which can be higher when using slow movement) */
1561 int anim_pos = (dx ? ABS(dx) : ABS(dy));
1562 int anim_frames = graphic_info[graphic].anim_frames;
1564 /* (we also need anim_delay here for movement animations with less frames) */
1565 int anim_delay = graphic_info[graphic].anim_delay;
1566 int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
1568 int sync_frame = anim_pos * anim_frames / TILESIZE;
1571 boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */
1572 boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */
1574 /* re-calculate animation frame for two-tile movement animation */
1575 frame = getGraphicAnimationFrame(graphic, sync_frame);
1579 printf("::: %d, %d, %d => %d [%d]\n",
1580 anim_pos, anim_frames, anim_delay, sync_frame, graphic);
1582 printf("::: %d, %d => %d\n",
1583 anim_pos, anim_frames, sync_frame);
1588 printf("::: %d [%d, %d] [%d] [%d]\n", frame, sync_frame, dy,
1589 GfxFrame[LEVELX(x)][LEVELY(y)], mask_mode);
1592 /* check if movement start graphic inside screen area and should be drawn */
1593 if (draw_start_tile && IN_SCR_FIELD(x1, y1))
1595 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
1598 dst_x = FX + x1 * TILEX_VAR;
1599 dst_y = FY + y1 * TILEY_VAR;
1601 dst_x = FX + x1 * TILEX;
1602 dst_y = FY + y1 * TILEY;
1605 if (mask_mode == USE_MASKING)
1607 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1608 dst_x - src_x, dst_y - src_y);
1609 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1613 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1616 MarkTileDirty(x1, y1);
1619 /* check if movement end graphic inside screen area and should be drawn */
1620 if (draw_end_tile && IN_SCR_FIELD(x2, y2))
1622 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
1625 dst_x = FX + x2 * TILEX_VAR;
1626 dst_y = FY + y2 * TILEY_VAR;
1628 dst_x = FX + x2 * TILEX;
1629 dst_y = FY + y2 * TILEY;
1632 if (mask_mode == USE_MASKING)
1634 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1635 dst_x - src_x, dst_y - src_y);
1636 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1640 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1643 MarkTileDirty(x2, y2);
1647 static void DrawGraphicShifted(int x, int y, int dx, int dy,
1648 int graphic, int frame,
1649 int cut_mode, int mask_mode)
1653 DrawGraphic(x, y, graphic, frame);
1658 if (graphic_info[graphic].double_movement) /* EM style movement images */
1659 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1661 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1664 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1665 int frame, int cut_mode)
1667 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1670 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1671 int cut_mode, int mask_mode)
1673 int lx = LEVELX(x), ly = LEVELY(y);
1677 if (IN_LEV_FIELD(lx, ly))
1679 SetRandomAnimationValue(lx, ly);
1681 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1682 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1684 /* do not use double (EM style) movement graphic when not moving */
1685 if (graphic_info[graphic].double_movement && !dx && !dy)
1687 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
1688 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1691 else /* border element */
1693 graphic = el2img(element);
1694 frame = getGraphicAnimationFrame(graphic, -1);
1697 if (element == EL_EXPANDABLE_WALL)
1699 boolean left_stopped = FALSE, right_stopped = FALSE;
1701 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1702 left_stopped = TRUE;
1703 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1704 right_stopped = TRUE;
1706 if (left_stopped && right_stopped)
1708 else if (left_stopped)
1710 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1711 frame = graphic_info[graphic].anim_frames - 1;
1713 else if (right_stopped)
1715 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1716 frame = graphic_info[graphic].anim_frames - 1;
1721 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1722 else if (mask_mode == USE_MASKING)
1723 DrawGraphicThruMask(x, y, graphic, frame);
1725 DrawGraphic(x, y, graphic, frame);
1728 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1729 int cut_mode, int mask_mode)
1731 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1732 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1733 cut_mode, mask_mode);
1736 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1739 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1742 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1745 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1748 void DrawLevelElementThruMask(int x, int y, int element)
1750 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1753 void DrawLevelFieldThruMask(int x, int y)
1755 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1758 /* !!! implementation of quicksand is totally broken !!! */
1759 #define IS_CRUMBLED_TILE(x, y, e) \
1760 (GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) || \
1761 !IS_MOVING(x, y) || \
1762 (e) == EL_QUICKSAND_EMPTYING || \
1763 (e) == EL_QUICKSAND_FAST_EMPTYING))
1765 static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
1770 int width, height, cx, cy;
1771 int sx = SCREENX(x), sy = SCREENY(y);
1772 int crumbled_border_size = graphic_info[graphic].border_size;
1775 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1777 for (i = 1; i < 4; i++)
1779 int dxx = (i & 1 ? dx : 0);
1780 int dyy = (i & 2 ? dy : 0);
1783 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1786 /* check if neighbour field is of same crumble type */
1787 boolean same = (IS_CRUMBLED_TILE(xx, yy, element) &&
1788 graphic_info[graphic].class ==
1789 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class);
1791 /* return if check prevents inner corner */
1792 if (same == (dxx == dx && dyy == dy))
1796 /* if we reach this point, we have an inner corner */
1798 getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
1801 width = crumbled_border_size * TILESIZE_VAR / TILESIZE;
1802 height = crumbled_border_size * TILESIZE_VAR / TILESIZE;
1803 cx = (dx > 0 ? TILEX - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
1804 cy = (dy > 0 ? TILEY - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
1806 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1807 width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
1809 width = crumbled_border_size;
1810 height = crumbled_border_size;
1811 cx = (dx > 0 ? TILEX - crumbled_border_size : 0);
1812 cy = (dy > 0 ? TILEY - crumbled_border_size : 0);
1814 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1815 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1819 static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
1824 int width, height, bx, by, cx, cy;
1825 int sx = SCREENX(x), sy = SCREENY(y);
1826 int crumbled_border_size = graphic_info[graphic].border_size;
1829 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1831 /* draw simple, sloppy, non-corner-accurate crumbled border */
1834 width = (dir == 1 || dir == 2 ? crumbled_border_size : TILEX);
1835 height = (dir == 0 || dir == 3 ? crumbled_border_size : TILEY);
1836 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
1837 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
1839 if (dir == 1 || dir == 2) /* left or right crumbled border */
1841 width = crumbled_border_size;
1843 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
1846 else /* top or bottom crumbled border */
1849 height = crumbled_border_size;
1851 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
1856 BlitBitmap(src_bitmap, drawto_field,
1857 src_x + cx * TILESIZE_VAR / TILESIZE,
1858 src_y + cy * TILESIZE_VAR / TILESIZE,
1859 width * TILESIZE_VAR / TILESIZE,
1860 height * TILESIZE_VAR / TILESIZE,
1861 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
1862 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
1864 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1865 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1868 /* (remaining middle border part must be at least as big as corner part) */
1869 if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
1870 crumbled_border_size >= TILESIZE / 3)
1873 /* correct corners of crumbled border, if needed */
1876 for (i = -1; i <= 1; i+=2)
1878 int xx = x + (dir == 0 || dir == 3 ? i : 0);
1879 int yy = y + (dir == 1 || dir == 2 ? i : 0);
1880 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1883 /* check if neighbour field is of same crumble type */
1884 if (IS_CRUMBLED_TILE(xx, yy, element) &&
1885 graphic_info[graphic].class ==
1886 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
1888 /* no crumbled corner, but continued crumbled border */
1890 int c1 = (dir == 2 || dir == 3 ? TILESIZE - crumbled_border_size : 0);
1891 int c2 = (i == 1 ? TILESIZE - crumbled_border_size : 0);
1892 int b1 = (i == 1 ? crumbled_border_size :
1893 TILESIZE - 2 * crumbled_border_size);
1895 width = crumbled_border_size;
1896 height = crumbled_border_size;
1898 if (dir == 1 || dir == 2)
1914 BlitBitmap(src_bitmap, drawto_field,
1915 src_x + bx * TILESIZE_VAR / TILESIZE,
1916 src_y + by * TILESIZE_VAR / TILESIZE,
1917 width * TILESIZE_VAR / TILESIZE,
1918 height * TILESIZE_VAR / TILESIZE,
1919 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
1920 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
1922 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
1923 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1928 if (dir == 1 || dir == 2) /* left or right crumbled border */
1930 for (i = -1; i <= 1; i+=2)
1934 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1937 /* check if neighbour field is of same crumble type */
1938 if (IS_CRUMBLED_TILE(xx, yy, element) &&
1939 graphic_info[graphic].class ==
1940 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
1942 /* no crumbled corner, but continued crumbled border */
1944 width = crumbled_border_size;
1945 height = crumbled_border_size;
1946 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
1947 cy = (i == 1 ? TILEY - crumbled_border_size : 0);
1949 by = (i == 1 ? crumbled_border_size :
1950 TILEY - 2 * crumbled_border_size);
1952 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
1953 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1957 else /* top or bottom crumbled border */
1959 for (i = -1; i <= 1; i+=2)
1963 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
1966 /* check if neighbour field is of same crumble type */
1967 if (IS_CRUMBLED_TILE(xx, yy, element) &&
1968 graphic_info[graphic].class ==
1969 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
1971 /* no crumbled corner, but continued crumbled border */
1973 width = crumbled_border_size;
1974 height = crumbled_border_size;
1975 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1976 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
1977 bx = (i == 1 ? crumbled_border_size :
1978 TILEX - 2 * crumbled_border_size);
1981 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
1982 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1989 static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
1991 int sx = SCREENX(x), sy = SCREENY(y);
1994 static int xy[4][2] =
2002 if (!IN_LEV_FIELD(x, y))
2005 element = TILE_GFX_ELEMENT(x, y);
2007 /* crumble field itself */
2008 if (IS_CRUMBLED_TILE(x, y, element))
2010 if (!IN_SCR_FIELD(sx, sy))
2013 for (i = 0; i < 4; i++)
2015 int xx = x + xy[i][0];
2016 int yy = y + xy[i][1];
2018 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2021 /* check if neighbour field is of same crumble type */
2023 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2024 graphic_info[graphic].class ==
2025 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2028 if (IS_CRUMBLED_TILE(xx, yy, element))
2032 DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
2035 if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
2036 graphic_info[graphic].anim_frames == 2)
2038 for (i = 0; i < 4; i++)
2040 int dx = (i & 1 ? +1 : -1);
2041 int dy = (i & 2 ? +1 : -1);
2043 DrawLevelFieldCrumbledInnerCorners(x, y, dx, dy, graphic);
2047 MarkTileDirty(sx, sy);
2049 else /* center field not crumbled -- crumble neighbour fields */
2051 for (i = 0; i < 4; i++)
2053 int xx = x + xy[i][0];
2054 int yy = y + xy[i][1];
2055 int sxx = sx + xy[i][0];
2056 int syy = sy + xy[i][1];
2058 if (!IN_LEV_FIELD(xx, yy) ||
2059 !IN_SCR_FIELD(sxx, syy))
2062 if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
2065 element = TILE_GFX_ELEMENT(xx, yy);
2067 if (!IS_CRUMBLED_TILE(xx, yy, element))
2070 graphic = el_act2crm(element, ACTION_DEFAULT);
2072 DrawLevelFieldCrumbledBorders(xx, yy, graphic, 0, 3 - i);
2074 MarkTileDirty(sxx, syy);
2079 void DrawLevelFieldCrumbled(int x, int y)
2083 if (!IN_LEV_FIELD(x, y))
2087 /* !!! CHECK THIS !!! */
2090 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2091 GFX_CRUMBLED(GfxElement[x][y]))
2094 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2095 GfxElement[x][y] != EL_UNDEFINED &&
2096 GFX_CRUMBLED(GfxElement[x][y]))
2098 DrawLevelFieldCrumbledDigging(x, y, GfxDir[x][y], GfxFrame[x][y]);
2105 graphic = el_act2crm(TILE_GFX_ELEMENT(x, y), ACTION_DEFAULT);
2107 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
2110 DrawLevelFieldCrumbledExt(x, y, graphic, 0);
2113 void DrawLevelFieldCrumbledDigging(int x, int y, int direction,
2116 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
2117 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
2118 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
2119 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
2120 int sx = SCREENX(x), sy = SCREENY(y);
2122 DrawGraphic(sx, sy, graphic1, frame1);
2123 DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
2126 void DrawLevelFieldCrumbledNeighbours(int x, int y)
2128 int sx = SCREENX(x), sy = SCREENY(y);
2129 static int xy[4][2] =
2138 for (i = 0; i < 4; i++)
2140 int xx = x + xy[i][0];
2141 int yy = y + xy[i][1];
2142 int sxx = sx + xy[i][0];
2143 int syy = sy + xy[i][1];
2145 if (!IN_LEV_FIELD(xx, yy) ||
2146 !IN_SCR_FIELD(sxx, syy) ||
2147 !GFX_CRUMBLED(Feld[xx][yy]) ||
2151 DrawLevelField(xx, yy);
2155 static int getBorderElement(int x, int y)
2159 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
2160 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
2161 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
2162 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
2163 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
2164 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
2165 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
2167 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2168 int steel_position = (x == -1 && y == -1 ? 0 :
2169 x == lev_fieldx && y == -1 ? 1 :
2170 x == -1 && y == lev_fieldy ? 2 :
2171 x == lev_fieldx && y == lev_fieldy ? 3 :
2172 x == -1 || x == lev_fieldx ? 4 :
2173 y == -1 || y == lev_fieldy ? 5 : 6);
2175 return border[steel_position][steel_type];
2178 void DrawScreenElement(int x, int y, int element)
2180 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
2181 DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
2184 void DrawLevelElement(int x, int y, int element)
2186 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2187 DrawScreenElement(SCREENX(x), SCREENY(y), element);
2190 void DrawScreenField(int x, int y)
2192 int lx = LEVELX(x), ly = LEVELY(y);
2193 int element, content;
2195 if (!IN_LEV_FIELD(lx, ly))
2197 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
2200 element = getBorderElement(lx, ly);
2202 DrawScreenElement(x, y, element);
2207 element = Feld[lx][ly];
2208 content = Store[lx][ly];
2210 if (IS_MOVING(lx, ly))
2212 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
2213 boolean cut_mode = NO_CUTTING;
2215 if (element == EL_QUICKSAND_EMPTYING ||
2216 element == EL_QUICKSAND_FAST_EMPTYING ||
2217 element == EL_MAGIC_WALL_EMPTYING ||
2218 element == EL_BD_MAGIC_WALL_EMPTYING ||
2219 element == EL_DC_MAGIC_WALL_EMPTYING ||
2220 element == EL_AMOEBA_DROPPING)
2221 cut_mode = CUT_ABOVE;
2222 else if (element == EL_QUICKSAND_FILLING ||
2223 element == EL_QUICKSAND_FAST_FILLING ||
2224 element == EL_MAGIC_WALL_FILLING ||
2225 element == EL_BD_MAGIC_WALL_FILLING ||
2226 element == EL_DC_MAGIC_WALL_FILLING)
2227 cut_mode = CUT_BELOW;
2230 if (lx == 9 && ly == 1)
2231 printf("::: %s [%d] [%d, %d] [%d]\n",
2232 EL_NAME(TILE_GFX_ELEMENT(lx, ly)),
2233 el_act2crm(TILE_GFX_ELEMENT(lx, ly), ACTION_DEFAULT),
2234 element_info[EL_QUICKSAND_EMPTYING].graphic[ACTION_DEFAULT],
2235 element_info[EL_QUICKSAND_EMPTYING].crumbled[ACTION_DEFAULT],
2236 GFX_CRUMBLED(TILE_GFX_ELEMENT(lx, ly)));
2239 if (cut_mode == CUT_ABOVE)
2241 DrawScreenElement(x, y, element);
2243 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
2246 DrawScreenElement(x, y, EL_EMPTY);
2249 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
2250 else if (cut_mode == NO_CUTTING)
2251 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
2254 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
2257 if (cut_mode == CUT_BELOW &&
2258 IN_LEV_FIELD(lx, ly + 1) && IN_SCR_FIELD(x, y + 1))
2259 DrawLevelElement(lx, ly + 1, element);
2263 if (content == EL_ACID)
2265 int dir = MovDir[lx][ly];
2266 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
2267 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
2269 DrawLevelElementThruMask(newlx, newly, EL_ACID);
2272 else if (IS_BLOCKED(lx, ly))
2277 boolean cut_mode = NO_CUTTING;
2278 int element_old, content_old;
2280 Blocked2Moving(lx, ly, &oldx, &oldy);
2283 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
2284 MovDir[oldx][oldy] == MV_RIGHT);
2286 element_old = Feld[oldx][oldy];
2287 content_old = Store[oldx][oldy];
2289 if (element_old == EL_QUICKSAND_EMPTYING ||
2290 element_old == EL_QUICKSAND_FAST_EMPTYING ||
2291 element_old == EL_MAGIC_WALL_EMPTYING ||
2292 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2293 element_old == EL_DC_MAGIC_WALL_EMPTYING ||
2294 element_old == EL_AMOEBA_DROPPING)
2295 cut_mode = CUT_ABOVE;
2297 DrawScreenElement(x, y, EL_EMPTY);
2300 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2302 else if (cut_mode == NO_CUTTING)
2303 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2306 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2309 else if (IS_DRAWABLE(element))
2310 DrawScreenElement(x, y, element);
2312 DrawScreenElement(x, y, EL_EMPTY);
2315 void DrawLevelField(int x, int y)
2317 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2318 DrawScreenField(SCREENX(x), SCREENY(y));
2319 else if (IS_MOVING(x, y))
2323 Moving2Blocked(x, y, &newx, &newy);
2324 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2325 DrawScreenField(SCREENX(newx), SCREENY(newy));
2327 else if (IS_BLOCKED(x, y))
2331 Blocked2Moving(x, y, &oldx, &oldy);
2332 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2333 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2337 void DrawMiniElement(int x, int y, int element)
2341 graphic = el2edimg(element);
2342 DrawMiniGraphic(x, y, graphic);
2345 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2347 int x = sx + scroll_x, y = sy + scroll_y;
2349 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2350 DrawMiniElement(sx, sy, EL_EMPTY);
2351 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2352 DrawMiniElement(sx, sy, Feld[x][y]);
2354 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
2357 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
2358 int x, int y, int xsize, int ysize, int font_nr)
2360 int font_width = getFontWidth(font_nr);
2361 int font_height = getFontHeight(font_nr);
2362 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2365 int dst_x = SX + startx + x * font_width;
2366 int dst_y = SY + starty + y * font_height;
2367 int width = graphic_info[graphic].width;
2368 int height = graphic_info[graphic].height;
2369 int inner_width = MAX(width - 2 * font_width, font_width);
2370 int inner_height = MAX(height - 2 * font_height, font_height);
2371 int inner_sx = (width >= 3 * font_width ? font_width : 0);
2372 int inner_sy = (height >= 3 * font_height ? font_height : 0);
2373 boolean draw_masked = graphic_info[graphic].draw_masked;
2375 getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2377 if (src_bitmap == NULL || width < font_width || height < font_height)
2379 ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
2383 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
2384 inner_sx + (x - 1) * font_width % inner_width);
2385 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
2386 inner_sy + (y - 1) * font_height % inner_height);
2390 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
2391 dst_x - src_x, dst_y - src_y);
2392 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
2396 BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
2400 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
2402 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2403 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2404 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2405 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2406 boolean no_delay = (tape.warp_forward);
2407 unsigned long anim_delay = 0;
2408 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2409 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
2410 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2411 int font_width = getFontWidth(font_nr);
2412 int font_height = getFontHeight(font_nr);
2413 int max_xsize = level.envelope[envelope_nr].xsize;
2414 int max_ysize = level.envelope[envelope_nr].ysize;
2415 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2416 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2417 int xend = max_xsize;
2418 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2419 int xstep = (xstart < xend ? 1 : 0);
2420 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2423 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2425 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2426 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2427 int sx = (SXSIZE - xsize * font_width) / 2;
2428 int sy = (SYSIZE - ysize * font_height) / 2;
2431 SetDrawtoField(DRAW_BUFFERED);
2433 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2435 SetDrawtoField(DRAW_BACKBUFFER);
2437 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
2438 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
2441 DrawTextBuffer(SX + sx + font_width, SY + sy + font_height,
2442 level.envelope[envelope_nr].text, font_nr, max_xsize,
2443 xsize - 2, ysize - 2, 0, mask_mode,
2444 level.envelope[envelope_nr].autowrap,
2445 level.envelope[envelope_nr].centered, FALSE);
2447 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
2448 level.envelope[envelope_nr].text, font_nr, max_xsize,
2449 xsize - 2, ysize - 2, mask_mode);
2452 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2455 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2459 void AnimateEnvelopeDoor(char *text, int anim_mode, int action)
2462 int envelope_nr = 0;
2464 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2465 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2466 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2467 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2468 boolean no_delay = (tape.warp_forward);
2469 unsigned long anim_delay = 0;
2470 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2471 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
2473 int max_word_len = maxWordLengthInString(text);
2474 int font_nr = (max_word_len > 7 ? FONT_TEXT_1 : FONT_TEXT_2);
2476 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2478 int font_width = getFontWidth(font_nr);
2479 int font_height = getFontHeight(font_nr);
2483 int max_xsize = DXSIZE / font_width;
2484 int max_ysize = DYSIZE / font_height;
2486 int max_xsize = 7; /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
2487 int max_ysize = 13; /* tools.c: MAX_REQUEST_LINES == 13 */
2491 int max_xsize = level.envelope[envelope_nr].xsize;
2492 int max_ysize = level.envelope[envelope_nr].ysize;
2494 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2495 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2496 int xend = max_xsize;
2497 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2498 int xstep = (xstart < xend ? 1 : 0);
2499 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2504 char *text_copy = getStringCopy(text);
2507 font_nr = FONT_TEXT_2;
2509 if (maxWordLengthInString(text) > 7) /* MAX_REQUEST_LINE_FONT1_LEN == 7 */
2511 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
2512 font_nr = FONT_TEXT_1;
2515 int max_word_len = 0;
2517 char *text_copy = getStringCopy(text);
2519 font_nr = FONT_TEXT_2;
2521 for (text_ptr = text; *text_ptr; text_ptr++)
2523 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2525 if (max_word_len > 7) /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
2527 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
2528 font_nr = FONT_TEXT_1;
2537 for (text_ptr = text_copy; *text_ptr; text_ptr++)
2538 if (*text_ptr == ' ')
2543 dDX = SX + (SXSIZE - DXSIZE) / 2 - DX;
2544 dDY = SY + (SYSIZE - DYSIZE) / 2 - DY;
2546 dDX = SX + SXSIZE / 2 - max_xsize * font_width / 2 - DX;
2547 dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY;
2550 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2552 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2553 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2554 int sx = (SXSIZE - xsize * font_width) / 2;
2555 int sy = (SYSIZE - ysize * font_height) / 2;
2559 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2561 SetDrawtoField(DRAW_BUFFERED);
2563 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2565 SetDrawtoField(DRAW_BACKBUFFER);
2568 for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
2569 DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
2574 DrawTextBuffer(SX + sx + font_width, SY + sy + font_height + 8,
2575 text_copy, font_nr, max_xsize,
2576 xsize - 2, ysize - 2, 2, mask_mode,
2577 FALSE, TRUE, FALSE);
2579 DrawTextBuffer(SX + sx + font_width, SY + sy + font_height,
2580 level.envelope[envelope_nr].text, font_nr, max_xsize,
2581 xsize - 2, ysize - 2, 0, mask_mode,
2582 level.envelope[envelope_nr].autowrap,
2583 level.envelope[envelope_nr].centered, FALSE);
2587 DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
2588 level.envelope[envelope_nr].text, font_nr, max_xsize,
2589 xsize - 2, ysize - 2, mask_mode);
2592 /* copy request gadgets to door backbuffer */
2594 if ((ysize - 2) > 13)
2595 BlitBitmap(bitmap_db_door, drawto,
2596 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
2597 DOOR_GFX_PAGEY1 + 13 * font_height,
2598 (xsize - 2) * font_width,
2599 (ysize - 2 - 13) * font_height,
2600 SX + sx + font_width,
2601 SY + sy + font_height * (1 + 13));
2603 if ((ysize - 2) > 13)
2604 BlitBitmap(bitmap_db_door, drawto,
2605 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
2606 DOOR_GFX_PAGEY1 + 13 * font_height,
2607 (xsize - 2) * font_width,
2608 (ysize - 2 - 13) * font_height,
2609 SX + sx + font_width,
2610 SY + sy + font_height * (1 + 13));
2614 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2615 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
2617 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2627 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2635 void ShowEnvelope(int envelope_nr)
2637 int element = EL_ENVELOPE_1 + envelope_nr;
2638 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2639 int sound_opening = element_info[element].sound[ACTION_OPENING];
2640 int sound_closing = element_info[element].sound[ACTION_CLOSING];
2641 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2642 boolean no_delay = (tape.warp_forward);
2643 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
2644 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
2645 int anim_mode = graphic_info[graphic].anim_mode;
2646 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
2647 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
2649 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
2651 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
2653 if (anim_mode == ANIM_DEFAULT)
2654 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
2656 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
2659 Delay(wait_delay_value);
2661 WaitForEventToContinue();
2663 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
2665 if (anim_mode != ANIM_NONE)
2666 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
2668 if (anim_mode == ANIM_DEFAULT)
2669 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
2671 game.envelope_active = FALSE;
2673 SetDrawtoField(DRAW_BUFFERED);
2675 redraw_mask |= REDRAW_FIELD;
2679 void ShowEnvelopeDoor(char *text, int action)
2682 int last_game_status = game_status; /* save current game status */
2683 // int last_draw_background_mask = gfx.draw_background_mask;
2684 int envelope_nr = 0;
2686 int element = EL_ENVELOPE_1 + envelope_nr;
2687 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2688 int sound_opening = element_info[element].sound[ACTION_OPENING];
2689 int sound_closing = element_info[element].sound[ACTION_CLOSING];
2691 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2692 boolean no_delay = (tape.warp_forward);
2693 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
2694 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
2696 int anim_mode = graphic_info[graphic].anim_mode;
2697 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
2698 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
2701 if (game_status == GAME_MODE_PLAYING)
2703 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
2704 BlitScreenToBitmap_EM(backbuffer);
2705 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
2706 BlitScreenToBitmap_SP(backbuffer);
2709 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2713 SetDrawtoField(DRAW_BACKBUFFER);
2715 // SetDrawBackgroundMask(REDRAW_NONE);
2717 if (action == ACTION_OPENING)
2719 BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2721 if (game_status != GAME_MODE_MAIN)
2725 /* force DOOR font inside door area */
2726 game_status = GAME_MODE_PSEUDO_DOOR;
2729 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
2731 if (action == ACTION_OPENING)
2733 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
2735 if (anim_mode == ANIM_DEFAULT)
2736 AnimateEnvelopeDoor(text, ANIM_DEFAULT, ACTION_OPENING);
2738 AnimateEnvelopeDoor(text, main_anim_mode, ACTION_OPENING);
2742 Delay(wait_delay_value);
2744 WaitForEventToContinue();
2749 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
2751 if (anim_mode != ANIM_NONE)
2752 AnimateEnvelopeDoor(text, main_anim_mode, ACTION_CLOSING);
2754 if (anim_mode == ANIM_DEFAULT)
2755 AnimateEnvelopeDoor(text, ANIM_DEFAULT, ACTION_CLOSING);
2758 game.envelope_active = FALSE;
2761 // game_status = last_game_status; /* restore current game status */
2763 if (action == ACTION_CLOSING)
2765 if (game_status != GAME_MODE_MAIN)
2768 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2771 SetDrawtoField(DRAW_BUFFERED);
2774 // SetDrawBackgroundMask(last_draw_background_mask);
2777 redraw_mask = REDRAW_FIELD;
2778 // redraw_mask |= REDRAW_ALL;
2780 redraw_mask |= REDRAW_FIELD;
2784 if (game_status == GAME_MODE_MAIN)
2789 /* (important: after "BackToFront()", but before "SetDrawtoField()") */
2790 game_status = last_game_status; /* restore current game status */
2792 if (game_status == GAME_MODE_PLAYING &&
2793 level.game_engine_type == GAME_ENGINE_TYPE_RND)
2794 SetDrawtoField(DRAW_BUFFERED);
2800 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
2804 int graphic = el2preimg(element);
2806 getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
2807 BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
2815 SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
2816 SetDrawBackgroundMask(REDRAW_FIELD);
2818 SetDrawBackgroundMask(REDRAW_NONE);
2823 for (x = BX1; x <= BX2; x++)
2824 for (y = BY1; y <= BY2; y++)
2825 DrawScreenField(x, y);
2827 redraw_mask |= REDRAW_FIELD;
2830 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
2834 for (x = 0; x < size_x; x++)
2835 for (y = 0; y < size_y; y++)
2836 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
2838 redraw_mask |= REDRAW_FIELD;
2841 static void DrawPreviewLevelExt(int from_x, int from_y)
2843 boolean show_level_border = (BorderElement != EL_EMPTY);
2844 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
2845 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
2846 int tile_size = preview.tile_size;
2847 int preview_width = preview.xsize * tile_size;
2848 int preview_height = preview.ysize * tile_size;
2849 int real_preview_xsize = MIN(level_xsize, preview.xsize);
2850 int real_preview_ysize = MIN(level_ysize, preview.ysize);
2851 int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
2852 int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
2855 DrawBackground(dst_x, dst_y, preview_width, preview_height);
2857 dst_x += (preview_width - real_preview_xsize * tile_size) / 2;
2858 dst_y += (preview_height - real_preview_ysize * tile_size) / 2;
2860 for (x = 0; x < real_preview_xsize; x++)
2862 for (y = 0; y < real_preview_ysize; y++)
2864 int lx = from_x + x + (show_level_border ? -1 : 0);
2865 int ly = from_y + y + (show_level_border ? -1 : 0);
2866 int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
2867 getBorderElement(lx, ly));
2869 DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size,
2870 element, tile_size);
2874 redraw_mask |= REDRAW_MICROLEVEL;
2877 #define MICROLABEL_EMPTY 0
2878 #define MICROLABEL_LEVEL_NAME 1
2879 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
2880 #define MICROLABEL_LEVEL_AUTHOR 3
2881 #define MICROLABEL_IMPORTED_FROM_HEAD 4
2882 #define MICROLABEL_IMPORTED_FROM 5
2883 #define MICROLABEL_IMPORTED_BY_HEAD 6
2884 #define MICROLABEL_IMPORTED_BY 7
2886 static int getMaxTextLength(struct TextPosInfo *pos, int font_nr)
2888 int max_text_width = SXSIZE;
2889 int font_width = getFontWidth(font_nr);
2891 if (pos->align == ALIGN_CENTER)
2892 max_text_width = (pos->x < SXSIZE / 2 ? pos->x * 2 : (SXSIZE - pos->x) * 2);
2893 else if (pos->align == ALIGN_RIGHT)
2894 max_text_width = pos->x;
2896 max_text_width = SXSIZE - pos->x;
2898 return max_text_width / font_width;
2901 static void DrawPreviewLevelLabelExt(int mode)
2903 struct TextPosInfo *pos = &menu.main.text.level_info_2;
2904 char label_text[MAX_OUTPUT_LINESIZE + 1];
2905 int max_len_label_text;
2907 int font_nr = pos->font;
2910 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
2911 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
2912 mode == MICROLABEL_IMPORTED_BY_HEAD)
2913 font_nr = pos->font_alt;
2915 int font_nr = FONT_TEXT_2;
2918 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
2919 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
2920 mode == MICROLABEL_IMPORTED_BY_HEAD)
2921 font_nr = FONT_TEXT_3;
2925 max_len_label_text = getMaxTextLength(pos, font_nr);
2927 max_len_label_text = SXSIZE / getFontWidth(font_nr);
2931 if (pos->size != -1)
2932 max_len_label_text = pos->size;
2935 for (i = 0; i < max_len_label_text; i++)
2936 label_text[i] = ' ';
2937 label_text[max_len_label_text] = '\0';
2939 if (strlen(label_text) > 0)
2942 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
2944 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
2945 int lypos = MICROLABEL2_YPOS;
2947 DrawText(lxpos, lypos, label_text, font_nr);
2952 (mode == MICROLABEL_LEVEL_NAME ? level.name :
2953 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
2954 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
2955 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
2956 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
2957 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
2958 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
2959 max_len_label_text);
2960 label_text[max_len_label_text] = '\0';
2962 if (strlen(label_text) > 0)
2965 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
2967 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
2968 int lypos = MICROLABEL2_YPOS;
2970 DrawText(lxpos, lypos, label_text, font_nr);
2974 redraw_mask |= REDRAW_MICROLEVEL;
2977 void DrawPreviewLevel(boolean restart)
2979 static unsigned long scroll_delay = 0;
2980 static unsigned long label_delay = 0;
2981 static int from_x, from_y, scroll_direction;
2982 static int label_state, label_counter;
2983 unsigned long scroll_delay_value = preview.step_delay;
2984 boolean show_level_border = (BorderElement != EL_EMPTY);
2985 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
2986 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
2987 int last_game_status = game_status; /* save current game status */
2990 /* force PREVIEW font on preview level */
2991 game_status = GAME_MODE_PSEUDO_PREVIEW;
2999 if (preview.anim_mode == ANIM_CENTERED)
3001 if (level_xsize > preview.xsize)
3002 from_x = (level_xsize - preview.xsize) / 2;
3003 if (level_ysize > preview.ysize)
3004 from_y = (level_ysize - preview.ysize) / 2;
3007 from_x += preview.xoffset;
3008 from_y += preview.yoffset;
3010 scroll_direction = MV_RIGHT;
3014 DrawPreviewLevelExt(from_x, from_y);
3015 DrawPreviewLevelLabelExt(label_state);
3017 /* initialize delay counters */
3018 DelayReached(&scroll_delay, 0);
3019 DelayReached(&label_delay, 0);
3021 if (leveldir_current->name)
3023 struct TextPosInfo *pos = &menu.main.text.level_info_1;
3024 char label_text[MAX_OUTPUT_LINESIZE + 1];
3026 int font_nr = pos->font;
3028 int font_nr = FONT_TEXT_1;
3031 int max_len_label_text = getMaxTextLength(pos, font_nr);
3033 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
3041 if (pos->size != -1)
3042 max_len_label_text = pos->size;
3045 strncpy(label_text, leveldir_current->name, max_len_label_text);
3046 label_text[max_len_label_text] = '\0';
3049 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3051 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3052 lypos = SY + MICROLABEL1_YPOS;
3054 DrawText(lxpos, lypos, label_text, font_nr);
3058 game_status = last_game_status; /* restore current game status */
3063 /* scroll preview level, if needed */
3064 if (preview.anim_mode != ANIM_NONE &&
3065 (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
3066 DelayReached(&scroll_delay, scroll_delay_value))
3068 switch (scroll_direction)
3073 from_x -= preview.step_offset;
3074 from_x = (from_x < 0 ? 0 : from_x);
3077 scroll_direction = MV_UP;
3081 if (from_x < level_xsize - preview.xsize)
3083 from_x += preview.step_offset;
3084 from_x = (from_x > level_xsize - preview.xsize ?
3085 level_xsize - preview.xsize : from_x);
3088 scroll_direction = MV_DOWN;
3094 from_y -= preview.step_offset;
3095 from_y = (from_y < 0 ? 0 : from_y);
3098 scroll_direction = MV_RIGHT;
3102 if (from_y < level_ysize - preview.ysize)
3104 from_y += preview.step_offset;
3105 from_y = (from_y > level_ysize - preview.ysize ?
3106 level_ysize - preview.ysize : from_y);
3109 scroll_direction = MV_LEFT;
3116 DrawPreviewLevelExt(from_x, from_y);
3119 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
3120 /* redraw micro level label, if needed */
3121 if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
3122 !strEqual(level.author, ANONYMOUS_NAME) &&
3123 !strEqual(level.author, leveldir_current->name) &&
3124 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
3126 int max_label_counter = 23;
3128 if (leveldir_current->imported_from != NULL &&
3129 strlen(leveldir_current->imported_from) > 0)
3130 max_label_counter += 14;
3131 if (leveldir_current->imported_by != NULL &&
3132 strlen(leveldir_current->imported_by) > 0)
3133 max_label_counter += 14;
3135 label_counter = (label_counter + 1) % max_label_counter;
3136 label_state = (label_counter >= 0 && label_counter <= 7 ?
3137 MICROLABEL_LEVEL_NAME :
3138 label_counter >= 9 && label_counter <= 12 ?
3139 MICROLABEL_LEVEL_AUTHOR_HEAD :
3140 label_counter >= 14 && label_counter <= 21 ?
3141 MICROLABEL_LEVEL_AUTHOR :
3142 label_counter >= 23 && label_counter <= 26 ?
3143 MICROLABEL_IMPORTED_FROM_HEAD :
3144 label_counter >= 28 && label_counter <= 35 ?
3145 MICROLABEL_IMPORTED_FROM :
3146 label_counter >= 37 && label_counter <= 40 ?
3147 MICROLABEL_IMPORTED_BY_HEAD :
3148 label_counter >= 42 && label_counter <= 49 ?
3149 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
3151 if (leveldir_current->imported_from == NULL &&
3152 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
3153 label_state == MICROLABEL_IMPORTED_FROM))
3154 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
3155 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
3157 DrawPreviewLevelLabelExt(label_state);
3160 game_status = last_game_status; /* restore current game status */
3163 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3164 int graphic, int sync_frame, int mask_mode)
3166 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3168 if (mask_mode == USE_MASKING)
3169 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3171 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
3174 inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3175 int graphic, int sync_frame,
3178 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3180 if (mask_mode == USE_MASKING)
3181 DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3183 DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
3186 inline void DrawGraphicAnimation(int x, int y, int graphic)
3188 int lx = LEVELX(x), ly = LEVELY(y);
3190 if (!IN_SCR_FIELD(x, y))
3194 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
3195 graphic, GfxFrame[lx][ly], NO_MASKING);
3197 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3198 graphic, GfxFrame[lx][ly], NO_MASKING);
3200 MarkTileDirty(x, y);
3203 inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
3205 int lx = LEVELX(x), ly = LEVELY(y);
3207 if (!IN_SCR_FIELD(x, y))
3210 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3211 graphic, GfxFrame[lx][ly], NO_MASKING);
3212 MarkTileDirty(x, y);
3215 void DrawLevelGraphicAnimation(int x, int y, int graphic)
3217 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3220 void DrawLevelElementAnimation(int x, int y, int element)
3222 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3224 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3227 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
3229 int sx = SCREENX(x), sy = SCREENY(y);
3231 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3234 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3237 DrawGraphicAnimation(sx, sy, graphic);
3240 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
3241 DrawLevelFieldCrumbled(x, y);
3243 if (GFX_CRUMBLED(Feld[x][y]))
3244 DrawLevelFieldCrumbled(x, y);
3248 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
3250 int sx = SCREENX(x), sy = SCREENY(y);
3253 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3256 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3258 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3261 DrawGraphicAnimation(sx, sy, graphic);
3263 if (GFX_CRUMBLED(element))
3264 DrawLevelFieldCrumbled(x, y);
3267 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
3269 if (player->use_murphy)
3271 /* this works only because currently only one player can be "murphy" ... */
3272 static int last_horizontal_dir = MV_LEFT;
3273 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
3275 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3276 last_horizontal_dir = move_dir;
3278 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
3280 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
3282 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
3288 return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
3291 static boolean equalGraphics(int graphic1, int graphic2)
3293 struct GraphicInfo *g1 = &graphic_info[graphic1];
3294 struct GraphicInfo *g2 = &graphic_info[graphic2];
3296 return (g1->bitmap == g2->bitmap &&
3297 g1->src_x == g2->src_x &&
3298 g1->src_y == g2->src_y &&
3299 g1->anim_frames == g2->anim_frames &&
3300 g1->anim_delay == g2->anim_delay &&
3301 g1->anim_mode == g2->anim_mode);
3304 void DrawAllPlayers()
3308 for (i = 0; i < MAX_PLAYERS; i++)
3309 if (stored_player[i].active)
3310 DrawPlayer(&stored_player[i]);
3313 void DrawPlayerField(int x, int y)
3315 if (!IS_PLAYER(x, y))
3318 DrawPlayer(PLAYERINFO(x, y));
3321 #define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
3323 void DrawPlayer(struct PlayerInfo *player)
3325 int jx = player->jx;
3326 int jy = player->jy;
3327 int move_dir = player->MovDir;
3328 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
3329 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
3330 int last_jx = (player->is_moving ? jx - dx : jx);
3331 int last_jy = (player->is_moving ? jy - dy : jy);
3332 int next_jx = jx + dx;
3333 int next_jy = jy + dy;
3334 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
3335 boolean player_is_opaque = FALSE;
3336 int sx = SCREENX(jx), sy = SCREENY(jy);
3337 int sxx = 0, syy = 0;
3338 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
3340 int action = ACTION_DEFAULT;
3341 int last_player_graphic = getPlayerGraphic(player, move_dir);
3342 int last_player_frame = player->Frame;
3345 /* GfxElement[][] is set to the element the player is digging or collecting;
3346 remove also for off-screen player if the player is not moving anymore */
3347 if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
3348 GfxElement[jx][jy] = EL_UNDEFINED;
3350 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
3354 if (!IN_LEV_FIELD(jx, jy))
3356 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
3357 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
3358 printf("DrawPlayerField(): This should never happen!\n");
3363 if (element == EL_EXPLOSION)
3366 action = (player->is_pushing ? ACTION_PUSHING :
3367 player->is_digging ? ACTION_DIGGING :
3368 player->is_collecting ? ACTION_COLLECTING :
3369 player->is_moving ? ACTION_MOVING :
3370 player->is_snapping ? ACTION_SNAPPING :
3371 player->is_dropping ? ACTION_DROPPING :
3372 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
3374 if (player->is_waiting)
3375 move_dir = player->dir_waiting;
3377 InitPlayerGfxAnimation(player, action, move_dir);
3379 /* ----------------------------------------------------------------------- */
3380 /* draw things in the field the player is leaving, if needed */
3381 /* ----------------------------------------------------------------------- */
3383 if (player->is_moving)
3385 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
3387 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
3389 if (last_element == EL_DYNAMITE_ACTIVE ||
3390 last_element == EL_EM_DYNAMITE_ACTIVE ||
3391 last_element == EL_SP_DISK_RED_ACTIVE)
3392 DrawDynamite(last_jx, last_jy);
3394 DrawLevelFieldThruMask(last_jx, last_jy);
3396 else if (last_element == EL_DYNAMITE_ACTIVE ||
3397 last_element == EL_EM_DYNAMITE_ACTIVE ||
3398 last_element == EL_SP_DISK_RED_ACTIVE)
3399 DrawDynamite(last_jx, last_jy);
3401 /* !!! this is not enough to prevent flickering of players which are
3402 moving next to each others without a free tile between them -- this
3403 can only be solved by drawing all players layer by layer (first the
3404 background, then the foreground etc.) !!! => TODO */
3405 else if (!IS_PLAYER(last_jx, last_jy))
3406 DrawLevelField(last_jx, last_jy);
3409 DrawLevelField(last_jx, last_jy);
3412 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
3413 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
3416 if (!IN_SCR_FIELD(sx, sy))
3419 /* ----------------------------------------------------------------------- */
3420 /* draw things behind the player, if needed */
3421 /* ----------------------------------------------------------------------- */
3424 DrawLevelElement(jx, jy, Back[jx][jy]);
3425 else if (IS_ACTIVE_BOMB(element))
3426 DrawLevelElement(jx, jy, EL_EMPTY);
3429 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
3431 int old_element = GfxElement[jx][jy];
3432 int old_graphic = el_act_dir2img(old_element, action, move_dir);
3433 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
3435 if (GFX_CRUMBLED(old_element))
3436 DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
3438 DrawGraphic(sx, sy, old_graphic, frame);
3440 if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
3441 player_is_opaque = TRUE;
3445 GfxElement[jx][jy] = EL_UNDEFINED;
3447 /* make sure that pushed elements are drawn with correct frame rate */
3449 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
3451 if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
3452 GfxFrame[jx][jy] = player->StepFrame;
3454 if (player->is_pushing && player->is_moving)
3455 GfxFrame[jx][jy] = player->StepFrame;
3458 DrawLevelField(jx, jy);
3462 #if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
3463 /* ----------------------------------------------------------------------- */
3464 /* draw player himself */
3465 /* ----------------------------------------------------------------------- */
3467 graphic = getPlayerGraphic(player, move_dir);
3469 /* in the case of changed player action or direction, prevent the current
3470 animation frame from being restarted for identical animations */
3471 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
3472 player->Frame = last_player_frame;
3474 frame = getGraphicAnimationFrame(graphic, player->Frame);
3478 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3479 sxx = player->GfxPos;
3481 syy = player->GfxPos;
3484 if (!setup.soft_scrolling && ScreenMovPos)
3487 if (player_is_opaque)
3488 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
3490 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3492 if (SHIELD_ON(player))
3494 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
3495 IMG_SHIELD_NORMAL_ACTIVE);
3496 int frame = getGraphicAnimationFrame(graphic, -1);
3498 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3502 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
3505 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3506 sxx = player->GfxPos;
3508 syy = player->GfxPos;
3512 /* ----------------------------------------------------------------------- */
3513 /* draw things the player is pushing, if needed */
3514 /* ----------------------------------------------------------------------- */
3517 printf("::: %d, %d [%d, %d] [%d]\n",
3518 player->is_pushing, player_is_moving, player->GfxAction,
3519 player->is_moving, player_is_moving);
3523 if (player->is_pushing && player->is_moving)
3525 int px = SCREENX(jx), py = SCREENY(jy);
3526 int pxx = (TILEX - ABS(sxx)) * dx;
3527 int pyy = (TILEY - ABS(syy)) * dy;
3528 int gfx_frame = GfxFrame[jx][jy];
3534 if (!IS_MOVING(jx, jy)) /* push movement already finished */
3536 element = Feld[next_jx][next_jy];
3537 gfx_frame = GfxFrame[next_jx][next_jy];
3540 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
3543 sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
3544 frame = getGraphicAnimationFrame(graphic, sync_frame);
3546 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
3549 /* draw background element under pushed element (like the Sokoban field) */
3551 if (game.use_masked_pushing && IS_MOVING(jx, jy))
3553 /* this allows transparent pushing animation over non-black background */
3556 DrawLevelElement(jx, jy, Back[jx][jy]);
3558 DrawLevelElement(jx, jy, EL_EMPTY);
3560 if (Back[next_jx][next_jy])
3561 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
3563 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
3565 else if (Back[next_jx][next_jy])
3566 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
3568 if (Back[next_jx][next_jy])
3569 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
3573 printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
3574 jx, px, player->GfxPos, player->StepFrame,
3579 GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
3583 /* do not draw (EM style) pushing animation when pushing is finished */
3584 /* (two-tile animations usually do not contain start and end frame) */
3585 if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
3586 DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
3588 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
3590 /* masked drawing is needed for EMC style (double) movement graphics */
3591 /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
3592 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
3597 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
3598 /* ----------------------------------------------------------------------- */
3599 /* draw player himself */
3600 /* ----------------------------------------------------------------------- */
3602 graphic = getPlayerGraphic(player, move_dir);
3604 /* in the case of changed player action or direction, prevent the current
3605 animation frame from being restarted for identical animations */
3606 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
3607 player->Frame = last_player_frame;
3609 frame = getGraphicAnimationFrame(graphic, player->Frame);
3613 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3614 sxx = player->GfxPos;
3616 syy = player->GfxPos;
3619 if (!setup.soft_scrolling && ScreenMovPos)
3622 if (player_is_opaque)
3623 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
3625 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3627 if (SHIELD_ON(player))
3629 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
3630 IMG_SHIELD_NORMAL_ACTIVE);
3631 int frame = getGraphicAnimationFrame(graphic, -1);
3633 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
3637 /* ----------------------------------------------------------------------- */
3638 /* draw things in front of player (active dynamite or dynabombs) */
3639 /* ----------------------------------------------------------------------- */
3641 if (IS_ACTIVE_BOMB(element))
3643 graphic = el2img(element);
3644 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
3646 if (game.emulation == EMU_SUPAPLEX)
3647 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
3649 DrawGraphicThruMask(sx, sy, graphic, frame);
3652 if (player_is_moving && last_element == EL_EXPLOSION)
3654 int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
3655 GfxElement[last_jx][last_jy] : EL_EMPTY);
3656 int graphic = el_act2img(element, ACTION_EXPLODING);
3657 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
3658 int phase = ExplodePhase[last_jx][last_jy] - 1;
3659 int frame = getGraphicAnimationFrame(graphic, phase - delay);
3662 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
3665 /* ----------------------------------------------------------------------- */
3666 /* draw elements the player is just walking/passing through/under */
3667 /* ----------------------------------------------------------------------- */
3669 if (player_is_moving)
3671 /* handle the field the player is leaving ... */
3672 if (IS_ACCESSIBLE_INSIDE(last_element))
3673 DrawLevelField(last_jx, last_jy);
3674 else if (IS_ACCESSIBLE_UNDER(last_element))
3675 DrawLevelFieldThruMask(last_jx, last_jy);
3678 /* do not redraw accessible elements if the player is just pushing them */
3679 if (!player_is_moving || !player->is_pushing)
3681 /* ... and the field the player is entering */
3682 if (IS_ACCESSIBLE_INSIDE(element))
3683 DrawLevelField(jx, jy);
3684 else if (IS_ACCESSIBLE_UNDER(element))
3685 DrawLevelFieldThruMask(jx, jy);
3688 MarkTileDirty(sx, sy);
3691 /* ------------------------------------------------------------------------- */
3693 void WaitForEventToContinue()
3695 boolean still_wait = TRUE;
3697 /* simulate releasing mouse button over last gadget, if still pressed */
3699 HandleGadgets(-1, -1, 0);
3701 button_status = MB_RELEASED;
3717 case EVENT_BUTTONPRESS:
3718 case EVENT_KEYPRESS:
3722 case EVENT_KEYRELEASE:
3723 ClearPlayerAction();
3727 HandleOtherEvents(&event);
3731 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
3738 /* don't eat all CPU time */
3743 #define MAX_REQUEST_LINES 13
3744 #define MAX_REQUEST_LINE_FONT1_LEN 7
3745 #define MAX_REQUEST_LINE_FONT2_LEN 10
3747 boolean Request(char *text, unsigned int req_state)
3749 int mx, my, ty, result = -1;
3750 unsigned int old_door_state;
3751 int last_game_status = game_status; /* save current game status */
3752 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
3753 int font_nr = FONT_TEXT_2;
3755 int max_word_len = 0;
3761 global.use_envelope_request = 0;
3765 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
3767 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
3768 font_nr = FONT_TEXT_1;
3771 for (text_ptr = text; *text_ptr; text_ptr++)
3773 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
3775 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
3777 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
3779 font_nr = FONT_TEXT_1;
3781 font_nr = FONT_LEVEL_NUMBER;
3789 if (game_status == GAME_MODE_PLAYING)
3791 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
3792 BlitScreenToBitmap_EM(backbuffer);
3793 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3794 BlitScreenToBitmap_SP(backbuffer);
3797 /* disable deactivated drawing when quick-loading level tape recording */
3798 if (tape.playing && tape.deactivate_display)
3799 TapeDeactivateDisplayOff(TRUE);
3801 SetMouseCursor(CURSOR_DEFAULT);
3803 #if defined(NETWORK_AVALIABLE)
3804 /* pause network game while waiting for request to answer */
3805 if (options.network &&
3806 game_status == GAME_MODE_PLAYING &&
3807 req_state & REQUEST_WAIT_FOR_INPUT)
3808 SendToServer_PausePlaying();
3811 old_door_state = GetDoorState();
3813 /* simulate releasing mouse button over last gadget, if still pressed */
3815 HandleGadgets(-1, -1, 0);
3819 /* draw released gadget before proceeding */
3823 if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request)
3825 if (old_door_state & DOOR_OPEN_1)
3829 if (!global.use_envelope_request)
3830 CloseDoor(DOOR_CLOSE_1);
3832 CloseDoor(DOOR_CLOSE_1);
3835 /* save old door content */
3836 BlitBitmap(bitmap_db_door, bitmap_db_door,
3837 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
3838 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
3842 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
3845 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
3847 /* clear door drawing field */
3848 DrawBackground(DX, DY, DXSIZE, DYSIZE);
3850 /* force DOOR font inside door area */
3851 game_status = GAME_MODE_PSEUDO_DOOR;
3853 /* write text for request */
3854 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
3856 char text_line[max_request_line_len + 1];
3862 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
3864 tc = *(text_ptr + tx);
3865 if (!tc || tc == ' ')
3876 strncpy(text_line, text_ptr, tl);
3879 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
3880 DY + 8 + ty * (getFontHeight(font_nr) + 2),
3881 text_line, font_nr);
3883 text_ptr += tl + (tc == ' ' ? 1 : 0);
3886 game_status = last_game_status; /* restore current game status */
3889 if (global.use_envelope_request)
3893 CreateToolButtons();
3897 if (req_state & REQ_ASK)
3899 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
3900 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
3902 else if (req_state & REQ_CONFIRM)
3904 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
3906 else if (req_state & REQ_PLAYER)
3908 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
3909 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
3910 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
3911 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
3914 /* copy request gadgets to door backbuffer */
3915 BlitBitmap(drawto, bitmap_db_door,
3916 DX, DY, DXSIZE, DYSIZE,
3917 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3920 if (global.use_envelope_request)
3922 ShowEnvelopeDoor(text, ACTION_OPENING);
3924 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3926 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
3927 i == TOOL_CTRL_ID_NO)) ||
3928 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
3929 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
3930 i == TOOL_CTRL_ID_PLAYER_2 &&
3931 i == TOOL_CTRL_ID_PLAYER_3 &&
3932 i == TOOL_CTRL_ID_PLAYER_4)))
3934 int x = tool_gadget[i]->x + dDX;
3935 int y = tool_gadget[i]->y + dDY;
3937 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
3944 if (!global.use_envelope_request)
3945 OpenDoor(DOOR_OPEN_1);
3947 OpenDoor(DOOR_OPEN_1);
3950 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
3952 if (game_status == GAME_MODE_PLAYING)
3954 SetPanelBackground();
3955 SetDrawBackgroundMask(REDRAW_DOOR_1);
3959 SetDrawBackgroundMask(REDRAW_FIELD);
3966 if (game_status != GAME_MODE_MAIN && !global.use_envelope_request)
3969 if (game_status != GAME_MODE_MAIN)
3973 button_status = MB_RELEASED;
3975 request_gadget_id = -1;
3977 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
3989 case EVENT_BUTTONPRESS:
3990 case EVENT_BUTTONRELEASE:
3991 case EVENT_MOTIONNOTIFY:
3993 if (event.type == EVENT_MOTIONNOTIFY)
3995 if (!PointerInWindow(window))
3996 continue; /* window and pointer are on different screens */
4001 motion_status = TRUE;
4002 mx = ((MotionEvent *) &event)->x;
4003 my = ((MotionEvent *) &event)->y;
4007 motion_status = FALSE;
4008 mx = ((ButtonEvent *) &event)->x;
4009 my = ((ButtonEvent *) &event)->y;
4010 if (event.type == EVENT_BUTTONPRESS)
4011 button_status = ((ButtonEvent *) &event)->button;
4013 button_status = MB_RELEASED;
4016 /* this sets 'request_gadget_id' */
4017 HandleGadgets(mx, my, button_status);
4019 switch (request_gadget_id)
4021 case TOOL_CTRL_ID_YES:
4024 case TOOL_CTRL_ID_NO:
4027 case TOOL_CTRL_ID_CONFIRM:
4028 result = TRUE | FALSE;
4031 case TOOL_CTRL_ID_PLAYER_1:
4034 case TOOL_CTRL_ID_PLAYER_2:
4037 case TOOL_CTRL_ID_PLAYER_3:
4040 case TOOL_CTRL_ID_PLAYER_4:
4051 case EVENT_KEYPRESS:
4052 switch (GetEventKey((KeyEvent *)&event, TRUE))
4055 if (req_state & REQ_CONFIRM)
4071 if (req_state & REQ_PLAYER)
4075 case EVENT_KEYRELEASE:
4076 ClearPlayerAction();
4080 HandleOtherEvents(&event);
4084 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4086 int joy = AnyJoystick();
4088 if (joy & JOY_BUTTON_1)
4090 else if (joy & JOY_BUTTON_2)
4096 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
4098 HandleGameActions();
4104 if (!PendingEvent()) /* delay only if no pending events */
4109 game_status = GAME_MODE_PSEUDO_DOOR;
4115 game_status = last_game_status; /* restore current game status */
4123 if (!PendingEvent()) /* delay only if no pending events */
4126 /* don't eat all CPU time */
4133 if (game_status != GAME_MODE_MAIN)
4139 if (global.use_envelope_request)
4140 ShowEnvelopeDoor(text, ACTION_CLOSING);
4144 if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request)
4146 if (!(req_state & REQ_STAY_OPEN))
4149 CloseDoor(DOOR_CLOSE_1);
4151 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
4152 (req_state & REQ_REOPEN))
4153 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
4158 if (game_status == GAME_MODE_PLAYING)
4160 SetPanelBackground();
4161 SetDrawBackgroundMask(REDRAW_DOOR_1);
4165 SetDrawBackgroundMask(REDRAW_FIELD);
4168 #if defined(NETWORK_AVALIABLE)
4169 /* continue network game after request */
4170 if (options.network &&
4171 game_status == GAME_MODE_PLAYING &&
4172 req_state & REQUEST_WAIT_FOR_INPUT)
4173 SendToServer_ContinuePlaying();
4176 /* restore deactivated drawing when quick-loading level tape recording */
4177 if (tape.playing && tape.deactivate_display)
4178 TapeDeactivateDisplayOn();
4183 unsigned int OpenDoor(unsigned int door_state)
4185 if (door_state & DOOR_COPY_BACK)
4187 if (door_state & DOOR_OPEN_1)
4188 BlitBitmap(bitmap_db_door, bitmap_db_door,
4189 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4190 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4192 if (door_state & DOOR_OPEN_2)
4193 BlitBitmap(bitmap_db_door, bitmap_db_door,
4194 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
4195 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
4197 door_state &= ~DOOR_COPY_BACK;
4200 return MoveDoor(door_state);
4203 unsigned int CloseDoor(unsigned int door_state)
4205 unsigned int old_door_state = GetDoorState();
4207 if (!(door_state & DOOR_NO_COPY_BACK))
4209 if (old_door_state & DOOR_OPEN_1)
4210 BlitBitmap(backbuffer, bitmap_db_door,
4211 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4213 if (old_door_state & DOOR_OPEN_2)
4214 BlitBitmap(backbuffer, bitmap_db_door,
4215 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
4217 door_state &= ~DOOR_NO_COPY_BACK;
4220 return MoveDoor(door_state);
4223 unsigned int GetDoorState()
4225 return MoveDoor(DOOR_GET_STATE);
4228 unsigned int SetDoorState(unsigned int door_state)
4230 return MoveDoor(door_state | DOOR_SET_STATE);
4233 unsigned int MoveDoor(unsigned int door_state)
4235 static int door1 = DOOR_OPEN_1;
4236 static int door2 = DOOR_CLOSE_2;
4237 unsigned long door_delay = 0;
4238 unsigned long door_delay_value;
4241 if (door_1.width < 0 || door_1.width > DXSIZE)
4242 door_1.width = DXSIZE;
4243 if (door_1.height < 0 || door_1.height > DYSIZE)
4244 door_1.height = DYSIZE;
4245 if (door_2.width < 0 || door_2.width > VXSIZE)
4246 door_2.width = VXSIZE;
4247 if (door_2.height < 0 || door_2.height > VYSIZE)
4248 door_2.height = VYSIZE;
4250 if (door_state == DOOR_GET_STATE)
4251 return (door1 | door2);
4253 if (door_state & DOOR_SET_STATE)
4255 if (door_state & DOOR_ACTION_1)
4256 door1 = door_state & DOOR_ACTION_1;
4257 if (door_state & DOOR_ACTION_2)
4258 door2 = door_state & DOOR_ACTION_2;
4260 return (door1 | door2);
4263 if (!(door_state & DOOR_FORCE_REDRAW))
4265 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
4266 door_state &= ~DOOR_OPEN_1;
4267 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
4268 door_state &= ~DOOR_CLOSE_1;
4269 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
4270 door_state &= ~DOOR_OPEN_2;
4271 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
4272 door_state &= ~DOOR_CLOSE_2;
4275 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
4278 if (setup.quick_doors)
4280 stepsize = 20; /* must be chosen to always draw last frame */
4281 door_delay_value = 0;
4284 if (global.autoplay_leveldir)
4286 door_state |= DOOR_NO_DELAY;
4287 door_state &= ~DOOR_CLOSE_ALL;
4291 if (game_status == GAME_MODE_EDITOR)
4292 door_state |= DOOR_NO_DELAY;
4295 if (door_state & DOOR_ACTION)
4297 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
4298 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
4299 boolean door_1_done = (!handle_door_1);
4300 boolean door_2_done = (!handle_door_2);
4301 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
4302 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
4303 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
4304 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
4305 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
4306 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
4307 int door_size = (handle_door_1 ? door_size_1 : door_size_2);
4308 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
4309 int door_skip = max_door_size - door_size;
4310 int end = door_size;
4311 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
4314 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
4316 /* opening door sound has priority over simultaneously closing door */
4317 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
4318 PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
4319 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
4320 PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
4323 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
4326 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
4327 GC gc = bitmap->stored_clip_gc;
4329 if (door_state & DOOR_ACTION_1)
4331 int a = MIN(x * door_1.step_offset, end);
4332 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
4333 int i = p + door_skip;
4335 if (door_1.anim_mode & ANIM_STATIC_PANEL)
4337 BlitBitmap(bitmap_db_door, drawto,
4338 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
4339 DXSIZE, DYSIZE, DX, DY);
4343 BlitBitmap(bitmap_db_door, drawto,
4344 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
4345 DXSIZE, DYSIZE - p / 2, DX, DY);
4347 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
4350 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
4352 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
4353 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
4354 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
4355 int dst2_x = DX, dst2_y = DY;
4356 int width = i, height = DYSIZE;
4358 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4359 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4362 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4363 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4366 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
4368 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
4369 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
4370 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
4371 int dst2_x = DX, dst2_y = DY;
4372 int width = DXSIZE, height = i;
4374 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4375 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4378 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4379 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4382 else if (x <= DXSIZE) /* ANIM_DEFAULT */
4384 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
4386 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
4387 BlitBitmapMasked(bitmap, drawto,
4388 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
4389 DX + DXSIZE - i, DY + j);
4390 BlitBitmapMasked(bitmap, drawto,
4391 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
4392 DX + DXSIZE - i, DY + 140 + j);
4393 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
4394 DY - (DOOR_GFX_PAGEY1 + j));
4395 BlitBitmapMasked(bitmap, drawto,
4396 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
4398 BlitBitmapMasked(bitmap, drawto,
4399 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
4402 BlitBitmapMasked(bitmap, drawto,
4403 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
4405 BlitBitmapMasked(bitmap, drawto,
4406 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
4408 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
4409 BlitBitmapMasked(bitmap, drawto,
4410 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
4411 DX + DXSIZE - i, DY + 77 + j);
4412 BlitBitmapMasked(bitmap, drawto,
4413 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
4414 DX + DXSIZE - i, DY + 203 + j);
4417 redraw_mask |= REDRAW_DOOR_1;
4418 door_1_done = (a == end);
4421 if (door_state & DOOR_ACTION_2)
4423 int a = MIN(x * door_2.step_offset, door_size);
4424 int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
4425 int i = p + door_skip;
4427 if (door_2.anim_mode & ANIM_STATIC_PANEL)
4429 BlitBitmap(bitmap_db_door, drawto,
4430 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
4431 VXSIZE, VYSIZE, VX, VY);
4433 else if (x <= VYSIZE)
4435 BlitBitmap(bitmap_db_door, drawto,
4436 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
4437 VXSIZE, VYSIZE - p / 2, VX, VY);
4439 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
4442 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
4444 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
4445 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
4446 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
4447 int dst2_x = VX, dst2_y = VY;
4448 int width = i, height = VYSIZE;
4450 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4451 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4454 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4455 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4458 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
4460 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
4461 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
4462 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
4463 int dst2_x = VX, dst2_y = VY;
4464 int width = VXSIZE, height = i;
4466 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
4467 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
4470 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
4471 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
4474 else if (x <= VXSIZE) /* ANIM_DEFAULT */
4476 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
4478 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
4479 BlitBitmapMasked(bitmap, drawto,
4480 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
4481 VX + VXSIZE - i, VY + j);
4482 SetClipOrigin(bitmap, gc,
4483 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
4484 BlitBitmapMasked(bitmap, drawto,
4485 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
4488 BlitBitmapMasked(bitmap, drawto,
4489 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
4490 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
4491 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
4492 BlitBitmapMasked(bitmap, drawto,
4493 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
4495 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
4498 redraw_mask |= REDRAW_DOOR_2;
4499 door_2_done = (a == VXSIZE);
4502 if (!(door_state & DOOR_NO_DELAY))
4506 if (game_status == GAME_MODE_MAIN)
4509 WaitUntilDelayReached(&door_delay, door_delay_value);
4514 if (door_state & DOOR_ACTION_1)
4515 door1 = door_state & DOOR_ACTION_1;
4516 if (door_state & DOOR_ACTION_2)
4517 door2 = door_state & DOOR_ACTION_2;
4519 return (door1 | door2);
4522 void DrawSpecialEditorDoor()
4524 /* draw bigger toolbox window */
4525 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
4526 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
4528 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
4529 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
4532 redraw_mask |= REDRAW_ALL;
4535 void UndrawSpecialEditorDoor()
4537 /* draw normal tape recorder window */
4538 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
4539 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
4542 redraw_mask |= REDRAW_ALL;
4546 /* ---------- new tool button stuff ---------------------------------------- */
4548 /* graphic position values for tool buttons */
4549 #define TOOL_BUTTON_YES_XPOS 2
4550 #define TOOL_BUTTON_YES_YPOS 250
4551 #define TOOL_BUTTON_YES_GFX_YPOS 0
4552 #define TOOL_BUTTON_YES_XSIZE 46
4553 #define TOOL_BUTTON_YES_YSIZE 28
4554 #define TOOL_BUTTON_NO_XPOS 52
4555 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
4556 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
4557 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
4558 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
4559 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
4560 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
4561 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
4562 #define TOOL_BUTTON_CONFIRM_XSIZE 96
4563 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
4564 #define TOOL_BUTTON_PLAYER_XSIZE 30
4565 #define TOOL_BUTTON_PLAYER_YSIZE 30
4566 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
4567 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
4568 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
4569 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
4570 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4571 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
4572 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4573 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
4574 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4575 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
4576 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
4577 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
4578 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4579 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
4580 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4581 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
4582 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4583 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
4584 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
4585 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
4594 } toolbutton_info[NUM_TOOL_BUTTONS] =
4597 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
4598 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
4599 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
4604 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
4605 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
4606 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
4611 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
4612 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
4613 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
4614 TOOL_CTRL_ID_CONFIRM,
4618 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4619 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
4620 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4621 TOOL_CTRL_ID_PLAYER_1,
4625 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4626 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
4627 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4628 TOOL_CTRL_ID_PLAYER_2,
4632 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4633 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
4634 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4635 TOOL_CTRL_ID_PLAYER_3,
4639 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
4640 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
4641 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
4642 TOOL_CTRL_ID_PLAYER_4,
4647 void CreateToolButtons()
4651 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4653 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
4654 Bitmap *deco_bitmap = None;
4655 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
4656 struct GadgetInfo *gi;
4657 unsigned long event_mask;
4658 int gd_xoffset, gd_yoffset;
4659 int gd_x1, gd_x2, gd_y;
4662 event_mask = GD_EVENT_RELEASED;
4664 gd_xoffset = toolbutton_info[i].xpos;
4665 gd_yoffset = toolbutton_info[i].ypos;
4666 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
4667 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
4668 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
4670 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
4672 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
4674 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
4675 &deco_bitmap, &deco_x, &deco_y);
4676 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
4677 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
4680 gi = CreateGadget(GDI_CUSTOM_ID, id,
4681 GDI_INFO_TEXT, toolbutton_info[i].infotext,
4682 GDI_X, DX + toolbutton_info[i].x,
4683 GDI_Y, DY + toolbutton_info[i].y,
4684 GDI_WIDTH, toolbutton_info[i].width,
4685 GDI_HEIGHT, toolbutton_info[i].height,
4686 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
4687 GDI_STATE, GD_BUTTON_UNPRESSED,
4688 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
4689 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
4690 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
4691 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
4692 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
4693 GDI_DECORATION_SHIFTING, 1, 1,
4694 GDI_DIRECT_DRAW, FALSE,
4695 GDI_EVENT_MASK, event_mask,
4696 GDI_CALLBACK_ACTION, HandleToolButtons,
4700 Error(ERR_EXIT, "cannot create gadget");
4702 tool_gadget[id] = gi;
4706 void FreeToolButtons()
4710 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4711 FreeGadget(tool_gadget[i]);
4714 static void UnmapToolButtons()
4718 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4719 UnmapGadget(tool_gadget[i]);
4722 static void HandleToolButtons(struct GadgetInfo *gi)
4724 request_gadget_id = gi->custom_id;
4727 static struct Mapping_EM_to_RND_object
4730 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
4731 boolean is_backside; /* backside of moving element */
4737 em_object_mapping_list[] =
4740 Xblank, TRUE, FALSE,
4744 Yacid_splash_eB, FALSE, FALSE,
4745 EL_ACID_SPLASH_RIGHT, -1, -1
4748 Yacid_splash_wB, FALSE, FALSE,
4749 EL_ACID_SPLASH_LEFT, -1, -1
4752 #ifdef EM_ENGINE_BAD_ROLL
4754 Xstone_force_e, FALSE, FALSE,
4755 EL_ROCK, -1, MV_BIT_RIGHT
4758 Xstone_force_w, FALSE, FALSE,
4759 EL_ROCK, -1, MV_BIT_LEFT
4762 Xnut_force_e, FALSE, FALSE,
4763 EL_NUT, -1, MV_BIT_RIGHT
4766 Xnut_force_w, FALSE, FALSE,
4767 EL_NUT, -1, MV_BIT_LEFT
4770 Xspring_force_e, FALSE, FALSE,
4771 EL_SPRING, -1, MV_BIT_RIGHT
4774 Xspring_force_w, FALSE, FALSE,
4775 EL_SPRING, -1, MV_BIT_LEFT
4778 Xemerald_force_e, FALSE, FALSE,
4779 EL_EMERALD, -1, MV_BIT_RIGHT
4782 Xemerald_force_w, FALSE, FALSE,
4783 EL_EMERALD, -1, MV_BIT_LEFT
4786 Xdiamond_force_e, FALSE, FALSE,
4787 EL_DIAMOND, -1, MV_BIT_RIGHT
4790 Xdiamond_force_w, FALSE, FALSE,
4791 EL_DIAMOND, -1, MV_BIT_LEFT
4794 Xbomb_force_e, FALSE, FALSE,
4795 EL_BOMB, -1, MV_BIT_RIGHT
4798 Xbomb_force_w, FALSE, FALSE,
4799 EL_BOMB, -1, MV_BIT_LEFT
4801 #endif /* EM_ENGINE_BAD_ROLL */
4804 Xstone, TRUE, FALSE,
4808 Xstone_pause, FALSE, FALSE,
4812 Xstone_fall, FALSE, FALSE,
4816 Ystone_s, FALSE, FALSE,
4817 EL_ROCK, ACTION_FALLING, -1
4820 Ystone_sB, FALSE, TRUE,
4821 EL_ROCK, ACTION_FALLING, -1
4824 Ystone_e, FALSE, FALSE,
4825 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
4828 Ystone_eB, FALSE, TRUE,
4829 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
4832 Ystone_w, FALSE, FALSE,
4833 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
4836 Ystone_wB, FALSE, TRUE,
4837 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
4844 Xnut_pause, FALSE, FALSE,
4848 Xnut_fall, FALSE, FALSE,
4852 Ynut_s, FALSE, FALSE,
4853 EL_NUT, ACTION_FALLING, -1
4856 Ynut_sB, FALSE, TRUE,
4857 EL_NUT, ACTION_FALLING, -1
4860 Ynut_e, FALSE, FALSE,
4861 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
4864 Ynut_eB, FALSE, TRUE,
4865 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
4868 Ynut_w, FALSE, FALSE,
4869 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
4872 Ynut_wB, FALSE, TRUE,
4873 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
4876 Xbug_n, TRUE, FALSE,
4880 Xbug_e, TRUE, FALSE,
4881 EL_BUG_RIGHT, -1, -1
4884 Xbug_s, TRUE, FALSE,
4888 Xbug_w, TRUE, FALSE,
4892 Xbug_gon, FALSE, FALSE,
4896 Xbug_goe, FALSE, FALSE,
4897 EL_BUG_RIGHT, -1, -1
4900 Xbug_gos, FALSE, FALSE,
4904 Xbug_gow, FALSE, FALSE,
4908 Ybug_n, FALSE, FALSE,
4909 EL_BUG, ACTION_MOVING, MV_BIT_UP
4912 Ybug_nB, FALSE, TRUE,
4913 EL_BUG, ACTION_MOVING, MV_BIT_UP
4916 Ybug_e, FALSE, FALSE,
4917 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
4920 Ybug_eB, FALSE, TRUE,
4921 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
4924 Ybug_s, FALSE, FALSE,
4925 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
4928 Ybug_sB, FALSE, TRUE,
4929 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
4932 Ybug_w, FALSE, FALSE,
4933 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
4936 Ybug_wB, FALSE, TRUE,
4937 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
4940 Ybug_w_n, FALSE, FALSE,
4941 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
4944 Ybug_n_e, FALSE, FALSE,
4945 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
4948 Ybug_e_s, FALSE, FALSE,
4949 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
4952 Ybug_s_w, FALSE, FALSE,
4953 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
4956 Ybug_e_n, FALSE, FALSE,
4957 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
4960 Ybug_s_e, FALSE, FALSE,
4961 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
4964 Ybug_w_s, FALSE, FALSE,
4965 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
4968 Ybug_n_w, FALSE, FALSE,
4969 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
4972 Ybug_stone, FALSE, FALSE,
4973 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
4976 Ybug_spring, FALSE, FALSE,
4977 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
4980 Xtank_n, TRUE, FALSE,
4981 EL_SPACESHIP_UP, -1, -1
4984 Xtank_e, TRUE, FALSE,
4985 EL_SPACESHIP_RIGHT, -1, -1
4988 Xtank_s, TRUE, FALSE,
4989 EL_SPACESHIP_DOWN, -1, -1
4992 Xtank_w, TRUE, FALSE,
4993 EL_SPACESHIP_LEFT, -1, -1
4996 Xtank_gon, FALSE, FALSE,
4997 EL_SPACESHIP_UP, -1, -1
5000 Xtank_goe, FALSE, FALSE,
5001 EL_SPACESHIP_RIGHT, -1, -1
5004 Xtank_gos, FALSE, FALSE,
5005 EL_SPACESHIP_DOWN, -1, -1
5008 Xtank_gow, FALSE, FALSE,
5009 EL_SPACESHIP_LEFT, -1, -1
5012 Ytank_n, FALSE, FALSE,
5013 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
5016 Ytank_nB, FALSE, TRUE,
5017 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
5020 Ytank_e, FALSE, FALSE,
5021 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
5024 Ytank_eB, FALSE, TRUE,
5025 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
5028 Ytank_s, FALSE, FALSE,
5029 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
5032 Ytank_sB, FALSE, TRUE,
5033 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
5036 Ytank_w, FALSE, FALSE,
5037 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
5040 Ytank_wB, FALSE, TRUE,
5041 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
5044 Ytank_w_n, FALSE, FALSE,
5045 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
5048 Ytank_n_e, FALSE, FALSE,
5049 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
5052 Ytank_e_s, FALSE, FALSE,
5053 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
5056 Ytank_s_w, FALSE, FALSE,
5057 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
5060 Ytank_e_n, FALSE, FALSE,
5061 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
5064 Ytank_s_e, FALSE, FALSE,
5065 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
5068 Ytank_w_s, FALSE, FALSE,
5069 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
5072 Ytank_n_w, FALSE, FALSE,
5073 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
5076 Ytank_stone, FALSE, FALSE,
5077 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
5080 Ytank_spring, FALSE, FALSE,
5081 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
5084 Xandroid, TRUE, FALSE,
5085 EL_EMC_ANDROID, ACTION_ACTIVE, -1
5088 Xandroid_1_n, FALSE, FALSE,
5089 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
5092 Xandroid_2_n, FALSE, FALSE,
5093 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
5096 Xandroid_1_e, FALSE, FALSE,
5097 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
5100 Xandroid_2_e, FALSE, FALSE,
5101 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
5104 Xandroid_1_w, FALSE, FALSE,
5105 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
5108 Xandroid_2_w, FALSE, FALSE,
5109 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
5112 Xandroid_1_s, FALSE, FALSE,
5113 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
5116 Xandroid_2_s, FALSE, FALSE,
5117 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
5120 Yandroid_n, FALSE, FALSE,
5121 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
5124 Yandroid_nB, FALSE, TRUE,
5125 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
5128 Yandroid_ne, FALSE, FALSE,
5129 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
5132 Yandroid_neB, FALSE, TRUE,
5133 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
5136 Yandroid_e, FALSE, FALSE,
5137 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
5140 Yandroid_eB, FALSE, TRUE,
5141 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
5144 Yandroid_se, FALSE, FALSE,
5145 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
5148 Yandroid_seB, FALSE, TRUE,
5149 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
5152 Yandroid_s, FALSE, FALSE,
5153 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
5156 Yandroid_sB, FALSE, TRUE,
5157 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
5160 Yandroid_sw, FALSE, FALSE,
5161 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
5164 Yandroid_swB, FALSE, TRUE,
5165 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
5168 Yandroid_w, FALSE, FALSE,
5169 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
5172 Yandroid_wB, FALSE, TRUE,
5173 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
5176 Yandroid_nw, FALSE, FALSE,
5177 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
5180 Yandroid_nwB, FALSE, TRUE,
5181 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
5184 Xspring, TRUE, FALSE,
5188 Xspring_pause, FALSE, FALSE,
5192 Xspring_e, FALSE, FALSE,
5196 Xspring_w, FALSE, FALSE,
5200 Xspring_fall, FALSE, FALSE,
5204 Yspring_s, FALSE, FALSE,
5205 EL_SPRING, ACTION_FALLING, -1
5208 Yspring_sB, FALSE, TRUE,
5209 EL_SPRING, ACTION_FALLING, -1
5212 Yspring_e, FALSE, FALSE,
5213 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
5216 Yspring_eB, FALSE, TRUE,
5217 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
5220 Yspring_w, FALSE, FALSE,
5221 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
5224 Yspring_wB, FALSE, TRUE,
5225 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
5228 Yspring_kill_e, FALSE, FALSE,
5229 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
5232 Yspring_kill_eB, FALSE, TRUE,
5233 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
5236 Yspring_kill_w, FALSE, FALSE,
5237 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
5240 Yspring_kill_wB, FALSE, TRUE,
5241 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
5244 Xeater_n, TRUE, FALSE,
5245 EL_YAMYAM_UP, -1, -1
5248 Xeater_e, TRUE, FALSE,
5249 EL_YAMYAM_RIGHT, -1, -1
5252 Xeater_w, TRUE, FALSE,
5253 EL_YAMYAM_LEFT, -1, -1
5256 Xeater_s, TRUE, FALSE,
5257 EL_YAMYAM_DOWN, -1, -1
5260 Yeater_n, FALSE, FALSE,
5261 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
5264 Yeater_nB, FALSE, TRUE,
5265 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
5268 Yeater_e, FALSE, FALSE,
5269 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
5272 Yeater_eB, FALSE, TRUE,
5273 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
5276 Yeater_s, FALSE, FALSE,
5277 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
5280 Yeater_sB, FALSE, TRUE,
5281 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
5284 Yeater_w, FALSE, FALSE,
5285 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
5288 Yeater_wB, FALSE, TRUE,
5289 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
5292 Yeater_stone, FALSE, FALSE,
5293 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
5296 Yeater_spring, FALSE, FALSE,
5297 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
5300 Xalien, TRUE, FALSE,
5304 Xalien_pause, FALSE, FALSE,
5308 Yalien_n, FALSE, FALSE,
5309 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
5312 Yalien_nB, FALSE, TRUE,
5313 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
5316 Yalien_e, FALSE, FALSE,
5317 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
5320 Yalien_eB, FALSE, TRUE,
5321 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
5324 Yalien_s, FALSE, FALSE,
5325 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
5328 Yalien_sB, FALSE, TRUE,
5329 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
5332 Yalien_w, FALSE, FALSE,
5333 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
5336 Yalien_wB, FALSE, TRUE,
5337 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
5340 Yalien_stone, FALSE, FALSE,
5341 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
5344 Yalien_spring, FALSE, FALSE,
5345 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
5348 Xemerald, TRUE, FALSE,
5352 Xemerald_pause, FALSE, FALSE,
5356 Xemerald_fall, FALSE, FALSE,
5360 Xemerald_shine, FALSE, FALSE,
5361 EL_EMERALD, ACTION_TWINKLING, -1
5364 Yemerald_s, FALSE, FALSE,
5365 EL_EMERALD, ACTION_FALLING, -1
5368 Yemerald_sB, FALSE, TRUE,
5369 EL_EMERALD, ACTION_FALLING, -1
5372 Yemerald_e, FALSE, FALSE,
5373 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
5376 Yemerald_eB, FALSE, TRUE,
5377 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
5380 Yemerald_w, FALSE, FALSE,
5381 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
5384 Yemerald_wB, FALSE, TRUE,
5385 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
5388 Yemerald_eat, FALSE, FALSE,
5389 EL_EMERALD, ACTION_COLLECTING, -1
5392 Yemerald_stone, FALSE, FALSE,
5393 EL_NUT, ACTION_BREAKING, -1
5396 Xdiamond, TRUE, FALSE,
5400 Xdiamond_pause, FALSE, FALSE,
5404 Xdiamond_fall, FALSE, FALSE,
5408 Xdiamond_shine, FALSE, FALSE,
5409 EL_DIAMOND, ACTION_TWINKLING, -1
5412 Ydiamond_s, FALSE, FALSE,
5413 EL_DIAMOND, ACTION_FALLING, -1
5416 Ydiamond_sB, FALSE, TRUE,
5417 EL_DIAMOND, ACTION_FALLING, -1
5420 Ydiamond_e, FALSE, FALSE,
5421 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
5424 Ydiamond_eB, FALSE, TRUE,
5425 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
5428 Ydiamond_w, FALSE, FALSE,
5429 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
5432 Ydiamond_wB, FALSE, TRUE,
5433 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
5436 Ydiamond_eat, FALSE, FALSE,
5437 EL_DIAMOND, ACTION_COLLECTING, -1
5440 Ydiamond_stone, FALSE, FALSE,
5441 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
5444 Xdrip_fall, TRUE, FALSE,
5445 EL_AMOEBA_DROP, -1, -1
5448 Xdrip_stretch, FALSE, FALSE,
5449 EL_AMOEBA_DROP, ACTION_FALLING, -1
5452 Xdrip_stretchB, FALSE, TRUE,
5453 EL_AMOEBA_DROP, ACTION_FALLING, -1
5456 Xdrip_eat, FALSE, FALSE,
5457 EL_AMOEBA_DROP, ACTION_GROWING, -1
5460 Ydrip_s1, FALSE, FALSE,
5461 EL_AMOEBA_DROP, ACTION_FALLING, -1
5464 Ydrip_s1B, FALSE, TRUE,
5465 EL_AMOEBA_DROP, ACTION_FALLING, -1
5468 Ydrip_s2, FALSE, FALSE,
5469 EL_AMOEBA_DROP, ACTION_FALLING, -1
5472 Ydrip_s2B, FALSE, TRUE,
5473 EL_AMOEBA_DROP, ACTION_FALLING, -1
5480 Xbomb_pause, FALSE, FALSE,
5484 Xbomb_fall, FALSE, FALSE,
5488 Ybomb_s, FALSE, FALSE,
5489 EL_BOMB, ACTION_FALLING, -1
5492 Ybomb_sB, FALSE, TRUE,
5493 EL_BOMB, ACTION_FALLING, -1
5496 Ybomb_e, FALSE, FALSE,
5497 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
5500 Ybomb_eB, FALSE, TRUE,
5501 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
5504 Ybomb_w, FALSE, FALSE,
5505 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
5508 Ybomb_wB, FALSE, TRUE,
5509 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
5512 Ybomb_eat, FALSE, FALSE,
5513 EL_BOMB, ACTION_ACTIVATING, -1
5516 Xballoon, TRUE, FALSE,
5520 Yballoon_n, FALSE, FALSE,
5521 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
5524 Yballoon_nB, FALSE, TRUE,
5525 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
5528 Yballoon_e, FALSE, FALSE,
5529 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
5532 Yballoon_eB, FALSE, TRUE,
5533 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
5536 Yballoon_s, FALSE, FALSE,
5537 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
5540 Yballoon_sB, FALSE, TRUE,
5541 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
5544 Yballoon_w, FALSE, FALSE,
5545 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
5548 Yballoon_wB, FALSE, TRUE,
5549 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
5552 Xgrass, TRUE, FALSE,
5553 EL_EMC_GRASS, -1, -1
5556 Ygrass_nB, FALSE, FALSE,
5557 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
5560 Ygrass_eB, FALSE, FALSE,
5561 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
5564 Ygrass_sB, FALSE, FALSE,
5565 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
5568 Ygrass_wB, FALSE, FALSE,
5569 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
5576 Ydirt_nB, FALSE, FALSE,
5577 EL_SAND, ACTION_DIGGING, MV_BIT_UP
5580 Ydirt_eB, FALSE, FALSE,
5581 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
5584 Ydirt_sB, FALSE, FALSE,
5585 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
5588 Ydirt_wB, FALSE, FALSE,
5589 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
5592 Xacid_ne, TRUE, FALSE,
5593 EL_ACID_POOL_TOPRIGHT, -1, -1
5596 Xacid_se, TRUE, FALSE,
5597 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
5600 Xacid_s, TRUE, FALSE,
5601 EL_ACID_POOL_BOTTOM, -1, -1
5604 Xacid_sw, TRUE, FALSE,
5605 EL_ACID_POOL_BOTTOMLEFT, -1, -1
5608 Xacid_nw, TRUE, FALSE,
5609 EL_ACID_POOL_TOPLEFT, -1, -1
5612 Xacid_1, TRUE, FALSE,
5616 Xacid_2, FALSE, FALSE,
5620 Xacid_3, FALSE, FALSE,
5624 Xacid_4, FALSE, FALSE,
5628 Xacid_5, FALSE, FALSE,
5632 Xacid_6, FALSE, FALSE,
5636 Xacid_7, FALSE, FALSE,
5640 Xacid_8, FALSE, FALSE,
5644 Xball_1, TRUE, FALSE,
5645 EL_EMC_MAGIC_BALL, -1, -1
5648 Xball_1B, FALSE, FALSE,
5649 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
5652 Xball_2, FALSE, FALSE,
5653 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
5656 Xball_2B, FALSE, FALSE,
5657 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
5660 Yball_eat, FALSE, FALSE,
5661 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
5664 Ykey_1_eat, FALSE, FALSE,
5665 EL_EM_KEY_1, ACTION_COLLECTING, -1
5668 Ykey_2_eat, FALSE, FALSE,
5669 EL_EM_KEY_2, ACTION_COLLECTING, -1
5672 Ykey_3_eat, FALSE, FALSE,
5673 EL_EM_KEY_3, ACTION_COLLECTING, -1
5676 Ykey_4_eat, FALSE, FALSE,
5677 EL_EM_KEY_4, ACTION_COLLECTING, -1
5680 Ykey_5_eat, FALSE, FALSE,
5681 EL_EMC_KEY_5, ACTION_COLLECTING, -1
5684 Ykey_6_eat, FALSE, FALSE,
5685 EL_EMC_KEY_6, ACTION_COLLECTING, -1
5688 Ykey_7_eat, FALSE, FALSE,
5689 EL_EMC_KEY_7, ACTION_COLLECTING, -1
5692 Ykey_8_eat, FALSE, FALSE,
5693 EL_EMC_KEY_8, ACTION_COLLECTING, -1
5696 Ylenses_eat, FALSE, FALSE,
5697 EL_EMC_LENSES, ACTION_COLLECTING, -1
5700 Ymagnify_eat, FALSE, FALSE,
5701 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
5704 Ygrass_eat, FALSE, FALSE,
5705 EL_EMC_GRASS, ACTION_SNAPPING, -1
5708 Ydirt_eat, FALSE, FALSE,
5709 EL_SAND, ACTION_SNAPPING, -1
5712 Xgrow_ns, TRUE, FALSE,
5713 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
5716 Ygrow_ns_eat, FALSE, FALSE,
5717 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
5720 Xgrow_ew, TRUE, FALSE,
5721 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
5724 Ygrow_ew_eat, FALSE, FALSE,
5725 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
5728 Xwonderwall, TRUE, FALSE,
5729 EL_MAGIC_WALL, -1, -1
5732 XwonderwallB, FALSE, FALSE,
5733 EL_MAGIC_WALL, ACTION_ACTIVE, -1
5736 Xamoeba_1, TRUE, FALSE,
5737 EL_AMOEBA_DRY, ACTION_OTHER, -1
5740 Xamoeba_2, FALSE, FALSE,
5741 EL_AMOEBA_DRY, ACTION_OTHER, -1
5744 Xamoeba_3, FALSE, FALSE,
5745 EL_AMOEBA_DRY, ACTION_OTHER, -1
5748 Xamoeba_4, FALSE, FALSE,
5749 EL_AMOEBA_DRY, ACTION_OTHER, -1
5752 Xamoeba_5, TRUE, FALSE,
5753 EL_AMOEBA_WET, ACTION_OTHER, -1
5756 Xamoeba_6, FALSE, FALSE,
5757 EL_AMOEBA_WET, ACTION_OTHER, -1
5760 Xamoeba_7, FALSE, FALSE,
5761 EL_AMOEBA_WET, ACTION_OTHER, -1
5764 Xamoeba_8, FALSE, FALSE,
5765 EL_AMOEBA_WET, ACTION_OTHER, -1
5768 Xdoor_1, TRUE, FALSE,
5769 EL_EM_GATE_1, -1, -1
5772 Xdoor_2, TRUE, FALSE,
5773 EL_EM_GATE_2, -1, -1
5776 Xdoor_3, TRUE, FALSE,
5777 EL_EM_GATE_3, -1, -1
5780 Xdoor_4, TRUE, FALSE,
5781 EL_EM_GATE_4, -1, -1
5784 Xdoor_5, TRUE, FALSE,
5785 EL_EMC_GATE_5, -1, -1
5788 Xdoor_6, TRUE, FALSE,
5789 EL_EMC_GATE_6, -1, -1
5792 Xdoor_7, TRUE, FALSE,
5793 EL_EMC_GATE_7, -1, -1
5796 Xdoor_8, TRUE, FALSE,
5797 EL_EMC_GATE_8, -1, -1
5800 Xkey_1, TRUE, FALSE,
5804 Xkey_2, TRUE, FALSE,
5808 Xkey_3, TRUE, FALSE,
5812 Xkey_4, TRUE, FALSE,
5816 Xkey_5, TRUE, FALSE,
5817 EL_EMC_KEY_5, -1, -1
5820 Xkey_6, TRUE, FALSE,
5821 EL_EMC_KEY_6, -1, -1
5824 Xkey_7, TRUE, FALSE,
5825 EL_EMC_KEY_7, -1, -1
5828 Xkey_8, TRUE, FALSE,
5829 EL_EMC_KEY_8, -1, -1
5832 Xwind_n, TRUE, FALSE,
5833 EL_BALLOON_SWITCH_UP, -1, -1
5836 Xwind_e, TRUE, FALSE,
5837 EL_BALLOON_SWITCH_RIGHT, -1, -1
5840 Xwind_s, TRUE, FALSE,
5841 EL_BALLOON_SWITCH_DOWN, -1, -1
5844 Xwind_w, TRUE, FALSE,
5845 EL_BALLOON_SWITCH_LEFT, -1, -1
5848 Xwind_nesw, TRUE, FALSE,
5849 EL_BALLOON_SWITCH_ANY, -1, -1
5852 Xwind_stop, TRUE, FALSE,
5853 EL_BALLOON_SWITCH_NONE, -1, -1
5857 EL_EM_EXIT_CLOSED, -1, -1
5860 Xexit_1, TRUE, FALSE,
5861 EL_EM_EXIT_OPEN, -1, -1
5864 Xexit_2, FALSE, FALSE,
5865 EL_EM_EXIT_OPEN, -1, -1
5868 Xexit_3, FALSE, FALSE,
5869 EL_EM_EXIT_OPEN, -1, -1
5872 Xdynamite, TRUE, FALSE,
5873 EL_EM_DYNAMITE, -1, -1
5876 Ydynamite_eat, FALSE, FALSE,
5877 EL_EM_DYNAMITE, ACTION_COLLECTING, -1
5880 Xdynamite_1, TRUE, FALSE,
5881 EL_EM_DYNAMITE_ACTIVE, -1, -1
5884 Xdynamite_2, FALSE, FALSE,
5885 EL_EM_DYNAMITE_ACTIVE, -1, -1
5888 Xdynamite_3, FALSE, FALSE,
5889 EL_EM_DYNAMITE_ACTIVE, -1, -1
5892 Xdynamite_4, FALSE, FALSE,
5893 EL_EM_DYNAMITE_ACTIVE, -1, -1
5896 Xbumper, TRUE, FALSE,
5897 EL_EMC_SPRING_BUMPER, -1, -1
5900 XbumperB, FALSE, FALSE,
5901 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
5904 Xwheel, TRUE, FALSE,
5905 EL_ROBOT_WHEEL, -1, -1
5908 XwheelB, FALSE, FALSE,
5909 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
5912 Xswitch, TRUE, FALSE,
5913 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
5916 XswitchB, FALSE, FALSE,
5917 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
5921 EL_QUICKSAND_EMPTY, -1, -1
5924 Xsand_stone, TRUE, FALSE,
5925 EL_QUICKSAND_FULL, -1, -1
5928 Xsand_stonein_1, FALSE, TRUE,
5929 EL_ROCK, ACTION_FILLING, -1
5932 Xsand_stonein_2, FALSE, TRUE,
5933 EL_ROCK, ACTION_FILLING, -1
5936 Xsand_stonein_3, FALSE, TRUE,
5937 EL_ROCK, ACTION_FILLING, -1
5940 Xsand_stonein_4, FALSE, TRUE,
5941 EL_ROCK, ACTION_FILLING, -1
5945 Xsand_stonesand_1, FALSE, FALSE,
5946 EL_QUICKSAND_EMPTYING, -1, -1
5949 Xsand_stonesand_2, FALSE, FALSE,
5950 EL_QUICKSAND_EMPTYING, -1, -1
5953 Xsand_stonesand_3, FALSE, FALSE,
5954 EL_QUICKSAND_EMPTYING, -1, -1
5957 Xsand_stonesand_4, FALSE, FALSE,
5958 EL_QUICKSAND_EMPTYING, -1, -1
5961 Xsand_stonesand_quickout_1, FALSE, FALSE,
5962 EL_QUICKSAND_EMPTYING, -1, -1
5965 Xsand_stonesand_quickout_2, FALSE, FALSE,
5966 EL_QUICKSAND_EMPTYING, -1, -1
5970 Xsand_stonesand_1, FALSE, FALSE,
5971 EL_QUICKSAND_FULL, -1, -1
5974 Xsand_stonesand_2, FALSE, FALSE,
5975 EL_QUICKSAND_FULL, -1, -1
5978 Xsand_stonesand_3, FALSE, FALSE,
5979 EL_QUICKSAND_FULL, -1, -1
5982 Xsand_stonesand_4, FALSE, FALSE,
5983 EL_QUICKSAND_FULL, -1, -1
5987 Xsand_stoneout_1, FALSE, FALSE,
5988 EL_ROCK, ACTION_EMPTYING, -1
5991 Xsand_stoneout_2, FALSE, FALSE,
5992 EL_ROCK, ACTION_EMPTYING, -1
5996 Xsand_sandstone_1, FALSE, FALSE,
5997 EL_QUICKSAND_FILLING, -1, -1
6000 Xsand_sandstone_2, FALSE, FALSE,
6001 EL_QUICKSAND_FILLING, -1, -1
6004 Xsand_sandstone_3, FALSE, FALSE,
6005 EL_QUICKSAND_FILLING, -1, -1
6008 Xsand_sandstone_4, FALSE, FALSE,
6009 EL_QUICKSAND_FILLING, -1, -1
6013 Xsand_sandstone_1, FALSE, FALSE,
6014 EL_QUICKSAND_FULL, -1, -1
6017 Xsand_sandstone_2, FALSE, FALSE,
6018 EL_QUICKSAND_FULL, -1, -1
6021 Xsand_sandstone_3, FALSE, FALSE,
6022 EL_QUICKSAND_FULL, -1, -1
6025 Xsand_sandstone_4, FALSE, FALSE,
6026 EL_QUICKSAND_FULL, -1, -1
6030 Xplant, TRUE, FALSE,
6031 EL_EMC_PLANT, -1, -1
6034 Yplant, FALSE, FALSE,
6035 EL_EMC_PLANT, -1, -1
6038 Xlenses, TRUE, FALSE,
6039 EL_EMC_LENSES, -1, -1
6042 Xmagnify, TRUE, FALSE,
6043 EL_EMC_MAGNIFIER, -1, -1
6046 Xdripper, TRUE, FALSE,
6047 EL_EMC_DRIPPER, -1, -1
6050 XdripperB, FALSE, FALSE,
6051 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
6054 Xfake_blank, TRUE, FALSE,
6055 EL_INVISIBLE_WALL, -1, -1
6058 Xfake_blankB, FALSE, FALSE,
6059 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
6062 Xfake_grass, TRUE, FALSE,
6063 EL_EMC_FAKE_GRASS, -1, -1
6066 Xfake_grassB, FALSE, FALSE,
6067 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
6070 Xfake_door_1, TRUE, FALSE,
6071 EL_EM_GATE_1_GRAY, -1, -1
6074 Xfake_door_2, TRUE, FALSE,
6075 EL_EM_GATE_2_GRAY, -1, -1
6078 Xfake_door_3, TRUE, FALSE,
6079 EL_EM_GATE_3_GRAY, -1, -1
6082 Xfake_door_4, TRUE, FALSE,
6083 EL_EM_GATE_4_GRAY, -1, -1
6086 Xfake_door_5, TRUE, FALSE,
6087 EL_EMC_GATE_5_GRAY, -1, -1
6090 Xfake_door_6, TRUE, FALSE,
6091 EL_EMC_GATE_6_GRAY, -1, -1
6094 Xfake_door_7, TRUE, FALSE,
6095 EL_EMC_GATE_7_GRAY, -1, -1
6098 Xfake_door_8, TRUE, FALSE,
6099 EL_EMC_GATE_8_GRAY, -1, -1
6102 Xfake_acid_1, TRUE, FALSE,
6103 EL_EMC_FAKE_ACID, -1, -1
6106 Xfake_acid_2, FALSE, FALSE,
6107 EL_EMC_FAKE_ACID, -1, -1
6110 Xfake_acid_3, FALSE, FALSE,
6111 EL_EMC_FAKE_ACID, -1, -1
6114 Xfake_acid_4, FALSE, FALSE,
6115 EL_EMC_FAKE_ACID, -1, -1
6118 Xfake_acid_5, FALSE, FALSE,
6119 EL_EMC_FAKE_ACID, -1, -1
6122 Xfake_acid_6, FALSE, FALSE,
6123 EL_EMC_FAKE_ACID, -1, -1
6126 Xfake_acid_7, FALSE, FALSE,
6127 EL_EMC_FAKE_ACID, -1, -1
6130 Xfake_acid_8, FALSE, FALSE,
6131 EL_EMC_FAKE_ACID, -1, -1
6134 Xsteel_1, TRUE, FALSE,
6135 EL_STEELWALL, -1, -1
6138 Xsteel_2, TRUE, FALSE,
6139 EL_EMC_STEELWALL_2, -1, -1
6142 Xsteel_3, TRUE, FALSE,
6143 EL_EMC_STEELWALL_3, -1, -1
6146 Xsteel_4, TRUE, FALSE,
6147 EL_EMC_STEELWALL_4, -1, -1
6150 Xwall_1, TRUE, FALSE,
6154 Xwall_2, TRUE, FALSE,
6155 EL_EMC_WALL_14, -1, -1
6158 Xwall_3, TRUE, FALSE,
6159 EL_EMC_WALL_15, -1, -1
6162 Xwall_4, TRUE, FALSE,
6163 EL_EMC_WALL_16, -1, -1
6166 Xround_wall_1, TRUE, FALSE,
6167 EL_WALL_SLIPPERY, -1, -1
6170 Xround_wall_2, TRUE, FALSE,
6171 EL_EMC_WALL_SLIPPERY_2, -1, -1
6174 Xround_wall_3, TRUE, FALSE,
6175 EL_EMC_WALL_SLIPPERY_3, -1, -1
6178 Xround_wall_4, TRUE, FALSE,
6179 EL_EMC_WALL_SLIPPERY_4, -1, -1
6182 Xdecor_1, TRUE, FALSE,
6183 EL_EMC_WALL_8, -1, -1
6186 Xdecor_2, TRUE, FALSE,
6187 EL_EMC_WALL_6, -1, -1
6190 Xdecor_3, TRUE, FALSE,
6191 EL_EMC_WALL_4, -1, -1
6194 Xdecor_4, TRUE, FALSE,
6195 EL_EMC_WALL_7, -1, -1
6198 Xdecor_5, TRUE, FALSE,
6199 EL_EMC_WALL_5, -1, -1
6202 Xdecor_6, TRUE, FALSE,
6203 EL_EMC_WALL_9, -1, -1
6206 Xdecor_7, TRUE, FALSE,
6207 EL_EMC_WALL_10, -1, -1
6210 Xdecor_8, TRUE, FALSE,
6211 EL_EMC_WALL_1, -1, -1
6214 Xdecor_9, TRUE, FALSE,
6215 EL_EMC_WALL_2, -1, -1
6218 Xdecor_10, TRUE, FALSE,
6219 EL_EMC_WALL_3, -1, -1
6222 Xdecor_11, TRUE, FALSE,
6223 EL_EMC_WALL_11, -1, -1
6226 Xdecor_12, TRUE, FALSE,
6227 EL_EMC_WALL_12, -1, -1
6230 Xalpha_0, TRUE, FALSE,
6231 EL_CHAR('0'), -1, -1
6234 Xalpha_1, TRUE, FALSE,
6235 EL_CHAR('1'), -1, -1
6238 Xalpha_2, TRUE, FALSE,
6239 EL_CHAR('2'), -1, -1
6242 Xalpha_3, TRUE, FALSE,
6243 EL_CHAR('3'), -1, -1
6246 Xalpha_4, TRUE, FALSE,
6247 EL_CHAR('4'), -1, -1
6250 Xalpha_5, TRUE, FALSE,
6251 EL_CHAR('5'), -1, -1
6254 Xalpha_6, TRUE, FALSE,
6255 EL_CHAR('6'), -1, -1
6258 Xalpha_7, TRUE, FALSE,
6259 EL_CHAR('7'), -1, -1
6262 Xalpha_8, TRUE, FALSE,
6263 EL_CHAR('8'), -1, -1
6266 Xalpha_9, TRUE, FALSE,
6267 EL_CHAR('9'), -1, -1
6270 Xalpha_excla, TRUE, FALSE,
6271 EL_CHAR('!'), -1, -1
6274 Xalpha_quote, TRUE, FALSE,
6275 EL_CHAR('"'), -1, -1
6278 Xalpha_comma, TRUE, FALSE,
6279 EL_CHAR(','), -1, -1
6282 Xalpha_minus, TRUE, FALSE,
6283 EL_CHAR('-'), -1, -1
6286 Xalpha_perio, TRUE, FALSE,
6287 EL_CHAR('.'), -1, -1
6290 Xalpha_colon, TRUE, FALSE,
6291 EL_CHAR(':'), -1, -1
6294 Xalpha_quest, TRUE, FALSE,
6295 EL_CHAR('?'), -1, -1
6298 Xalpha_a, TRUE, FALSE,
6299 EL_CHAR('A'), -1, -1
6302 Xalpha_b, TRUE, FALSE,
6303 EL_CHAR('B'), -1, -1
6306 Xalpha_c, TRUE, FALSE,
6307 EL_CHAR('C'), -1, -1
6310 Xalpha_d, TRUE, FALSE,
6311 EL_CHAR('D'), -1, -1
6314 Xalpha_e, TRUE, FALSE,
6315 EL_CHAR('E'), -1, -1
6318 Xalpha_f, TRUE, FALSE,
6319 EL_CHAR('F'), -1, -1
6322 Xalpha_g, TRUE, FALSE,
6323 EL_CHAR('G'), -1, -1
6326 Xalpha_h, TRUE, FALSE,
6327 EL_CHAR('H'), -1, -1
6330 Xalpha_i, TRUE, FALSE,
6331 EL_CHAR('I'), -1, -1
6334 Xalpha_j, TRUE, FALSE,
6335 EL_CHAR('J'), -1, -1
6338 Xalpha_k, TRUE, FALSE,
6339 EL_CHAR('K'), -1, -1
6342 Xalpha_l, TRUE, FALSE,
6343 EL_CHAR('L'), -1, -1
6346 Xalpha_m, TRUE, FALSE,
6347 EL_CHAR('M'), -1, -1
6350 Xalpha_n, TRUE, FALSE,
6351 EL_CHAR('N'), -1, -1
6354 Xalpha_o, TRUE, FALSE,
6355 EL_CHAR('O'), -1, -1
6358 Xalpha_p, TRUE, FALSE,
6359 EL_CHAR('P'), -1, -1
6362 Xalpha_q, TRUE, FALSE,
6363 EL_CHAR('Q'), -1, -1
6366 Xalpha_r, TRUE, FALSE,
6367 EL_CHAR('R'), -1, -1
6370 Xalpha_s, TRUE, FALSE,
6371 EL_CHAR('S'), -1, -1
6374 Xalpha_t, TRUE, FALSE,
6375 EL_CHAR('T'), -1, -1
6378 Xalpha_u, TRUE, FALSE,
6379 EL_CHAR('U'), -1, -1
6382 Xalpha_v, TRUE, FALSE,
6383 EL_CHAR('V'), -1, -1
6386 Xalpha_w, TRUE, FALSE,
6387 EL_CHAR('W'), -1, -1
6390 Xalpha_x, TRUE, FALSE,
6391 EL_CHAR('X'), -1, -1
6394 Xalpha_y, TRUE, FALSE,
6395 EL_CHAR('Y'), -1, -1
6398 Xalpha_z, TRUE, FALSE,
6399 EL_CHAR('Z'), -1, -1
6402 Xalpha_arrow_e, TRUE, FALSE,
6403 EL_CHAR('>'), -1, -1
6406 Xalpha_arrow_w, TRUE, FALSE,
6407 EL_CHAR('<'), -1, -1
6410 Xalpha_copyr, TRUE, FALSE,
6411 EL_CHAR('©'), -1, -1
6415 Xboom_bug, FALSE, FALSE,
6416 EL_BUG, ACTION_EXPLODING, -1
6419 Xboom_bomb, FALSE, FALSE,
6420 EL_BOMB, ACTION_EXPLODING, -1
6423 Xboom_android, FALSE, FALSE,
6424 EL_EMC_ANDROID, ACTION_OTHER, -1
6427 Xboom_1, FALSE, FALSE,
6428 EL_DEFAULT, ACTION_EXPLODING, -1
6431 Xboom_2, FALSE, FALSE,
6432 EL_DEFAULT, ACTION_EXPLODING, -1
6435 Znormal, FALSE, FALSE,
6439 Zdynamite, FALSE, FALSE,
6443 Zplayer, FALSE, FALSE,
6447 ZBORDER, FALSE, FALSE,
6457 static struct Mapping_EM_to_RND_player
6466 em_player_mapping_list[] =
6470 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
6474 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
6478 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
6482 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
6486 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
6490 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
6494 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
6498 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
6502 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
6506 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
6510 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
6514 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
6518 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
6522 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
6526 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
6530 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
6534 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
6538 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
6542 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
6546 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
6550 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
6554 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
6558 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
6562 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
6566 EL_PLAYER_1, ACTION_DEFAULT, -1,
6570 EL_PLAYER_2, ACTION_DEFAULT, -1,
6574 EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
6578 EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
6582 EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
6586 EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
6590 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
6594 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
6598 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
6602 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
6606 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
6610 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
6614 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
6618 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
6622 EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
6626 EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
6630 EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
6634 EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
6638 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
6642 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
6646 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
6650 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
6654 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
6658 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
6662 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
6666 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
6670 EL_PLAYER_3, ACTION_DEFAULT, -1,
6674 EL_PLAYER_4, ACTION_DEFAULT, -1,
6683 int map_element_RND_to_EM(int element_rnd)
6685 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
6686 static boolean mapping_initialized = FALSE;
6688 if (!mapping_initialized)
6692 /* return "Xalpha_quest" for all undefined elements in mapping array */
6693 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
6694 mapping_RND_to_EM[i] = Xalpha_quest;
6696 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
6697 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
6698 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
6699 em_object_mapping_list[i].element_em;
6701 mapping_initialized = TRUE;
6704 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
6705 return mapping_RND_to_EM[element_rnd];
6707 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
6712 int map_element_EM_to_RND(int element_em)
6714 static unsigned short mapping_EM_to_RND[TILE_MAX];
6715 static boolean mapping_initialized = FALSE;
6717 if (!mapping_initialized)
6721 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
6722 for (i = 0; i < TILE_MAX; i++)
6723 mapping_EM_to_RND[i] = EL_UNKNOWN;
6725 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
6726 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
6727 em_object_mapping_list[i].element_rnd;
6729 mapping_initialized = TRUE;
6732 if (element_em >= 0 && element_em < TILE_MAX)
6733 return mapping_EM_to_RND[element_em];
6735 Error(ERR_WARN, "invalid EM level element %d", element_em);
6740 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
6742 struct LevelInfo_EM *level_em = level->native_em_level;
6743 struct LEVEL *lev = level_em->lev;
6746 for (i = 0; i < TILE_MAX; i++)
6747 lev->android_array[i] = Xblank;
6749 for (i = 0; i < level->num_android_clone_elements; i++)
6751 int element_rnd = level->android_clone_element[i];
6752 int element_em = map_element_RND_to_EM(element_rnd);
6754 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
6755 if (em_object_mapping_list[j].element_rnd == element_rnd)
6756 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
6760 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
6762 struct LevelInfo_EM *level_em = level->native_em_level;
6763 struct LEVEL *lev = level_em->lev;
6766 level->num_android_clone_elements = 0;
6768 for (i = 0; i < TILE_MAX; i++)
6770 int element_em = lev->android_array[i];
6772 boolean element_found = FALSE;
6774 if (element_em == Xblank)
6777 element_rnd = map_element_EM_to_RND(element_em);
6779 for (j = 0; j < level->num_android_clone_elements; j++)
6780 if (level->android_clone_element[j] == element_rnd)
6781 element_found = TRUE;
6785 level->android_clone_element[level->num_android_clone_elements++] =
6788 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
6793 if (level->num_android_clone_elements == 0)
6795 level->num_android_clone_elements = 1;
6796 level->android_clone_element[0] = EL_EMPTY;
6800 int map_direction_RND_to_EM(int direction)
6802 return (direction == MV_UP ? 0 :
6803 direction == MV_RIGHT ? 1 :
6804 direction == MV_DOWN ? 2 :
6805 direction == MV_LEFT ? 3 :
6809 int map_direction_EM_to_RND(int direction)
6811 return (direction == 0 ? MV_UP :
6812 direction == 1 ? MV_RIGHT :
6813 direction == 2 ? MV_DOWN :
6814 direction == 3 ? MV_LEFT :
6818 int map_element_RND_to_SP(int element_rnd)
6820 int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
6822 if (element_rnd >= EL_SP_START &&
6823 element_rnd <= EL_SP_END)
6824 element_sp = element_rnd - EL_SP_START;
6825 else if (element_rnd == EL_EMPTY_SPACE)
6827 else if (element_rnd == EL_INVISIBLE_WALL)
6833 int map_element_SP_to_RND(int element_sp)
6835 int element_rnd = EL_UNKNOWN;
6837 if (element_sp >= 0x00 &&
6839 element_rnd = EL_SP_START + element_sp;
6840 else if (element_sp == 0x28)
6841 element_rnd = EL_INVISIBLE_WALL;
6846 int map_action_SP_to_RND(int action_sp)
6850 case actActive: return ACTION_ACTIVE;
6851 case actImpact: return ACTION_IMPACT;
6852 case actExploding: return ACTION_EXPLODING;
6853 case actDigging: return ACTION_DIGGING;
6854 case actSnapping: return ACTION_SNAPPING;
6855 case actCollecting: return ACTION_COLLECTING;
6856 case actPassing: return ACTION_PASSING;
6857 case actPushing: return ACTION_PUSHING;
6858 case actDropping: return ACTION_DROPPING;
6860 default: return ACTION_DEFAULT;
6864 int get_next_element(int element)
6868 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
6869 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
6870 case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL;
6871 case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY;
6872 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
6873 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
6874 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
6875 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
6876 case EL_DC_MAGIC_WALL_FILLING: return EL_DC_MAGIC_WALL_FULL;
6877 case EL_DC_MAGIC_WALL_EMPTYING: return EL_DC_MAGIC_WALL_ACTIVE;
6878 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
6880 default: return element;
6885 int el_act_dir2img(int element, int action, int direction)
6887 element = GFX_ELEMENT(element);
6889 if (direction == MV_NONE)
6890 return element_info[element].graphic[action];
6892 direction = MV_DIR_TO_BIT(direction);
6894 return element_info[element].direction_graphic[action][direction];
6897 int el_act_dir2img(int element, int action, int direction)
6899 element = GFX_ELEMENT(element);
6900 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
6902 /* direction_graphic[][] == graphic[] for undefined direction graphics */
6903 return element_info[element].direction_graphic[action][direction];
6908 static int el_act_dir2crm(int element, int action, int direction)
6910 element = GFX_ELEMENT(element);
6912 if (direction == MV_NONE)
6913 return element_info[element].crumbled[action];
6915 direction = MV_DIR_TO_BIT(direction);
6917 return element_info[element].direction_crumbled[action][direction];
6920 static int el_act_dir2crm(int element, int action, int direction)
6922 element = GFX_ELEMENT(element);
6923 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
6925 /* direction_graphic[][] == graphic[] for undefined direction graphics */
6926 return element_info[element].direction_crumbled[action][direction];
6930 int el_act2img(int element, int action)
6932 element = GFX_ELEMENT(element);
6934 return element_info[element].graphic[action];
6937 int el_act2crm(int element, int action)
6939 element = GFX_ELEMENT(element);
6941 return element_info[element].crumbled[action];
6944 int el_dir2img(int element, int direction)
6946 element = GFX_ELEMENT(element);
6948 return el_act_dir2img(element, ACTION_DEFAULT, direction);
6951 int el2baseimg(int element)
6953 return element_info[element].graphic[ACTION_DEFAULT];
6956 int el2img(int element)
6958 element = GFX_ELEMENT(element);
6960 return element_info[element].graphic[ACTION_DEFAULT];
6963 int el2edimg(int element)
6965 element = GFX_ELEMENT(element);
6967 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
6970 int el2preimg(int element)
6972 element = GFX_ELEMENT(element);
6974 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
6977 int el2panelimg(int element)
6979 element = GFX_ELEMENT(element);
6981 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PANEL];
6984 int font2baseimg(int font_nr)
6986 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
6989 int getBeltNrFromBeltElement(int element)
6991 return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 :
6992 element < EL_CONVEYOR_BELT_3_LEFT ? 1 :
6993 element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3);
6996 int getBeltNrFromBeltActiveElement(int element)
6998 return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 :
6999 element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 :
7000 element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3);
7003 int getBeltNrFromBeltSwitchElement(int element)
7005 return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 :
7006 element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 :
7007 element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3);
7010 int getBeltDirNrFromBeltElement(int element)
7012 static int belt_base_element[4] =
7014 EL_CONVEYOR_BELT_1_LEFT,
7015 EL_CONVEYOR_BELT_2_LEFT,
7016 EL_CONVEYOR_BELT_3_LEFT,
7017 EL_CONVEYOR_BELT_4_LEFT
7020 int belt_nr = getBeltNrFromBeltElement(element);
7021 int belt_dir_nr = element - belt_base_element[belt_nr];
7023 return (belt_dir_nr % 3);
7026 int getBeltDirNrFromBeltSwitchElement(int element)
7028 static int belt_base_element[4] =
7030 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
7031 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
7032 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
7033 EL_CONVEYOR_BELT_4_SWITCH_LEFT
7036 int belt_nr = getBeltNrFromBeltSwitchElement(element);
7037 int belt_dir_nr = element - belt_base_element[belt_nr];
7039 return (belt_dir_nr % 3);
7042 int getBeltDirFromBeltElement(int element)
7044 static int belt_move_dir[3] =
7051 int belt_dir_nr = getBeltDirNrFromBeltElement(element);
7053 return belt_move_dir[belt_dir_nr];
7056 int getBeltDirFromBeltSwitchElement(int element)
7058 static int belt_move_dir[3] =
7065 int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(element);
7067 return belt_move_dir[belt_dir_nr];
7070 int getBeltElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
7072 static int belt_base_element[4] =
7074 EL_CONVEYOR_BELT_1_LEFT,
7075 EL_CONVEYOR_BELT_2_LEFT,
7076 EL_CONVEYOR_BELT_3_LEFT,
7077 EL_CONVEYOR_BELT_4_LEFT
7080 return belt_base_element[belt_nr] + belt_dir_nr;
7083 int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
7085 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
7087 return getBeltElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
7090 int getBeltSwitchElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
7092 static int belt_base_element[4] =
7094 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
7095 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
7096 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
7097 EL_CONVEYOR_BELT_4_SWITCH_LEFT
7100 return belt_base_element[belt_nr] + belt_dir_nr;
7103 int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
7105 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
7107 return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
7110 int getNumActivePlayers_EM()
7112 int num_players = 0;
7118 for (i = 0; i < MAX_PLAYERS; i++)
7119 if (tape.player_participates[i])
7125 int getGameFrameDelay_EM(int native_em_game_frame_delay)
7127 int game_frame_delay_value;
7129 game_frame_delay_value =
7130 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
7131 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
7134 if (tape.playing && tape.warp_forward && !tape.pausing)
7135 game_frame_delay_value = 0;
7137 return game_frame_delay_value;
7140 unsigned int InitRND(long seed)
7142 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
7143 return InitEngineRandom_EM(seed);
7144 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
7145 return InitEngineRandom_SP(seed);
7147 return InitEngineRandom_RND(seed);
7151 static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
7152 static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
7155 inline static int get_effective_element_EM(int tile, int frame_em)
7157 int element = object_mapping[tile].element_rnd;
7158 int action = object_mapping[tile].action;
7159 boolean is_backside = object_mapping[tile].is_backside;
7160 boolean action_removing = (action == ACTION_DIGGING ||
7161 action == ACTION_SNAPPING ||
7162 action == ACTION_COLLECTING);
7168 case Yacid_splash_eB:
7169 case Yacid_splash_wB:
7170 return (frame_em > 5 ? EL_EMPTY : element);
7173 case Ydiamond_stone:
7174 // if (!game.use_native_emc_graphics_engine)
7182 else /* frame_em == 7 */
7186 case Yacid_splash_eB:
7187 case Yacid_splash_wB:
7190 case Yemerald_stone:
7193 case Ydiamond_stone:
7197 case Xdrip_stretchB:
7216 case Xsand_stonein_1:
7217 case Xsand_stonein_2:
7218 case Xsand_stonein_3:
7219 case Xsand_stonein_4:
7223 return (is_backside || action_removing ? EL_EMPTY : element);
7228 inline static boolean check_linear_animation_EM(int tile)
7232 case Xsand_stonesand_1:
7233 case Xsand_stonesand_quickout_1:
7234 case Xsand_sandstone_1:
7235 case Xsand_stonein_1:
7236 case Xsand_stoneout_1:
7256 case Yacid_splash_eB:
7257 case Yacid_splash_wB:
7258 case Yemerald_stone:
7266 inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
7267 boolean has_crumbled_graphics,
7268 int crumbled, int sync_frame)
7270 /* if element can be crumbled, but certain action graphics are just empty
7271 space (like instantly snapping sand to empty space in 1 frame), do not
7272 treat these empty space graphics as crumbled graphics in EMC engine */
7273 if (crumbled == IMG_EMPTY_SPACE)
7274 has_crumbled_graphics = FALSE;
7276 if (has_crumbled_graphics)
7278 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
7279 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
7280 g_crumbled->anim_delay,
7281 g_crumbled->anim_mode,
7282 g_crumbled->anim_start_frame,
7285 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
7286 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
7288 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
7290 g_em->has_crumbled_graphics = TRUE;
7294 g_em->crumbled_bitmap = NULL;
7295 g_em->crumbled_src_x = 0;
7296 g_em->crumbled_src_y = 0;
7297 g_em->crumbled_border_size = 0;
7299 g_em->has_crumbled_graphics = FALSE;
7303 void ResetGfxAnimation_EM(int x, int y, int tile)
7308 void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
7309 int tile, int frame_em, int x, int y)
7311 int action = object_mapping[tile].action;
7313 int direction = object_mapping[tile].direction;
7314 int effective_element = get_effective_element_EM(tile, frame_em);
7315 int graphic = (direction == MV_NONE ?
7316 el_act2img(effective_element, action) :
7317 el_act_dir2img(effective_element, action, direction));
7318 struct GraphicInfo *g = &graphic_info[graphic];
7321 boolean action_removing = (action == ACTION_DIGGING ||
7322 action == ACTION_SNAPPING ||
7323 action == ACTION_COLLECTING);
7324 boolean action_moving = (action == ACTION_FALLING ||
7325 action == ACTION_MOVING ||
7326 action == ACTION_PUSHING ||
7327 action == ACTION_EATING ||
7328 action == ACTION_FILLING ||
7329 action == ACTION_EMPTYING);
7330 boolean action_falling = (action == ACTION_FALLING ||
7331 action == ACTION_FILLING ||
7332 action == ACTION_EMPTYING);
7334 /* special case: graphic uses "2nd movement tile" and has defined
7335 7 frames for movement animation (or less) => use default graphic
7336 for last (8th) frame which ends the movement animation */
7337 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
7339 action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
7340 graphic = (direction == MV_NONE ?
7341 el_act2img(effective_element, action) :
7342 el_act_dir2img(effective_element, action, direction));
7344 g = &graphic_info[graphic];
7348 if (tile == Xsand_stonesand_1 ||
7349 tile == Xsand_stonesand_2 ||
7350 tile == Xsand_stonesand_3 ||
7351 tile == Xsand_stonesand_4)
7352 printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
7356 if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
7360 // printf("::: resetting... [%d]\n", tile);
7363 if (action_removing || check_linear_animation_EM(tile))
7365 GfxFrame[x][y] = frame_em;
7367 // printf("::: resetting... [%d]\n", tile);
7370 else if (action_moving)
7372 boolean is_backside = object_mapping[tile].is_backside;
7376 int direction = object_mapping[tile].direction;
7377 int move_dir = (action_falling ? MV_DOWN : direction);
7382 /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
7383 if (g->double_movement && frame_em == 0)
7387 // printf("::: resetting... [%d]\n", tile);
7391 if (move_dir == MV_LEFT)
7392 GfxFrame[x - 1][y] = GfxFrame[x][y];
7393 else if (move_dir == MV_RIGHT)
7394 GfxFrame[x + 1][y] = GfxFrame[x][y];
7395 else if (move_dir == MV_UP)
7396 GfxFrame[x][y - 1] = GfxFrame[x][y];
7397 else if (move_dir == MV_DOWN)
7398 GfxFrame[x][y + 1] = GfxFrame[x][y];
7405 /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
7406 if (tile == Xsand_stonesand_quickout_1 ||
7407 tile == Xsand_stonesand_quickout_2)
7412 if (tile == Xsand_stonesand_1 ||
7413 tile == Xsand_stonesand_2 ||
7414 tile == Xsand_stonesand_3 ||
7415 tile == Xsand_stonesand_4)
7416 printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
7420 if (graphic_info[graphic].anim_global_sync)
7421 sync_frame = FrameCounter;
7422 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
7423 sync_frame = GfxFrame[x][y];
7425 sync_frame = 0; /* playfield border (pseudo steel) */
7427 SetRandomAnimationValue(x, y);
7429 int frame = getAnimationFrame(g->anim_frames,
7432 g->anim_start_frame,
7435 g_em->unique_identifier =
7436 (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
7440 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
7441 int tile, int frame_em, int x, int y)
7443 int action = object_mapping[tile].action;
7444 int direction = object_mapping[tile].direction;
7445 boolean is_backside = object_mapping[tile].is_backside;
7446 int effective_element = get_effective_element_EM(tile, frame_em);
7448 int effective_action = action;
7450 int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
7452 int graphic = (direction == MV_NONE ?
7453 el_act2img(effective_element, effective_action) :
7454 el_act_dir2img(effective_element, effective_action,
7456 int crumbled = (direction == MV_NONE ?
7457 el_act2crm(effective_element, effective_action) :
7458 el_act_dir2crm(effective_element, effective_action,
7460 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
7461 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
7462 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
7463 struct GraphicInfo *g = &graphic_info[graphic];
7465 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
7469 /* special case: graphic uses "2nd movement tile" and has defined
7470 7 frames for movement animation (or less) => use default graphic
7471 for last (8th) frame which ends the movement animation */
7472 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
7474 effective_action = ACTION_DEFAULT;
7475 graphic = (direction == MV_NONE ?
7476 el_act2img(effective_element, effective_action) :
7477 el_act_dir2img(effective_element, effective_action,
7479 crumbled = (direction == MV_NONE ?
7480 el_act2crm(effective_element, effective_action) :
7481 el_act_dir2crm(effective_element, effective_action,
7484 g = &graphic_info[graphic];
7494 if (frame_em == 0) /* reset animation frame for certain elements */
7496 if (check_linear_animation_EM(tile))
7501 if (graphic_info[graphic].anim_global_sync)
7502 sync_frame = FrameCounter;
7503 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
7504 sync_frame = GfxFrame[x][y];
7506 sync_frame = 0; /* playfield border (pseudo steel) */
7508 SetRandomAnimationValue(x, y);
7513 int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
7514 i == Xdrip_stretchB ? 7 :
7515 i == Ydrip_s2 ? j + 8 :
7516 i == Ydrip_s2B ? j + 8 :
7525 i == Xfake_acid_1 ? 0 :
7526 i == Xfake_acid_2 ? 10 :
7527 i == Xfake_acid_3 ? 20 :
7528 i == Xfake_acid_4 ? 30 :
7529 i == Xfake_acid_5 ? 40 :
7530 i == Xfake_acid_6 ? 50 :
7531 i == Xfake_acid_7 ? 60 :
7532 i == Xfake_acid_8 ? 70 :
7534 i == Xball_2B ? j + 8 :
7535 i == Yball_eat ? j + 1 :
7536 i == Ykey_1_eat ? j + 1 :
7537 i == Ykey_2_eat ? j + 1 :
7538 i == Ykey_3_eat ? j + 1 :
7539 i == Ykey_4_eat ? j + 1 :
7540 i == Ykey_5_eat ? j + 1 :
7541 i == Ykey_6_eat ? j + 1 :
7542 i == Ykey_7_eat ? j + 1 :
7543 i == Ykey_8_eat ? j + 1 :
7544 i == Ylenses_eat ? j + 1 :
7545 i == Ymagnify_eat ? j + 1 :
7546 i == Ygrass_eat ? j + 1 :
7547 i == Ydirt_eat ? j + 1 :
7548 i == Xamoeba_1 ? 0 :
7549 i == Xamoeba_2 ? 1 :
7550 i == Xamoeba_3 ? 2 :
7551 i == Xamoeba_4 ? 3 :
7552 i == Xamoeba_5 ? 0 :
7553 i == Xamoeba_6 ? 1 :
7554 i == Xamoeba_7 ? 2 :
7555 i == Xamoeba_8 ? 3 :
7556 i == Xexit_2 ? j + 8 :
7557 i == Xexit_3 ? j + 16 :
7558 i == Xdynamite_1 ? 0 :
7559 i == Xdynamite_2 ? 8 :
7560 i == Xdynamite_3 ? 16 :
7561 i == Xdynamite_4 ? 24 :
7562 i == Xsand_stonein_1 ? j + 1 :
7563 i == Xsand_stonein_2 ? j + 9 :
7564 i == Xsand_stonein_3 ? j + 17 :
7565 i == Xsand_stonein_4 ? j + 25 :
7566 i == Xsand_stoneout_1 && j == 0 ? 0 :
7567 i == Xsand_stoneout_1 && j == 1 ? 0 :
7568 i == Xsand_stoneout_1 && j == 2 ? 1 :
7569 i == Xsand_stoneout_1 && j == 3 ? 2 :
7570 i == Xsand_stoneout_1 && j == 4 ? 2 :
7571 i == Xsand_stoneout_1 && j == 5 ? 3 :
7572 i == Xsand_stoneout_1 && j == 6 ? 4 :
7573 i == Xsand_stoneout_1 && j == 7 ? 4 :
7574 i == Xsand_stoneout_2 && j == 0 ? 5 :
7575 i == Xsand_stoneout_2 && j == 1 ? 6 :
7576 i == Xsand_stoneout_2 && j == 2 ? 7 :
7577 i == Xsand_stoneout_2 && j == 3 ? 8 :
7578 i == Xsand_stoneout_2 && j == 4 ? 9 :
7579 i == Xsand_stoneout_2 && j == 5 ? 11 :
7580 i == Xsand_stoneout_2 && j == 6 ? 13 :
7581 i == Xsand_stoneout_2 && j == 7 ? 15 :
7582 i == Xboom_bug && j == 1 ? 2 :
7583 i == Xboom_bug && j == 2 ? 2 :
7584 i == Xboom_bug && j == 3 ? 4 :
7585 i == Xboom_bug && j == 4 ? 4 :
7586 i == Xboom_bug && j == 5 ? 2 :
7587 i == Xboom_bug && j == 6 ? 2 :
7588 i == Xboom_bug && j == 7 ? 0 :
7589 i == Xboom_bomb && j == 1 ? 2 :
7590 i == Xboom_bomb && j == 2 ? 2 :
7591 i == Xboom_bomb && j == 3 ? 4 :
7592 i == Xboom_bomb && j == 4 ? 4 :
7593 i == Xboom_bomb && j == 5 ? 2 :
7594 i == Xboom_bomb && j == 6 ? 2 :
7595 i == Xboom_bomb && j == 7 ? 0 :
7596 i == Xboom_android && j == 7 ? 6 :
7597 i == Xboom_1 && j == 1 ? 2 :
7598 i == Xboom_1 && j == 2 ? 2 :
7599 i == Xboom_1 && j == 3 ? 4 :
7600 i == Xboom_1 && j == 4 ? 4 :
7601 i == Xboom_1 && j == 5 ? 6 :
7602 i == Xboom_1 && j == 6 ? 6 :
7603 i == Xboom_1 && j == 7 ? 8 :
7604 i == Xboom_2 && j == 0 ? 8 :
7605 i == Xboom_2 && j == 1 ? 8 :
7606 i == Xboom_2 && j == 2 ? 10 :
7607 i == Xboom_2 && j == 3 ? 10 :
7608 i == Xboom_2 && j == 4 ? 10 :
7609 i == Xboom_2 && j == 5 ? 12 :
7610 i == Xboom_2 && j == 6 ? 12 :
7611 i == Xboom_2 && j == 7 ? 12 :
7613 special_animation && j == 4 ? 3 :
7614 effective_action != action ? 0 :
7620 int xxx_effective_action;
7621 int xxx_has_action_graphics;
7624 int element = object_mapping[i].element_rnd;
7625 int action = object_mapping[i].action;
7626 int direction = object_mapping[i].direction;
7627 boolean is_backside = object_mapping[i].is_backside;
7629 boolean action_removing = (action == ACTION_DIGGING ||
7630 action == ACTION_SNAPPING ||
7631 action == ACTION_COLLECTING);
7633 boolean action_exploding = ((action == ACTION_EXPLODING ||
7634 action == ACTION_SMASHED_BY_ROCK ||
7635 action == ACTION_SMASHED_BY_SPRING) &&
7636 element != EL_DIAMOND);
7637 boolean action_active = (action == ACTION_ACTIVE);
7638 boolean action_other = (action == ACTION_OTHER);
7642 int effective_element = get_effective_element_EM(i, j);
7644 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
7645 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
7647 i == Xdrip_stretch ? element :
7648 i == Xdrip_stretchB ? element :
7649 i == Ydrip_s1 ? element :
7650 i == Ydrip_s1B ? element :
7651 i == Xball_1B ? element :
7652 i == Xball_2 ? element :
7653 i == Xball_2B ? element :
7654 i == Yball_eat ? element :
7655 i == Ykey_1_eat ? element :
7656 i == Ykey_2_eat ? element :
7657 i == Ykey_3_eat ? element :
7658 i == Ykey_4_eat ? element :
7659 i == Ykey_5_eat ? element :
7660 i == Ykey_6_eat ? element :
7661 i == Ykey_7_eat ? element :
7662 i == Ykey_8_eat ? element :
7663 i == Ylenses_eat ? element :
7664 i == Ymagnify_eat ? element :
7665 i == Ygrass_eat ? element :
7666 i == Ydirt_eat ? element :
7667 i == Yemerald_stone ? EL_EMERALD :
7668 i == Ydiamond_stone ? EL_ROCK :
7669 i == Xsand_stonein_1 ? element :
7670 i == Xsand_stonein_2 ? element :
7671 i == Xsand_stonein_3 ? element :
7672 i == Xsand_stonein_4 ? element :
7673 is_backside ? EL_EMPTY :
7674 action_removing ? EL_EMPTY :
7677 int effective_action = (j < 7 ? action :
7678 i == Xdrip_stretch ? action :
7679 i == Xdrip_stretchB ? action :
7680 i == Ydrip_s1 ? action :
7681 i == Ydrip_s1B ? action :
7682 i == Xball_1B ? action :
7683 i == Xball_2 ? action :
7684 i == Xball_2B ? action :
7685 i == Yball_eat ? action :
7686 i == Ykey_1_eat ? action :
7687 i == Ykey_2_eat ? action :
7688 i == Ykey_3_eat ? action :
7689 i == Ykey_4_eat ? action :
7690 i == Ykey_5_eat ? action :
7691 i == Ykey_6_eat ? action :
7692 i == Ykey_7_eat ? action :
7693 i == Ykey_8_eat ? action :
7694 i == Ylenses_eat ? action :
7695 i == Ymagnify_eat ? action :
7696 i == Ygrass_eat ? action :
7697 i == Ydirt_eat ? action :
7698 i == Xsand_stonein_1 ? action :
7699 i == Xsand_stonein_2 ? action :
7700 i == Xsand_stonein_3 ? action :
7701 i == Xsand_stonein_4 ? action :
7702 i == Xsand_stoneout_1 ? action :
7703 i == Xsand_stoneout_2 ? action :
7704 i == Xboom_android ? ACTION_EXPLODING :
7705 action_exploding ? ACTION_EXPLODING :
7706 action_active ? action :
7707 action_other ? action :
7709 int graphic = (el_act_dir2img(effective_element, effective_action,
7711 int crumbled = (el_act_dir2crm(effective_element, effective_action,
7713 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
7714 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
7715 boolean has_action_graphics = (graphic != base_graphic);
7716 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
7717 struct GraphicInfo *g = &graphic_info[graphic];
7719 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
7721 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
7724 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
7725 boolean special_animation = (action != ACTION_DEFAULT &&
7726 g->anim_frames == 3 &&
7727 g->anim_delay == 2 &&
7728 g->anim_mode & ANIM_LINEAR);
7729 xxx_sync_frame = (i == Xdrip_stretch ? 7 :
7730 i == Xdrip_stretchB ? 7 :
7731 i == Ydrip_s2 ? j + 8 :
7732 i == Ydrip_s2B ? j + 8 :
7741 i == Xfake_acid_1 ? 0 :
7742 i == Xfake_acid_2 ? 10 :
7743 i == Xfake_acid_3 ? 20 :
7744 i == Xfake_acid_4 ? 30 :
7745 i == Xfake_acid_5 ? 40 :
7746 i == Xfake_acid_6 ? 50 :
7747 i == Xfake_acid_7 ? 60 :
7748 i == Xfake_acid_8 ? 70 :
7750 i == Xball_2B ? j + 8 :
7751 i == Yball_eat ? j + 1 :
7752 i == Ykey_1_eat ? j + 1 :
7753 i == Ykey_2_eat ? j + 1 :
7754 i == Ykey_3_eat ? j + 1 :
7755 i == Ykey_4_eat ? j + 1 :
7756 i == Ykey_5_eat ? j + 1 :
7757 i == Ykey_6_eat ? j + 1 :
7758 i == Ykey_7_eat ? j + 1 :
7759 i == Ykey_8_eat ? j + 1 :
7760 i == Ylenses_eat ? j + 1 :
7761 i == Ymagnify_eat ? j + 1 :
7762 i == Ygrass_eat ? j + 1 :
7763 i == Ydirt_eat ? j + 1 :
7764 i == Xamoeba_1 ? 0 :
7765 i == Xamoeba_2 ? 1 :
7766 i == Xamoeba_3 ? 2 :
7767 i == Xamoeba_4 ? 3 :
7768 i == Xamoeba_5 ? 0 :
7769 i == Xamoeba_6 ? 1 :
7770 i == Xamoeba_7 ? 2 :
7771 i == Xamoeba_8 ? 3 :
7772 i == Xexit_2 ? j + 8 :
7773 i == Xexit_3 ? j + 16 :
7774 i == Xdynamite_1 ? 0 :
7775 i == Xdynamite_2 ? 8 :
7776 i == Xdynamite_3 ? 16 :
7777 i == Xdynamite_4 ? 24 :
7778 i == Xsand_stonein_1 ? j + 1 :
7779 i == Xsand_stonein_2 ? j + 9 :
7780 i == Xsand_stonein_3 ? j + 17 :
7781 i == Xsand_stonein_4 ? j + 25 :
7782 i == Xsand_stoneout_1 && j == 0 ? 0 :
7783 i == Xsand_stoneout_1 && j == 1 ? 0 :
7784 i == Xsand_stoneout_1 && j == 2 ? 1 :
7785 i == Xsand_stoneout_1 && j == 3 ? 2 :
7786 i == Xsand_stoneout_1 && j == 4 ? 2 :
7787 i == Xsand_stoneout_1 && j == 5 ? 3 :
7788 i == Xsand_stoneout_1 && j == 6 ? 4 :
7789 i == Xsand_stoneout_1 && j == 7 ? 4 :
7790 i == Xsand_stoneout_2 && j == 0 ? 5 :
7791 i == Xsand_stoneout_2 && j == 1 ? 6 :
7792 i == Xsand_stoneout_2 && j == 2 ? 7 :
7793 i == Xsand_stoneout_2 && j == 3 ? 8 :
7794 i == Xsand_stoneout_2 && j == 4 ? 9 :
7795 i == Xsand_stoneout_2 && j == 5 ? 11 :
7796 i == Xsand_stoneout_2 && j == 6 ? 13 :
7797 i == Xsand_stoneout_2 && j == 7 ? 15 :
7798 i == Xboom_bug && j == 1 ? 2 :
7799 i == Xboom_bug && j == 2 ? 2 :
7800 i == Xboom_bug && j == 3 ? 4 :
7801 i == Xboom_bug && j == 4 ? 4 :
7802 i == Xboom_bug && j == 5 ? 2 :
7803 i == Xboom_bug && j == 6 ? 2 :
7804 i == Xboom_bug && j == 7 ? 0 :
7805 i == Xboom_bomb && j == 1 ? 2 :
7806 i == Xboom_bomb && j == 2 ? 2 :
7807 i == Xboom_bomb && j == 3 ? 4 :
7808 i == Xboom_bomb && j == 4 ? 4 :
7809 i == Xboom_bomb && j == 5 ? 2 :
7810 i == Xboom_bomb && j == 6 ? 2 :
7811 i == Xboom_bomb && j == 7 ? 0 :
7812 i == Xboom_android && j == 7 ? 6 :
7813 i == Xboom_1 && j == 1 ? 2 :
7814 i == Xboom_1 && j == 2 ? 2 :
7815 i == Xboom_1 && j == 3 ? 4 :
7816 i == Xboom_1 && j == 4 ? 4 :
7817 i == Xboom_1 && j == 5 ? 6 :
7818 i == Xboom_1 && j == 6 ? 6 :
7819 i == Xboom_1 && j == 7 ? 8 :
7820 i == Xboom_2 && j == 0 ? 8 :
7821 i == Xboom_2 && j == 1 ? 8 :
7822 i == Xboom_2 && j == 2 ? 10 :
7823 i == Xboom_2 && j == 3 ? 10 :
7824 i == Xboom_2 && j == 4 ? 10 :
7825 i == Xboom_2 && j == 5 ? 12 :
7826 i == Xboom_2 && j == 6 ? 12 :
7827 i == Xboom_2 && j == 7 ? 12 :
7828 special_animation && j == 4 ? 3 :
7829 effective_action != action ? 0 :
7832 xxx_effective_action = effective_action;
7833 xxx_has_action_graphics = has_action_graphics;
7838 int frame = getAnimationFrame(g->anim_frames,
7841 g->anim_start_frame,
7855 int old_src_x = g_em->src_x;
7856 int old_src_y = g_em->src_y;
7860 getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
7861 g->double_movement && is_backside);
7863 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
7864 &g_em->src_x, &g_em->src_y, FALSE);
7869 if (tile == Ydiamond_stone)
7870 printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n",
7875 g->anim_start_frame,
7878 g_em->src_x, g_em->src_y,
7879 g_em->src_offset_x, g_em->src_offset_y,
7880 g_em->dst_offset_x, g_em->dst_offset_y,
7892 if (graphic == IMG_BUG_MOVING_RIGHT)
7893 printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
7894 g->double_movement, is_backside,
7895 old_src_x, old_src_y, g_em->src_x, g_em->src_y);
7903 g_em->src_offset_x = 0;
7904 g_em->src_offset_y = 0;
7905 g_em->dst_offset_x = 0;
7906 g_em->dst_offset_y = 0;
7907 g_em->width = TILEX;
7908 g_em->height = TILEY;
7910 g_em->preserve_background = FALSE;
7913 /* (updating the "crumbled" graphic definitions is probably not really needed,
7914 as animations for crumbled graphics can't be longer than one EMC cycle) */
7916 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
7921 g_em->crumbled_bitmap = NULL;
7922 g_em->crumbled_src_x = 0;
7923 g_em->crumbled_src_y = 0;
7925 g_em->has_crumbled_graphics = FALSE;
7927 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
7929 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
7930 g_crumbled->anim_delay,
7931 g_crumbled->anim_mode,
7932 g_crumbled->anim_start_frame,
7935 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
7936 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
7938 g_em->has_crumbled_graphics = TRUE;
7944 int effective_action = xxx_effective_action;
7945 int has_action_graphics = xxx_has_action_graphics;
7947 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
7948 effective_action == ACTION_MOVING ||
7949 effective_action == ACTION_PUSHING ||
7950 effective_action == ACTION_EATING)) ||
7951 (!has_action_graphics && (effective_action == ACTION_FILLING ||
7952 effective_action == ACTION_EMPTYING)))
7955 (effective_action == ACTION_FALLING ||
7956 effective_action == ACTION_FILLING ||
7957 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
7958 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
7959 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
7960 int num_steps = (i == Ydrip_s1 ? 16 :
7961 i == Ydrip_s1B ? 16 :
7962 i == Ydrip_s2 ? 16 :
7963 i == Ydrip_s2B ? 16 :
7964 i == Xsand_stonein_1 ? 32 :
7965 i == Xsand_stonein_2 ? 32 :
7966 i == Xsand_stonein_3 ? 32 :
7967 i == Xsand_stonein_4 ? 32 :
7968 i == Xsand_stoneout_1 ? 16 :
7969 i == Xsand_stoneout_2 ? 16 : 8);
7970 int cx = ABS(dx) * (TILEX / num_steps);
7971 int cy = ABS(dy) * (TILEY / num_steps);
7972 int step_frame = (i == Ydrip_s2 ? j + 8 :
7973 i == Ydrip_s2B ? j + 8 :
7974 i == Xsand_stonein_2 ? j + 8 :
7975 i == Xsand_stonein_3 ? j + 16 :
7976 i == Xsand_stonein_4 ? j + 24 :
7977 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
7978 int step = (is_backside ? step_frame : num_steps - step_frame);
7980 if (is_backside) /* tile where movement starts */
7982 if (dx < 0 || dy < 0)
7984 g_em->src_offset_x = cx * step;
7985 g_em->src_offset_y = cy * step;
7989 g_em->dst_offset_x = cx * step;
7990 g_em->dst_offset_y = cy * step;
7993 else /* tile where movement ends */
7995 if (dx < 0 || dy < 0)
7997 g_em->dst_offset_x = cx * step;
7998 g_em->dst_offset_y = cy * step;
8002 g_em->src_offset_x = cx * step;
8003 g_em->src_offset_y = cy * step;
8007 g_em->width = TILEX - cx * step;
8008 g_em->height = TILEY - cy * step;
8011 /* create unique graphic identifier to decide if tile must be redrawn */
8012 /* bit 31 - 16 (16 bit): EM style graphic
8013 bit 15 - 12 ( 4 bit): EM style frame
8014 bit 11 - 6 ( 6 bit): graphic width
8015 bit 5 - 0 ( 6 bit): graphic height */
8016 g_em->unique_identifier =
8017 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
8023 void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
8024 int player_nr, int anim, int frame_em)
8026 int element = player_mapping[player_nr][anim].element_rnd;
8027 int action = player_mapping[player_nr][anim].action;
8028 int direction = player_mapping[player_nr][anim].direction;
8029 int graphic = (direction == MV_NONE ?
8030 el_act2img(element, action) :
8031 el_act_dir2img(element, action, direction));
8032 struct GraphicInfo *g = &graphic_info[graphic];
8035 InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
8037 stored_player[player_nr].StepFrame = frame_em;
8039 sync_frame = stored_player[player_nr].Frame;
8041 int frame = getAnimationFrame(g->anim_frames,
8044 g->anim_start_frame,
8047 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
8048 &g_em->src_x, &g_em->src_y, FALSE);
8051 printf("::: %d: %d, %d [%d]\n",
8053 stored_player[player_nr].Frame,
8054 stored_player[player_nr].StepFrame,
8059 void InitGraphicInfo_EM(void)
8062 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
8063 struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
8068 int num_em_gfx_errors = 0;
8070 if (graphic_info_em_object[0][0].bitmap == NULL)
8072 /* EM graphics not yet initialized in em_open_all() */
8077 printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
8080 /* always start with reliable default values */
8081 for (i = 0; i < TILE_MAX; i++)
8083 object_mapping[i].element_rnd = EL_UNKNOWN;
8084 object_mapping[i].is_backside = FALSE;
8085 object_mapping[i].action = ACTION_DEFAULT;
8086 object_mapping[i].direction = MV_NONE;
8089 /* always start with reliable default values */
8090 for (p = 0; p < MAX_PLAYERS; p++)
8092 for (i = 0; i < SPR_MAX; i++)
8094 player_mapping[p][i].element_rnd = EL_UNKNOWN;
8095 player_mapping[p][i].action = ACTION_DEFAULT;
8096 player_mapping[p][i].direction = MV_NONE;
8100 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
8102 int e = em_object_mapping_list[i].element_em;
8104 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
8105 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
8107 if (em_object_mapping_list[i].action != -1)
8108 object_mapping[e].action = em_object_mapping_list[i].action;
8110 if (em_object_mapping_list[i].direction != -1)
8111 object_mapping[e].direction =
8112 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
8115 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
8117 int a = em_player_mapping_list[i].action_em;
8118 int p = em_player_mapping_list[i].player_nr;
8120 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
8122 if (em_player_mapping_list[i].action != -1)
8123 player_mapping[p][a].action = em_player_mapping_list[i].action;
8125 if (em_player_mapping_list[i].direction != -1)
8126 player_mapping[p][a].direction =
8127 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
8130 for (i = 0; i < TILE_MAX; i++)
8132 int element = object_mapping[i].element_rnd;
8133 int action = object_mapping[i].action;
8134 int direction = object_mapping[i].direction;
8135 boolean is_backside = object_mapping[i].is_backside;
8137 boolean action_removing = (action == ACTION_DIGGING ||
8138 action == ACTION_SNAPPING ||
8139 action == ACTION_COLLECTING);
8141 boolean action_exploding = ((action == ACTION_EXPLODING ||
8142 action == ACTION_SMASHED_BY_ROCK ||
8143 action == ACTION_SMASHED_BY_SPRING) &&
8144 element != EL_DIAMOND);
8145 boolean action_active = (action == ACTION_ACTIVE);
8146 boolean action_other = (action == ACTION_OTHER);
8148 for (j = 0; j < 8; j++)
8151 int effective_element = get_effective_element_EM(i, j);
8153 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
8154 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
8156 i == Xdrip_stretch ? element :
8157 i == Xdrip_stretchB ? element :
8158 i == Ydrip_s1 ? element :
8159 i == Ydrip_s1B ? element :
8160 i == Xball_1B ? element :
8161 i == Xball_2 ? element :
8162 i == Xball_2B ? element :
8163 i == Yball_eat ? element :
8164 i == Ykey_1_eat ? element :
8165 i == Ykey_2_eat ? element :
8166 i == Ykey_3_eat ? element :
8167 i == Ykey_4_eat ? element :
8168 i == Ykey_5_eat ? element :
8169 i == Ykey_6_eat ? element :
8170 i == Ykey_7_eat ? element :
8171 i == Ykey_8_eat ? element :
8172 i == Ylenses_eat ? element :
8173 i == Ymagnify_eat ? element :
8174 i == Ygrass_eat ? element :
8175 i == Ydirt_eat ? element :
8176 i == Yemerald_stone ? EL_EMERALD :
8177 i == Ydiamond_stone ? EL_ROCK :
8178 i == Xsand_stonein_1 ? element :
8179 i == Xsand_stonein_2 ? element :
8180 i == Xsand_stonein_3 ? element :
8181 i == Xsand_stonein_4 ? element :
8182 is_backside ? EL_EMPTY :
8183 action_removing ? EL_EMPTY :
8186 int effective_action = (j < 7 ? action :
8187 i == Xdrip_stretch ? action :
8188 i == Xdrip_stretchB ? action :
8189 i == Ydrip_s1 ? action :
8190 i == Ydrip_s1B ? action :
8191 i == Xball_1B ? action :
8192 i == Xball_2 ? action :
8193 i == Xball_2B ? action :
8194 i == Yball_eat ? action :
8195 i == Ykey_1_eat ? action :
8196 i == Ykey_2_eat ? action :
8197 i == Ykey_3_eat ? action :
8198 i == Ykey_4_eat ? action :
8199 i == Ykey_5_eat ? action :
8200 i == Ykey_6_eat ? action :
8201 i == Ykey_7_eat ? action :
8202 i == Ykey_8_eat ? action :
8203 i == Ylenses_eat ? action :
8204 i == Ymagnify_eat ? action :
8205 i == Ygrass_eat ? action :
8206 i == Ydirt_eat ? action :
8207 i == Xsand_stonein_1 ? action :
8208 i == Xsand_stonein_2 ? action :
8209 i == Xsand_stonein_3 ? action :
8210 i == Xsand_stonein_4 ? action :
8211 i == Xsand_stoneout_1 ? action :
8212 i == Xsand_stoneout_2 ? action :
8213 i == Xboom_android ? ACTION_EXPLODING :
8214 action_exploding ? ACTION_EXPLODING :
8215 action_active ? action :
8216 action_other ? action :
8218 int graphic = (el_act_dir2img(effective_element, effective_action,
8220 int crumbled = (el_act_dir2crm(effective_element, effective_action,
8222 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
8223 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
8224 boolean has_action_graphics = (graphic != base_graphic);
8225 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
8226 struct GraphicInfo *g = &graphic_info[graphic];
8228 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
8230 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
8233 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
8234 boolean special_animation = (action != ACTION_DEFAULT &&
8235 g->anim_frames == 3 &&
8236 g->anim_delay == 2 &&
8237 g->anim_mode & ANIM_LINEAR);
8238 int sync_frame = (i == Xdrip_stretch ? 7 :
8239 i == Xdrip_stretchB ? 7 :
8240 i == Ydrip_s2 ? j + 8 :
8241 i == Ydrip_s2B ? j + 8 :
8250 i == Xfake_acid_1 ? 0 :
8251 i == Xfake_acid_2 ? 10 :
8252 i == Xfake_acid_3 ? 20 :
8253 i == Xfake_acid_4 ? 30 :
8254 i == Xfake_acid_5 ? 40 :
8255 i == Xfake_acid_6 ? 50 :
8256 i == Xfake_acid_7 ? 60 :
8257 i == Xfake_acid_8 ? 70 :
8259 i == Xball_2B ? j + 8 :
8260 i == Yball_eat ? j + 1 :
8261 i == Ykey_1_eat ? j + 1 :
8262 i == Ykey_2_eat ? j + 1 :
8263 i == Ykey_3_eat ? j + 1 :
8264 i == Ykey_4_eat ? j + 1 :
8265 i == Ykey_5_eat ? j + 1 :
8266 i == Ykey_6_eat ? j + 1 :
8267 i == Ykey_7_eat ? j + 1 :
8268 i == Ykey_8_eat ? j + 1 :
8269 i == Ylenses_eat ? j + 1 :
8270 i == Ymagnify_eat ? j + 1 :
8271 i == Ygrass_eat ? j + 1 :
8272 i == Ydirt_eat ? j + 1 :
8273 i == Xamoeba_1 ? 0 :
8274 i == Xamoeba_2 ? 1 :
8275 i == Xamoeba_3 ? 2 :
8276 i == Xamoeba_4 ? 3 :
8277 i == Xamoeba_5 ? 0 :
8278 i == Xamoeba_6 ? 1 :
8279 i == Xamoeba_7 ? 2 :
8280 i == Xamoeba_8 ? 3 :
8281 i == Xexit_2 ? j + 8 :
8282 i == Xexit_3 ? j + 16 :
8283 i == Xdynamite_1 ? 0 :
8284 i == Xdynamite_2 ? 8 :
8285 i == Xdynamite_3 ? 16 :
8286 i == Xdynamite_4 ? 24 :
8287 i == Xsand_stonein_1 ? j + 1 :
8288 i == Xsand_stonein_2 ? j + 9 :
8289 i == Xsand_stonein_3 ? j + 17 :
8290 i == Xsand_stonein_4 ? j + 25 :
8291 i == Xsand_stoneout_1 && j == 0 ? 0 :
8292 i == Xsand_stoneout_1 && j == 1 ? 0 :
8293 i == Xsand_stoneout_1 && j == 2 ? 1 :
8294 i == Xsand_stoneout_1 && j == 3 ? 2 :
8295 i == Xsand_stoneout_1 && j == 4 ? 2 :
8296 i == Xsand_stoneout_1 && j == 5 ? 3 :
8297 i == Xsand_stoneout_1 && j == 6 ? 4 :
8298 i == Xsand_stoneout_1 && j == 7 ? 4 :
8299 i == Xsand_stoneout_2 && j == 0 ? 5 :
8300 i == Xsand_stoneout_2 && j == 1 ? 6 :
8301 i == Xsand_stoneout_2 && j == 2 ? 7 :
8302 i == Xsand_stoneout_2 && j == 3 ? 8 :
8303 i == Xsand_stoneout_2 && j == 4 ? 9 :
8304 i == Xsand_stoneout_2 && j == 5 ? 11 :
8305 i == Xsand_stoneout_2 && j == 6 ? 13 :
8306 i == Xsand_stoneout_2 && j == 7 ? 15 :
8307 i == Xboom_bug && j == 1 ? 2 :
8308 i == Xboom_bug && j == 2 ? 2 :
8309 i == Xboom_bug && j == 3 ? 4 :
8310 i == Xboom_bug && j == 4 ? 4 :
8311 i == Xboom_bug && j == 5 ? 2 :
8312 i == Xboom_bug && j == 6 ? 2 :
8313 i == Xboom_bug && j == 7 ? 0 :
8314 i == Xboom_bomb && j == 1 ? 2 :
8315 i == Xboom_bomb && j == 2 ? 2 :
8316 i == Xboom_bomb && j == 3 ? 4 :
8317 i == Xboom_bomb && j == 4 ? 4 :
8318 i == Xboom_bomb && j == 5 ? 2 :
8319 i == Xboom_bomb && j == 6 ? 2 :
8320 i == Xboom_bomb && j == 7 ? 0 :
8321 i == Xboom_android && j == 7 ? 6 :
8322 i == Xboom_1 && j == 1 ? 2 :
8323 i == Xboom_1 && j == 2 ? 2 :
8324 i == Xboom_1 && j == 3 ? 4 :
8325 i == Xboom_1 && j == 4 ? 4 :
8326 i == Xboom_1 && j == 5 ? 6 :
8327 i == Xboom_1 && j == 6 ? 6 :
8328 i == Xboom_1 && j == 7 ? 8 :
8329 i == Xboom_2 && j == 0 ? 8 :
8330 i == Xboom_2 && j == 1 ? 8 :
8331 i == Xboom_2 && j == 2 ? 10 :
8332 i == Xboom_2 && j == 3 ? 10 :
8333 i == Xboom_2 && j == 4 ? 10 :
8334 i == Xboom_2 && j == 5 ? 12 :
8335 i == Xboom_2 && j == 6 ? 12 :
8336 i == Xboom_2 && j == 7 ? 12 :
8337 special_animation && j == 4 ? 3 :
8338 effective_action != action ? 0 :
8342 Bitmap *debug_bitmap = g_em->bitmap;
8343 int debug_src_x = g_em->src_x;
8344 int debug_src_y = g_em->src_y;
8347 int frame = getAnimationFrame(g->anim_frames,
8350 g->anim_start_frame,
8353 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
8354 g->double_movement && is_backside);
8356 g_em->bitmap = src_bitmap;
8357 g_em->src_x = src_x;
8358 g_em->src_y = src_y;
8359 g_em->src_offset_x = 0;
8360 g_em->src_offset_y = 0;
8361 g_em->dst_offset_x = 0;
8362 g_em->dst_offset_y = 0;
8363 g_em->width = TILEX;
8364 g_em->height = TILEY;
8366 g_em->preserve_background = FALSE;
8369 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
8374 g_em->crumbled_bitmap = NULL;
8375 g_em->crumbled_src_x = 0;
8376 g_em->crumbled_src_y = 0;
8377 g_em->crumbled_border_size = 0;
8379 g_em->has_crumbled_graphics = FALSE;
8382 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
8383 printf("::: empty crumbled: %d [%s], %d, %d\n",
8384 effective_element, element_info[effective_element].token_name,
8385 effective_action, direction);
8388 /* if element can be crumbled, but certain action graphics are just empty
8389 space (like instantly snapping sand to empty space in 1 frame), do not
8390 treat these empty space graphics as crumbled graphics in EMC engine */
8391 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
8393 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
8394 g_crumbled->anim_delay,
8395 g_crumbled->anim_mode,
8396 g_crumbled->anim_start_frame,
8399 getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
8401 g_em->has_crumbled_graphics = TRUE;
8402 g_em->crumbled_bitmap = src_bitmap;
8403 g_em->crumbled_src_x = src_x;
8404 g_em->crumbled_src_y = src_y;
8405 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
8409 if (g_em == &graphic_info_em_object[207][0])
8410 printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
8411 graphic_info_em_object[207][0].crumbled_src_x,
8412 graphic_info_em_object[207][0].crumbled_src_y,
8414 crumbled, frame, src_x, src_y,
8419 g->anim_start_frame,
8421 gfx.anim_random_frame,
8426 printf("::: EMC tile %d is crumbled\n", i);
8432 if (element == EL_ROCK &&
8433 effective_action == ACTION_FILLING)
8434 printf("::: has_action_graphics == %d\n", has_action_graphics);
8437 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
8438 effective_action == ACTION_MOVING ||
8439 effective_action == ACTION_PUSHING ||
8440 effective_action == ACTION_EATING)) ||
8441 (!has_action_graphics && (effective_action == ACTION_FILLING ||
8442 effective_action == ACTION_EMPTYING)))
8445 (effective_action == ACTION_FALLING ||
8446 effective_action == ACTION_FILLING ||
8447 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
8448 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
8449 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
8450 int num_steps = (i == Ydrip_s1 ? 16 :
8451 i == Ydrip_s1B ? 16 :
8452 i == Ydrip_s2 ? 16 :
8453 i == Ydrip_s2B ? 16 :
8454 i == Xsand_stonein_1 ? 32 :
8455 i == Xsand_stonein_2 ? 32 :
8456 i == Xsand_stonein_3 ? 32 :
8457 i == Xsand_stonein_4 ? 32 :
8458 i == Xsand_stoneout_1 ? 16 :
8459 i == Xsand_stoneout_2 ? 16 : 8);
8460 int cx = ABS(dx) * (TILEX / num_steps);
8461 int cy = ABS(dy) * (TILEY / num_steps);
8462 int step_frame = (i == Ydrip_s2 ? j + 8 :
8463 i == Ydrip_s2B ? j + 8 :
8464 i == Xsand_stonein_2 ? j + 8 :
8465 i == Xsand_stonein_3 ? j + 16 :
8466 i == Xsand_stonein_4 ? j + 24 :
8467 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
8468 int step = (is_backside ? step_frame : num_steps - step_frame);
8470 if (is_backside) /* tile where movement starts */
8472 if (dx < 0 || dy < 0)
8474 g_em->src_offset_x = cx * step;
8475 g_em->src_offset_y = cy * step;
8479 g_em->dst_offset_x = cx * step;
8480 g_em->dst_offset_y = cy * step;
8483 else /* tile where movement ends */
8485 if (dx < 0 || dy < 0)
8487 g_em->dst_offset_x = cx * step;
8488 g_em->dst_offset_y = cy * step;
8492 g_em->src_offset_x = cx * step;
8493 g_em->src_offset_y = cy * step;
8497 g_em->width = TILEX - cx * step;
8498 g_em->height = TILEY - cy * step;
8501 /* create unique graphic identifier to decide if tile must be redrawn */
8502 /* bit 31 - 16 (16 bit): EM style graphic
8503 bit 15 - 12 ( 4 bit): EM style frame
8504 bit 11 - 6 ( 6 bit): graphic width
8505 bit 5 - 0 ( 6 bit): graphic height */
8506 g_em->unique_identifier =
8507 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
8511 /* skip check for EMC elements not contained in original EMC artwork */
8512 if (element == EL_EMC_FAKE_ACID)
8515 if (g_em->bitmap != debug_bitmap ||
8516 g_em->src_x != debug_src_x ||
8517 g_em->src_y != debug_src_y ||
8518 g_em->src_offset_x != 0 ||
8519 g_em->src_offset_y != 0 ||
8520 g_em->dst_offset_x != 0 ||
8521 g_em->dst_offset_y != 0 ||
8522 g_em->width != TILEX ||
8523 g_em->height != TILEY)
8525 static int last_i = -1;
8533 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
8534 i, element, element_info[element].token_name,
8535 element_action_info[effective_action].suffix, direction);
8537 if (element != effective_element)
8538 printf(" [%d ('%s')]",
8540 element_info[effective_element].token_name);
8544 if (g_em->bitmap != debug_bitmap)
8545 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
8546 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
8548 if (g_em->src_x != debug_src_x ||
8549 g_em->src_y != debug_src_y)
8550 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
8551 j, (is_backside ? 'B' : 'F'),
8552 g_em->src_x, g_em->src_y,
8553 g_em->src_x / 32, g_em->src_y / 32,
8554 debug_src_x, debug_src_y,
8555 debug_src_x / 32, debug_src_y / 32);
8557 if (g_em->src_offset_x != 0 ||
8558 g_em->src_offset_y != 0 ||
8559 g_em->dst_offset_x != 0 ||
8560 g_em->dst_offset_y != 0)
8561 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
8563 g_em->src_offset_x, g_em->src_offset_y,
8564 g_em->dst_offset_x, g_em->dst_offset_y);
8566 if (g_em->width != TILEX ||
8567 g_em->height != TILEY)
8568 printf(" %d (%d): size %d,%d should be %d,%d\n",
8570 g_em->width, g_em->height, TILEX, TILEY);
8572 num_em_gfx_errors++;
8579 for (i = 0; i < TILE_MAX; i++)
8581 for (j = 0; j < 8; j++)
8583 int element = object_mapping[i].element_rnd;
8584 int action = object_mapping[i].action;
8585 int direction = object_mapping[i].direction;
8586 boolean is_backside = object_mapping[i].is_backside;
8587 int graphic_action = el_act_dir2img(element, action, direction);
8588 int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
8590 if ((action == ACTION_SMASHED_BY_ROCK ||
8591 action == ACTION_SMASHED_BY_SPRING ||
8592 action == ACTION_EATING) &&
8593 graphic_action == graphic_default)
8595 int e = (action == ACTION_SMASHED_BY_ROCK ? Ystone_s :
8596 action == ACTION_SMASHED_BY_SPRING ? Yspring_s :
8597 direction == MV_LEFT ? (is_backside? Yspring_wB: Yspring_w) :
8598 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
8601 /* no separate animation for "smashed by rock" -- use rock instead */
8602 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
8603 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
8605 g_em->bitmap = g_xx->bitmap;
8606 g_em->src_x = g_xx->src_x;
8607 g_em->src_y = g_xx->src_y;
8608 g_em->src_offset_x = g_xx->src_offset_x;
8609 g_em->src_offset_y = g_xx->src_offset_y;
8610 g_em->dst_offset_x = g_xx->dst_offset_x;
8611 g_em->dst_offset_y = g_xx->dst_offset_y;
8612 g_em->width = g_xx->width;
8613 g_em->height = g_xx->height;
8614 g_em->unique_identifier = g_xx->unique_identifier;
8617 g_em->preserve_background = TRUE;
8622 for (p = 0; p < MAX_PLAYERS; p++)
8624 for (i = 0; i < SPR_MAX; i++)
8626 int element = player_mapping[p][i].element_rnd;
8627 int action = player_mapping[p][i].action;
8628 int direction = player_mapping[p][i].direction;
8630 for (j = 0; j < 8; j++)
8632 int effective_element = element;
8633 int effective_action = action;
8634 int graphic = (direction == MV_NONE ?
8635 el_act2img(effective_element, effective_action) :
8636 el_act_dir2img(effective_element, effective_action,
8638 struct GraphicInfo *g = &graphic_info[graphic];
8639 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
8645 Bitmap *debug_bitmap = g_em->bitmap;
8646 int debug_src_x = g_em->src_x;
8647 int debug_src_y = g_em->src_y;
8650 int frame = getAnimationFrame(g->anim_frames,
8653 g->anim_start_frame,
8656 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
8658 g_em->bitmap = src_bitmap;
8659 g_em->src_x = src_x;
8660 g_em->src_y = src_y;
8661 g_em->src_offset_x = 0;
8662 g_em->src_offset_y = 0;
8663 g_em->dst_offset_x = 0;
8664 g_em->dst_offset_y = 0;
8665 g_em->width = TILEX;
8666 g_em->height = TILEY;
8670 /* skip check for EMC elements not contained in original EMC artwork */
8671 if (element == EL_PLAYER_3 ||
8672 element == EL_PLAYER_4)
8675 if (g_em->bitmap != debug_bitmap ||
8676 g_em->src_x != debug_src_x ||
8677 g_em->src_y != debug_src_y)
8679 static int last_i = -1;
8687 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
8688 p, i, element, element_info[element].token_name,
8689 element_action_info[effective_action].suffix, direction);
8691 if (element != effective_element)
8692 printf(" [%d ('%s')]",
8694 element_info[effective_element].token_name);
8698 if (g_em->bitmap != debug_bitmap)
8699 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
8700 j, (int)(g_em->bitmap), (int)(debug_bitmap));
8702 if (g_em->src_x != debug_src_x ||
8703 g_em->src_y != debug_src_y)
8704 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
8706 g_em->src_x, g_em->src_y,
8707 g_em->src_x / 32, g_em->src_y / 32,
8708 debug_src_x, debug_src_y,
8709 debug_src_x / 32, debug_src_y / 32);
8711 num_em_gfx_errors++;
8721 printf("::: [%d errors found]\n", num_em_gfx_errors);
8727 void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
8728 boolean any_player_moving,
8729 boolean player_is_dropping)
8733 if (tape.single_step && tape.recording && !tape.pausing)
8735 boolean active_players = FALSE;
8737 for (i = 0; i < MAX_PLAYERS; i++)
8738 if (action[i] != JOY_NO_ACTION)
8739 active_players = TRUE;
8742 if (frame == 0 && !player_is_dropping)
8743 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
8747 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
8748 boolean murphy_is_dropping)
8751 printf("::: waiting: %d, dropping: %d\n",
8752 murphy_is_waiting, murphy_is_dropping);
8755 if (tape.single_step && tape.recording && !tape.pausing)
8757 // if (murphy_is_waiting || murphy_is_dropping)
8758 if (murphy_is_waiting)
8761 printf("::: murphy is waiting -> pause mode\n");
8764 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
8769 void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
8770 int graphic, int sync_frame, int x, int y)
8772 int frame = getGraphicAnimationFrame(graphic, sync_frame);
8774 getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
8777 boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
8779 return (IS_NEXT_FRAME(sync_frame, graphic));
8782 int getGraphicInfo_Delay(int graphic)
8784 return graphic_info[graphic].anim_delay;
8787 void PlayMenuSoundExt(int sound)
8789 if (sound == SND_UNDEFINED)
8792 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
8793 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
8796 if (IS_LOOP_SOUND(sound))
8797 PlaySoundLoop(sound);
8802 void PlayMenuSound()
8804 PlayMenuSoundExt(menu.sound[game_status]);
8807 void PlayMenuSoundStereo(int sound, int stereo_position)
8809 if (sound == SND_UNDEFINED)
8812 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
8813 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
8816 if (IS_LOOP_SOUND(sound))
8817 PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP);
8819 PlaySoundStereo(sound, stereo_position);
8822 void PlayMenuSoundIfLoopExt(int sound)
8824 if (sound == SND_UNDEFINED)
8827 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
8828 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
8831 if (IS_LOOP_SOUND(sound))
8832 PlaySoundLoop(sound);
8835 void PlayMenuSoundIfLoop()
8837 PlayMenuSoundIfLoopExt(menu.sound[game_status]);
8840 void PlayMenuMusicExt(int music)
8842 if (music == MUS_UNDEFINED)
8845 if (!setup.sound_music)
8851 void PlayMenuMusic()
8853 PlayMenuMusicExt(menu.music[game_status]);
8856 void PlaySoundActivating()
8859 PlaySound(SND_MENU_ITEM_ACTIVATING);
8863 void PlaySoundSelecting()
8866 PlaySound(SND_MENU_ITEM_SELECTING);
8870 void ToggleFullscreenIfNeeded()
8872 boolean change_fullscreen = (setup.fullscreen !=
8873 video.fullscreen_enabled);
8874 boolean change_fullscreen_mode = (video.fullscreen_enabled &&
8875 !strEqual(setup.fullscreen_mode,
8876 video.fullscreen_mode_current));
8878 if (!video.fullscreen_available)
8881 if (change_fullscreen || change_fullscreen_mode)
8883 Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
8885 /* save backbuffer content which gets lost when toggling fullscreen mode */
8886 BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
8888 if (change_fullscreen_mode)
8890 /* keep fullscreen, but change fullscreen mode (screen resolution) */
8891 video.fullscreen_enabled = FALSE; /* force new fullscreen mode */
8894 /* toggle fullscreen */
8895 ChangeVideoModeIfNeeded(setup.fullscreen);
8897 setup.fullscreen = video.fullscreen_enabled;
8899 /* restore backbuffer content from temporary backbuffer backup bitmap */
8900 BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
8902 FreeBitmap(tmp_backbuffer);
8905 /* update visible window/screen */
8906 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
8908 redraw_mask = REDRAW_ALL;
8913 void ChangeViewportPropertiesIfNeeded()
8915 int *door_1_x = &DX;
8916 int *door_1_y = &DY;
8917 int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
8918 int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
8919 int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
8920 game_status == GAME_MODE_EDITOR ? game_status :
8922 struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
8923 struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
8924 struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode];
8925 int border_size = vp_playfield->border_size;
8926 int new_sx = vp_playfield->x + border_size;
8927 int new_sy = vp_playfield->y + border_size;
8928 int new_sxsize = vp_playfield->width - 2 * border_size;
8929 int new_sysize = vp_playfield->height - 2 * border_size;
8930 int new_real_sx = vp_playfield->x;
8931 int new_real_sy = vp_playfield->y;
8932 int new_full_sxsize = vp_playfield->width;
8933 int new_full_sysize = vp_playfield->height;
8935 int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
8936 int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
8937 gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
8938 int new_scr_fieldx = new_sxsize / tilesize;
8939 int new_scr_fieldy = new_sysize / tilesize;
8940 int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var;
8941 int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
8943 int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE;
8944 int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE;
8946 boolean init_gfx_buffers = FALSE;
8947 boolean init_video_buffer = FALSE;
8948 boolean init_gadgets_and_toons = FALSE;
8951 /* !!! TEST ONLY !!! */
8952 // InitGfxBuffers();
8956 if (viewport.window.width != WIN_XSIZE ||
8957 viewport.window.height != WIN_YSIZE)
8959 WIN_XSIZE = viewport.window.width;
8960 WIN_YSIZE = viewport.window.height;
8963 init_video_buffer = TRUE;
8964 init_gfx_buffers = TRUE;
8966 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
8970 SetDrawDeactivationMask(REDRAW_NONE);
8971 SetDrawBackgroundMask(REDRAW_FIELD);
8973 // RedrawBackground();
8977 // printf("::: video: init_video_buffer, init_gfx_buffers\n");
8980 if (new_scr_fieldx != SCR_FIELDX ||
8981 new_scr_fieldy != SCR_FIELDY)
8983 /* this always toggles between MAIN and GAME when using small tile size */
8985 SCR_FIELDX = new_scr_fieldx;
8986 SCR_FIELDY = new_scr_fieldy;
8988 // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
8992 if (new_tilesize_var != TILESIZE_VAR &&
8993 gfx_game_mode == GAME_MODE_PLAYING)
8995 /* doing this outside GAME_MODE_PLAYING would give wrong playfield size */
8997 TILESIZE_VAR = new_tilesize_var;
8999 init_gfx_buffers = TRUE;
9001 // printf("::: tilesize: init_gfx_buffers\n");
9007 new_sxsize != SXSIZE ||
9008 new_sysize != SYSIZE ||
9009 new_real_sx != REAL_SX ||
9010 new_real_sy != REAL_SY ||
9011 new_full_sxsize != FULL_SXSIZE ||
9012 new_full_sysize != FULL_SYSIZE ||
9013 new_tilesize_var != TILESIZE_VAR ||
9014 vp_door_1->x != *door_1_x ||
9015 vp_door_1->y != *door_1_y ||
9016 vp_door_2->x != *door_2_x ||
9017 vp_door_2->y != *door_2_y)
9021 SXSIZE = new_sxsize;
9022 SYSIZE = new_sysize;
9023 REAL_SX = new_real_sx;
9024 REAL_SY = new_real_sy;
9025 FULL_SXSIZE = new_full_sxsize;
9026 FULL_SYSIZE = new_full_sysize;
9027 TILESIZE_VAR = new_tilesize_var;
9030 printf("::: %d, %d, %d [%d]\n",
9031 SCR_FIELDX, SCR_FIELDY, TILESIZE_VAR,
9032 setup.small_game_graphics);
9035 *door_1_x = vp_door_1->x;
9036 *door_1_y = vp_door_1->y;
9037 *door_2_x = vp_door_2->x;
9038 *door_2_y = vp_door_2->y;
9041 init_gfx_buffers = TRUE;
9043 // printf("::: viewports: init_gfx_buffers\n");
9048 if (gfx_game_mode == GAME_MODE_MAIN)
9051 init_gadgets_and_toons = TRUE;
9053 // printf("::: viewports: init_gadgets_and_toons\n");
9061 if (init_gfx_buffers)
9063 // printf("::: init_gfx_buffers\n");
9065 SCR_FIELDX = new_scr_fieldx_buffers;
9066 SCR_FIELDY = new_scr_fieldy_buffers;
9070 SCR_FIELDX = new_scr_fieldx;
9071 SCR_FIELDY = new_scr_fieldy;
9074 if (init_video_buffer)
9076 // printf("::: init_video_buffer\n");
9078 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
9080 SetDrawDeactivationMask(REDRAW_NONE);
9081 SetDrawBackgroundMask(REDRAW_FIELD);
9084 if (init_gadgets_and_toons)
9086 // printf("::: init_gadgets_and_toons\n");
9093 printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status);