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 /* constants for number of doors and door parts */
42 #define MAX_NUM_DOOR_PARTS 8
45 struct DoorPartOrderInfo
51 static struct DoorPartOrderInfo door_part_order[NUM_DOORS * MAX_NUM_DOOR_PARTS];
53 struct DoorPartControlInfo
57 struct TextPosInfo *pos;
60 static struct DoorPartControlInfo door_part_controls[] =
64 IMG_DOOR_1_GFX_PART_1,
69 IMG_DOOR_1_GFX_PART_2,
74 IMG_DOOR_1_GFX_PART_3,
79 IMG_DOOR_1_GFX_PART_4,
84 IMG_DOOR_1_GFX_PART_5,
89 IMG_DOOR_1_GFX_PART_6,
94 IMG_DOOR_1_GFX_PART_7,
99 IMG_DOOR_1_GFX_PART_8,
104 IMG_DOOR_2_GFX_PART_1,
109 IMG_DOOR_2_GFX_PART_2,
114 IMG_DOOR_2_GFX_PART_3,
119 IMG_DOOR_2_GFX_PART_4,
124 IMG_DOOR_2_GFX_PART_5,
129 IMG_DOOR_2_GFX_PART_6,
134 IMG_DOOR_2_GFX_PART_7,
139 IMG_DOOR_2_GFX_PART_8,
151 /* forward declaration for internal use */
152 static void UnmapToolButtons();
153 static void HandleToolButtons(struct GadgetInfo *);
154 static int el_act_dir2crm(int, int, int);
155 static int el_act2crm(int, int);
157 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
158 static int request_gadget_id = -1;
160 static char *print_if_not_empty(int element)
162 static char *s = NULL;
163 char *token_name = element_info[element].token_name;
168 s = checked_malloc(strlen(token_name) + 10 + 1);
170 if (element != EL_EMPTY)
171 sprintf(s, "%d\t['%s']", element, token_name);
173 sprintf(s, "%d", element);
178 void DumpTile(int x, int y)
183 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
189 printf_line("-", 79);
190 printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
191 printf_line("-", 79);
193 if (!IN_LEV_FIELD(x, y))
195 printf("(not in level field)\n");
201 printf(" Feld: %d\t['%s']\n", Feld[x][y],
202 element_info[Feld[x][y]].token_name);
203 printf(" Back: %s\n", print_if_not_empty(Back[x][y]));
204 printf(" Store: %s\n", print_if_not_empty(Store[x][y]));
205 printf(" Store2: %s\n", print_if_not_empty(Store2[x][y]));
206 printf(" StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
207 printf(" MovPos: %d\n", MovPos[x][y]);
208 printf(" MovDir: %d\n", MovDir[x][y]);
209 printf(" MovDelay: %d\n", MovDelay[x][y]);
210 printf(" ChangeDelay: %d\n", ChangeDelay[x][y]);
211 printf(" CustomValue: %d\n", CustomValue[x][y]);
212 printf(" GfxElement: %d\n", GfxElement[x][y]);
213 printf(" GfxAction: %d\n", GfxAction[x][y]);
214 printf(" GfxFrame: %d\n", GfxFrame[x][y]);
218 void SetDrawtoField(int mode)
220 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
228 BX2 = SCR_FIELDX + 1;
229 BY2 = SCR_FIELDY + 1;
248 BX2 = SCR_FIELDX + 1;
249 BY2 = SCR_FIELDY + 1;
264 drawto_field = fieldbuffer;
266 else /* DRAW_BACKBUFFER */
272 BX2 = SCR_FIELDX - 1;
273 BY2 = SCR_FIELDY - 1;
277 drawto_field = backbuffer;
281 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
283 if (game_status == GAME_MODE_PLAYING &&
284 level.game_engine_type == GAME_ENGINE_TYPE_EM)
286 /* currently there is no partial redraw -- always redraw whole playfield */
287 RedrawPlayfield_EM(TRUE);
289 /* blit playfield from scroll buffer to normal back buffer for fading in */
290 BlitScreenToBitmap_EM(backbuffer);
292 else if (game_status == GAME_MODE_PLAYING &&
293 level.game_engine_type == GAME_ENGINE_TYPE_SP)
295 /* currently there is no partial redraw -- always redraw whole playfield */
296 RedrawPlayfield_SP(TRUE);
298 /* blit playfield from scroll buffer to normal back buffer for fading in */
299 BlitScreenToBitmap_SP(backbuffer);
301 else if (game_status == GAME_MODE_PLAYING &&
302 !game.envelope_active)
308 width = gfx.sxsize + 2 * TILEX;
309 height = gfx.sysize + 2 * TILEY;
315 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
316 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
318 for (xx = BX1; xx <= BX2; xx++)
319 for (yy = BY1; yy <= BY2; yy++)
320 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
321 DrawScreenField(xx, yy);
325 if (setup.soft_scrolling)
327 int fx = FX, fy = FY;
329 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
330 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
332 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
344 BlitBitmap(drawto, window, x, y, width, height, x, y);
347 void DrawMaskedBorder_Rect(int x, int y, int width, int height)
349 Bitmap *bitmap = graphic_info[IMG_GLOBAL_BORDER].bitmap;
351 SetClipOrigin(bitmap, bitmap->stored_clip_gc, 0, 0);
352 BlitBitmapMasked(bitmap, backbuffer, x, y, width, height, x, y);
355 void DrawMaskedBorder_FIELD()
357 if (global.border_status >= GAME_MODE_TITLE &&
358 global.border_status <= GAME_MODE_PLAYING &&
359 border.draw_masked[global.border_status])
360 DrawMaskedBorder_Rect(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
363 void DrawMaskedBorder_DOOR_1()
365 if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
366 (global.border_status != GAME_MODE_EDITOR ||
367 border.draw_masked[GFX_SPECIAL_ARG_EDITOR]))
368 DrawMaskedBorder_Rect(DX, DY, DXSIZE, DYSIZE);
371 void DrawMaskedBorder_DOOR_2()
373 if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
374 global.border_status != GAME_MODE_EDITOR)
375 DrawMaskedBorder_Rect(VX, VY, VXSIZE, VYSIZE);
378 void DrawMaskedBorder_DOOR_3()
380 /* currently not available */
383 void DrawMaskedBorder_ALL()
385 DrawMaskedBorder_FIELD();
386 DrawMaskedBorder_DOOR_1();
387 DrawMaskedBorder_DOOR_2();
388 DrawMaskedBorder_DOOR_3();
391 void DrawMaskedBorder(int redraw_mask)
393 /* never draw masked screen borders on borderless screens */
394 if (effectiveGameStatus() == GAME_MODE_LOADING ||
395 effectiveGameStatus() == GAME_MODE_TITLE)
398 /* never draw masked screen borders when displaying request outside door */
399 if (effectiveGameStatus() == GAME_MODE_PSEUDO_DOOR &&
400 global.use_envelope_request)
403 if (redraw_mask & REDRAW_ALL)
404 DrawMaskedBorder_ALL();
407 if (redraw_mask & REDRAW_FIELD)
408 DrawMaskedBorder_FIELD();
409 if (redraw_mask & REDRAW_DOOR_1)
410 DrawMaskedBorder_DOOR_1();
411 if (redraw_mask & REDRAW_DOOR_2)
412 DrawMaskedBorder_DOOR_2();
413 if (redraw_mask & REDRAW_DOOR_3)
414 DrawMaskedBorder_DOOR_3();
418 void BlitScreenToBitmap(Bitmap *target_bitmap)
420 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
421 int fx = FX, fy = FY;
424 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
425 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
426 int dx_var = dx * TILESIZE_VAR / TILESIZE;
427 int dy_var = dy * TILESIZE_VAR / TILESIZE;
430 // fx += dx * TILESIZE_VAR / TILESIZE;
431 // fy += dy * TILESIZE_VAR / TILESIZE;
433 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
434 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
437 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
438 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
440 if (EVEN(SCR_FIELDX))
442 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
443 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
445 fx += (dx_var > 0 ? TILEX_VAR : 0);
452 if (EVEN(SCR_FIELDY))
454 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
455 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
457 fy += (dy_var > 0 ? TILEY_VAR : 0);
465 printf("::: (%d, %d) [(%d / %d, %d / %d)] => %d, %d\n",
468 SBY_Upper, SBY_Lower,
472 if (border.draw_masked[GAME_MODE_PLAYING])
474 if (buffer != backbuffer)
476 /* copy playfield buffer to backbuffer to add masked border */
477 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
478 DrawMaskedBorder(REDRAW_FIELD);
481 BlitBitmap(backbuffer, target_bitmap,
482 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
487 BlitBitmap(buffer, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
494 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
497 printf("::: TILES TO REFRESH: %d\n", redraw_tiles);
498 for (x = 0; x < SCR_FIELDX; x++)
499 for (y = 0 ; y < SCR_FIELDY; y++)
500 if (redraw[redraw_x1 + x][redraw_y1 + y])
501 printf("::: - %d, %d [%s]\n",
502 LEVELX(x), LEVELY(y),
503 EL_NAME(Feld[LEVELX(x)][LEVELY(y)]));
506 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
507 redraw_mask |= REDRAW_FIELD;
510 // never redraw single tiles, always redraw the whole field
511 // (redrawing single tiles up to a certain threshold was faster on old,
512 // now legacy graphics, but slows things down on modern graphics now)
513 // UPDATE: this is now globally defined by value of REDRAWTILES_THRESHOLD
514 if (redraw_mask & REDRAW_TILES)
515 redraw_mask |= REDRAW_FIELD;
519 /* !!! TEST ONLY !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
520 /* (force full redraw) */
521 if (game_status == GAME_MODE_PLAYING)
522 redraw_mask |= REDRAW_FIELD;
525 if (redraw_mask & REDRAW_FIELD)
526 redraw_mask &= ~REDRAW_TILES;
528 if (redraw_mask == REDRAW_NONE)
533 if (redraw_mask & REDRAW_ALL)
534 printf("[REDRAW_ALL]");
535 if (redraw_mask & REDRAW_FIELD)
536 printf("[REDRAW_FIELD]");
537 if (redraw_mask & REDRAW_TILES)
538 printf("[REDRAW_TILES]");
539 if (redraw_mask & REDRAW_DOOR_1)
540 printf("[REDRAW_DOOR_1]");
541 if (redraw_mask & REDRAW_DOOR_2)
542 printf("[REDRAW_DOOR_2]");
543 if (redraw_mask & REDRAW_FROM_BACKBUFFER)
544 printf("[REDRAW_FROM_BACKBUFFER]");
545 printf(" [%d]\n", FrameCounter);
548 if (redraw_mask & REDRAW_TILES &&
549 game_status == GAME_MODE_PLAYING &&
550 border.draw_masked[GAME_MODE_PLAYING])
551 redraw_mask |= REDRAW_FIELD;
553 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
555 static boolean last_frame_skipped = FALSE;
556 boolean skip_even_when_not_scrolling = TRUE;
557 boolean just_scrolling = (ScreenMovDir != 0);
558 boolean verbose = FALSE;
560 if (global.fps_slowdown_factor > 1 &&
561 (FrameCounter % global.fps_slowdown_factor) &&
562 (just_scrolling || skip_even_when_not_scrolling))
564 redraw_mask &= ~REDRAW_MAIN;
566 last_frame_skipped = TRUE;
569 printf("FRAME SKIPPED\n");
573 if (last_frame_skipped)
574 redraw_mask |= REDRAW_FIELD;
576 last_frame_skipped = FALSE;
579 printf("frame not skipped\n");
583 /* synchronize X11 graphics at this point; if we would synchronize the
584 display immediately after the buffer switching (after the XFlush),
585 this could mean that we have to wait for the graphics to complete,
586 although we could go on doing calculations for the next frame */
590 /* never draw masked border to backbuffer when using playfield buffer */
591 if (game_status != GAME_MODE_PLAYING ||
592 redraw_mask & REDRAW_FROM_BACKBUFFER ||
593 buffer == backbuffer)
594 DrawMaskedBorder(redraw_mask);
596 DrawMaskedBorder(redraw_mask & REDRAW_DOORS);
598 if (redraw_mask & REDRAW_ALL)
600 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
602 redraw_mask = REDRAW_NONE;
605 if (redraw_mask & REDRAW_FIELD)
608 printf("::: REDRAW_FIELD\n");
611 if (game_status != GAME_MODE_PLAYING ||
612 redraw_mask & REDRAW_FROM_BACKBUFFER)
614 BlitBitmap(backbuffer, window,
615 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
620 BlitScreenToBitmap(window);
622 int fx = FX, fy = FY;
625 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
626 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
627 int dx_var = dx * TILESIZE_VAR / TILESIZE;
628 int dy_var = dy * TILESIZE_VAR / TILESIZE;
631 // fx += dx * TILESIZE_VAR / TILESIZE;
632 // fy += dy * TILESIZE_VAR / TILESIZE;
634 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
635 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
638 /* !!! THIS WORKS !!! */
640 printf("::: %d, %d\n", scroll_x, scroll_y);
642 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
643 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
645 if (EVEN(SCR_FIELDX))
647 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
648 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
650 fx += (dx > 0 ? TILEX_VAR : 0);
657 if (EVEN(SCR_FIELDY))
659 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
660 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
662 fy += (dy > 0 ? TILEY_VAR : 0);
669 if (border.draw_masked[GAME_MODE_PLAYING])
671 if (buffer != backbuffer)
673 /* copy playfield buffer to backbuffer to add masked border */
674 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
675 DrawMaskedBorder(REDRAW_FIELD);
678 BlitBitmap(backbuffer, window,
679 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
684 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
690 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
692 (setup.soft_scrolling ?
693 "setup.soft_scrolling" :
694 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
695 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
696 ABS(ScreenGfxPos) == ScrollStepSize ?
697 "ABS(ScreenGfxPos) == ScrollStepSize" :
698 "redraw_tiles > REDRAWTILES_THRESHOLD"));
703 redraw_mask &= ~REDRAW_MAIN;
706 if (redraw_mask & REDRAW_DOORS)
708 if (redraw_mask & REDRAW_DOOR_1)
709 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
711 if (redraw_mask & REDRAW_DOOR_2)
712 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
714 if (redraw_mask & REDRAW_DOOR_3)
715 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
717 redraw_mask &= ~REDRAW_DOORS;
720 if (redraw_mask & REDRAW_MICROLEVEL)
722 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
723 SX, SY + 10 * TILEY);
725 redraw_mask &= ~REDRAW_MICROLEVEL;
728 if (redraw_mask & REDRAW_TILES)
731 printf("::: REDRAW_TILES\n");
737 InitGfxClipRegion(TRUE, SX, SY, SXSIZE, SYSIZE);
740 int sx = SX; // - (EVEN(SCR_FIELDX) ? TILEX_VAR / 2 : 0);
741 int sy = SY; // + (EVEN(SCR_FIELDY) ? TILEY_VAR / 2 : 0);
744 int dx_var = dx * TILESIZE_VAR / TILESIZE;
745 int dy_var = dy * TILESIZE_VAR / TILESIZE;
747 int fx = FX, fy = FY;
749 int scr_fieldx = SCR_FIELDX + (EVEN(SCR_FIELDX) ? 2 : 0);
750 int scr_fieldy = SCR_FIELDY + (EVEN(SCR_FIELDY) ? 2 : 0);
752 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
753 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
755 if (EVEN(SCR_FIELDX))
757 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
759 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
768 fx += (dx_var > 0 ? TILEX_VAR : 0);
772 if (EVEN(SCR_FIELDY))
774 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
776 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
785 fy += (dy_var > 0 ? TILEY_VAR : 0);
790 printf("::: %d, %d, %d, %d\n", sx, sy, SCR_FIELDX, SCR_FIELDY);
793 for (x = 0; x < scr_fieldx; x++)
794 for (y = 0 ; y < scr_fieldy; y++)
795 if (redraw[redraw_x1 + x][redraw_y1 + y])
796 BlitBitmap(buffer, window,
797 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
798 TILEX_VAR, TILEY_VAR,
799 sx + x * TILEX_VAR, sy + y * TILEY_VAR);
802 InitGfxClipRegion(FALSE, -1, -1, -1, -1);
804 for (x = 0; x < SCR_FIELDX; x++)
805 for (y = 0 ; y < SCR_FIELDY; y++)
806 if (redraw[redraw_x1 + x][redraw_y1 + y])
807 BlitBitmap(buffer, window,
808 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
809 TILEX_VAR, TILEY_VAR,
810 SX + x * TILEX_VAR, SY + y * TILEY_VAR);
814 for (x = 0; x < SCR_FIELDX; x++)
815 for (y = 0 ; y < SCR_FIELDY; y++)
816 if (redraw[redraw_x1 + x][redraw_y1 + y])
817 BlitBitmap(buffer, window,
818 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
819 SX + x * TILEX, SY + y * TILEY);
823 if (redraw_mask & REDRAW_FPS) /* display frames per second */
828 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
829 if (!global.fps_slowdown)
832 sprintf(text, "%04.1f fps%s", global.frames_per_second, info1);
834 DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE);
836 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
842 for (x = 0; x < MAX_BUF_XSIZE; x++)
843 for (y = 0; y < MAX_BUF_YSIZE; y++)
846 redraw_mask = REDRAW_NONE;
849 static void FadeCrossSaveBackbuffer()
851 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
854 static void FadeExt(int fade_mask, int fade_mode, int fade_type)
856 static int fade_type_skip = FADE_TYPE_NONE;
857 void (*draw_border_function)(void) = NULL;
858 Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL);
859 int x, y, width, height;
860 int fade_delay, post_delay;
862 if (fade_type == FADE_TYPE_FADE_OUT)
864 if (fade_type_skip != FADE_TYPE_NONE)
867 printf("::: skipping %d ... [%d] (X)\n", fade_mode, fade_type_skip);
870 /* skip all fade operations until specified fade operation */
871 if (fade_type & fade_type_skip)
872 fade_type_skip = FADE_TYPE_NONE;
877 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
879 FadeCrossSaveBackbuffer();
885 redraw_mask |= fade_mask;
887 if (fade_type == FADE_TYPE_SKIP)
890 printf("::: will skip %d ... [%d]\n", fade_mode, fade_type_skip);
893 fade_type_skip = fade_mode;
899 printf("::: !!! FADING %d ... [%d] [%d]\n", fade_mode, fade_type,
904 fade_delay = fading.fade_delay;
905 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
908 if (fade_type_skip != FADE_TYPE_NONE)
911 printf("::: skipping %d ... [%d]\n", fade_mode, fade_type_skip);
914 /* skip all fade operations until specified fade operation */
915 if (fade_type & fade_type_skip)
916 fade_type_skip = FADE_TYPE_NONE;
926 if (global.autoplay_leveldir)
928 // fading.fade_mode = FADE_MODE_NONE;
935 if (fading.fade_mode == FADE_MODE_NONE)
943 /* !!! what about fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */
946 printf("::: NOW FADING %d ... [%d]\n", fade_mode, fade_type);
950 if (fade_mask == REDRAW_NONE)
951 fade_mask = REDRAW_FIELD;
954 // if (fade_mask & REDRAW_FIELD)
955 if (fade_mask == REDRAW_FIELD)
960 height = FULL_SYSIZE;
963 fade_delay = fading.fade_delay;
964 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
967 if (border.draw_masked_when_fading)
968 draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */
970 DrawMaskedBorder_FIELD(); /* draw once */
972 else /* REDRAW_ALL */
980 fade_delay = fading.fade_delay;
981 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
986 if (!setup.fade_screens ||
988 fading.fade_mode == FADE_MODE_NONE)
990 if (!setup.fade_screens || fade_delay == 0)
993 if (fade_mode == FADE_MODE_FADE_OUT)
997 if (fade_mode == FADE_MODE_FADE_OUT &&
998 fading.fade_mode != FADE_MODE_NONE)
999 ClearRectangle(backbuffer, x, y, width, height);
1003 BlitBitmap(backbuffer, window, x, y, width, height, x, y);
1004 redraw_mask = REDRAW_NONE;
1012 FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay,
1013 draw_border_function);
1015 redraw_mask &= ~fade_mask;
1018 void FadeIn(int fade_mask)
1020 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
1021 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN);
1023 FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN);
1026 void FadeOut(int fade_mask)
1028 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
1029 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_OUT);
1031 FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT);
1033 global.border_status = game_status;
1036 static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set)
1038 static struct TitleFadingInfo fading_leave_stored;
1041 fading_leave_stored = fading_leave;
1043 fading = fading_leave_stored;
1046 void FadeSetEnterMenu()
1048 fading = menu.enter_menu;
1051 printf("::: storing enter_menu\n");
1054 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1057 void FadeSetLeaveMenu()
1059 fading = menu.leave_menu;
1062 printf("::: storing leave_menu\n");
1065 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1068 void FadeSetEnterScreen()
1070 fading = menu.enter_screen[game_status];
1073 printf("::: storing leave_screen[%d]\n", game_status);
1076 FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */
1079 void FadeSetNextScreen()
1081 fading = menu.next_screen;
1084 printf("::: storing next_screen\n");
1087 // (do not overwrite fade mode set by FadeSetEnterScreen)
1088 // FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1091 void FadeSetLeaveScreen()
1094 printf("::: recalling last stored value\n");
1097 FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */
1100 void FadeSetFromType(int type)
1102 if (type & TYPE_ENTER_SCREEN)
1103 FadeSetEnterScreen();
1104 else if (type & TYPE_ENTER)
1106 else if (type & TYPE_LEAVE)
1110 void FadeSetDisabled()
1112 static struct TitleFadingInfo fading_none = { FADE_MODE_NONE, -1, -1, -1 };
1114 fading = fading_none;
1117 void FadeSkipNextFadeIn()
1119 FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP);
1122 void FadeSkipNextFadeOut()
1124 FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
1127 void SetWindowBackgroundImageIfDefined(int graphic)
1129 if (graphic_info[graphic].bitmap)
1130 SetWindowBackgroundBitmap(graphic_info[graphic].bitmap);
1133 void SetMainBackgroundImageIfDefined(int graphic)
1135 if (graphic_info[graphic].bitmap)
1136 SetMainBackgroundBitmap(graphic_info[graphic].bitmap);
1139 void SetDoorBackgroundImageIfDefined(int graphic)
1141 if (graphic_info[graphic].bitmap)
1142 SetDoorBackgroundBitmap(graphic_info[graphic].bitmap);
1145 void SetWindowBackgroundImage(int graphic)
1147 SetWindowBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1148 graphic_info[graphic].bitmap ?
1149 graphic_info[graphic].bitmap :
1150 graphic_info[IMG_BACKGROUND].bitmap);
1153 void SetMainBackgroundImage(int graphic)
1155 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1156 graphic_info[graphic].bitmap ?
1157 graphic_info[graphic].bitmap :
1158 graphic_info[IMG_BACKGROUND].bitmap);
1161 void SetDoorBackgroundImage(int graphic)
1163 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1164 graphic_info[graphic].bitmap ?
1165 graphic_info[graphic].bitmap :
1166 graphic_info[IMG_BACKGROUND].bitmap);
1169 void SetPanelBackground()
1172 struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL];
1175 BlitBitmapTiled(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1176 gfx->width, gfx->height, 0, 0, DXSIZE, DYSIZE);
1178 /* (ClearRectangle() only needed if panel bitmap is smaller than panel) */
1179 ClearRectangle(bitmap_db_panel, DX, DY, DXSIZE, DYSIZE);
1180 BlitBitmap(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1181 MIN(gfx->width, DXSIZE), MIN(gfx->height, DYSIZE), 0, 0);
1184 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, bitmap_db_panel,
1185 DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, 0, 0);
1188 SetDoorBackgroundBitmap(bitmap_db_panel);
1191 void DrawBackground(int x, int y, int width, int height)
1193 /* !!! "drawto" might still point to playfield buffer here (see below) !!! */
1194 /* (when entering hall of fame after playing) */
1196 ClearRectangleOnBackground(drawto, x, y, width, height);
1198 ClearRectangleOnBackground(backbuffer, x, y, width, height);
1204 if (IN_GFX_FIELD_FULL(x, y))
1205 redraw_mask |= REDRAW_FIELD;
1206 else if (IN_GFX_DOOR_1(x, y))
1207 redraw_mask |= REDRAW_DOOR_1;
1208 else if (IN_GFX_DOOR_2(x, y))
1209 redraw_mask |= REDRAW_DOOR_2;
1210 else if (IN_GFX_DOOR_3(x, y))
1211 redraw_mask |= REDRAW_DOOR_3;
1213 /* (this only works for the current arrangement of playfield and panels) */
1215 redraw_mask |= REDRAW_FIELD;
1216 else if (y < gfx.vy)
1217 redraw_mask |= REDRAW_DOOR_1;
1219 redraw_mask |= REDRAW_DOOR_2;
1223 /* (this is just wrong (when drawing to one of the two door panel areas)) */
1224 redraw_mask |= REDRAW_FIELD;
1228 void DrawBackgroundForFont(int x, int y, int width, int height, int font_nr)
1230 struct FontBitmapInfo *font = getFontBitmapInfo(font_nr);
1232 if (font->bitmap == NULL)
1235 DrawBackground(x, y, width, height);
1238 void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic)
1240 struct GraphicInfo *g = &graphic_info[graphic];
1242 if (g->bitmap == NULL)
1245 DrawBackground(x, y, width, height);
1250 /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
1251 /* (when entering hall of fame after playing) */
1252 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
1254 /* !!! maybe this should be done before clearing the background !!! */
1255 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
1257 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
1258 SetDrawtoField(DRAW_BUFFERED);
1261 SetDrawtoField(DRAW_BACKBUFFER);
1264 void MarkTileDirty(int x, int y)
1266 int xx = redraw_x1 + x;
1267 int yy = redraw_y1 + y;
1269 if (!redraw[xx][yy])
1272 redraw[xx][yy] = TRUE;
1273 redraw_mask |= REDRAW_TILES;
1276 void SetBorderElement()
1280 BorderElement = EL_EMPTY;
1282 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
1284 for (x = 0; x < lev_fieldx; x++)
1286 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
1287 BorderElement = EL_STEELWALL;
1289 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
1295 void FloodFillLevel(int from_x, int from_y, int fill_element,
1296 short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
1297 int max_fieldx, int max_fieldy)
1301 static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
1302 static int safety = 0;
1304 /* check if starting field still has the desired content */
1305 if (field[from_x][from_y] == fill_element)
1310 if (safety > max_fieldx * max_fieldy)
1311 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
1313 old_element = field[from_x][from_y];
1314 field[from_x][from_y] = fill_element;
1316 for (i = 0; i < 4; i++)
1318 x = from_x + check[i][0];
1319 y = from_y + check[i][1];
1321 if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
1322 FloodFillLevel(x, y, fill_element, field, max_fieldx, max_fieldy);
1328 void SetRandomAnimationValue(int x, int y)
1330 gfx.anim_random_frame = GfxRandom[x][y];
1333 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
1335 /* animation synchronized with global frame counter, not move position */
1336 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
1337 sync_frame = FrameCounter;
1339 return getAnimationFrame(graphic_info[graphic].anim_frames,
1340 graphic_info[graphic].anim_delay,
1341 graphic_info[graphic].anim_mode,
1342 graphic_info[graphic].anim_start_frame,
1346 void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw,
1347 Bitmap **bitmap, int *x, int *y,
1348 boolean get_backside)
1352 int width_mult, width_div;
1353 int height_mult, height_div;
1357 { 15, 16, 2, 3 }, /* 1 x 1 */
1358 { 7, 8, 2, 3 }, /* 2 x 2 */
1359 { 3, 4, 2, 3 }, /* 4 x 4 */
1360 { 1, 2, 2, 3 }, /* 8 x 8 */
1361 { 0, 1, 2, 3 }, /* 16 x 16 */
1362 { 0, 1, 0, 1 }, /* 32 x 32 */
1364 struct GraphicInfo *g = &graphic_info[graphic];
1365 Bitmap *src_bitmap = g->bitmap;
1366 int tilesize = MIN(MAX(1, tilesize_raw), TILESIZE);
1367 int offset_calc_pos = log_2(tilesize);
1368 int width_mult = offset_calc[offset_calc_pos].width_mult;
1369 int width_div = offset_calc[offset_calc_pos].width_div;
1370 int height_mult = offset_calc[offset_calc_pos].height_mult;
1371 int height_div = offset_calc[offset_calc_pos].height_div;
1372 int startx = src_bitmap->width * width_mult / width_div;
1373 int starty = src_bitmap->height * height_mult / height_div;
1375 int src_x = (g->src_x + (get_backside ? g->offset2_x : 0)) *
1376 tilesize / TILESIZE;
1377 int src_y = (g->src_y + (get_backside ? g->offset2_y : 0)) *
1378 tilesize / TILESIZE;
1380 int src_x = g->src_x * tilesize / TILESIZE;
1381 int src_y = g->src_y * tilesize / TILESIZE;
1383 int width = g->width * tilesize / TILESIZE;
1384 int height = g->height * tilesize / TILESIZE;
1385 int offset_x = g->offset_x * tilesize / TILESIZE;
1386 int offset_y = g->offset_y * tilesize / TILESIZE;
1388 if (g->offset_y == 0) /* frames are ordered horizontally */
1390 int max_width = g->anim_frames_per_line * width;
1391 int pos = (src_y / height) * max_width + src_x + frame * offset_x;
1393 src_x = pos % max_width;
1394 src_y = src_y % height + pos / max_width * height;
1396 else if (g->offset_x == 0) /* frames are ordered vertically */
1398 int max_height = g->anim_frames_per_line * height;
1399 int pos = (src_x / width) * max_height + src_y + frame * offset_y;
1401 src_x = src_x % width + pos / max_height * width;
1402 src_y = pos % max_height;
1404 else /* frames are ordered diagonally */
1406 src_x = src_x + frame * offset_x;
1407 src_y = src_y + frame * offset_y;
1410 *bitmap = src_bitmap;
1411 *x = startx + src_x;
1412 *y = starty + src_y;
1415 void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1416 int *x, int *y, boolean get_backside)
1418 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y,
1422 void getSizedGraphicSource(int graphic, int frame, int tilesize_raw,
1423 Bitmap **bitmap, int *x, int *y)
1425 getSizedGraphicSourceExt(graphic, frame, tilesize_raw, bitmap, x, y, FALSE);
1428 void getFixedGraphicSource(int graphic, int frame,
1429 Bitmap **bitmap, int *x, int *y)
1431 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y, FALSE);
1434 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1437 getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
1439 struct GraphicInfo *g = &graphic_info[graphic];
1440 int mini_startx = 0;
1441 int mini_starty = g->bitmap->height * 2 / 3;
1443 *bitmap = g->bitmap;
1444 *x = mini_startx + g->src_x / 2;
1445 *y = mini_starty + g->src_y / 2;
1449 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1450 int *x, int *y, boolean get_backside)
1452 struct GraphicInfo *g = &graphic_info[graphic];
1453 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
1454 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
1457 if (TILESIZE_VAR != TILESIZE)
1458 return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
1462 *bitmap = g->bitmap;
1464 if (g->offset_y == 0) /* frames are ordered horizontally */
1466 int max_width = g->anim_frames_per_line * g->width;
1467 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
1469 *x = pos % max_width;
1470 *y = src_y % g->height + pos / max_width * g->height;
1472 else if (g->offset_x == 0) /* frames are ordered vertically */
1474 int max_height = g->anim_frames_per_line * g->height;
1475 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
1477 *x = src_x % g->width + pos / max_height * g->width;
1478 *y = pos % max_height;
1480 else /* frames are ordered diagonally */
1482 *x = src_x + frame * g->offset_x;
1483 *y = src_y + frame * g->offset_y;
1487 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
1489 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
1492 void DrawGraphic(int x, int y, int graphic, int frame)
1495 if (!IN_SCR_FIELD(x, y))
1497 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1498 printf("DrawGraphic(): This should never happen!\n");
1504 DrawGraphicExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR, graphic,
1507 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
1509 MarkTileDirty(x, y);
1512 void DrawFixedGraphic(int x, int y, int graphic, int frame)
1515 if (!IN_SCR_FIELD(x, y))
1517 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1518 printf("DrawGraphic(): This should never happen!\n");
1523 DrawFixedGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1525 MarkTileDirty(x, y);
1528 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1534 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1536 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX_VAR, TILEY_VAR, x, y);
1538 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1542 void DrawFixedGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1548 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1549 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1552 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
1555 if (!IN_SCR_FIELD(x, y))
1557 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1558 printf("DrawGraphicThruMask(): This should never happen!\n");
1564 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
1567 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1570 MarkTileDirty(x, y);
1573 void DrawFixedGraphicThruMask(int x, int y, int graphic, int frame)
1576 if (!IN_SCR_FIELD(x, y))
1578 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1579 printf("DrawGraphicThruMask(): This should never happen!\n");
1584 DrawFixedGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1586 MarkTileDirty(x, y);
1589 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
1595 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1597 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1598 dst_x - src_x, dst_y - src_y);
1600 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX_VAR, TILEY_VAR,
1603 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1607 void DrawFixedGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y,
1608 int graphic, int frame)
1613 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1615 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1616 dst_x - src_x, dst_y - src_y);
1617 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1620 void DrawSizedGraphic(int x, int y, int graphic, int frame, int tilesize)
1622 DrawSizedGraphicExt(drawto, SX + x * tilesize, SY + y * tilesize, graphic,
1624 MarkTileDirty(x / tilesize, y / tilesize);
1627 void DrawSizedGraphicExt(DrawBuffer *d, int x, int y, int graphic, int frame,
1633 getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
1634 BlitBitmap(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
1637 void DrawMiniGraphic(int x, int y, int graphic)
1639 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1640 MarkTileDirty(x / 2, y / 2);
1643 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1648 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1649 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1652 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
1653 int graphic, int frame,
1654 int cut_mode, int mask_mode)
1659 int width = TILEX, height = TILEY;
1662 if (dx || dy) /* shifted graphic */
1664 if (x < BX1) /* object enters playfield from the left */
1671 else if (x > BX2) /* object enters playfield from the right */
1677 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1683 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1685 else if (dx) /* general horizontal movement */
1686 MarkTileDirty(x + SIGN(dx), y);
1688 if (y < BY1) /* object enters playfield from the top */
1690 if (cut_mode==CUT_BELOW) /* object completely above top border */
1698 else if (y > BY2) /* object enters playfield from the bottom */
1704 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1710 else if (dy > 0 && cut_mode == CUT_ABOVE)
1712 if (y == BY2) /* object completely above bottom border */
1718 MarkTileDirty(x, y + 1);
1719 } /* object leaves playfield to the bottom */
1720 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1722 else if (dy) /* general vertical movement */
1723 MarkTileDirty(x, y + SIGN(dy));
1727 if (!IN_SCR_FIELD(x, y))
1729 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1730 printf("DrawGraphicShifted(): This should never happen!\n");
1736 width = width * TILESIZE_VAR / TILESIZE;
1737 height = height * TILESIZE_VAR / TILESIZE;
1738 cx = cx * TILESIZE_VAR / TILESIZE;
1739 cy = cy * TILESIZE_VAR / TILESIZE;
1740 dx = dx * TILESIZE_VAR / TILESIZE;
1741 dy = dy * TILESIZE_VAR / TILESIZE;
1744 if (width > 0 && height > 0)
1746 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1752 dst_x = FX + x * TILEX_VAR + dx;
1753 dst_y = FY + y * TILEY_VAR + dy;
1755 dst_x = FX + x * TILEX + dx;
1756 dst_y = FY + y * TILEY + dy;
1759 if (mask_mode == USE_MASKING)
1761 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1762 dst_x - src_x, dst_y - src_y);
1763 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1767 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1770 MarkTileDirty(x, y);
1774 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
1775 int graphic, int frame,
1776 int cut_mode, int mask_mode)
1782 int width = TILEX_VAR, height = TILEY_VAR;
1784 int width = TILEX, height = TILEY;
1788 int x2 = x + SIGN(dx);
1789 int y2 = y + SIGN(dy);
1791 /* !!! DOES NOT WORK FOR SLOW MOVEMENT !!! */
1792 int sync_frame = GfxFrame[LEVELX(x)][LEVELY(y)];
1794 /* movement with two-tile animations must be sync'ed with movement position,
1795 not with current GfxFrame (which can be higher when using slow movement) */
1796 int anim_pos = (dx ? ABS(dx) : ABS(dy));
1797 int anim_frames = graphic_info[graphic].anim_frames;
1799 /* (we also need anim_delay here for movement animations with less frames) */
1800 int anim_delay = graphic_info[graphic].anim_delay;
1801 int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
1803 int sync_frame = anim_pos * anim_frames / TILESIZE;
1806 boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */
1807 boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */
1809 /* re-calculate animation frame for two-tile movement animation */
1810 frame = getGraphicAnimationFrame(graphic, sync_frame);
1814 printf("::: %d, %d, %d => %d [%d]\n",
1815 anim_pos, anim_frames, anim_delay, sync_frame, graphic);
1817 printf("::: %d, %d => %d\n",
1818 anim_pos, anim_frames, sync_frame);
1823 printf("::: %d [%d, %d] [%d] [%d]\n", frame, sync_frame, dy,
1824 GfxFrame[LEVELX(x)][LEVELY(y)], mask_mode);
1827 /* check if movement start graphic inside screen area and should be drawn */
1828 if (draw_start_tile && IN_SCR_FIELD(x1, y1))
1830 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
1833 dst_x = FX + x1 * TILEX_VAR;
1834 dst_y = FY + y1 * TILEY_VAR;
1836 dst_x = FX + x1 * TILEX;
1837 dst_y = FY + y1 * TILEY;
1840 if (mask_mode == USE_MASKING)
1842 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1843 dst_x - src_x, dst_y - src_y);
1844 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1848 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1851 MarkTileDirty(x1, y1);
1854 /* check if movement end graphic inside screen area and should be drawn */
1855 if (draw_end_tile && IN_SCR_FIELD(x2, y2))
1857 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
1860 dst_x = FX + x2 * TILEX_VAR;
1861 dst_y = FY + y2 * TILEY_VAR;
1863 dst_x = FX + x2 * TILEX;
1864 dst_y = FY + y2 * TILEY;
1867 if (mask_mode == USE_MASKING)
1869 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1870 dst_x - src_x, dst_y - src_y);
1871 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1875 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1878 MarkTileDirty(x2, y2);
1882 static void DrawGraphicShifted(int x, int y, int dx, int dy,
1883 int graphic, int frame,
1884 int cut_mode, int mask_mode)
1888 DrawGraphic(x, y, graphic, frame);
1893 if (graphic_info[graphic].double_movement) /* EM style movement images */
1894 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1896 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1899 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1900 int frame, int cut_mode)
1902 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1905 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1906 int cut_mode, int mask_mode)
1908 int lx = LEVELX(x), ly = LEVELY(y);
1912 if (IN_LEV_FIELD(lx, ly))
1914 SetRandomAnimationValue(lx, ly);
1916 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1917 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1919 /* do not use double (EM style) movement graphic when not moving */
1920 if (graphic_info[graphic].double_movement && !dx && !dy)
1922 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
1923 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1926 else /* border element */
1928 graphic = el2img(element);
1929 frame = getGraphicAnimationFrame(graphic, -1);
1932 if (element == EL_EXPANDABLE_WALL)
1934 boolean left_stopped = FALSE, right_stopped = FALSE;
1936 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1937 left_stopped = TRUE;
1938 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1939 right_stopped = TRUE;
1941 if (left_stopped && right_stopped)
1943 else if (left_stopped)
1945 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1946 frame = graphic_info[graphic].anim_frames - 1;
1948 else if (right_stopped)
1950 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1951 frame = graphic_info[graphic].anim_frames - 1;
1956 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1957 else if (mask_mode == USE_MASKING)
1958 DrawGraphicThruMask(x, y, graphic, frame);
1960 DrawGraphic(x, y, graphic, frame);
1963 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1964 int cut_mode, int mask_mode)
1966 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1967 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1968 cut_mode, mask_mode);
1971 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1974 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1977 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1980 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1983 void DrawLevelElementThruMask(int x, int y, int element)
1985 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1988 void DrawLevelFieldThruMask(int x, int y)
1990 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1993 /* !!! implementation of quicksand is totally broken !!! */
1994 #define IS_CRUMBLED_TILE(x, y, e) \
1995 (GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) || \
1996 !IS_MOVING(x, y) || \
1997 (e) == EL_QUICKSAND_EMPTYING || \
1998 (e) == EL_QUICKSAND_FAST_EMPTYING))
2000 static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
2005 int width, height, cx, cy;
2006 int sx = SCREENX(x), sy = SCREENY(y);
2007 int crumbled_border_size = graphic_info[graphic].border_size;
2010 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2012 for (i = 1; i < 4; i++)
2014 int dxx = (i & 1 ? dx : 0);
2015 int dyy = (i & 2 ? dy : 0);
2018 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2021 /* check if neighbour field is of same crumble type */
2022 boolean same = (IS_CRUMBLED_TILE(xx, yy, element) &&
2023 graphic_info[graphic].class ==
2024 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class);
2026 /* return if check prevents inner corner */
2027 if (same == (dxx == dx && dyy == dy))
2031 /* if we reach this point, we have an inner corner */
2033 getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
2036 width = crumbled_border_size * TILESIZE_VAR / TILESIZE;
2037 height = crumbled_border_size * TILESIZE_VAR / TILESIZE;
2038 cx = (dx > 0 ? TILEX - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
2039 cy = (dy > 0 ? TILEY - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
2041 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2042 width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
2044 width = crumbled_border_size;
2045 height = crumbled_border_size;
2046 cx = (dx > 0 ? TILEX - crumbled_border_size : 0);
2047 cy = (dy > 0 ? TILEY - crumbled_border_size : 0);
2049 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2050 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2054 static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
2059 int width, height, bx, by, cx, cy;
2060 int sx = SCREENX(x), sy = SCREENY(y);
2061 int crumbled_border_size = graphic_info[graphic].border_size;
2064 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
2066 /* draw simple, sloppy, non-corner-accurate crumbled border */
2069 width = (dir == 1 || dir == 2 ? crumbled_border_size : TILEX);
2070 height = (dir == 0 || dir == 3 ? crumbled_border_size : TILEY);
2071 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2072 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2074 if (dir == 1 || dir == 2) /* left or right crumbled border */
2076 width = crumbled_border_size;
2078 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2081 else /* top or bottom crumbled border */
2084 height = crumbled_border_size;
2086 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2091 BlitBitmap(src_bitmap, drawto_field,
2092 src_x + cx * TILESIZE_VAR / TILESIZE,
2093 src_y + cy * TILESIZE_VAR / TILESIZE,
2094 width * TILESIZE_VAR / TILESIZE,
2095 height * TILESIZE_VAR / TILESIZE,
2096 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
2097 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
2099 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2100 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2103 /* (remaining middle border part must be at least as big as corner part) */
2104 if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
2105 crumbled_border_size >= TILESIZE / 3)
2108 /* correct corners of crumbled border, if needed */
2111 for (i = -1; i <= 1; i+=2)
2113 int xx = x + (dir == 0 || dir == 3 ? i : 0);
2114 int yy = y + (dir == 1 || dir == 2 ? i : 0);
2115 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2118 /* check if neighbour field is of same crumble type */
2119 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2120 graphic_info[graphic].class ==
2121 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2123 /* no crumbled corner, but continued crumbled border */
2125 int c1 = (dir == 2 || dir == 3 ? TILESIZE - crumbled_border_size : 0);
2126 int c2 = (i == 1 ? TILESIZE - crumbled_border_size : 0);
2127 int b1 = (i == 1 ? crumbled_border_size :
2128 TILESIZE - 2 * crumbled_border_size);
2130 width = crumbled_border_size;
2131 height = crumbled_border_size;
2133 if (dir == 1 || dir == 2)
2149 BlitBitmap(src_bitmap, drawto_field,
2150 src_x + bx * TILESIZE_VAR / TILESIZE,
2151 src_y + by * TILESIZE_VAR / TILESIZE,
2152 width * TILESIZE_VAR / TILESIZE,
2153 height * TILESIZE_VAR / TILESIZE,
2154 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
2155 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
2157 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2158 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2163 if (dir == 1 || dir == 2) /* left or right crumbled border */
2165 for (i = -1; i <= 1; i+=2)
2169 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2172 /* check if neighbour field is of same crumble type */
2173 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2174 graphic_info[graphic].class ==
2175 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2177 /* no crumbled corner, but continued crumbled border */
2179 width = crumbled_border_size;
2180 height = crumbled_border_size;
2181 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2182 cy = (i == 1 ? TILEY - crumbled_border_size : 0);
2184 by = (i == 1 ? crumbled_border_size :
2185 TILEY - 2 * crumbled_border_size);
2187 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2188 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2192 else /* top or bottom crumbled border */
2194 for (i = -1; i <= 1; i+=2)
2198 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2201 /* check if neighbour field is of same crumble type */
2202 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2203 graphic_info[graphic].class ==
2204 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2206 /* no crumbled corner, but continued crumbled border */
2208 width = crumbled_border_size;
2209 height = crumbled_border_size;
2210 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
2211 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2212 bx = (i == 1 ? crumbled_border_size :
2213 TILEX - 2 * crumbled_border_size);
2216 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2217 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2224 static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
2226 int sx = SCREENX(x), sy = SCREENY(y);
2229 static int xy[4][2] =
2237 if (!IN_LEV_FIELD(x, y))
2240 element = TILE_GFX_ELEMENT(x, y);
2242 /* crumble field itself */
2243 if (IS_CRUMBLED_TILE(x, y, element))
2245 if (!IN_SCR_FIELD(sx, sy))
2248 for (i = 0; i < 4; i++)
2250 int xx = x + xy[i][0];
2251 int yy = y + xy[i][1];
2253 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2256 /* check if neighbour field is of same crumble type */
2258 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2259 graphic_info[graphic].class ==
2260 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2263 if (IS_CRUMBLED_TILE(xx, yy, element))
2267 DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
2270 if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
2271 graphic_info[graphic].anim_frames == 2)
2273 for (i = 0; i < 4; i++)
2275 int dx = (i & 1 ? +1 : -1);
2276 int dy = (i & 2 ? +1 : -1);
2278 DrawLevelFieldCrumbledInnerCorners(x, y, dx, dy, graphic);
2282 MarkTileDirty(sx, sy);
2284 else /* center field not crumbled -- crumble neighbour fields */
2286 for (i = 0; i < 4; i++)
2288 int xx = x + xy[i][0];
2289 int yy = y + xy[i][1];
2290 int sxx = sx + xy[i][0];
2291 int syy = sy + xy[i][1];
2293 if (!IN_LEV_FIELD(xx, yy) ||
2294 !IN_SCR_FIELD(sxx, syy))
2297 if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
2300 element = TILE_GFX_ELEMENT(xx, yy);
2302 if (!IS_CRUMBLED_TILE(xx, yy, element))
2305 graphic = el_act2crm(element, ACTION_DEFAULT);
2307 DrawLevelFieldCrumbledBorders(xx, yy, graphic, 0, 3 - i);
2309 MarkTileDirty(sxx, syy);
2314 void DrawLevelFieldCrumbled(int x, int y)
2318 if (!IN_LEV_FIELD(x, y))
2322 /* !!! CHECK THIS !!! */
2325 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2326 GFX_CRUMBLED(GfxElement[x][y]))
2329 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2330 GfxElement[x][y] != EL_UNDEFINED &&
2331 GFX_CRUMBLED(GfxElement[x][y]))
2333 DrawLevelFieldCrumbledDigging(x, y, GfxDir[x][y], GfxFrame[x][y]);
2340 graphic = el_act2crm(TILE_GFX_ELEMENT(x, y), ACTION_DEFAULT);
2342 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
2345 DrawLevelFieldCrumbledExt(x, y, graphic, 0);
2348 void DrawLevelFieldCrumbledDigging(int x, int y, int direction,
2351 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
2352 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
2353 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
2354 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
2355 int sx = SCREENX(x), sy = SCREENY(y);
2357 DrawGraphic(sx, sy, graphic1, frame1);
2358 DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
2361 void DrawLevelFieldCrumbledNeighbours(int x, int y)
2363 int sx = SCREENX(x), sy = SCREENY(y);
2364 static int xy[4][2] =
2373 for (i = 0; i < 4; i++)
2375 int xx = x + xy[i][0];
2376 int yy = y + xy[i][1];
2377 int sxx = sx + xy[i][0];
2378 int syy = sy + xy[i][1];
2380 if (!IN_LEV_FIELD(xx, yy) ||
2381 !IN_SCR_FIELD(sxx, syy) ||
2382 !GFX_CRUMBLED(Feld[xx][yy]) ||
2386 DrawLevelField(xx, yy);
2390 static int getBorderElement(int x, int y)
2394 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
2395 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
2396 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
2397 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
2398 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
2399 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
2400 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
2402 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2403 int steel_position = (x == -1 && y == -1 ? 0 :
2404 x == lev_fieldx && y == -1 ? 1 :
2405 x == -1 && y == lev_fieldy ? 2 :
2406 x == lev_fieldx && y == lev_fieldy ? 3 :
2407 x == -1 || x == lev_fieldx ? 4 :
2408 y == -1 || y == lev_fieldy ? 5 : 6);
2410 return border[steel_position][steel_type];
2413 void DrawScreenElement(int x, int y, int element)
2415 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
2416 DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
2419 void DrawLevelElement(int x, int y, int element)
2421 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2422 DrawScreenElement(SCREENX(x), SCREENY(y), element);
2425 void DrawScreenField(int x, int y)
2427 int lx = LEVELX(x), ly = LEVELY(y);
2428 int element, content;
2430 if (!IN_LEV_FIELD(lx, ly))
2432 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
2435 element = getBorderElement(lx, ly);
2437 DrawScreenElement(x, y, element);
2442 element = Feld[lx][ly];
2443 content = Store[lx][ly];
2445 if (IS_MOVING(lx, ly))
2447 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
2448 boolean cut_mode = NO_CUTTING;
2450 if (element == EL_QUICKSAND_EMPTYING ||
2451 element == EL_QUICKSAND_FAST_EMPTYING ||
2452 element == EL_MAGIC_WALL_EMPTYING ||
2453 element == EL_BD_MAGIC_WALL_EMPTYING ||
2454 element == EL_DC_MAGIC_WALL_EMPTYING ||
2455 element == EL_AMOEBA_DROPPING)
2456 cut_mode = CUT_ABOVE;
2457 else if (element == EL_QUICKSAND_FILLING ||
2458 element == EL_QUICKSAND_FAST_FILLING ||
2459 element == EL_MAGIC_WALL_FILLING ||
2460 element == EL_BD_MAGIC_WALL_FILLING ||
2461 element == EL_DC_MAGIC_WALL_FILLING)
2462 cut_mode = CUT_BELOW;
2465 if (lx == 9 && ly == 1)
2466 printf("::: %s [%d] [%d, %d] [%d]\n",
2467 EL_NAME(TILE_GFX_ELEMENT(lx, ly)),
2468 el_act2crm(TILE_GFX_ELEMENT(lx, ly), ACTION_DEFAULT),
2469 element_info[EL_QUICKSAND_EMPTYING].graphic[ACTION_DEFAULT],
2470 element_info[EL_QUICKSAND_EMPTYING].crumbled[ACTION_DEFAULT],
2471 GFX_CRUMBLED(TILE_GFX_ELEMENT(lx, ly)));
2474 if (cut_mode == CUT_ABOVE)
2476 DrawScreenElement(x, y, element);
2478 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
2481 DrawScreenElement(x, y, EL_EMPTY);
2484 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
2485 else if (cut_mode == NO_CUTTING)
2486 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
2489 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
2492 if (cut_mode == CUT_BELOW &&
2493 IN_LEV_FIELD(lx, ly + 1) && IN_SCR_FIELD(x, y + 1))
2494 DrawLevelElement(lx, ly + 1, element);
2498 if (content == EL_ACID)
2500 int dir = MovDir[lx][ly];
2501 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
2502 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
2504 DrawLevelElementThruMask(newlx, newly, EL_ACID);
2507 else if (IS_BLOCKED(lx, ly))
2512 boolean cut_mode = NO_CUTTING;
2513 int element_old, content_old;
2515 Blocked2Moving(lx, ly, &oldx, &oldy);
2518 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
2519 MovDir[oldx][oldy] == MV_RIGHT);
2521 element_old = Feld[oldx][oldy];
2522 content_old = Store[oldx][oldy];
2524 if (element_old == EL_QUICKSAND_EMPTYING ||
2525 element_old == EL_QUICKSAND_FAST_EMPTYING ||
2526 element_old == EL_MAGIC_WALL_EMPTYING ||
2527 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2528 element_old == EL_DC_MAGIC_WALL_EMPTYING ||
2529 element_old == EL_AMOEBA_DROPPING)
2530 cut_mode = CUT_ABOVE;
2532 DrawScreenElement(x, y, EL_EMPTY);
2535 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2537 else if (cut_mode == NO_CUTTING)
2538 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2541 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2544 else if (IS_DRAWABLE(element))
2545 DrawScreenElement(x, y, element);
2547 DrawScreenElement(x, y, EL_EMPTY);
2550 void DrawLevelField(int x, int y)
2552 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2553 DrawScreenField(SCREENX(x), SCREENY(y));
2554 else if (IS_MOVING(x, y))
2558 Moving2Blocked(x, y, &newx, &newy);
2559 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2560 DrawScreenField(SCREENX(newx), SCREENY(newy));
2562 else if (IS_BLOCKED(x, y))
2566 Blocked2Moving(x, y, &oldx, &oldy);
2567 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2568 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2572 void DrawMiniElement(int x, int y, int element)
2576 graphic = el2edimg(element);
2577 DrawMiniGraphic(x, y, graphic);
2580 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2582 int x = sx + scroll_x, y = sy + scroll_y;
2584 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2585 DrawMiniElement(sx, sy, EL_EMPTY);
2586 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2587 DrawMiniElement(sx, sy, Feld[x][y]);
2589 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
2592 void DrawEnvelopeBackgroundTiles(int graphic, int startx, int starty,
2593 int x, int y, int xsize, int ysize,
2594 int tile_width, int tile_height)
2598 int dst_x = startx + x * tile_width;
2599 int dst_y = starty + y * tile_height;
2600 int width = graphic_info[graphic].width;
2601 int height = graphic_info[graphic].height;
2602 int inner_width_raw = MAX(width - 2 * tile_width, tile_width);
2603 int inner_height_raw = MAX(height - 2 * tile_height, tile_height);
2604 int inner_width = inner_width_raw - (inner_width_raw % tile_width);
2605 int inner_height = inner_height_raw - (inner_height_raw % tile_height);
2606 int inner_sx = (width >= 3 * tile_width ? tile_width : 0);
2607 int inner_sy = (height >= 3 * tile_height ? tile_height : 0);
2608 boolean draw_masked = graphic_info[graphic].draw_masked;
2610 getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2612 if (src_bitmap == NULL || width < tile_width || height < tile_height)
2614 ClearRectangle(drawto, dst_x, dst_y, tile_width, tile_height);
2618 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - tile_width :
2619 inner_sx + (x - 1) * tile_width % inner_width);
2620 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - tile_height :
2621 inner_sy + (y - 1) * tile_height % inner_height);
2625 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
2626 dst_x - src_x, dst_y - src_y);
2627 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
2631 BlitBitmap(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
2635 void DrawEnvelopeBackground(int graphic, int startx, int starty,
2636 int x, int y, int xsize, int ysize, int font_nr)
2638 int font_width = getFontWidth(font_nr);
2639 int font_height = getFontHeight(font_nr);
2641 DrawEnvelopeBackgroundTiles(graphic, startx, starty, x, y, xsize, ysize,
2642 font_width, font_height);
2645 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
2647 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2648 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2649 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2650 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2651 boolean no_delay = (tape.warp_forward);
2652 unsigned int anim_delay = 0;
2653 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2654 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
2655 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2656 int font_width = getFontWidth(font_nr);
2657 int font_height = getFontHeight(font_nr);
2658 int max_xsize = level.envelope[envelope_nr].xsize;
2659 int max_ysize = level.envelope[envelope_nr].ysize;
2660 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2661 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2662 int xend = max_xsize;
2663 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2664 int xstep = (xstart < xend ? 1 : 0);
2665 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2668 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2670 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2671 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2672 int sx = SX + (SXSIZE - xsize * font_width) / 2;
2673 int sy = SY + (SYSIZE - ysize * font_height) / 2;
2676 SetDrawtoField(DRAW_BUFFERED);
2679 BlitScreenToBitmap(backbuffer);
2681 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2684 SetDrawtoField(DRAW_BACKBUFFER);
2686 for (yy = 0; yy < ysize; yy++)
2687 for (xx = 0; xx < xsize; xx++)
2688 DrawEnvelopeBackground(graphic, sx, sy, xx, yy, xsize, ysize, font_nr);
2691 DrawTextBuffer(sx + font_width, sy + font_height,
2692 level.envelope[envelope_nr].text, font_nr, max_xsize,
2693 xsize - 2, ysize - 2, 0, mask_mode,
2694 level.envelope[envelope_nr].autowrap,
2695 level.envelope[envelope_nr].centered, FALSE);
2697 DrawTextToTextArea(sx + font_width, sy + font_height,
2698 level.envelope[envelope_nr].text, font_nr, max_xsize,
2699 xsize - 2, ysize - 2, mask_mode);
2702 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2705 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2709 void ShowEnvelope(int envelope_nr)
2711 int element = EL_ENVELOPE_1 + envelope_nr;
2712 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2713 int sound_opening = element_info[element].sound[ACTION_OPENING];
2714 int sound_closing = element_info[element].sound[ACTION_CLOSING];
2715 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2716 boolean no_delay = (tape.warp_forward);
2717 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
2718 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
2719 int anim_mode = graphic_info[graphic].anim_mode;
2720 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
2721 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
2723 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
2725 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
2727 if (anim_mode == ANIM_DEFAULT)
2728 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
2730 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
2733 Delay(wait_delay_value);
2735 WaitForEventToContinue();
2737 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
2739 if (anim_mode != ANIM_NONE)
2740 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
2742 if (anim_mode == ANIM_DEFAULT)
2743 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
2745 game.envelope_active = FALSE;
2747 SetDrawtoField(DRAW_BUFFERED);
2749 redraw_mask |= REDRAW_FIELD;
2753 static void setRequestPosition(int *x, int *y, boolean add_border_size)
2755 int border_size = request.border_size;
2756 int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2);
2757 int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2);
2758 int sx = sx_center - request.width / 2;
2759 int sy = sy_center - request.height / 2;
2761 if (add_border_size)
2771 void DrawEnvelopeRequest(char *text)
2773 char *text_final = text;
2774 char *text_door_style = NULL;
2775 int graphic = IMG_BACKGROUND_REQUEST;
2776 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2777 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2778 int font_nr = FONT_REQUEST;
2779 int font_width = getFontWidth(font_nr);
2780 int font_height = getFontHeight(font_nr);
2781 int border_size = request.border_size;
2782 int line_spacing = request.line_spacing;
2783 int line_height = font_height + line_spacing;
2784 int text_width = request.width - 2 * border_size;
2785 int text_height = request.height - 2 * border_size;
2786 int line_length = text_width / font_width;
2787 int max_lines = text_height / line_height;
2788 int width = request.width;
2789 int height = request.height;
2790 int tile_size = request.step_offset;
2791 int x_steps = width / tile_size;
2792 int y_steps = height / tile_size;
2796 if (request.wrap_single_words)
2798 char *src_text_ptr, *dst_text_ptr;
2800 text_door_style = checked_malloc(2 * strlen(text) + 1);
2802 src_text_ptr = text;
2803 dst_text_ptr = text_door_style;
2805 while (*src_text_ptr)
2807 if (*src_text_ptr == ' ' ||
2808 *src_text_ptr == '?' ||
2809 *src_text_ptr == '!')
2810 *dst_text_ptr++ = '\n';
2812 if (*src_text_ptr != ' ')
2813 *dst_text_ptr++ = *src_text_ptr;
2818 *dst_text_ptr = '\0';
2820 text_final = text_door_style;
2823 setRequestPosition(&sx, &sy, FALSE);
2825 ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
2827 for (y = 0; y < y_steps; y++)
2828 for (x = 0; x < x_steps; x++)
2829 DrawEnvelopeBackgroundTiles(graphic, sx, sy,
2830 x, y, x_steps, y_steps,
2831 tile_size, tile_size);
2833 DrawTextBuffer(sx + border_size, sy + border_size, text_final, font_nr,
2834 line_length, -1, max_lines, line_spacing, mask_mode,
2835 request.autowrap, request.centered, FALSE);
2837 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2838 RedrawGadget(tool_gadget[i]);
2840 // store readily prepared envelope request for later use when animating
2841 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2845 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2846 BlitBitmap(bitmap_db_cross, backbuffer, sx, sy, width, height, sx, sy);
2848 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2853 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2855 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2861 if (text_door_style)
2862 free(text_door_style);
2867 void AnimateEnvelopeRequest(int anim_mode, int action)
2869 int graphic = IMG_BACKGROUND_REQUEST;
2870 boolean draw_masked = graphic_info[graphic].draw_masked;
2872 int delay_value_normal = request.step_delay;
2873 int delay_value_fast = delay_value_normal / 2;
2875 int delay_value_normal = GameFrameDelay;
2876 int delay_value_fast = FfwdFrameDelay;
2878 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2879 boolean no_delay = (tape.warp_forward);
2880 int delay_value = (ffwd_delay ? delay_value_fast : delay_value_normal);
2881 int anim_delay_value = (no_delay ? 0 : delay_value + 500 * 0);
2882 unsigned int anim_delay = 0;
2884 int width = request.width;
2885 int height = request.height;
2886 int tile_size = request.step_offset;
2887 int max_xsize = width / tile_size;
2888 int max_ysize = height / tile_size;
2889 int max_xsize_inner = max_xsize - 2;
2890 int max_ysize_inner = max_ysize - 2;
2892 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize_inner : 0);
2893 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize_inner : 0);
2894 int xend = max_xsize_inner;
2895 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize_inner : 0);
2896 int xstep = (xstart < xend ? 1 : 0);
2897 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2900 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2902 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2903 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2904 int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2);
2905 int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2);
2906 int src_x = sx_center - width / 2;
2907 int src_y = sy_center - height / 2;
2908 int dst_x = sx_center - xsize * tile_size / 2;
2909 int dst_y = sy_center - ysize * tile_size / 2;
2910 int xsize_size_left = (xsize - 1) * tile_size;
2911 int ysize_size_top = (ysize - 1) * tile_size;
2912 int max_xsize_pos = (max_xsize - 1) * tile_size;
2913 int max_ysize_pos = (max_ysize - 1) * tile_size;
2916 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2919 for (yy = 0; yy < 2; yy++)
2921 for (xx = 0; xx < 2; xx++)
2923 int src_xx = src_x + xx * max_xsize_pos;
2924 int src_yy = src_y + yy * max_ysize_pos;
2925 int dst_xx = dst_x + xx * xsize_size_left;
2926 int dst_yy = dst_y + yy * ysize_size_top;
2927 int xx_size = (xx ? tile_size : xsize_size_left);
2928 int yy_size = (yy ? tile_size : ysize_size_top);
2931 BlitBitmapMasked(bitmap_db_cross, backbuffer,
2932 src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
2934 BlitBitmap(bitmap_db_cross, backbuffer,
2935 src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
2939 BlitBitmap(bitmap_db_cross, backbuffer,
2941 xsize_size_left, ysize_size_top,
2943 BlitBitmap(bitmap_db_cross, backbuffer,
2944 src_x + max_xsize_pos, src_y,
2945 tile_size, ysize_size_top,
2946 dst_x + xsize_size_left, dst_y);
2947 BlitBitmap(bitmap_db_cross, backbuffer,
2948 src_x, src_y + max_ysize_pos,
2949 xsize_size_left, tile_size,
2950 dst_x, dst_y + ysize_size_top);
2951 BlitBitmap(bitmap_db_cross, backbuffer,
2952 src_x + max_xsize_pos, src_y + max_ysize_pos,
2953 tile_size, tile_size,
2954 dst_x + xsize_size_left, dst_y + ysize_size_top);
2958 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2959 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
2961 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2971 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2977 void AnimateEnvelopeRequest(char *text, int anim_mode, int action)
2980 int envelope_nr = 0;
2983 int graphic = IMG_BACKGROUND_REQUEST;
2985 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2987 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2988 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2989 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2990 boolean no_delay = (tape.warp_forward);
2991 unsigned int anim_delay = 0;
2992 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2993 int anim_delay_value = (no_delay ? 0 : frame_delay_value + 500 * 0);
2995 int max_word_len = maxWordLengthInString(text);
2996 int font_nr = (max_word_len > 7 ? FONT_TEXT_1 : FONT_TEXT_2);
2998 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
3000 int font_width = getFontWidth(font_nr);
3001 int font_height = getFontHeight(font_nr);
3002 int line_spacing = 2 * 1;
3006 int max_xsize = DXSIZE / font_width;
3007 // int max_ysize = DYSIZE / font_height;
3008 int max_ysize = DYSIZE / (font_height + line_spacing);
3010 int max_xsize = 7; /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
3011 int max_ysize = 13; /* tools.c: MAX_REQUEST_LINES == 13 */
3015 int max_xsize = level.envelope[envelope_nr].xsize;
3016 int max_ysize = level.envelope[envelope_nr].ysize;
3018 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
3019 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
3020 int xend = max_xsize;
3021 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
3022 int xstep = (xstart < xend ? 1 : 0);
3023 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
3028 char *text_copy = getStringCopy(text);
3031 font_nr = FONT_TEXT_2;
3033 if (maxWordLengthInString(text) > 7) /* MAX_REQUEST_LINE_FONT1_LEN == 7 */
3035 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
3036 font_nr = FONT_TEXT_1;
3039 int max_word_len = 0;
3041 char *text_copy = getStringCopy(text);
3043 font_nr = FONT_TEXT_2;
3045 for (text_ptr = text; *text_ptr; text_ptr++)
3047 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
3049 if (max_word_len > 7) /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
3051 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
3052 font_nr = FONT_TEXT_1;
3061 for (text_ptr = text_copy; *text_ptr; text_ptr++)
3062 if (*text_ptr == ' ')
3067 dDX = SX + (SXSIZE - DXSIZE) / 2 - DX;
3068 dDY = SY + (SYSIZE - DYSIZE) / 2 - DY;
3070 dDX = SX + SXSIZE / 2 - max_xsize * font_width / 2 - DX;
3071 dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY;
3074 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
3076 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
3077 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
3078 int sx = SX + (SXSIZE - xsize * font_width) / 2;
3079 // int sy = SX + (SYSIZE - ysize * font_height) / 2;
3080 int sy = SY + (SYSIZE - ysize * (font_height + line_spacing)) / 2;
3084 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3086 SetDrawtoField(DRAW_BUFFERED);
3089 BlitScreenToBitmap(backbuffer);
3091 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
3094 SetDrawtoField(DRAW_BACKBUFFER);
3097 for (yy = 0; yy < ysize; yy++)
3098 for (xx = 0; xx < xsize; xx++)
3099 DrawEnvelopeBackgroundTiles(graphic, sx, sy, xx, yy, xsize, ysize,
3100 getFontWidth(font_nr),
3101 getFontHeight(font_nr) + line_spacing);
3106 DrawTextBuffer(sx + font_width, sy + font_height + 8,
3107 text_copy, font_nr, max_xsize,
3108 xsize - 2, ysize - 2, line_spacing, mask_mode,
3109 FALSE, TRUE, FALSE);
3111 DrawTextBuffer(sx + font_width, sy + font_height,
3112 level.envelope[envelope_nr].text, font_nr, max_xsize,
3113 xsize - 2, ysize - 2, 0, mask_mode,
3114 level.envelope[envelope_nr].autowrap,
3115 level.envelope[envelope_nr].centered, FALSE);
3119 DrawTextToTextArea(sx + font_width, sy + font_height,
3120 level.envelope[envelope_nr].text, font_nr, max_xsize,
3121 xsize - 2, ysize - 2, mask_mode);
3124 /* copy request gadgets to door backbuffer */
3127 if ((ysize - 2) > 13)
3128 BlitBitmap(bitmap_db_door, drawto,
3129 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3130 DOOR_GFX_PAGEY1 + 13 * font_height,
3131 (xsize - 2) * font_width,
3132 (ysize - 2 - 13) * font_height,
3134 sy + font_height * (1 + 13));
3136 if ((ysize - 2) > 13)
3137 BlitBitmap(bitmap_db_door, drawto,
3138 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3139 DOOR_GFX_PAGEY1 + 11 * (font_height + line_spacing * 0),
3140 (xsize - 2) * font_width,
3141 (ysize - 2 - 13) * (font_height + line_spacing),
3143 sy + (font_height + line_spacing) * (1 + 13));
3145 if ((ysize - 2) > 13)
3146 BlitBitmap(bitmap_db_door, drawto,
3147 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3148 DOOR_GFX_PAGEY1 + 13 * font_height,
3149 (xsize - 2) * font_width,
3150 (ysize - 2 - 13) * font_height,
3152 sy + font_height * (1 + 13));
3156 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3157 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
3159 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3169 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
3179 void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
3182 int last_game_status = game_status; /* save current game status */
3183 // int last_draw_background_mask = gfx.draw_background_mask;
3186 int graphic = IMG_BACKGROUND_REQUEST;
3187 int sound_opening = SND_REQUEST_OPENING;
3188 int sound_closing = SND_REQUEST_CLOSING;
3190 int envelope_nr = 0;
3191 int element = EL_ENVELOPE_1 + envelope_nr;
3192 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
3193 int sound_opening = element_info[element].sound[ACTION_OPENING];
3194 int sound_closing = element_info[element].sound[ACTION_CLOSING];
3197 boolean ffwd_delay = (tape.playing && tape.fast_forward);
3198 boolean no_delay = (tape.warp_forward);
3199 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
3200 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
3202 int anim_mode = graphic_info[graphic].anim_mode;
3203 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
3204 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
3206 char *text_copy = getStringCopy(text);
3209 for (text_ptr = text_copy; *text_ptr; text_ptr++)
3210 if (*text_ptr == ' ')
3215 if (game_status == GAME_MODE_PLAYING)
3217 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
3218 BlitScreenToBitmap_EM(backbuffer);
3219 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3220 BlitScreenToBitmap_SP(backbuffer);
3223 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
3227 SetDrawtoField(DRAW_BACKBUFFER);
3229 // SetDrawBackgroundMask(REDRAW_NONE);
3231 if (action == ACTION_OPENING)
3233 BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3236 if (req_state & REQ_ASK)
3238 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
3239 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
3241 else if (req_state & REQ_CONFIRM)
3243 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
3245 else if (req_state & REQ_PLAYER)
3247 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
3248 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
3249 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
3250 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
3255 DrawEnvelopeRequest(text);
3257 DrawEnvelopeRequest(text_copy);
3260 if (game_status != GAME_MODE_MAIN)
3264 /* force DOOR font inside door area */
3265 game_status = GAME_MODE_PSEUDO_DOOR;
3268 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
3270 if (action == ACTION_OPENING)
3272 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
3274 if (anim_mode == ANIM_DEFAULT)
3275 AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_OPENING);
3277 AnimateEnvelopeRequest(main_anim_mode, ACTION_OPENING);
3281 Delay(wait_delay_value);
3283 WaitForEventToContinue();
3288 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
3290 if (anim_mode != ANIM_NONE)
3291 AnimateEnvelopeRequest(main_anim_mode, ACTION_CLOSING);
3293 if (anim_mode == ANIM_DEFAULT)
3294 AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_CLOSING);
3297 game.envelope_active = FALSE;
3300 // game_status = last_game_status; /* restore current game status */
3302 if (action == ACTION_CLOSING)
3304 if (game_status != GAME_MODE_MAIN)
3307 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3310 SetDrawtoField(DRAW_BUFFERED);
3313 // SetDrawBackgroundMask(last_draw_background_mask);
3316 redraw_mask = REDRAW_FIELD;
3317 // redraw_mask |= REDRAW_ALL;
3319 redraw_mask |= REDRAW_FIELD;
3323 if (game_status == GAME_MODE_MAIN)
3328 /* (important: after "BackToFront()", but before "SetDrawtoField()") */
3329 game_status = last_game_status; /* restore current game status */
3332 if (action == ACTION_CLOSING &&
3333 game_status == GAME_MODE_PLAYING &&
3334 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3335 SetDrawtoField(DRAW_BUFFERED);
3337 if (game_status == GAME_MODE_PLAYING &&
3338 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3339 SetDrawtoField(DRAW_BUFFERED);
3351 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
3355 int graphic = el2preimg(element);
3357 getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
3358 BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
3366 SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
3367 SetDrawBackgroundMask(REDRAW_FIELD);
3369 SetDrawBackgroundMask(REDRAW_NONE);
3374 for (x = BX1; x <= BX2; x++)
3375 for (y = BY1; y <= BY2; y++)
3376 DrawScreenField(x, y);
3378 redraw_mask |= REDRAW_FIELD;
3381 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
3385 for (x = 0; x < size_x; x++)
3386 for (y = 0; y < size_y; y++)
3387 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
3389 redraw_mask |= REDRAW_FIELD;
3392 static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y)
3394 boolean show_level_border = (BorderElement != EL_EMPTY);
3395 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3396 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3397 int tile_size = preview.tile_size;
3398 int preview_width = preview.xsize * tile_size;
3399 int preview_height = preview.ysize * tile_size;
3400 int real_preview_xsize = MIN(level_xsize, preview.xsize);
3401 int real_preview_ysize = MIN(level_ysize, preview.ysize);
3402 int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
3403 int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
3406 DrawBackground(dst_x, dst_y, preview_width, preview_height);
3408 dst_x += (preview_width - real_preview_xsize * tile_size) / 2;
3409 dst_y += (preview_height - real_preview_ysize * tile_size) / 2;
3411 for (x = 0; x < real_preview_xsize; x++)
3413 for (y = 0; y < real_preview_ysize; y++)
3415 int lx = from_x + x + (show_level_border ? -1 : 0);
3416 int ly = from_y + y + (show_level_border ? -1 : 0);
3417 int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
3418 getBorderElement(lx, ly));
3420 DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size,
3421 element, tile_size);
3425 redraw_mask |= REDRAW_MICROLEVEL;
3428 #define MICROLABEL_EMPTY 0
3429 #define MICROLABEL_LEVEL_NAME 1
3430 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
3431 #define MICROLABEL_LEVEL_AUTHOR 3
3432 #define MICROLABEL_IMPORTED_FROM_HEAD 4
3433 #define MICROLABEL_IMPORTED_FROM 5
3434 #define MICROLABEL_IMPORTED_BY_HEAD 6
3435 #define MICROLABEL_IMPORTED_BY 7
3437 static int getMaxTextLength(struct TextPosInfo *pos, int font_nr)
3439 int max_text_width = SXSIZE;
3440 int font_width = getFontWidth(font_nr);
3442 if (pos->align == ALIGN_CENTER)
3443 max_text_width = (pos->x < SXSIZE / 2 ? pos->x * 2 : (SXSIZE - pos->x) * 2);
3444 else if (pos->align == ALIGN_RIGHT)
3445 max_text_width = pos->x;
3447 max_text_width = SXSIZE - pos->x;
3449 return max_text_width / font_width;
3452 static void DrawPreviewLevelLabelExt(int mode)
3454 struct TextPosInfo *pos = &menu.main.text.level_info_2;
3455 char label_text[MAX_OUTPUT_LINESIZE + 1];
3456 int max_len_label_text;
3458 int font_nr = pos->font;
3461 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3462 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3463 mode == MICROLABEL_IMPORTED_BY_HEAD)
3464 font_nr = pos->font_alt;
3466 int font_nr = FONT_TEXT_2;
3469 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3470 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3471 mode == MICROLABEL_IMPORTED_BY_HEAD)
3472 font_nr = FONT_TEXT_3;
3476 max_len_label_text = getMaxTextLength(pos, font_nr);
3478 max_len_label_text = SXSIZE / getFontWidth(font_nr);
3482 if (pos->size != -1)
3483 max_len_label_text = pos->size;
3486 for (i = 0; i < max_len_label_text; i++)
3487 label_text[i] = ' ';
3488 label_text[max_len_label_text] = '\0';
3490 if (strlen(label_text) > 0)
3493 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3495 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3496 int lypos = MICROLABEL2_YPOS;
3498 DrawText(lxpos, lypos, label_text, font_nr);
3503 (mode == MICROLABEL_LEVEL_NAME ? level.name :
3504 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
3505 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
3506 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
3507 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
3508 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
3509 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
3510 max_len_label_text);
3511 label_text[max_len_label_text] = '\0';
3513 if (strlen(label_text) > 0)
3516 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3518 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3519 int lypos = MICROLABEL2_YPOS;
3521 DrawText(lxpos, lypos, label_text, font_nr);
3525 redraw_mask |= REDRAW_MICROLEVEL;
3528 static void DrawPreviewLevelExt(boolean restart)
3530 static unsigned int scroll_delay = 0;
3531 static unsigned int label_delay = 0;
3532 static int from_x, from_y, scroll_direction;
3533 static int label_state, label_counter;
3534 unsigned int scroll_delay_value = preview.step_delay;
3535 boolean show_level_border = (BorderElement != EL_EMPTY);
3536 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3537 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3538 int last_game_status = game_status; /* save current game status */
3541 /* force PREVIEW font on preview level */
3542 game_status = GAME_MODE_PSEUDO_PREVIEW;
3550 if (preview.anim_mode == ANIM_CENTERED)
3552 if (level_xsize > preview.xsize)
3553 from_x = (level_xsize - preview.xsize) / 2;
3554 if (level_ysize > preview.ysize)
3555 from_y = (level_ysize - preview.ysize) / 2;
3558 from_x += preview.xoffset;
3559 from_y += preview.yoffset;
3561 scroll_direction = MV_RIGHT;
3565 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3566 DrawPreviewLevelLabelExt(label_state);
3568 /* initialize delay counters */
3569 DelayReached(&scroll_delay, 0);
3570 DelayReached(&label_delay, 0);
3572 if (leveldir_current->name)
3574 struct TextPosInfo *pos = &menu.main.text.level_info_1;
3575 char label_text[MAX_OUTPUT_LINESIZE + 1];
3577 int font_nr = pos->font;
3579 int font_nr = FONT_TEXT_1;
3582 int max_len_label_text = getMaxTextLength(pos, font_nr);
3584 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
3592 if (pos->size != -1)
3593 max_len_label_text = pos->size;
3596 strncpy(label_text, leveldir_current->name, max_len_label_text);
3597 label_text[max_len_label_text] = '\0';
3600 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3602 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3603 lypos = SY + MICROLABEL1_YPOS;
3605 DrawText(lxpos, lypos, label_text, font_nr);
3609 game_status = last_game_status; /* restore current game status */
3614 /* scroll preview level, if needed */
3615 if (preview.anim_mode != ANIM_NONE &&
3616 (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
3617 DelayReached(&scroll_delay, scroll_delay_value))
3619 switch (scroll_direction)
3624 from_x -= preview.step_offset;
3625 from_x = (from_x < 0 ? 0 : from_x);
3628 scroll_direction = MV_UP;
3632 if (from_x < level_xsize - preview.xsize)
3634 from_x += preview.step_offset;
3635 from_x = (from_x > level_xsize - preview.xsize ?
3636 level_xsize - preview.xsize : from_x);
3639 scroll_direction = MV_DOWN;
3645 from_y -= preview.step_offset;
3646 from_y = (from_y < 0 ? 0 : from_y);
3649 scroll_direction = MV_RIGHT;
3653 if (from_y < level_ysize - preview.ysize)
3655 from_y += preview.step_offset;
3656 from_y = (from_y > level_ysize - preview.ysize ?
3657 level_ysize - preview.ysize : from_y);
3660 scroll_direction = MV_LEFT;
3667 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3670 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
3671 /* redraw micro level label, if needed */
3672 if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
3673 !strEqual(level.author, ANONYMOUS_NAME) &&
3674 !strEqual(level.author, leveldir_current->name) &&
3675 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
3677 int max_label_counter = 23;
3679 if (leveldir_current->imported_from != NULL &&
3680 strlen(leveldir_current->imported_from) > 0)
3681 max_label_counter += 14;
3682 if (leveldir_current->imported_by != NULL &&
3683 strlen(leveldir_current->imported_by) > 0)
3684 max_label_counter += 14;
3686 label_counter = (label_counter + 1) % max_label_counter;
3687 label_state = (label_counter >= 0 && label_counter <= 7 ?
3688 MICROLABEL_LEVEL_NAME :
3689 label_counter >= 9 && label_counter <= 12 ?
3690 MICROLABEL_LEVEL_AUTHOR_HEAD :
3691 label_counter >= 14 && label_counter <= 21 ?
3692 MICROLABEL_LEVEL_AUTHOR :
3693 label_counter >= 23 && label_counter <= 26 ?
3694 MICROLABEL_IMPORTED_FROM_HEAD :
3695 label_counter >= 28 && label_counter <= 35 ?
3696 MICROLABEL_IMPORTED_FROM :
3697 label_counter >= 37 && label_counter <= 40 ?
3698 MICROLABEL_IMPORTED_BY_HEAD :
3699 label_counter >= 42 && label_counter <= 49 ?
3700 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
3702 if (leveldir_current->imported_from == NULL &&
3703 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
3704 label_state == MICROLABEL_IMPORTED_FROM))
3705 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
3706 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
3708 DrawPreviewLevelLabelExt(label_state);
3711 game_status = last_game_status; /* restore current game status */
3714 void DrawPreviewLevelInitial()
3716 DrawPreviewLevelExt(TRUE);
3719 void DrawPreviewLevelAnimation()
3721 DrawPreviewLevelExt(FALSE);
3724 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3725 int graphic, int sync_frame, int mask_mode)
3727 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3729 if (mask_mode == USE_MASKING)
3730 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3732 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
3735 inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3736 int graphic, int sync_frame,
3739 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3741 if (mask_mode == USE_MASKING)
3742 DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3744 DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
3747 inline void DrawGraphicAnimation(int x, int y, int graphic)
3749 int lx = LEVELX(x), ly = LEVELY(y);
3751 if (!IN_SCR_FIELD(x, y))
3755 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
3756 graphic, GfxFrame[lx][ly], NO_MASKING);
3758 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3759 graphic, GfxFrame[lx][ly], NO_MASKING);
3761 MarkTileDirty(x, y);
3764 inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
3766 int lx = LEVELX(x), ly = LEVELY(y);
3768 if (!IN_SCR_FIELD(x, y))
3771 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3772 graphic, GfxFrame[lx][ly], NO_MASKING);
3773 MarkTileDirty(x, y);
3776 void DrawLevelGraphicAnimation(int x, int y, int graphic)
3778 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3781 void DrawLevelElementAnimation(int x, int y, int element)
3783 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3785 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3788 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
3790 int sx = SCREENX(x), sy = SCREENY(y);
3792 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3795 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3798 DrawGraphicAnimation(sx, sy, graphic);
3801 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
3802 DrawLevelFieldCrumbled(x, y);
3804 if (GFX_CRUMBLED(Feld[x][y]))
3805 DrawLevelFieldCrumbled(x, y);
3809 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
3811 int sx = SCREENX(x), sy = SCREENY(y);
3814 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3817 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3819 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3822 DrawGraphicAnimation(sx, sy, graphic);
3824 if (GFX_CRUMBLED(element))
3825 DrawLevelFieldCrumbled(x, y);
3828 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
3830 if (player->use_murphy)
3832 /* this works only because currently only one player can be "murphy" ... */
3833 static int last_horizontal_dir = MV_LEFT;
3834 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
3836 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3837 last_horizontal_dir = move_dir;
3839 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
3841 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
3843 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
3849 return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
3852 static boolean equalGraphics(int graphic1, int graphic2)
3854 struct GraphicInfo *g1 = &graphic_info[graphic1];
3855 struct GraphicInfo *g2 = &graphic_info[graphic2];
3857 return (g1->bitmap == g2->bitmap &&
3858 g1->src_x == g2->src_x &&
3859 g1->src_y == g2->src_y &&
3860 g1->anim_frames == g2->anim_frames &&
3861 g1->anim_delay == g2->anim_delay &&
3862 g1->anim_mode == g2->anim_mode);
3865 void DrawAllPlayers()
3869 for (i = 0; i < MAX_PLAYERS; i++)
3870 if (stored_player[i].active)
3871 DrawPlayer(&stored_player[i]);
3874 void DrawPlayerField(int x, int y)
3876 if (!IS_PLAYER(x, y))
3879 DrawPlayer(PLAYERINFO(x, y));
3882 #define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
3884 void DrawPlayer(struct PlayerInfo *player)
3886 int jx = player->jx;
3887 int jy = player->jy;
3888 int move_dir = player->MovDir;
3889 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
3890 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
3891 int last_jx = (player->is_moving ? jx - dx : jx);
3892 int last_jy = (player->is_moving ? jy - dy : jy);
3893 int next_jx = jx + dx;
3894 int next_jy = jy + dy;
3895 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
3896 boolean player_is_opaque = FALSE;
3897 int sx = SCREENX(jx), sy = SCREENY(jy);
3898 int sxx = 0, syy = 0;
3899 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
3901 int action = ACTION_DEFAULT;
3902 int last_player_graphic = getPlayerGraphic(player, move_dir);
3903 int last_player_frame = player->Frame;
3906 /* GfxElement[][] is set to the element the player is digging or collecting;
3907 remove also for off-screen player if the player is not moving anymore */
3908 if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
3909 GfxElement[jx][jy] = EL_UNDEFINED;
3911 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
3915 if (!IN_LEV_FIELD(jx, jy))
3917 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
3918 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
3919 printf("DrawPlayerField(): This should never happen!\n");
3924 if (element == EL_EXPLOSION)
3927 action = (player->is_pushing ? ACTION_PUSHING :
3928 player->is_digging ? ACTION_DIGGING :
3929 player->is_collecting ? ACTION_COLLECTING :
3930 player->is_moving ? ACTION_MOVING :
3931 player->is_snapping ? ACTION_SNAPPING :
3932 player->is_dropping ? ACTION_DROPPING :
3933 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
3935 if (player->is_waiting)
3936 move_dir = player->dir_waiting;
3938 InitPlayerGfxAnimation(player, action, move_dir);
3940 /* ----------------------------------------------------------------------- */
3941 /* draw things in the field the player is leaving, if needed */
3942 /* ----------------------------------------------------------------------- */
3944 if (player->is_moving)
3946 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
3948 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
3950 if (last_element == EL_DYNAMITE_ACTIVE ||
3951 last_element == EL_EM_DYNAMITE_ACTIVE ||
3952 last_element == EL_SP_DISK_RED_ACTIVE)
3953 DrawDynamite(last_jx, last_jy);
3955 DrawLevelFieldThruMask(last_jx, last_jy);
3957 else if (last_element == EL_DYNAMITE_ACTIVE ||
3958 last_element == EL_EM_DYNAMITE_ACTIVE ||
3959 last_element == EL_SP_DISK_RED_ACTIVE)
3960 DrawDynamite(last_jx, last_jy);
3962 /* !!! this is not enough to prevent flickering of players which are
3963 moving next to each others without a free tile between them -- this
3964 can only be solved by drawing all players layer by layer (first the
3965 background, then the foreground etc.) !!! => TODO */
3966 else if (!IS_PLAYER(last_jx, last_jy))
3967 DrawLevelField(last_jx, last_jy);
3970 DrawLevelField(last_jx, last_jy);
3973 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
3974 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
3977 if (!IN_SCR_FIELD(sx, sy))
3980 /* ----------------------------------------------------------------------- */
3981 /* draw things behind the player, if needed */
3982 /* ----------------------------------------------------------------------- */
3985 DrawLevelElement(jx, jy, Back[jx][jy]);
3986 else if (IS_ACTIVE_BOMB(element))
3987 DrawLevelElement(jx, jy, EL_EMPTY);
3990 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
3992 int old_element = GfxElement[jx][jy];
3993 int old_graphic = el_act_dir2img(old_element, action, move_dir);
3994 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
3996 if (GFX_CRUMBLED(old_element))
3997 DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
3999 DrawGraphic(sx, sy, old_graphic, frame);
4001 if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
4002 player_is_opaque = TRUE;
4006 GfxElement[jx][jy] = EL_UNDEFINED;
4008 /* make sure that pushed elements are drawn with correct frame rate */
4010 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4012 if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
4013 GfxFrame[jx][jy] = player->StepFrame;
4015 if (player->is_pushing && player->is_moving)
4016 GfxFrame[jx][jy] = player->StepFrame;
4019 DrawLevelField(jx, jy);
4023 #if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
4024 /* ----------------------------------------------------------------------- */
4025 /* draw player himself */
4026 /* ----------------------------------------------------------------------- */
4028 graphic = getPlayerGraphic(player, move_dir);
4030 /* in the case of changed player action or direction, prevent the current
4031 animation frame from being restarted for identical animations */
4032 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4033 player->Frame = last_player_frame;
4035 frame = getGraphicAnimationFrame(graphic, player->Frame);
4039 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4040 sxx = player->GfxPos;
4042 syy = player->GfxPos;
4045 if (!setup.soft_scrolling && ScreenMovPos)
4048 if (player_is_opaque)
4049 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4051 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4053 if (SHIELD_ON(player))
4055 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4056 IMG_SHIELD_NORMAL_ACTIVE);
4057 int frame = getGraphicAnimationFrame(graphic, -1);
4059 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4063 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4066 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4067 sxx = player->GfxPos;
4069 syy = player->GfxPos;
4073 /* ----------------------------------------------------------------------- */
4074 /* draw things the player is pushing, if needed */
4075 /* ----------------------------------------------------------------------- */
4078 printf("::: %d, %d [%d, %d] [%d]\n",
4079 player->is_pushing, player_is_moving, player->GfxAction,
4080 player->is_moving, player_is_moving);
4084 if (player->is_pushing && player->is_moving)
4086 int px = SCREENX(jx), py = SCREENY(jy);
4087 int pxx = (TILEX - ABS(sxx)) * dx;
4088 int pyy = (TILEY - ABS(syy)) * dy;
4089 int gfx_frame = GfxFrame[jx][jy];
4095 if (!IS_MOVING(jx, jy)) /* push movement already finished */
4097 element = Feld[next_jx][next_jy];
4098 gfx_frame = GfxFrame[next_jx][next_jy];
4101 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4104 sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
4105 frame = getGraphicAnimationFrame(graphic, sync_frame);
4107 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
4110 /* draw background element under pushed element (like the Sokoban field) */
4112 if (game.use_masked_pushing && IS_MOVING(jx, jy))
4114 /* this allows transparent pushing animation over non-black background */
4117 DrawLevelElement(jx, jy, Back[jx][jy]);
4119 DrawLevelElement(jx, jy, EL_EMPTY);
4121 if (Back[next_jx][next_jy])
4122 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4124 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4126 else if (Back[next_jx][next_jy])
4127 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4129 if (Back[next_jx][next_jy])
4130 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4134 printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
4135 jx, px, player->GfxPos, player->StepFrame,
4140 GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
4144 /* do not draw (EM style) pushing animation when pushing is finished */
4145 /* (two-tile animations usually do not contain start and end frame) */
4146 if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
4147 DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
4149 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4151 /* masked drawing is needed for EMC style (double) movement graphics */
4152 /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
4153 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4158 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4159 /* ----------------------------------------------------------------------- */
4160 /* draw player himself */
4161 /* ----------------------------------------------------------------------- */
4163 graphic = getPlayerGraphic(player, move_dir);
4165 /* in the case of changed player action or direction, prevent the current
4166 animation frame from being restarted for identical animations */
4167 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4168 player->Frame = last_player_frame;
4170 frame = getGraphicAnimationFrame(graphic, player->Frame);
4174 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4175 sxx = player->GfxPos;
4177 syy = player->GfxPos;
4180 if (!setup.soft_scrolling && ScreenMovPos)
4183 if (player_is_opaque)
4184 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4186 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4188 if (SHIELD_ON(player))
4190 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4191 IMG_SHIELD_NORMAL_ACTIVE);
4192 int frame = getGraphicAnimationFrame(graphic, -1);
4194 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4198 /* ----------------------------------------------------------------------- */
4199 /* draw things in front of player (active dynamite or dynabombs) */
4200 /* ----------------------------------------------------------------------- */
4202 if (IS_ACTIVE_BOMB(element))
4204 graphic = el2img(element);
4205 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
4207 if (game.emulation == EMU_SUPAPLEX)
4208 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
4210 DrawGraphicThruMask(sx, sy, graphic, frame);
4213 if (player_is_moving && last_element == EL_EXPLOSION)
4215 int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
4216 GfxElement[last_jx][last_jy] : EL_EMPTY);
4217 int graphic = el_act2img(element, ACTION_EXPLODING);
4218 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
4219 int phase = ExplodePhase[last_jx][last_jy] - 1;
4220 int frame = getGraphicAnimationFrame(graphic, phase - delay);
4223 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
4226 /* ----------------------------------------------------------------------- */
4227 /* draw elements the player is just walking/passing through/under */
4228 /* ----------------------------------------------------------------------- */
4230 if (player_is_moving)
4232 /* handle the field the player is leaving ... */
4233 if (IS_ACCESSIBLE_INSIDE(last_element))
4234 DrawLevelField(last_jx, last_jy);
4235 else if (IS_ACCESSIBLE_UNDER(last_element))
4236 DrawLevelFieldThruMask(last_jx, last_jy);
4239 /* do not redraw accessible elements if the player is just pushing them */
4240 if (!player_is_moving || !player->is_pushing)
4242 /* ... and the field the player is entering */
4243 if (IS_ACCESSIBLE_INSIDE(element))
4244 DrawLevelField(jx, jy);
4245 else if (IS_ACCESSIBLE_UNDER(element))
4246 DrawLevelFieldThruMask(jx, jy);
4249 MarkTileDirty(sx, sy);
4252 /* ------------------------------------------------------------------------- */
4254 void WaitForEventToContinue()
4256 boolean still_wait = TRUE;
4258 /* simulate releasing mouse button over last gadget, if still pressed */
4260 HandleGadgets(-1, -1, 0);
4262 button_status = MB_RELEASED;
4278 case EVENT_BUTTONPRESS:
4279 case EVENT_KEYPRESS:
4283 case EVENT_KEYRELEASE:
4284 ClearPlayerAction();
4288 HandleOtherEvents(&event);
4292 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4299 /* don't eat all CPU time */
4304 #define MAX_REQUEST_LINES 13
4305 #define MAX_REQUEST_LINE_FONT1_LEN 7
4306 #define MAX_REQUEST_LINE_FONT2_LEN 10
4310 static int RequestHandleEvents(unsigned int req_state)
4312 int last_game_status = game_status; /* save current game status */
4316 button_status = MB_RELEASED;
4318 request_gadget_id = -1;
4331 case EVENT_BUTTONPRESS:
4332 case EVENT_BUTTONRELEASE:
4333 case EVENT_MOTIONNOTIFY:
4335 if (event.type == EVENT_MOTIONNOTIFY)
4337 if (!PointerInWindow(window))
4338 continue; /* window and pointer are on different screens */
4343 motion_status = TRUE;
4344 mx = ((MotionEvent *) &event)->x;
4345 my = ((MotionEvent *) &event)->y;
4349 motion_status = FALSE;
4350 mx = ((ButtonEvent *) &event)->x;
4351 my = ((ButtonEvent *) &event)->y;
4352 if (event.type == EVENT_BUTTONPRESS)
4353 button_status = ((ButtonEvent *) &event)->button;
4355 button_status = MB_RELEASED;
4358 /* this sets 'request_gadget_id' */
4359 HandleGadgets(mx, my, button_status);
4361 switch (request_gadget_id)
4363 case TOOL_CTRL_ID_YES:
4366 case TOOL_CTRL_ID_NO:
4369 case TOOL_CTRL_ID_CONFIRM:
4370 result = TRUE | FALSE;
4373 case TOOL_CTRL_ID_PLAYER_1:
4376 case TOOL_CTRL_ID_PLAYER_2:
4379 case TOOL_CTRL_ID_PLAYER_3:
4382 case TOOL_CTRL_ID_PLAYER_4:
4393 case EVENT_KEYPRESS:
4394 switch (GetEventKey((KeyEvent *)&event, TRUE))
4397 if (req_state & REQ_CONFIRM)
4406 #if defined(TARGET_SDL2)
4416 if (req_state & REQ_PLAYER)
4420 case EVENT_KEYRELEASE:
4421 ClearPlayerAction();
4425 HandleOtherEvents(&event);
4429 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4431 int joy = AnyJoystick();
4433 if (joy & JOY_BUTTON_1)
4435 else if (joy & JOY_BUTTON_2)
4441 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
4443 HandleGameActions();
4449 if (!PendingEvent()) /* delay only if no pending events */
4454 game_status = GAME_MODE_PSEUDO_DOOR;
4460 game_status = last_game_status; /* restore current game status */
4468 if (!PendingEvent()) /* delay only if no pending events */
4471 /* don't eat all CPU time */
4481 static boolean RequestDoor(char *text, unsigned int req_state)
4483 unsigned int old_door_state;
4484 int last_game_status = game_status; /* save current game status */
4485 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4486 int font_nr = FONT_TEXT_2;
4491 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4493 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4494 font_nr = FONT_TEXT_1;
4497 if (game_status == GAME_MODE_PLAYING)
4499 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4500 BlitScreenToBitmap_EM(backbuffer);
4501 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4502 BlitScreenToBitmap_SP(backbuffer);
4505 /* disable deactivated drawing when quick-loading level tape recording */
4506 if (tape.playing && tape.deactivate_display)
4507 TapeDeactivateDisplayOff(TRUE);
4509 SetMouseCursor(CURSOR_DEFAULT);
4511 #if defined(NETWORK_AVALIABLE)
4512 /* pause network game while waiting for request to answer */
4513 if (options.network &&
4514 game_status == GAME_MODE_PLAYING &&
4515 req_state & REQUEST_WAIT_FOR_INPUT)
4516 SendToServer_PausePlaying();
4519 old_door_state = GetDoorState();
4521 /* simulate releasing mouse button over last gadget, if still pressed */
4523 HandleGadgets(-1, -1, 0);
4527 /* draw released gadget before proceeding */
4530 if (old_door_state & DOOR_OPEN_1)
4532 CloseDoor(DOOR_CLOSE_1);
4534 /* save old door content */
4535 BlitBitmap(bitmap_db_door, bitmap_db_door,
4536 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4537 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
4540 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4541 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4543 /* clear door drawing field */
4544 DrawBackground(DX, DY, DXSIZE, DYSIZE);
4546 /* force DOOR font inside door area */
4547 game_status = GAME_MODE_PSEUDO_DOOR;
4549 /* write text for request */
4550 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
4552 char text_line[max_request_line_len + 1];
4558 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
4560 tc = *(text_ptr + tx);
4561 // if (!tc || tc == ' ')
4562 if (!tc || tc == ' ' || tc == '?' || tc == '!')
4566 if ((tc == '?' || tc == '!') && tl == 0)
4576 strncpy(text_line, text_ptr, tl);
4579 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
4580 DY + 8 + ty * (getFontHeight(font_nr) + 2),
4581 text_line, font_nr);
4583 text_ptr += tl + (tc == ' ' ? 1 : 0);
4584 // text_ptr += tl + (tc == ' ' || tc == '?' || tc == '!' ? 1 : 0);
4587 game_status = last_game_status; /* restore current game status */
4589 if (req_state & REQ_ASK)
4591 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4592 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4594 else if (req_state & REQ_CONFIRM)
4596 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4598 else if (req_state & REQ_PLAYER)
4600 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4601 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4602 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4603 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4606 /* copy request gadgets to door backbuffer */
4607 BlitBitmap(drawto, bitmap_db_door,
4608 DX, DY, DXSIZE, DYSIZE,
4609 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4611 OpenDoor(DOOR_OPEN_1);
4613 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4615 if (game_status == GAME_MODE_PLAYING)
4617 SetPanelBackground();
4618 SetDrawBackgroundMask(REDRAW_DOOR_1);
4622 SetDrawBackgroundMask(REDRAW_FIELD);
4628 if (game_status != GAME_MODE_MAIN)
4631 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4633 // ---------- handle request buttons ----------
4634 result = RequestHandleEvents(req_state);
4636 if (game_status != GAME_MODE_MAIN)
4641 if (!(req_state & REQ_STAY_OPEN))
4643 CloseDoor(DOOR_CLOSE_1);
4645 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
4646 (req_state & REQ_REOPEN))
4647 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
4652 if (game_status == GAME_MODE_PLAYING)
4654 SetPanelBackground();
4655 SetDrawBackgroundMask(REDRAW_DOOR_1);
4659 SetDrawBackgroundMask(REDRAW_FIELD);
4662 #if defined(NETWORK_AVALIABLE)
4663 /* continue network game after request */
4664 if (options.network &&
4665 game_status == GAME_MODE_PLAYING &&
4666 req_state & REQUEST_WAIT_FOR_INPUT)
4667 SendToServer_ContinuePlaying();
4670 /* restore deactivated drawing when quick-loading level tape recording */
4671 if (tape.playing && tape.deactivate_display)
4672 TapeDeactivateDisplayOn();
4677 static boolean RequestEnvelope(char *text, unsigned int req_state)
4684 if (game_status == GAME_MODE_PLAYING)
4686 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4687 BlitScreenToBitmap_EM(backbuffer);
4688 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4689 BlitScreenToBitmap_SP(backbuffer);
4692 /* disable deactivated drawing when quick-loading level tape recording */
4693 if (tape.playing && tape.deactivate_display)
4694 TapeDeactivateDisplayOff(TRUE);
4696 SetMouseCursor(CURSOR_DEFAULT);
4698 #if defined(NETWORK_AVALIABLE)
4699 /* pause network game while waiting for request to answer */
4700 if (options.network &&
4701 game_status == GAME_MODE_PLAYING &&
4702 req_state & REQUEST_WAIT_FOR_INPUT)
4703 SendToServer_PausePlaying();
4706 /* simulate releasing mouse button over last gadget, if still pressed */
4708 HandleGadgets(-1, -1, 0);
4712 // (replace with setting corresponding request background)
4713 // SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4714 // SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4716 /* clear door drawing field */
4717 // DrawBackground(DX, DY, DXSIZE, DYSIZE);
4720 if (global.use_envelope_request)
4724 CreateToolButtons();
4730 if (req_state & REQ_ASK)
4732 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_YES], FALSE);
4733 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_NO], FALSE);
4735 else if (req_state & REQ_CONFIRM)
4737 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_CONFIRM], FALSE);
4739 else if (req_state & REQ_PLAYER)
4741 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_1], FALSE);
4742 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_2], FALSE);
4743 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_3], FALSE);
4744 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_4], FALSE);
4747 if (req_state & REQ_ASK)
4749 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4750 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4752 else if (req_state & REQ_CONFIRM)
4754 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4756 else if (req_state & REQ_PLAYER)
4758 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4759 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4760 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4761 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4766 ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
4769 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4771 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
4772 i == TOOL_CTRL_ID_NO)) ||
4773 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
4774 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
4775 i == TOOL_CTRL_ID_PLAYER_2 &&
4776 i == TOOL_CTRL_ID_PLAYER_3 &&
4777 i == TOOL_CTRL_ID_PLAYER_4)))
4779 int x = tool_gadget[i]->x + dDX;
4780 int y = tool_gadget[i]->y + dDY;
4782 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
4787 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4789 if (game_status == GAME_MODE_PLAYING)
4791 SetPanelBackground();
4792 SetDrawBackgroundMask(REDRAW_DOOR_1);
4796 SetDrawBackgroundMask(REDRAW_FIELD);
4803 if (game_status != GAME_MODE_MAIN)
4807 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4809 // ---------- handle request buttons ----------
4810 result = RequestHandleEvents(req_state);
4812 if (game_status != GAME_MODE_MAIN)
4817 ShowEnvelopeRequest(text, req_state, ACTION_CLOSING);
4821 if (game_status == GAME_MODE_PLAYING)
4823 SetPanelBackground();
4824 SetDrawBackgroundMask(REDRAW_DOOR_1);
4828 SetDrawBackgroundMask(REDRAW_FIELD);
4831 #if defined(NETWORK_AVALIABLE)
4832 /* continue network game after request */
4833 if (options.network &&
4834 game_status == GAME_MODE_PLAYING &&
4835 req_state & REQUEST_WAIT_FOR_INPUT)
4836 SendToServer_ContinuePlaying();
4839 /* restore deactivated drawing when quick-loading level tape recording */
4840 if (tape.playing && tape.deactivate_display)
4841 TapeDeactivateDisplayOn();
4846 boolean Request(char *text, unsigned int req_state)
4848 if (global.use_envelope_request)
4849 return RequestEnvelope(text, req_state);
4851 return RequestDoor(text, req_state);
4854 #else // =====================================================================
4856 boolean Request(char *text, unsigned int req_state)
4858 int mx, my, ty, result = -1;
4859 unsigned int old_door_state;
4860 int last_game_status = game_status; /* save current game status */
4861 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4862 int font_nr = FONT_TEXT_2;
4864 int max_word_len = 0;
4870 global.use_envelope_request = 1;
4874 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4876 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4877 font_nr = FONT_TEXT_1;
4880 for (text_ptr = text; *text_ptr; text_ptr++)
4882 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
4884 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
4886 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4888 font_nr = FONT_TEXT_1;
4890 font_nr = FONT_LEVEL_NUMBER;
4898 if (game_status == GAME_MODE_PLAYING)
4900 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4901 BlitScreenToBitmap_EM(backbuffer);
4902 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4903 BlitScreenToBitmap_SP(backbuffer);
4906 /* disable deactivated drawing when quick-loading level tape recording */
4907 if (tape.playing && tape.deactivate_display)
4908 TapeDeactivateDisplayOff(TRUE);
4910 SetMouseCursor(CURSOR_DEFAULT);
4912 #if defined(NETWORK_AVALIABLE)
4913 /* pause network game while waiting for request to answer */
4914 if (options.network &&
4915 game_status == GAME_MODE_PLAYING &&
4916 req_state & REQUEST_WAIT_FOR_INPUT)
4917 SendToServer_PausePlaying();
4920 old_door_state = GetDoorState();
4922 /* simulate releasing mouse button over last gadget, if still pressed */
4924 HandleGadgets(-1, -1, 0);
4928 /* draw released gadget before proceeding */
4932 if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request)
4934 if (old_door_state & DOOR_OPEN_1)
4938 if (!global.use_envelope_request)
4939 CloseDoor(DOOR_CLOSE_1);
4941 CloseDoor(DOOR_CLOSE_1);
4944 /* save old door content */
4945 BlitBitmap(bitmap_db_door, bitmap_db_door,
4946 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4947 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
4951 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4954 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4956 /* clear door drawing field */
4957 DrawBackground(DX, DY, DXSIZE, DYSIZE);
4959 /* force DOOR font inside door area */
4960 game_status = GAME_MODE_PSEUDO_DOOR;
4962 /* write text for request */
4963 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
4965 char text_line[max_request_line_len + 1];
4971 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
4973 tc = *(text_ptr + tx);
4974 if (!tc || tc == ' ')
4985 strncpy(text_line, text_ptr, tl);
4988 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
4989 DY + 8 + ty * (getFontHeight(font_nr) + 2),
4990 text_line, font_nr);
4992 text_ptr += tl + (tc == ' ' ? 1 : 0);
4995 game_status = last_game_status; /* restore current game status */
4998 if (global.use_envelope_request)
5002 CreateToolButtons();
5006 if (req_state & REQ_ASK)
5008 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
5009 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
5011 else if (req_state & REQ_CONFIRM)
5013 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
5015 else if (req_state & REQ_PLAYER)
5017 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
5018 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
5019 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
5020 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
5023 /* copy request gadgets to door backbuffer */
5024 BlitBitmap(drawto, bitmap_db_door,
5025 DX, DY, DXSIZE, DYSIZE,
5026 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5029 if (global.use_envelope_request)
5031 ShowEnvelopeRequest(text, ACTION_OPENING);
5033 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
5035 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
5036 i == TOOL_CTRL_ID_NO)) ||
5037 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
5038 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
5039 i == TOOL_CTRL_ID_PLAYER_2 &&
5040 i == TOOL_CTRL_ID_PLAYER_3 &&
5041 i == TOOL_CTRL_ID_PLAYER_4)))
5043 int x = tool_gadget[i]->x + dDX;
5044 int y = tool_gadget[i]->y + dDY;
5046 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
5053 if (!global.use_envelope_request)
5054 OpenDoor(DOOR_OPEN_1);
5056 OpenDoor(DOOR_OPEN_1);
5059 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
5061 if (game_status == GAME_MODE_PLAYING)
5063 SetPanelBackground();
5064 SetDrawBackgroundMask(REDRAW_DOOR_1);
5068 SetDrawBackgroundMask(REDRAW_FIELD);
5075 if (game_status != GAME_MODE_MAIN && !global.use_envelope_request)
5078 if (game_status != GAME_MODE_MAIN)
5082 button_status = MB_RELEASED;
5084 request_gadget_id = -1;
5086 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
5098 case EVENT_BUTTONPRESS:
5099 case EVENT_BUTTONRELEASE:
5100 case EVENT_MOTIONNOTIFY:
5102 if (event.type == EVENT_MOTIONNOTIFY)
5104 if (!PointerInWindow(window))
5105 continue; /* window and pointer are on different screens */
5110 motion_status = TRUE;
5111 mx = ((MotionEvent *) &event)->x;
5112 my = ((MotionEvent *) &event)->y;
5116 motion_status = FALSE;
5117 mx = ((ButtonEvent *) &event)->x;
5118 my = ((ButtonEvent *) &event)->y;
5119 if (event.type == EVENT_BUTTONPRESS)
5120 button_status = ((ButtonEvent *) &event)->button;
5122 button_status = MB_RELEASED;
5125 /* this sets 'request_gadget_id' */
5126 HandleGadgets(mx, my, button_status);
5128 switch (request_gadget_id)
5130 case TOOL_CTRL_ID_YES:
5133 case TOOL_CTRL_ID_NO:
5136 case TOOL_CTRL_ID_CONFIRM:
5137 result = TRUE | FALSE;
5140 case TOOL_CTRL_ID_PLAYER_1:
5143 case TOOL_CTRL_ID_PLAYER_2:
5146 case TOOL_CTRL_ID_PLAYER_3:
5149 case TOOL_CTRL_ID_PLAYER_4:
5160 case EVENT_KEYPRESS:
5161 switch (GetEventKey((KeyEvent *)&event, TRUE))
5164 if (req_state & REQ_CONFIRM)
5173 #if defined(TARGET_SDL2)
5183 if (req_state & REQ_PLAYER)
5187 case EVENT_KEYRELEASE:
5188 ClearPlayerAction();
5192 HandleOtherEvents(&event);
5196 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
5198 int joy = AnyJoystick();
5200 if (joy & JOY_BUTTON_1)
5202 else if (joy & JOY_BUTTON_2)
5208 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
5210 HandleGameActions();
5216 if (!PendingEvent()) /* delay only if no pending events */
5221 game_status = GAME_MODE_PSEUDO_DOOR;
5227 game_status = last_game_status; /* restore current game status */
5235 if (!PendingEvent()) /* delay only if no pending events */
5238 /* don't eat all CPU time */
5245 if (game_status != GAME_MODE_MAIN)
5251 if (global.use_envelope_request)
5252 ShowEnvelopeRequest(text, ACTION_CLOSING);
5256 if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request)
5258 if (!(req_state & REQ_STAY_OPEN))
5261 CloseDoor(DOOR_CLOSE_1);
5263 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
5264 (req_state & REQ_REOPEN))
5265 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
5270 if (game_status == GAME_MODE_PLAYING)
5272 SetPanelBackground();
5273 SetDrawBackgroundMask(REDRAW_DOOR_1);
5277 SetDrawBackgroundMask(REDRAW_FIELD);
5280 #if defined(NETWORK_AVALIABLE)
5281 /* continue network game after request */
5282 if (options.network &&
5283 game_status == GAME_MODE_PLAYING &&
5284 req_state & REQUEST_WAIT_FOR_INPUT)
5285 SendToServer_ContinuePlaying();
5288 /* restore deactivated drawing when quick-loading level tape recording */
5289 if (tape.playing && tape.deactivate_display)
5290 TapeDeactivateDisplayOn();
5297 static int compareDoorPartOrderInfo(const void *object1, const void *object2)
5299 const struct DoorPartOrderInfo *dpo1 = (struct DoorPartOrderInfo *)object1;
5300 const struct DoorPartOrderInfo *dpo2 = (struct DoorPartOrderInfo *)object2;
5303 if (dpo1->sort_priority != dpo2->sort_priority)
5304 compare_result = dpo1->sort_priority - dpo2->sort_priority;
5306 compare_result = dpo1->nr - dpo2->nr;
5308 return compare_result;
5315 for (i = 0; door_part_controls[i].door_nr != -1; i++)
5317 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5318 struct DoorPartOrderInfo *dpo = &door_part_order[i];
5320 /* fill structure for door part draw order */
5322 dpo->sort_priority = dpc->pos->sort_priority;
5325 /* sort door part controls according to sort_priority and graphic number */
5326 qsort(door_part_order, NUM_DOORS * MAX_NUM_DOOR_PARTS,
5327 sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo);
5330 unsigned int OpenDoor(unsigned int door_state)
5332 if (door_state & DOOR_COPY_BACK)
5334 if (door_state & DOOR_OPEN_1)
5335 BlitBitmap(bitmap_db_door, bitmap_db_door,
5336 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
5337 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5339 if (door_state & DOOR_OPEN_2)
5340 BlitBitmap(bitmap_db_door, bitmap_db_door,
5341 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
5342 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5344 door_state &= ~DOOR_COPY_BACK;
5347 return MoveDoor(door_state);
5350 unsigned int CloseDoor(unsigned int door_state)
5352 unsigned int old_door_state = GetDoorState();
5354 if (!(door_state & DOOR_NO_COPY_BACK))
5356 if (old_door_state & DOOR_OPEN_1)
5357 BlitBitmap(backbuffer, bitmap_db_door,
5358 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5360 if (old_door_state & DOOR_OPEN_2)
5361 BlitBitmap(backbuffer, bitmap_db_door,
5362 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5364 door_state &= ~DOOR_NO_COPY_BACK;
5367 return MoveDoor(door_state);
5370 unsigned int GetDoorState()
5372 return MoveDoor(DOOR_GET_STATE);
5375 unsigned int SetDoorState(unsigned int door_state)
5377 return MoveDoor(door_state | DOOR_SET_STATE);
5382 // ========== TEST 1 ===========================================================
5384 unsigned int MoveDoor(unsigned int door_state)
5386 static int door1 = DOOR_OPEN_1;
5387 static int door2 = DOOR_CLOSE_2;
5389 unsigned int door_delay = 0;
5390 unsigned int door_delay_value;
5396 if (door_1.width < 0 || door_1.width > DXSIZE)
5397 door_1.width = DXSIZE;
5398 if (door_1.height < 0 || door_1.height > DYSIZE)
5399 door_1.height = DYSIZE;
5400 if (door_2.width < 0 || door_2.width > VXSIZE)
5401 door_2.width = VXSIZE;
5402 if (door_2.height < 0 || door_2.height > VYSIZE)
5403 door_2.height = VYSIZE;
5406 if (door_state == DOOR_GET_STATE)
5407 return (door1 | door2);
5409 if (door_state & DOOR_SET_STATE)
5411 if (door_state & DOOR_ACTION_1)
5412 door1 = door_state & DOOR_ACTION_1;
5413 if (door_state & DOOR_ACTION_2)
5414 door2 = door_state & DOOR_ACTION_2;
5416 return (door1 | door2);
5419 if (!(door_state & DOOR_FORCE_REDRAW))
5421 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
5422 door_state &= ~DOOR_OPEN_1;
5423 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
5424 door_state &= ~DOOR_CLOSE_1;
5425 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
5426 door_state &= ~DOOR_OPEN_2;
5427 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
5428 door_state &= ~DOOR_CLOSE_2;
5432 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
5435 if (setup.quick_doors)
5437 stepsize = 20; /* must be chosen to always draw last frame */
5438 door_delay_value = 0;
5442 if (global.autoplay_leveldir)
5444 door_state |= DOOR_NO_DELAY;
5445 door_state &= ~DOOR_CLOSE_ALL;
5449 if (game_status == GAME_MODE_EDITOR)
5450 door_state |= DOOR_NO_DELAY;
5453 if (door_state & DOOR_ACTION)
5455 for (i = 0; i < NUM_DOORS * MAX_NUM_DOOR_PARTS; i++)
5457 int nr = door_part_order[i].nr;
5458 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5459 int door_token = dpc->door_nr;
5460 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5461 int graphic = dpc->graphic;
5462 struct GraphicInfo *g = &graphic_info[graphic];
5463 struct TextPosInfo *pos = dpc->pos;
5464 int panel_src_x, panel_src_y;
5465 int dx, dy, dxsize, dysize;
5466 static boolean door_panel_drawn[NUM_DOORS];
5469 for (j = 0; j < NUM_DOORS; j++)
5470 door_panel_drawn[j] = FALSE;
5472 if (door_token == DOOR_1)
5474 panel_src_x = DOOR_GFX_PAGEX1;
5475 panel_src_y = DOOR_GFX_PAGEY1;
5483 panel_src_x = DOOR_GFX_PAGEX1;
5484 panel_src_y = DOOR_GFX_PAGEY2;
5491 if (!(door_state & door_token))
5497 if (!door_panel_drawn[door_index])
5499 BlitBitmap(bitmap_db_door, drawto, panel_src_x, panel_src_y,
5500 dxsize, dysize, dx, dy);
5502 door_panel_drawn[door_index] = TRUE;
5507 if (!((door_state & door_token) & DOOR_CLOSE))
5511 BlitBitmapMasked(g->bitmap, drawto, g->src_x, g->src_y,
5512 g->width, g->height, dx + pos->x, dy + pos->y);
5514 redraw_mask |= REDRAW_DOOR_FROM_TOKEN(door_token);
5518 redraw_mask |= REDRAW_ALL;
5520 if (door_state & DOOR_ACTION_1)
5521 door1 = door_state & DOOR_ACTION_1;
5522 if (door_state & DOOR_ACTION_2)
5523 door2 = door_state & DOOR_ACTION_2;
5525 return (door1 | door2);
5530 // ========== OLD ==============================================================
5532 unsigned int MoveDoor(unsigned int door_state)
5534 static int door1 = DOOR_OPEN_1;
5535 static int door2 = DOOR_CLOSE_2;
5536 unsigned int door_delay = 0;
5537 unsigned int door_delay_value;
5541 if (door_1.width < 0 || door_1.width > DXSIZE)
5542 door_1.width = DXSIZE;
5543 if (door_1.height < 0 || door_1.height > DYSIZE)
5544 door_1.height = DYSIZE;
5545 if (door_2.width < 0 || door_2.width > VXSIZE)
5546 door_2.width = VXSIZE;
5547 if (door_2.height < 0 || door_2.height > VYSIZE)
5548 door_2.height = VYSIZE;
5551 if (door_state == DOOR_GET_STATE)
5552 return (door1 | door2);
5554 if (door_state & DOOR_SET_STATE)
5556 if (door_state & DOOR_ACTION_1)
5557 door1 = door_state & DOOR_ACTION_1;
5558 if (door_state & DOOR_ACTION_2)
5559 door2 = door_state & DOOR_ACTION_2;
5561 return (door1 | door2);
5564 if (!(door_state & DOOR_FORCE_REDRAW))
5566 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
5567 door_state &= ~DOOR_OPEN_1;
5568 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
5569 door_state &= ~DOOR_CLOSE_1;
5570 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
5571 door_state &= ~DOOR_OPEN_2;
5572 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
5573 door_state &= ~DOOR_CLOSE_2;
5576 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
5579 // door_delay_value *= 4; // !!! TEST ONLY !!!
5581 if (setup.quick_doors)
5583 stepsize = 20; /* must be chosen to always draw last frame */
5584 door_delay_value = 0;
5587 if (global.autoplay_leveldir)
5589 door_state |= DOOR_NO_DELAY;
5590 door_state &= ~DOOR_CLOSE_ALL;
5594 if (game_status == GAME_MODE_EDITOR)
5595 door_state |= DOOR_NO_DELAY;
5598 if (door_state & DOOR_ACTION)
5601 struct GraphicInfo *g1_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
5602 struct GraphicInfo *g1_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
5603 struct GraphicInfo *g2_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
5604 struct GraphicInfo *g2_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
5605 int door_1_left_width = g1_left->width;
5606 int door_1_left_height = g1_left->height;
5607 int door_1_right_width = g1_right->width;
5608 int door_1_right_height = g1_right->height;
5609 int door_2_left_width = g2_left->width;
5610 int door_2_left_height = g2_left->height;
5611 int door_2_right_width = g2_right->width;
5612 int door_2_right_height = g2_right->height;
5613 int door_1_width = MAX(door_1_left_width, door_1_right_width);
5614 int door_1_height = MAX(door_1_left_height, door_1_right_height);
5615 int door_2_width = MAX(door_2_left_width, door_2_right_width);
5616 int door_2_height = MAX(door_2_left_height, door_2_right_height);
5618 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
5619 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
5620 boolean door_1_done = (!handle_door_1);
5621 boolean door_2_done = (!handle_door_2);
5622 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
5623 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
5626 int door_size_1 = (door_1_vertical ? door_1_height : door_1_width);
5627 int door_size_2 = (door_2_vertical ? door_2_height : door_2_width);
5629 int door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
5630 int door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
5633 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
5634 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
5636 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
5637 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
5638 // int door_size = (handle_door_1 ? door_size_1 : door_size_2);
5639 int door_size = (handle_door_2 ? door_size_2 : door_size_1);
5640 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
5641 int door_skip = max_door_size - door_size;
5642 int end = door_size;
5643 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
5646 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
5648 /* opening door sound has priority over simultaneously closing door */
5649 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
5650 PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
5651 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
5652 PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
5655 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
5659 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
5660 GC gc = bitmap->stored_clip_gc;
5663 if (door_state & DOOR_ACTION_1 &&
5664 x * door_1.step_offset <= door_size_1)
5666 int a = MIN(x * door_1.step_offset, end);
5667 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
5671 int i = p + door_skip;
5675 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
5676 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
5677 Bitmap *bm_left = g_left->bitmap;
5678 Bitmap *bm_right = g_right->bitmap;
5679 GC gc_left = bm_left->stored_clip_gc;
5680 GC gc_right = bm_right->stored_clip_gc;
5683 int classic_dxsize = 100;
5684 int classic_dysize = 280;
5685 boolean classic_door_1_size = (DXSIZE == classic_dxsize &&
5686 DYSIZE == classic_dysize);
5688 if (door_1.anim_mode & ANIM_STATIC_PANEL)
5690 BlitBitmap(bitmap_db_door, drawto,
5691 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
5692 DXSIZE, DYSIZE, DX, DY);
5696 BlitBitmap(bitmap_db_door, drawto,
5697 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
5698 DXSIZE, DYSIZE - p / 2, DX, DY);
5701 // printf("::: p == %d\n", p);
5702 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
5706 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
5709 int src1_x = g_right->src_x;
5710 int src1_y = g_right->src_y;
5711 int src2_x = g_left->src_x + g_left->width - i;
5712 int src2_y = g_left->src_y;
5713 int dst1_x = DX + DXSIZE - i;
5718 int height = DYSIZE;
5720 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
5721 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
5724 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
5725 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
5728 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
5729 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
5730 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
5731 int dst2_x = DX, dst2_y = DY;
5732 int width = i, height = DYSIZE;
5734 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
5735 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
5738 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
5739 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
5743 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
5746 int src1_x = g_right->src_x;
5747 int src1_y = g_right->src_y;
5748 int src2_x = g_left->src_x;
5749 int src2_y = g_left->src_y + g_left->height - i;
5751 int dst1_y = DY + DYSIZE - i;
5757 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
5758 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
5761 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
5762 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
5765 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
5766 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
5767 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
5768 int dst2_x = DX, dst2_y = DY;
5769 int width = DXSIZE, height = i;
5771 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
5772 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
5775 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
5776 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
5780 else if (classic_door_1_size && x <= DXSIZE) /* ANIM_DEFAULT */
5782 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
5785 int src1_x = g_right->src_x;
5786 int src1_y = g_right->src_y;
5787 int src2_x = g_left->src_x + g_left->width - i;
5788 int src2_y = g_left->src_y;
5789 int dst1_x = DX + DXSIZE - i;
5794 int height1 = 63, height2 = DYSIZE / 2 - height1;
5795 int ypos1 = 0, ypos2 = height2;
5796 int ypos3 = DYSIZE / 2, ypos4 = DYSIZE - height2;
5798 SetClipOrigin(bm_right, gc_right,
5799 dst1_x - src1_x, dst1_y - src1_y + j);
5800 BlitBitmapMasked(bm_right, drawto,
5801 src1_x, src1_y + ypos1, width, height2,
5802 dst1_x, dst1_y + ypos1 + j);
5803 BlitBitmapMasked(bm_right, drawto,
5804 src1_x, src1_y + ypos3, width, height1,
5805 dst1_x, dst1_y + ypos3 + j);
5806 SetClipOrigin(bm_left, gc_left,
5807 dst2_x - src2_x, dst2_y - src2_y - j);
5808 BlitBitmapMasked(bm_left, drawto,
5809 src2_x, src2_y + ypos1 + j, width, height2 - j,
5810 dst2_x, dst2_y + ypos1);
5811 BlitBitmapMasked(bm_left, drawto,
5812 src2_x, src2_y + ypos3, width, height1,
5813 dst2_x, dst2_y + ypos3 - j);
5815 SetClipOrigin(bm_left, gc_left,
5816 dst2_x - src2_x, dst2_y - src2_y - j);
5817 BlitBitmapMasked(bm_left, drawto,
5818 src2_x, src2_y + ypos2, width, height1,
5819 dst2_x, dst2_y + ypos2 - j);
5820 BlitBitmapMasked(bm_left, drawto,
5821 src2_x, src2_y + ypos4, width, height2,
5822 dst2_x, dst2_y + ypos4 - j);
5823 SetClipOrigin(bm_right, gc_right,
5824 dst1_x - src1_x, dst1_y - src1_y + j);
5825 BlitBitmapMasked(bm_right, drawto,
5826 src1_x, src1_y + ypos2, width, height1,
5827 dst1_x, dst1_y + ypos2 + j);
5828 BlitBitmapMasked(bm_right, drawto,
5829 src1_x, src1_y + ypos4, width, height2 - j,
5830 dst1_x, dst1_y + ypos4 + j);
5833 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
5834 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
5835 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
5836 int dst2_x = DX, dst2_y = DY;
5837 int width = i, height = DYSIZE;
5838 int ypos1 = 63, ypos2 = 77, ypos3 = 140, ypos4 = 203;
5840 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
5841 BlitBitmapMasked(bitmap, drawto,
5842 src1_x, src1_y, width, ypos2,
5843 dst1_x, dst1_y + j);
5844 BlitBitmapMasked(bitmap, drawto,
5845 src1_x, src1_y + ypos3, width, ypos1,
5846 dst1_x, dst1_y + ypos3 + j);
5847 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
5848 BlitBitmapMasked(bitmap, drawto,
5849 src2_x, src2_y + j, width, ypos2 - j,
5851 BlitBitmapMasked(bitmap, drawto,
5852 src2_x, src2_y + ypos3, width, ypos1,
5853 dst2_x, dst2_y + ypos3 - j);
5855 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
5856 BlitBitmapMasked(bitmap, drawto,
5857 src2_x, src2_y + ypos2, width, ypos1,
5858 dst2_x, dst2_y + ypos2 - j);
5859 BlitBitmapMasked(bitmap, drawto,
5860 src2_x, src2_y + ypos4, width, ypos2,
5861 dst2_x, dst2_y + ypos4 - j);
5862 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
5863 BlitBitmapMasked(bitmap, drawto,
5864 src1_x, src1_y + ypos2, width, ypos1,
5865 dst1_x, dst1_y + ypos2 + j);
5866 BlitBitmapMasked(bitmap, drawto,
5867 src1_x, src1_y + ypos4, width, ypos2 - j,
5868 dst1_x, dst1_y + ypos4 + j);
5871 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
5872 BlitBitmapMasked(bitmap, drawto,
5873 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
5874 DX + DXSIZE - i, DY + j);
5875 BlitBitmapMasked(bitmap, drawto,
5876 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
5877 DX + DXSIZE - i, DY + 140 + j);
5878 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
5879 DY - (DOOR_GFX_PAGEY1 + j));
5880 BlitBitmapMasked(bitmap, drawto,
5881 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
5883 BlitBitmapMasked(bitmap, drawto,
5884 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
5887 BlitBitmapMasked(bitmap, drawto,
5888 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
5890 BlitBitmapMasked(bitmap, drawto,
5891 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
5893 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
5894 BlitBitmapMasked(bitmap, drawto,
5895 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
5896 DX + DXSIZE - i, DY + 77 + j);
5897 BlitBitmapMasked(bitmap, drawto,
5898 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
5899 DX + DXSIZE - i, DY + 203 + j);
5904 redraw_mask |= REDRAW_DOOR_1;
5905 door_1_done = (a == end);
5908 if (door_state & DOOR_ACTION_2 &&
5909 x * door_2.step_offset <= door_size_2)
5911 int a = MIN(x * door_2.step_offset, door_size);
5912 int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
5913 int i = p + door_skip;
5916 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
5917 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
5918 Bitmap *bm_left = g_left->bitmap;
5919 Bitmap *bm_right = g_right->bitmap;
5920 GC gc_left = bm_left->stored_clip_gc;
5921 GC gc_right = bm_right->stored_clip_gc;
5924 int classic_vxsize = 100;
5925 int classic_vysize = 100;
5926 boolean classic_door_2_size = (VXSIZE == classic_vxsize &&
5927 VYSIZE == classic_vysize);
5929 if (door_2.anim_mode & ANIM_STATIC_PANEL)
5931 BlitBitmap(bitmap_db_door, drawto,
5932 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
5933 VXSIZE, VYSIZE, VX, VY);
5935 else if (x <= VYSIZE)
5937 BlitBitmap(bitmap_db_door, drawto,
5938 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
5939 VXSIZE, VYSIZE - p / 2, VX, VY);
5941 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
5944 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
5947 int src1_x = g_right->src_x;
5948 int src1_y = g_right->src_y;
5949 int src2_x = g_left->src_x + g_left->width - i;
5950 int src2_y = g_left->src_y;
5951 int dst1_x = VX + VXSIZE - i;
5956 int height = VYSIZE;
5958 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
5959 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
5962 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
5963 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
5966 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
5967 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
5968 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
5969 int dst2_x = VX, dst2_y = VY;
5970 int width = i, height = VYSIZE;
5972 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
5973 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
5976 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
5977 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
5981 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
5984 int src1_x = g_right->src_x;
5985 int src1_y = g_right->src_y;
5986 int src2_x = g_left->src_x;
5987 int src2_y = g_left->src_y + g_left->height - i;
5989 int dst1_y = VY + VYSIZE - i;
5995 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
5996 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
5999 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6000 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6003 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6004 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
6005 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
6006 int dst2_x = VX, dst2_y = VY;
6007 int width = VXSIZE, height = i;
6009 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6010 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6013 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6014 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6018 else if (classic_door_2_size && x <= VXSIZE) /* ANIM_DEFAULT */
6020 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
6023 int src1_x = g_right->src_x;
6024 int src1_y = g_right->src_y;
6025 int src2_x = g_left->src_x + g_left->width - i;
6026 int src2_y = g_left->src_y;
6027 int dst1_x = VX + VXSIZE - i;
6032 int height = VYSIZE / 2;
6033 int ypos1 = 0, ypos2 = VYSIZE / 2;
6035 SetClipOrigin(bm_right, gc_right,
6036 dst1_x - src1_x, dst1_y - src1_y + j);
6037 BlitBitmapMasked(bm_right, drawto,
6038 src1_x, src1_y + ypos1, width, height,
6039 dst1_x, dst1_y + ypos1 + j);
6040 SetClipOrigin(bm_left, gc_left,
6041 dst2_x - src2_x, dst2_y - src2_y - j);
6042 BlitBitmapMasked(bm_left, drawto,
6043 src2_x, src2_y + ypos1 + j, width, height - j,
6044 dst2_x, dst2_y + ypos1);
6046 SetClipOrigin(bm_left, gc_left,
6047 dst2_x - src2_x, dst2_y - src2_y - j);
6048 BlitBitmapMasked(bm_left, drawto,
6049 src2_x, src2_y + ypos2, width, height,
6050 dst2_x, dst2_y + ypos2 - j);
6051 SetClipOrigin(bm_right, gc_right,
6052 dst1_x - src1_x, dst1_y - src1_y + j);
6053 BlitBitmapMasked(bm_right, drawto,
6054 src1_x, src1_y + ypos2, width, height - j,
6055 dst1_x, dst1_y + ypos2 + j);
6057 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6058 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6059 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6060 int dst2_x = VX, dst2_y = VY;
6061 int width = i, height = VYSIZE;
6062 int ypos = VYSIZE / 2;
6064 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6065 BlitBitmapMasked(bitmap, drawto,
6066 src1_x, src1_y, width, ypos,
6067 dst1_x, dst1_y + j);
6068 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6069 BlitBitmapMasked(bitmap, drawto,
6070 src2_x, src2_y + j, width, ypos - j,
6073 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6074 BlitBitmapMasked(bitmap, drawto,
6075 src2_x, src2_y + ypos, width, ypos,
6076 dst2_x, dst2_y + ypos - j);
6077 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6078 BlitBitmapMasked(bitmap, drawto,
6079 src1_x, src1_y + ypos, width, ypos - j,
6080 dst1_x, dst1_y + ypos + j);
6083 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6084 BlitBitmapMasked(bitmap, drawto,
6085 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
6086 VX + VXSIZE - i, VY + j);
6087 SetClipOrigin(bitmap, gc,
6088 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
6089 BlitBitmapMasked(bitmap, drawto,
6090 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
6093 BlitBitmapMasked(bitmap, drawto,
6094 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6095 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
6096 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6097 BlitBitmapMasked(bitmap, drawto,
6098 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6100 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
6105 redraw_mask |= REDRAW_DOOR_2;
6106 door_2_done = (a == VXSIZE);
6109 if (!(door_state & DOOR_NO_DELAY))
6113 if (game_status == GAME_MODE_MAIN)
6116 WaitUntilDelayReached(&door_delay, door_delay_value);
6121 if (door_state & DOOR_ACTION_1)
6122 door1 = door_state & DOOR_ACTION_1;
6123 if (door_state & DOOR_ACTION_2)
6124 door2 = door_state & DOOR_ACTION_2;
6126 return (door1 | door2);
6131 void DrawSpecialEditorDoor()
6134 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6135 int top_border_width = gfx1->width;
6136 int top_border_height = gfx1->height;
6137 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6138 int ex = EX - outer_border;
6139 int ey = EY - outer_border;
6140 int vy = VY - outer_border;
6141 int exsize = EXSIZE + 2 * outer_border;
6143 CloseDoor(DOOR_CLOSE_2);
6145 /* draw bigger level editor toolbox window */
6146 BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
6147 top_border_width, top_border_height, ex, ey - top_border_height);
6148 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
6149 exsize, EYSIZE - VYSIZE + outer_border, ex, ey);
6151 /* draw bigger level editor toolbox window */
6152 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
6153 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
6155 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6156 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
6160 redraw_mask |= REDRAW_ALL;
6163 void UndrawSpecialEditorDoor()
6166 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6167 int top_border_width = gfx1->width;
6168 int top_border_height = gfx1->height;
6169 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6170 int ex = EX - outer_border;
6171 int ey = EY - outer_border;
6172 int ey_top = ey - top_border_height;
6173 int exsize = EXSIZE + 2 * outer_border;
6174 int eysize = EYSIZE + 2 * outer_border;
6176 /* draw normal tape recorder window */
6177 if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
6179 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6180 ex, ey_top, top_border_width, top_border_height,
6182 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6183 ex, ey, exsize, eysize, ex, ey);
6187 // if screen background is set to "[NONE]", clear editor toolbox window
6188 ClearRectangle(drawto, ex, ey_top, top_border_width, top_border_height);
6189 ClearRectangle(drawto, ex, ey, exsize, eysize);
6192 /* draw normal tape recorder window */
6193 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6194 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
6198 redraw_mask |= REDRAW_ALL;
6202 /* ---------- new tool button stuff ---------------------------------------- */
6209 struct TextPosInfo *pos;
6212 } toolbutton_info[NUM_TOOL_BUTTONS] =
6215 IMG_REQUEST_BUTTON_GFX_YES, &request.button.yes,
6216 TOOL_CTRL_ID_YES, "yes"
6219 IMG_REQUEST_BUTTON_GFX_NO, &request.button.no,
6220 TOOL_CTRL_ID_NO, "no"
6223 IMG_REQUEST_BUTTON_GFX_CONFIRM, &request.button.confirm,
6224 TOOL_CTRL_ID_CONFIRM, "confirm"
6227 IMG_REQUEST_BUTTON_GFX_PLAYER_1, &request.button.player_1,
6228 TOOL_CTRL_ID_PLAYER_1, "player 1"
6231 IMG_REQUEST_BUTTON_GFX_PLAYER_2, &request.button.player_2,
6232 TOOL_CTRL_ID_PLAYER_2, "player 2"
6235 IMG_REQUEST_BUTTON_GFX_PLAYER_3, &request.button.player_3,
6236 TOOL_CTRL_ID_PLAYER_3, "player 3"
6239 IMG_REQUEST_BUTTON_GFX_PLAYER_4, &request.button.player_4,
6240 TOOL_CTRL_ID_PLAYER_4, "player 4"
6244 void CreateToolButtons()
6248 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6250 struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
6251 struct TextPosInfo *pos = toolbutton_info[i].pos;
6252 struct GadgetInfo *gi;
6253 Bitmap *deco_bitmap = None;
6254 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6255 unsigned int event_mask = GD_EVENT_RELEASED;
6258 int gd_x = gfx->src_x;
6259 int gd_y = gfx->src_y;
6260 int gd_xp = gfx->src_x + gfx->pressed_xoffset;
6261 int gd_yp = gfx->src_y + gfx->pressed_yoffset;
6264 if (global.use_envelope_request)
6265 setRequestPosition(&dx, &dy, TRUE);
6267 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
6269 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
6271 getSizedGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0,
6272 pos->size, &deco_bitmap, &deco_x, &deco_y);
6273 deco_xpos = (gfx->width - pos->size) / 2;
6274 deco_ypos = (gfx->height - pos->size) / 2;
6277 gi = CreateGadget(GDI_CUSTOM_ID, id,
6278 GDI_INFO_TEXT, toolbutton_info[i].infotext,
6281 GDI_WIDTH, gfx->width,
6282 GDI_HEIGHT, gfx->height,
6283 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
6284 GDI_STATE, GD_BUTTON_UNPRESSED,
6285 GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y,
6286 GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp,
6287 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
6288 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
6289 GDI_DECORATION_SIZE, pos->size, pos->size,
6290 GDI_DECORATION_SHIFTING, 1, 1,
6291 GDI_DIRECT_DRAW, FALSE,
6292 GDI_EVENT_MASK, event_mask,
6293 GDI_CALLBACK_ACTION, HandleToolButtons,
6297 Error(ERR_EXIT, "cannot create gadget");
6299 tool_gadget[id] = gi;
6305 /* graphic position values for tool buttons */
6306 #define TOOL_BUTTON_YES_XPOS 2
6307 #define TOOL_BUTTON_YES_YPOS 250
6308 #define TOOL_BUTTON_YES_GFX_YPOS 0
6309 #define TOOL_BUTTON_YES_XSIZE 46
6310 #define TOOL_BUTTON_YES_YSIZE 28
6311 #define TOOL_BUTTON_NO_XPOS 52
6312 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
6313 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
6314 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
6315 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
6316 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
6317 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
6318 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
6319 #define TOOL_BUTTON_CONFIRM_XSIZE 96
6320 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
6321 #define TOOL_BUTTON_PLAYER_XSIZE 30
6322 #define TOOL_BUTTON_PLAYER_YSIZE 30
6323 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
6324 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
6325 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
6326 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
6327 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6328 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6329 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6330 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6331 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6332 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6333 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6334 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6335 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6336 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6337 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6338 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6339 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6340 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6341 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6342 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6351 } toolbutton_info[NUM_TOOL_BUTTONS] =
6354 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
6355 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
6356 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
6361 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
6362 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
6363 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
6368 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
6369 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
6370 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
6371 TOOL_CTRL_ID_CONFIRM,
6375 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6376 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
6377 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6378 TOOL_CTRL_ID_PLAYER_1,
6382 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6383 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
6384 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6385 TOOL_CTRL_ID_PLAYER_2,
6389 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6390 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
6391 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6392 TOOL_CTRL_ID_PLAYER_3,
6396 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6397 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
6398 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6399 TOOL_CTRL_ID_PLAYER_4,
6404 void CreateToolButtons()
6408 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6410 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6411 Bitmap *deco_bitmap = None;
6412 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6413 struct GadgetInfo *gi;
6414 unsigned int event_mask;
6415 int gd_xoffset, gd_yoffset;
6416 int gd_x1, gd_x2, gd_y;
6419 event_mask = GD_EVENT_RELEASED;
6421 gd_xoffset = toolbutton_info[i].xpos;
6422 gd_yoffset = toolbutton_info[i].ypos;
6423 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
6424 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
6425 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
6427 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
6429 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
6431 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
6432 &deco_bitmap, &deco_x, &deco_y);
6433 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
6434 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
6437 gi = CreateGadget(GDI_CUSTOM_ID, id,
6438 GDI_INFO_TEXT, toolbutton_info[i].infotext,
6439 GDI_X, DX + toolbutton_info[i].x,
6440 GDI_Y, DY + toolbutton_info[i].y,
6441 GDI_WIDTH, toolbutton_info[i].width,
6442 GDI_HEIGHT, toolbutton_info[i].height,
6443 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
6444 GDI_STATE, GD_BUTTON_UNPRESSED,
6445 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
6446 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
6447 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
6448 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
6449 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
6450 GDI_DECORATION_SHIFTING, 1, 1,
6451 GDI_DIRECT_DRAW, FALSE,
6452 GDI_EVENT_MASK, event_mask,
6453 GDI_CALLBACK_ACTION, HandleToolButtons,
6457 Error(ERR_EXIT, "cannot create gadget");
6459 tool_gadget[id] = gi;
6465 void FreeToolButtons()
6469 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6470 FreeGadget(tool_gadget[i]);
6473 static void UnmapToolButtons()
6477 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6478 UnmapGadget(tool_gadget[i]);
6481 static void HandleToolButtons(struct GadgetInfo *gi)
6483 request_gadget_id = gi->custom_id;
6486 static struct Mapping_EM_to_RND_object
6489 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
6490 boolean is_backside; /* backside of moving element */
6496 em_object_mapping_list[] =
6499 Xblank, TRUE, FALSE,
6503 Yacid_splash_eB, FALSE, FALSE,
6504 EL_ACID_SPLASH_RIGHT, -1, -1
6507 Yacid_splash_wB, FALSE, FALSE,
6508 EL_ACID_SPLASH_LEFT, -1, -1
6511 #ifdef EM_ENGINE_BAD_ROLL
6513 Xstone_force_e, FALSE, FALSE,
6514 EL_ROCK, -1, MV_BIT_RIGHT
6517 Xstone_force_w, FALSE, FALSE,
6518 EL_ROCK, -1, MV_BIT_LEFT
6521 Xnut_force_e, FALSE, FALSE,
6522 EL_NUT, -1, MV_BIT_RIGHT
6525 Xnut_force_w, FALSE, FALSE,
6526 EL_NUT, -1, MV_BIT_LEFT
6529 Xspring_force_e, FALSE, FALSE,
6530 EL_SPRING, -1, MV_BIT_RIGHT
6533 Xspring_force_w, FALSE, FALSE,
6534 EL_SPRING, -1, MV_BIT_LEFT
6537 Xemerald_force_e, FALSE, FALSE,
6538 EL_EMERALD, -1, MV_BIT_RIGHT
6541 Xemerald_force_w, FALSE, FALSE,
6542 EL_EMERALD, -1, MV_BIT_LEFT
6545 Xdiamond_force_e, FALSE, FALSE,
6546 EL_DIAMOND, -1, MV_BIT_RIGHT
6549 Xdiamond_force_w, FALSE, FALSE,
6550 EL_DIAMOND, -1, MV_BIT_LEFT
6553 Xbomb_force_e, FALSE, FALSE,
6554 EL_BOMB, -1, MV_BIT_RIGHT
6557 Xbomb_force_w, FALSE, FALSE,
6558 EL_BOMB, -1, MV_BIT_LEFT
6560 #endif /* EM_ENGINE_BAD_ROLL */
6563 Xstone, TRUE, FALSE,
6567 Xstone_pause, FALSE, FALSE,
6571 Xstone_fall, FALSE, FALSE,
6575 Ystone_s, FALSE, FALSE,
6576 EL_ROCK, ACTION_FALLING, -1
6579 Ystone_sB, FALSE, TRUE,
6580 EL_ROCK, ACTION_FALLING, -1
6583 Ystone_e, FALSE, FALSE,
6584 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
6587 Ystone_eB, FALSE, TRUE,
6588 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
6591 Ystone_w, FALSE, FALSE,
6592 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
6595 Ystone_wB, FALSE, TRUE,
6596 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
6603 Xnut_pause, FALSE, FALSE,
6607 Xnut_fall, FALSE, FALSE,
6611 Ynut_s, FALSE, FALSE,
6612 EL_NUT, ACTION_FALLING, -1
6615 Ynut_sB, FALSE, TRUE,
6616 EL_NUT, ACTION_FALLING, -1
6619 Ynut_e, FALSE, FALSE,
6620 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
6623 Ynut_eB, FALSE, TRUE,
6624 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
6627 Ynut_w, FALSE, FALSE,
6628 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
6631 Ynut_wB, FALSE, TRUE,
6632 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
6635 Xbug_n, TRUE, FALSE,
6639 Xbug_e, TRUE, FALSE,
6640 EL_BUG_RIGHT, -1, -1
6643 Xbug_s, TRUE, FALSE,
6647 Xbug_w, TRUE, FALSE,
6651 Xbug_gon, FALSE, FALSE,
6655 Xbug_goe, FALSE, FALSE,
6656 EL_BUG_RIGHT, -1, -1
6659 Xbug_gos, FALSE, FALSE,
6663 Xbug_gow, FALSE, FALSE,
6667 Ybug_n, FALSE, FALSE,
6668 EL_BUG, ACTION_MOVING, MV_BIT_UP
6671 Ybug_nB, FALSE, TRUE,
6672 EL_BUG, ACTION_MOVING, MV_BIT_UP
6675 Ybug_e, FALSE, FALSE,
6676 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
6679 Ybug_eB, FALSE, TRUE,
6680 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
6683 Ybug_s, FALSE, FALSE,
6684 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
6687 Ybug_sB, FALSE, TRUE,
6688 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
6691 Ybug_w, FALSE, FALSE,
6692 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
6695 Ybug_wB, FALSE, TRUE,
6696 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
6699 Ybug_w_n, FALSE, FALSE,
6700 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
6703 Ybug_n_e, FALSE, FALSE,
6704 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
6707 Ybug_e_s, FALSE, FALSE,
6708 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
6711 Ybug_s_w, FALSE, FALSE,
6712 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
6715 Ybug_e_n, FALSE, FALSE,
6716 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
6719 Ybug_s_e, FALSE, FALSE,
6720 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
6723 Ybug_w_s, FALSE, FALSE,
6724 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
6727 Ybug_n_w, FALSE, FALSE,
6728 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
6731 Ybug_stone, FALSE, FALSE,
6732 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
6735 Ybug_spring, FALSE, FALSE,
6736 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
6739 Xtank_n, TRUE, FALSE,
6740 EL_SPACESHIP_UP, -1, -1
6743 Xtank_e, TRUE, FALSE,
6744 EL_SPACESHIP_RIGHT, -1, -1
6747 Xtank_s, TRUE, FALSE,
6748 EL_SPACESHIP_DOWN, -1, -1
6751 Xtank_w, TRUE, FALSE,
6752 EL_SPACESHIP_LEFT, -1, -1
6755 Xtank_gon, FALSE, FALSE,
6756 EL_SPACESHIP_UP, -1, -1
6759 Xtank_goe, FALSE, FALSE,
6760 EL_SPACESHIP_RIGHT, -1, -1
6763 Xtank_gos, FALSE, FALSE,
6764 EL_SPACESHIP_DOWN, -1, -1
6767 Xtank_gow, FALSE, FALSE,
6768 EL_SPACESHIP_LEFT, -1, -1
6771 Ytank_n, FALSE, FALSE,
6772 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
6775 Ytank_nB, FALSE, TRUE,
6776 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
6779 Ytank_e, FALSE, FALSE,
6780 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
6783 Ytank_eB, FALSE, TRUE,
6784 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
6787 Ytank_s, FALSE, FALSE,
6788 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
6791 Ytank_sB, FALSE, TRUE,
6792 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
6795 Ytank_w, FALSE, FALSE,
6796 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
6799 Ytank_wB, FALSE, TRUE,
6800 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
6803 Ytank_w_n, FALSE, FALSE,
6804 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
6807 Ytank_n_e, FALSE, FALSE,
6808 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
6811 Ytank_e_s, FALSE, FALSE,
6812 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
6815 Ytank_s_w, FALSE, FALSE,
6816 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
6819 Ytank_e_n, FALSE, FALSE,
6820 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
6823 Ytank_s_e, FALSE, FALSE,
6824 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
6827 Ytank_w_s, FALSE, FALSE,
6828 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
6831 Ytank_n_w, FALSE, FALSE,
6832 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
6835 Ytank_stone, FALSE, FALSE,
6836 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
6839 Ytank_spring, FALSE, FALSE,
6840 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
6843 Xandroid, TRUE, FALSE,
6844 EL_EMC_ANDROID, ACTION_ACTIVE, -1
6847 Xandroid_1_n, FALSE, FALSE,
6848 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
6851 Xandroid_2_n, FALSE, FALSE,
6852 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
6855 Xandroid_1_e, FALSE, FALSE,
6856 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
6859 Xandroid_2_e, FALSE, FALSE,
6860 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
6863 Xandroid_1_w, FALSE, FALSE,
6864 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
6867 Xandroid_2_w, FALSE, FALSE,
6868 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
6871 Xandroid_1_s, FALSE, FALSE,
6872 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
6875 Xandroid_2_s, FALSE, FALSE,
6876 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
6879 Yandroid_n, FALSE, FALSE,
6880 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
6883 Yandroid_nB, FALSE, TRUE,
6884 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
6887 Yandroid_ne, FALSE, FALSE,
6888 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
6891 Yandroid_neB, FALSE, TRUE,
6892 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
6895 Yandroid_e, FALSE, FALSE,
6896 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
6899 Yandroid_eB, FALSE, TRUE,
6900 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
6903 Yandroid_se, FALSE, FALSE,
6904 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
6907 Yandroid_seB, FALSE, TRUE,
6908 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
6911 Yandroid_s, FALSE, FALSE,
6912 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
6915 Yandroid_sB, FALSE, TRUE,
6916 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
6919 Yandroid_sw, FALSE, FALSE,
6920 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
6923 Yandroid_swB, FALSE, TRUE,
6924 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
6927 Yandroid_w, FALSE, FALSE,
6928 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
6931 Yandroid_wB, FALSE, TRUE,
6932 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
6935 Yandroid_nw, FALSE, FALSE,
6936 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
6939 Yandroid_nwB, FALSE, TRUE,
6940 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
6943 Xspring, TRUE, FALSE,
6947 Xspring_pause, FALSE, FALSE,
6951 Xspring_e, FALSE, FALSE,
6955 Xspring_w, FALSE, FALSE,
6959 Xspring_fall, FALSE, FALSE,
6963 Yspring_s, FALSE, FALSE,
6964 EL_SPRING, ACTION_FALLING, -1
6967 Yspring_sB, FALSE, TRUE,
6968 EL_SPRING, ACTION_FALLING, -1
6971 Yspring_e, FALSE, FALSE,
6972 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
6975 Yspring_eB, FALSE, TRUE,
6976 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
6979 Yspring_w, FALSE, FALSE,
6980 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
6983 Yspring_wB, FALSE, TRUE,
6984 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
6987 Yspring_kill_e, FALSE, FALSE,
6988 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
6991 Yspring_kill_eB, FALSE, TRUE,
6992 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
6995 Yspring_kill_w, FALSE, FALSE,
6996 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
6999 Yspring_kill_wB, FALSE, TRUE,
7000 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7003 Xeater_n, TRUE, FALSE,
7004 EL_YAMYAM_UP, -1, -1
7007 Xeater_e, TRUE, FALSE,
7008 EL_YAMYAM_RIGHT, -1, -1
7011 Xeater_w, TRUE, FALSE,
7012 EL_YAMYAM_LEFT, -1, -1
7015 Xeater_s, TRUE, FALSE,
7016 EL_YAMYAM_DOWN, -1, -1
7019 Yeater_n, FALSE, FALSE,
7020 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7023 Yeater_nB, FALSE, TRUE,
7024 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7027 Yeater_e, FALSE, FALSE,
7028 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7031 Yeater_eB, FALSE, TRUE,
7032 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7035 Yeater_s, FALSE, FALSE,
7036 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7039 Yeater_sB, FALSE, TRUE,
7040 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7043 Yeater_w, FALSE, FALSE,
7044 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7047 Yeater_wB, FALSE, TRUE,
7048 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7051 Yeater_stone, FALSE, FALSE,
7052 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
7055 Yeater_spring, FALSE, FALSE,
7056 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
7059 Xalien, TRUE, FALSE,
7063 Xalien_pause, FALSE, FALSE,
7067 Yalien_n, FALSE, FALSE,
7068 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7071 Yalien_nB, FALSE, TRUE,
7072 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7075 Yalien_e, FALSE, FALSE,
7076 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7079 Yalien_eB, FALSE, TRUE,
7080 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7083 Yalien_s, FALSE, FALSE,
7084 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7087 Yalien_sB, FALSE, TRUE,
7088 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7091 Yalien_w, FALSE, FALSE,
7092 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7095 Yalien_wB, FALSE, TRUE,
7096 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7099 Yalien_stone, FALSE, FALSE,
7100 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
7103 Yalien_spring, FALSE, FALSE,
7104 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
7107 Xemerald, TRUE, FALSE,
7111 Xemerald_pause, FALSE, FALSE,
7115 Xemerald_fall, FALSE, FALSE,
7119 Xemerald_shine, FALSE, FALSE,
7120 EL_EMERALD, ACTION_TWINKLING, -1
7123 Yemerald_s, FALSE, FALSE,
7124 EL_EMERALD, ACTION_FALLING, -1
7127 Yemerald_sB, FALSE, TRUE,
7128 EL_EMERALD, ACTION_FALLING, -1
7131 Yemerald_e, FALSE, FALSE,
7132 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7135 Yemerald_eB, FALSE, TRUE,
7136 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7139 Yemerald_w, FALSE, FALSE,
7140 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7143 Yemerald_wB, FALSE, TRUE,
7144 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7147 Yemerald_eat, FALSE, FALSE,
7148 EL_EMERALD, ACTION_COLLECTING, -1
7151 Yemerald_stone, FALSE, FALSE,
7152 EL_NUT, ACTION_BREAKING, -1
7155 Xdiamond, TRUE, FALSE,
7159 Xdiamond_pause, FALSE, FALSE,
7163 Xdiamond_fall, FALSE, FALSE,
7167 Xdiamond_shine, FALSE, FALSE,
7168 EL_DIAMOND, ACTION_TWINKLING, -1
7171 Ydiamond_s, FALSE, FALSE,
7172 EL_DIAMOND, ACTION_FALLING, -1
7175 Ydiamond_sB, FALSE, TRUE,
7176 EL_DIAMOND, ACTION_FALLING, -1
7179 Ydiamond_e, FALSE, FALSE,
7180 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7183 Ydiamond_eB, FALSE, TRUE,
7184 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7187 Ydiamond_w, FALSE, FALSE,
7188 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7191 Ydiamond_wB, FALSE, TRUE,
7192 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7195 Ydiamond_eat, FALSE, FALSE,
7196 EL_DIAMOND, ACTION_COLLECTING, -1
7199 Ydiamond_stone, FALSE, FALSE,
7200 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
7203 Xdrip_fall, TRUE, FALSE,
7204 EL_AMOEBA_DROP, -1, -1
7207 Xdrip_stretch, FALSE, FALSE,
7208 EL_AMOEBA_DROP, ACTION_FALLING, -1
7211 Xdrip_stretchB, FALSE, TRUE,
7212 EL_AMOEBA_DROP, ACTION_FALLING, -1
7215 Xdrip_eat, FALSE, FALSE,
7216 EL_AMOEBA_DROP, ACTION_GROWING, -1
7219 Ydrip_s1, FALSE, FALSE,
7220 EL_AMOEBA_DROP, ACTION_FALLING, -1
7223 Ydrip_s1B, FALSE, TRUE,
7224 EL_AMOEBA_DROP, ACTION_FALLING, -1
7227 Ydrip_s2, FALSE, FALSE,
7228 EL_AMOEBA_DROP, ACTION_FALLING, -1
7231 Ydrip_s2B, FALSE, TRUE,
7232 EL_AMOEBA_DROP, ACTION_FALLING, -1
7239 Xbomb_pause, FALSE, FALSE,
7243 Xbomb_fall, FALSE, FALSE,
7247 Ybomb_s, FALSE, FALSE,
7248 EL_BOMB, ACTION_FALLING, -1
7251 Ybomb_sB, FALSE, TRUE,
7252 EL_BOMB, ACTION_FALLING, -1
7255 Ybomb_e, FALSE, FALSE,
7256 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7259 Ybomb_eB, FALSE, TRUE,
7260 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7263 Ybomb_w, FALSE, FALSE,
7264 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7267 Ybomb_wB, FALSE, TRUE,
7268 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7271 Ybomb_eat, FALSE, FALSE,
7272 EL_BOMB, ACTION_ACTIVATING, -1
7275 Xballoon, TRUE, FALSE,
7279 Yballoon_n, FALSE, FALSE,
7280 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7283 Yballoon_nB, FALSE, TRUE,
7284 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7287 Yballoon_e, FALSE, FALSE,
7288 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7291 Yballoon_eB, FALSE, TRUE,
7292 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7295 Yballoon_s, FALSE, FALSE,
7296 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7299 Yballoon_sB, FALSE, TRUE,
7300 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7303 Yballoon_w, FALSE, FALSE,
7304 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7307 Yballoon_wB, FALSE, TRUE,
7308 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7311 Xgrass, TRUE, FALSE,
7312 EL_EMC_GRASS, -1, -1
7315 Ygrass_nB, FALSE, FALSE,
7316 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
7319 Ygrass_eB, FALSE, FALSE,
7320 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
7323 Ygrass_sB, FALSE, FALSE,
7324 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
7327 Ygrass_wB, FALSE, FALSE,
7328 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
7335 Ydirt_nB, FALSE, FALSE,
7336 EL_SAND, ACTION_DIGGING, MV_BIT_UP
7339 Ydirt_eB, FALSE, FALSE,
7340 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
7343 Ydirt_sB, FALSE, FALSE,
7344 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
7347 Ydirt_wB, FALSE, FALSE,
7348 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
7351 Xacid_ne, TRUE, FALSE,
7352 EL_ACID_POOL_TOPRIGHT, -1, -1
7355 Xacid_se, TRUE, FALSE,
7356 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
7359 Xacid_s, TRUE, FALSE,
7360 EL_ACID_POOL_BOTTOM, -1, -1
7363 Xacid_sw, TRUE, FALSE,
7364 EL_ACID_POOL_BOTTOMLEFT, -1, -1
7367 Xacid_nw, TRUE, FALSE,
7368 EL_ACID_POOL_TOPLEFT, -1, -1
7371 Xacid_1, TRUE, FALSE,
7375 Xacid_2, FALSE, FALSE,
7379 Xacid_3, FALSE, FALSE,
7383 Xacid_4, FALSE, FALSE,
7387 Xacid_5, FALSE, FALSE,
7391 Xacid_6, FALSE, FALSE,
7395 Xacid_7, FALSE, FALSE,
7399 Xacid_8, FALSE, FALSE,
7403 Xball_1, TRUE, FALSE,
7404 EL_EMC_MAGIC_BALL, -1, -1
7407 Xball_1B, FALSE, FALSE,
7408 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7411 Xball_2, FALSE, FALSE,
7412 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7415 Xball_2B, FALSE, FALSE,
7416 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7419 Yball_eat, FALSE, FALSE,
7420 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
7423 Ykey_1_eat, FALSE, FALSE,
7424 EL_EM_KEY_1, ACTION_COLLECTING, -1
7427 Ykey_2_eat, FALSE, FALSE,
7428 EL_EM_KEY_2, ACTION_COLLECTING, -1
7431 Ykey_3_eat, FALSE, FALSE,
7432 EL_EM_KEY_3, ACTION_COLLECTING, -1
7435 Ykey_4_eat, FALSE, FALSE,
7436 EL_EM_KEY_4, ACTION_COLLECTING, -1
7439 Ykey_5_eat, FALSE, FALSE,
7440 EL_EMC_KEY_5, ACTION_COLLECTING, -1
7443 Ykey_6_eat, FALSE, FALSE,
7444 EL_EMC_KEY_6, ACTION_COLLECTING, -1
7447 Ykey_7_eat, FALSE, FALSE,
7448 EL_EMC_KEY_7, ACTION_COLLECTING, -1
7451 Ykey_8_eat, FALSE, FALSE,
7452 EL_EMC_KEY_8, ACTION_COLLECTING, -1
7455 Ylenses_eat, FALSE, FALSE,
7456 EL_EMC_LENSES, ACTION_COLLECTING, -1
7459 Ymagnify_eat, FALSE, FALSE,
7460 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
7463 Ygrass_eat, FALSE, FALSE,
7464 EL_EMC_GRASS, ACTION_SNAPPING, -1
7467 Ydirt_eat, FALSE, FALSE,
7468 EL_SAND, ACTION_SNAPPING, -1
7471 Xgrow_ns, TRUE, FALSE,
7472 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
7475 Ygrow_ns_eat, FALSE, FALSE,
7476 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
7479 Xgrow_ew, TRUE, FALSE,
7480 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
7483 Ygrow_ew_eat, FALSE, FALSE,
7484 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
7487 Xwonderwall, TRUE, FALSE,
7488 EL_MAGIC_WALL, -1, -1
7491 XwonderwallB, FALSE, FALSE,
7492 EL_MAGIC_WALL, ACTION_ACTIVE, -1
7495 Xamoeba_1, TRUE, FALSE,
7496 EL_AMOEBA_DRY, ACTION_OTHER, -1
7499 Xamoeba_2, FALSE, FALSE,
7500 EL_AMOEBA_DRY, ACTION_OTHER, -1
7503 Xamoeba_3, FALSE, FALSE,
7504 EL_AMOEBA_DRY, ACTION_OTHER, -1
7507 Xamoeba_4, FALSE, FALSE,
7508 EL_AMOEBA_DRY, ACTION_OTHER, -1
7511 Xamoeba_5, TRUE, FALSE,
7512 EL_AMOEBA_WET, ACTION_OTHER, -1
7515 Xamoeba_6, FALSE, FALSE,
7516 EL_AMOEBA_WET, ACTION_OTHER, -1
7519 Xamoeba_7, FALSE, FALSE,
7520 EL_AMOEBA_WET, ACTION_OTHER, -1
7523 Xamoeba_8, FALSE, FALSE,
7524 EL_AMOEBA_WET, ACTION_OTHER, -1
7527 Xdoor_1, TRUE, FALSE,
7528 EL_EM_GATE_1, -1, -1
7531 Xdoor_2, TRUE, FALSE,
7532 EL_EM_GATE_2, -1, -1
7535 Xdoor_3, TRUE, FALSE,
7536 EL_EM_GATE_3, -1, -1
7539 Xdoor_4, TRUE, FALSE,
7540 EL_EM_GATE_4, -1, -1
7543 Xdoor_5, TRUE, FALSE,
7544 EL_EMC_GATE_5, -1, -1
7547 Xdoor_6, TRUE, FALSE,
7548 EL_EMC_GATE_6, -1, -1
7551 Xdoor_7, TRUE, FALSE,
7552 EL_EMC_GATE_7, -1, -1
7555 Xdoor_8, TRUE, FALSE,
7556 EL_EMC_GATE_8, -1, -1
7559 Xkey_1, TRUE, FALSE,
7563 Xkey_2, TRUE, FALSE,
7567 Xkey_3, TRUE, FALSE,
7571 Xkey_4, TRUE, FALSE,
7575 Xkey_5, TRUE, FALSE,
7576 EL_EMC_KEY_5, -1, -1
7579 Xkey_6, TRUE, FALSE,
7580 EL_EMC_KEY_6, -1, -1
7583 Xkey_7, TRUE, FALSE,
7584 EL_EMC_KEY_7, -1, -1
7587 Xkey_8, TRUE, FALSE,
7588 EL_EMC_KEY_8, -1, -1
7591 Xwind_n, TRUE, FALSE,
7592 EL_BALLOON_SWITCH_UP, -1, -1
7595 Xwind_e, TRUE, FALSE,
7596 EL_BALLOON_SWITCH_RIGHT, -1, -1
7599 Xwind_s, TRUE, FALSE,
7600 EL_BALLOON_SWITCH_DOWN, -1, -1
7603 Xwind_w, TRUE, FALSE,
7604 EL_BALLOON_SWITCH_LEFT, -1, -1
7607 Xwind_nesw, TRUE, FALSE,
7608 EL_BALLOON_SWITCH_ANY, -1, -1
7611 Xwind_stop, TRUE, FALSE,
7612 EL_BALLOON_SWITCH_NONE, -1, -1
7616 EL_EM_EXIT_CLOSED, -1, -1
7619 Xexit_1, TRUE, FALSE,
7620 EL_EM_EXIT_OPEN, -1, -1
7623 Xexit_2, FALSE, FALSE,
7624 EL_EM_EXIT_OPEN, -1, -1
7627 Xexit_3, FALSE, FALSE,
7628 EL_EM_EXIT_OPEN, -1, -1
7631 Xdynamite, TRUE, FALSE,
7632 EL_EM_DYNAMITE, -1, -1
7635 Ydynamite_eat, FALSE, FALSE,
7636 EL_EM_DYNAMITE, ACTION_COLLECTING, -1
7639 Xdynamite_1, TRUE, FALSE,
7640 EL_EM_DYNAMITE_ACTIVE, -1, -1
7643 Xdynamite_2, FALSE, FALSE,
7644 EL_EM_DYNAMITE_ACTIVE, -1, -1
7647 Xdynamite_3, FALSE, FALSE,
7648 EL_EM_DYNAMITE_ACTIVE, -1, -1
7651 Xdynamite_4, FALSE, FALSE,
7652 EL_EM_DYNAMITE_ACTIVE, -1, -1
7655 Xbumper, TRUE, FALSE,
7656 EL_EMC_SPRING_BUMPER, -1, -1
7659 XbumperB, FALSE, FALSE,
7660 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
7663 Xwheel, TRUE, FALSE,
7664 EL_ROBOT_WHEEL, -1, -1
7667 XwheelB, FALSE, FALSE,
7668 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
7671 Xswitch, TRUE, FALSE,
7672 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
7675 XswitchB, FALSE, FALSE,
7676 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
7680 EL_QUICKSAND_EMPTY, -1, -1
7683 Xsand_stone, TRUE, FALSE,
7684 EL_QUICKSAND_FULL, -1, -1
7687 Xsand_stonein_1, FALSE, TRUE,
7688 EL_ROCK, ACTION_FILLING, -1
7691 Xsand_stonein_2, FALSE, TRUE,
7692 EL_ROCK, ACTION_FILLING, -1
7695 Xsand_stonein_3, FALSE, TRUE,
7696 EL_ROCK, ACTION_FILLING, -1
7699 Xsand_stonein_4, FALSE, TRUE,
7700 EL_ROCK, ACTION_FILLING, -1
7704 Xsand_stonesand_1, FALSE, FALSE,
7705 EL_QUICKSAND_EMPTYING, -1, -1
7708 Xsand_stonesand_2, FALSE, FALSE,
7709 EL_QUICKSAND_EMPTYING, -1, -1
7712 Xsand_stonesand_3, FALSE, FALSE,
7713 EL_QUICKSAND_EMPTYING, -1, -1
7716 Xsand_stonesand_4, FALSE, FALSE,
7717 EL_QUICKSAND_EMPTYING, -1, -1
7720 Xsand_stonesand_quickout_1, FALSE, FALSE,
7721 EL_QUICKSAND_EMPTYING, -1, -1
7724 Xsand_stonesand_quickout_2, FALSE, FALSE,
7725 EL_QUICKSAND_EMPTYING, -1, -1
7729 Xsand_stonesand_1, FALSE, FALSE,
7730 EL_QUICKSAND_FULL, -1, -1
7733 Xsand_stonesand_2, FALSE, FALSE,
7734 EL_QUICKSAND_FULL, -1, -1
7737 Xsand_stonesand_3, FALSE, FALSE,
7738 EL_QUICKSAND_FULL, -1, -1
7741 Xsand_stonesand_4, FALSE, FALSE,
7742 EL_QUICKSAND_FULL, -1, -1
7746 Xsand_stoneout_1, FALSE, FALSE,
7747 EL_ROCK, ACTION_EMPTYING, -1
7750 Xsand_stoneout_2, FALSE, FALSE,
7751 EL_ROCK, ACTION_EMPTYING, -1
7755 Xsand_sandstone_1, FALSE, FALSE,
7756 EL_QUICKSAND_FILLING, -1, -1
7759 Xsand_sandstone_2, FALSE, FALSE,
7760 EL_QUICKSAND_FILLING, -1, -1
7763 Xsand_sandstone_3, FALSE, FALSE,
7764 EL_QUICKSAND_FILLING, -1, -1
7767 Xsand_sandstone_4, FALSE, FALSE,
7768 EL_QUICKSAND_FILLING, -1, -1
7772 Xsand_sandstone_1, FALSE, FALSE,
7773 EL_QUICKSAND_FULL, -1, -1
7776 Xsand_sandstone_2, FALSE, FALSE,
7777 EL_QUICKSAND_FULL, -1, -1
7780 Xsand_sandstone_3, FALSE, FALSE,
7781 EL_QUICKSAND_FULL, -1, -1
7784 Xsand_sandstone_4, FALSE, FALSE,
7785 EL_QUICKSAND_FULL, -1, -1
7789 Xplant, TRUE, FALSE,
7790 EL_EMC_PLANT, -1, -1
7793 Yplant, FALSE, FALSE,
7794 EL_EMC_PLANT, -1, -1
7797 Xlenses, TRUE, FALSE,
7798 EL_EMC_LENSES, -1, -1
7801 Xmagnify, TRUE, FALSE,
7802 EL_EMC_MAGNIFIER, -1, -1
7805 Xdripper, TRUE, FALSE,
7806 EL_EMC_DRIPPER, -1, -1
7809 XdripperB, FALSE, FALSE,
7810 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
7813 Xfake_blank, TRUE, FALSE,
7814 EL_INVISIBLE_WALL, -1, -1
7817 Xfake_blankB, FALSE, FALSE,
7818 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
7821 Xfake_grass, TRUE, FALSE,
7822 EL_EMC_FAKE_GRASS, -1, -1
7825 Xfake_grassB, FALSE, FALSE,
7826 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
7829 Xfake_door_1, TRUE, FALSE,
7830 EL_EM_GATE_1_GRAY, -1, -1
7833 Xfake_door_2, TRUE, FALSE,
7834 EL_EM_GATE_2_GRAY, -1, -1
7837 Xfake_door_3, TRUE, FALSE,
7838 EL_EM_GATE_3_GRAY, -1, -1
7841 Xfake_door_4, TRUE, FALSE,
7842 EL_EM_GATE_4_GRAY, -1, -1
7845 Xfake_door_5, TRUE, FALSE,
7846 EL_EMC_GATE_5_GRAY, -1, -1
7849 Xfake_door_6, TRUE, FALSE,
7850 EL_EMC_GATE_6_GRAY, -1, -1
7853 Xfake_door_7, TRUE, FALSE,
7854 EL_EMC_GATE_7_GRAY, -1, -1
7857 Xfake_door_8, TRUE, FALSE,
7858 EL_EMC_GATE_8_GRAY, -1, -1
7861 Xfake_acid_1, TRUE, FALSE,
7862 EL_EMC_FAKE_ACID, -1, -1
7865 Xfake_acid_2, FALSE, FALSE,
7866 EL_EMC_FAKE_ACID, -1, -1
7869 Xfake_acid_3, FALSE, FALSE,
7870 EL_EMC_FAKE_ACID, -1, -1
7873 Xfake_acid_4, FALSE, FALSE,
7874 EL_EMC_FAKE_ACID, -1, -1
7877 Xfake_acid_5, FALSE, FALSE,
7878 EL_EMC_FAKE_ACID, -1, -1
7881 Xfake_acid_6, FALSE, FALSE,
7882 EL_EMC_FAKE_ACID, -1, -1
7885 Xfake_acid_7, FALSE, FALSE,
7886 EL_EMC_FAKE_ACID, -1, -1
7889 Xfake_acid_8, FALSE, FALSE,
7890 EL_EMC_FAKE_ACID, -1, -1
7893 Xsteel_1, TRUE, FALSE,
7894 EL_STEELWALL, -1, -1
7897 Xsteel_2, TRUE, FALSE,
7898 EL_EMC_STEELWALL_2, -1, -1
7901 Xsteel_3, TRUE, FALSE,
7902 EL_EMC_STEELWALL_3, -1, -1
7905 Xsteel_4, TRUE, FALSE,
7906 EL_EMC_STEELWALL_4, -1, -1
7909 Xwall_1, TRUE, FALSE,
7913 Xwall_2, TRUE, FALSE,
7914 EL_EMC_WALL_14, -1, -1
7917 Xwall_3, TRUE, FALSE,
7918 EL_EMC_WALL_15, -1, -1
7921 Xwall_4, TRUE, FALSE,
7922 EL_EMC_WALL_16, -1, -1
7925 Xround_wall_1, TRUE, FALSE,
7926 EL_WALL_SLIPPERY, -1, -1
7929 Xround_wall_2, TRUE, FALSE,
7930 EL_EMC_WALL_SLIPPERY_2, -1, -1
7933 Xround_wall_3, TRUE, FALSE,
7934 EL_EMC_WALL_SLIPPERY_3, -1, -1
7937 Xround_wall_4, TRUE, FALSE,
7938 EL_EMC_WALL_SLIPPERY_4, -1, -1
7941 Xdecor_1, TRUE, FALSE,
7942 EL_EMC_WALL_8, -1, -1
7945 Xdecor_2, TRUE, FALSE,
7946 EL_EMC_WALL_6, -1, -1
7949 Xdecor_3, TRUE, FALSE,
7950 EL_EMC_WALL_4, -1, -1
7953 Xdecor_4, TRUE, FALSE,
7954 EL_EMC_WALL_7, -1, -1
7957 Xdecor_5, TRUE, FALSE,
7958 EL_EMC_WALL_5, -1, -1
7961 Xdecor_6, TRUE, FALSE,
7962 EL_EMC_WALL_9, -1, -1
7965 Xdecor_7, TRUE, FALSE,
7966 EL_EMC_WALL_10, -1, -1
7969 Xdecor_8, TRUE, FALSE,
7970 EL_EMC_WALL_1, -1, -1
7973 Xdecor_9, TRUE, FALSE,
7974 EL_EMC_WALL_2, -1, -1
7977 Xdecor_10, TRUE, FALSE,
7978 EL_EMC_WALL_3, -1, -1
7981 Xdecor_11, TRUE, FALSE,
7982 EL_EMC_WALL_11, -1, -1
7985 Xdecor_12, TRUE, FALSE,
7986 EL_EMC_WALL_12, -1, -1
7989 Xalpha_0, TRUE, FALSE,
7990 EL_CHAR('0'), -1, -1
7993 Xalpha_1, TRUE, FALSE,
7994 EL_CHAR('1'), -1, -1
7997 Xalpha_2, TRUE, FALSE,
7998 EL_CHAR('2'), -1, -1
8001 Xalpha_3, TRUE, FALSE,
8002 EL_CHAR('3'), -1, -1
8005 Xalpha_4, TRUE, FALSE,
8006 EL_CHAR('4'), -1, -1
8009 Xalpha_5, TRUE, FALSE,
8010 EL_CHAR('5'), -1, -1
8013 Xalpha_6, TRUE, FALSE,
8014 EL_CHAR('6'), -1, -1
8017 Xalpha_7, TRUE, FALSE,
8018 EL_CHAR('7'), -1, -1
8021 Xalpha_8, TRUE, FALSE,
8022 EL_CHAR('8'), -1, -1
8025 Xalpha_9, TRUE, FALSE,
8026 EL_CHAR('9'), -1, -1
8029 Xalpha_excla, TRUE, FALSE,
8030 EL_CHAR('!'), -1, -1
8033 Xalpha_quote, TRUE, FALSE,
8034 EL_CHAR('"'), -1, -1
8037 Xalpha_comma, TRUE, FALSE,
8038 EL_CHAR(','), -1, -1
8041 Xalpha_minus, TRUE, FALSE,
8042 EL_CHAR('-'), -1, -1
8045 Xalpha_perio, TRUE, FALSE,
8046 EL_CHAR('.'), -1, -1
8049 Xalpha_colon, TRUE, FALSE,
8050 EL_CHAR(':'), -1, -1
8053 Xalpha_quest, TRUE, FALSE,
8054 EL_CHAR('?'), -1, -1
8057 Xalpha_a, TRUE, FALSE,
8058 EL_CHAR('A'), -1, -1
8061 Xalpha_b, TRUE, FALSE,
8062 EL_CHAR('B'), -1, -1
8065 Xalpha_c, TRUE, FALSE,
8066 EL_CHAR('C'), -1, -1
8069 Xalpha_d, TRUE, FALSE,
8070 EL_CHAR('D'), -1, -1
8073 Xalpha_e, TRUE, FALSE,
8074 EL_CHAR('E'), -1, -1
8077 Xalpha_f, TRUE, FALSE,
8078 EL_CHAR('F'), -1, -1
8081 Xalpha_g, TRUE, FALSE,
8082 EL_CHAR('G'), -1, -1
8085 Xalpha_h, TRUE, FALSE,
8086 EL_CHAR('H'), -1, -1
8089 Xalpha_i, TRUE, FALSE,
8090 EL_CHAR('I'), -1, -1
8093 Xalpha_j, TRUE, FALSE,
8094 EL_CHAR('J'), -1, -1
8097 Xalpha_k, TRUE, FALSE,
8098 EL_CHAR('K'), -1, -1
8101 Xalpha_l, TRUE, FALSE,
8102 EL_CHAR('L'), -1, -1
8105 Xalpha_m, TRUE, FALSE,
8106 EL_CHAR('M'), -1, -1
8109 Xalpha_n, TRUE, FALSE,
8110 EL_CHAR('N'), -1, -1
8113 Xalpha_o, TRUE, FALSE,
8114 EL_CHAR('O'), -1, -1
8117 Xalpha_p, TRUE, FALSE,
8118 EL_CHAR('P'), -1, -1
8121 Xalpha_q, TRUE, FALSE,
8122 EL_CHAR('Q'), -1, -1
8125 Xalpha_r, TRUE, FALSE,
8126 EL_CHAR('R'), -1, -1
8129 Xalpha_s, TRUE, FALSE,
8130 EL_CHAR('S'), -1, -1
8133 Xalpha_t, TRUE, FALSE,
8134 EL_CHAR('T'), -1, -1
8137 Xalpha_u, TRUE, FALSE,
8138 EL_CHAR('U'), -1, -1
8141 Xalpha_v, TRUE, FALSE,
8142 EL_CHAR('V'), -1, -1
8145 Xalpha_w, TRUE, FALSE,
8146 EL_CHAR('W'), -1, -1
8149 Xalpha_x, TRUE, FALSE,
8150 EL_CHAR('X'), -1, -1
8153 Xalpha_y, TRUE, FALSE,
8154 EL_CHAR('Y'), -1, -1
8157 Xalpha_z, TRUE, FALSE,
8158 EL_CHAR('Z'), -1, -1
8161 Xalpha_arrow_e, TRUE, FALSE,
8162 EL_CHAR('>'), -1, -1
8165 Xalpha_arrow_w, TRUE, FALSE,
8166 EL_CHAR('<'), -1, -1
8169 Xalpha_copyr, TRUE, FALSE,
8170 EL_CHAR('©'), -1, -1
8174 Xboom_bug, FALSE, FALSE,
8175 EL_BUG, ACTION_EXPLODING, -1
8178 Xboom_bomb, FALSE, FALSE,
8179 EL_BOMB, ACTION_EXPLODING, -1
8182 Xboom_android, FALSE, FALSE,
8183 EL_EMC_ANDROID, ACTION_OTHER, -1
8186 Xboom_1, FALSE, FALSE,
8187 EL_DEFAULT, ACTION_EXPLODING, -1
8190 Xboom_2, FALSE, FALSE,
8191 EL_DEFAULT, ACTION_EXPLODING, -1
8194 Znormal, FALSE, FALSE,
8198 Zdynamite, FALSE, FALSE,
8202 Zplayer, FALSE, FALSE,
8206 ZBORDER, FALSE, FALSE,
8216 static struct Mapping_EM_to_RND_player
8225 em_player_mapping_list[] =
8229 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
8233 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
8237 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
8241 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
8245 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
8249 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
8253 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
8257 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
8261 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
8265 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
8269 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
8273 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
8277 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
8281 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
8285 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
8289 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
8293 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
8297 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
8301 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
8305 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
8309 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
8313 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
8317 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
8321 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
8325 EL_PLAYER_1, ACTION_DEFAULT, -1,
8329 EL_PLAYER_2, ACTION_DEFAULT, -1,
8333 EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
8337 EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
8341 EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
8345 EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
8349 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
8353 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
8357 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
8361 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
8365 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
8369 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
8373 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
8377 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
8381 EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
8385 EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
8389 EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
8393 EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
8397 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
8401 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
8405 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
8409 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
8413 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
8417 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
8421 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
8425 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
8429 EL_PLAYER_3, ACTION_DEFAULT, -1,
8433 EL_PLAYER_4, ACTION_DEFAULT, -1,
8442 int map_element_RND_to_EM(int element_rnd)
8444 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
8445 static boolean mapping_initialized = FALSE;
8447 if (!mapping_initialized)
8451 /* return "Xalpha_quest" for all undefined elements in mapping array */
8452 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
8453 mapping_RND_to_EM[i] = Xalpha_quest;
8455 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
8456 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
8457 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
8458 em_object_mapping_list[i].element_em;
8460 mapping_initialized = TRUE;
8463 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
8464 return mapping_RND_to_EM[element_rnd];
8466 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
8471 int map_element_EM_to_RND(int element_em)
8473 static unsigned short mapping_EM_to_RND[TILE_MAX];
8474 static boolean mapping_initialized = FALSE;
8476 if (!mapping_initialized)
8480 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
8481 for (i = 0; i < TILE_MAX; i++)
8482 mapping_EM_to_RND[i] = EL_UNKNOWN;
8484 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
8485 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
8486 em_object_mapping_list[i].element_rnd;
8488 mapping_initialized = TRUE;
8491 if (element_em >= 0 && element_em < TILE_MAX)
8492 return mapping_EM_to_RND[element_em];
8494 Error(ERR_WARN, "invalid EM level element %d", element_em);
8499 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
8501 struct LevelInfo_EM *level_em = level->native_em_level;
8502 struct LEVEL *lev = level_em->lev;
8505 for (i = 0; i < TILE_MAX; i++)
8506 lev->android_array[i] = Xblank;
8508 for (i = 0; i < level->num_android_clone_elements; i++)
8510 int element_rnd = level->android_clone_element[i];
8511 int element_em = map_element_RND_to_EM(element_rnd);
8513 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
8514 if (em_object_mapping_list[j].element_rnd == element_rnd)
8515 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
8519 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
8521 struct LevelInfo_EM *level_em = level->native_em_level;
8522 struct LEVEL *lev = level_em->lev;
8525 level->num_android_clone_elements = 0;
8527 for (i = 0; i < TILE_MAX; i++)
8529 int element_em = lev->android_array[i];
8531 boolean element_found = FALSE;
8533 if (element_em == Xblank)
8536 element_rnd = map_element_EM_to_RND(element_em);
8538 for (j = 0; j < level->num_android_clone_elements; j++)
8539 if (level->android_clone_element[j] == element_rnd)
8540 element_found = TRUE;
8544 level->android_clone_element[level->num_android_clone_elements++] =
8547 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
8552 if (level->num_android_clone_elements == 0)
8554 level->num_android_clone_elements = 1;
8555 level->android_clone_element[0] = EL_EMPTY;
8559 int map_direction_RND_to_EM(int direction)
8561 return (direction == MV_UP ? 0 :
8562 direction == MV_RIGHT ? 1 :
8563 direction == MV_DOWN ? 2 :
8564 direction == MV_LEFT ? 3 :
8568 int map_direction_EM_to_RND(int direction)
8570 return (direction == 0 ? MV_UP :
8571 direction == 1 ? MV_RIGHT :
8572 direction == 2 ? MV_DOWN :
8573 direction == 3 ? MV_LEFT :
8577 int map_element_RND_to_SP(int element_rnd)
8579 int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
8581 if (element_rnd >= EL_SP_START &&
8582 element_rnd <= EL_SP_END)
8583 element_sp = element_rnd - EL_SP_START;
8584 else if (element_rnd == EL_EMPTY_SPACE)
8586 else if (element_rnd == EL_INVISIBLE_WALL)
8592 int map_element_SP_to_RND(int element_sp)
8594 int element_rnd = EL_UNKNOWN;
8596 if (element_sp >= 0x00 &&
8598 element_rnd = EL_SP_START + element_sp;
8599 else if (element_sp == 0x28)
8600 element_rnd = EL_INVISIBLE_WALL;
8605 int map_action_SP_to_RND(int action_sp)
8609 case actActive: return ACTION_ACTIVE;
8610 case actImpact: return ACTION_IMPACT;
8611 case actExploding: return ACTION_EXPLODING;
8612 case actDigging: return ACTION_DIGGING;
8613 case actSnapping: return ACTION_SNAPPING;
8614 case actCollecting: return ACTION_COLLECTING;
8615 case actPassing: return ACTION_PASSING;
8616 case actPushing: return ACTION_PUSHING;
8617 case actDropping: return ACTION_DROPPING;
8619 default: return ACTION_DEFAULT;
8623 int get_next_element(int element)
8627 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
8628 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
8629 case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL;
8630 case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY;
8631 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
8632 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
8633 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
8634 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
8635 case EL_DC_MAGIC_WALL_FILLING: return EL_DC_MAGIC_WALL_FULL;
8636 case EL_DC_MAGIC_WALL_EMPTYING: return EL_DC_MAGIC_WALL_ACTIVE;
8637 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
8639 default: return element;
8644 int el_act_dir2img(int element, int action, int direction)
8646 element = GFX_ELEMENT(element);
8648 if (direction == MV_NONE)
8649 return element_info[element].graphic[action];
8651 direction = MV_DIR_TO_BIT(direction);
8653 return element_info[element].direction_graphic[action][direction];
8656 int el_act_dir2img(int element, int action, int direction)
8658 element = GFX_ELEMENT(element);
8659 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
8661 /* direction_graphic[][] == graphic[] for undefined direction graphics */
8662 return element_info[element].direction_graphic[action][direction];
8667 static int el_act_dir2crm(int element, int action, int direction)
8669 element = GFX_ELEMENT(element);
8671 if (direction == MV_NONE)
8672 return element_info[element].crumbled[action];
8674 direction = MV_DIR_TO_BIT(direction);
8676 return element_info[element].direction_crumbled[action][direction];
8679 static int el_act_dir2crm(int element, int action, int direction)
8681 element = GFX_ELEMENT(element);
8682 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
8684 /* direction_graphic[][] == graphic[] for undefined direction graphics */
8685 return element_info[element].direction_crumbled[action][direction];
8689 int el_act2img(int element, int action)
8691 element = GFX_ELEMENT(element);
8693 return element_info[element].graphic[action];
8696 int el_act2crm(int element, int action)
8698 element = GFX_ELEMENT(element);
8700 return element_info[element].crumbled[action];
8703 int el_dir2img(int element, int direction)
8705 element = GFX_ELEMENT(element);
8707 return el_act_dir2img(element, ACTION_DEFAULT, direction);
8710 int el2baseimg(int element)
8712 return element_info[element].graphic[ACTION_DEFAULT];
8715 int el2img(int element)
8717 element = GFX_ELEMENT(element);
8719 return element_info[element].graphic[ACTION_DEFAULT];
8722 int el2edimg(int element)
8724 element = GFX_ELEMENT(element);
8726 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
8729 int el2preimg(int element)
8731 element = GFX_ELEMENT(element);
8733 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
8736 int el2panelimg(int element)
8738 element = GFX_ELEMENT(element);
8740 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PANEL];
8743 int font2baseimg(int font_nr)
8745 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
8748 int getBeltNrFromBeltElement(int element)
8750 return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 :
8751 element < EL_CONVEYOR_BELT_3_LEFT ? 1 :
8752 element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3);
8755 int getBeltNrFromBeltActiveElement(int element)
8757 return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 :
8758 element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 :
8759 element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3);
8762 int getBeltNrFromBeltSwitchElement(int element)
8764 return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 :
8765 element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 :
8766 element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3);
8769 int getBeltDirNrFromBeltElement(int element)
8771 static int belt_base_element[4] =
8773 EL_CONVEYOR_BELT_1_LEFT,
8774 EL_CONVEYOR_BELT_2_LEFT,
8775 EL_CONVEYOR_BELT_3_LEFT,
8776 EL_CONVEYOR_BELT_4_LEFT
8779 int belt_nr = getBeltNrFromBeltElement(element);
8780 int belt_dir_nr = element - belt_base_element[belt_nr];
8782 return (belt_dir_nr % 3);
8785 int getBeltDirNrFromBeltSwitchElement(int element)
8787 static int belt_base_element[4] =
8789 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
8790 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
8791 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
8792 EL_CONVEYOR_BELT_4_SWITCH_LEFT
8795 int belt_nr = getBeltNrFromBeltSwitchElement(element);
8796 int belt_dir_nr = element - belt_base_element[belt_nr];
8798 return (belt_dir_nr % 3);
8801 int getBeltDirFromBeltElement(int element)
8803 static int belt_move_dir[3] =
8810 int belt_dir_nr = getBeltDirNrFromBeltElement(element);
8812 return belt_move_dir[belt_dir_nr];
8815 int getBeltDirFromBeltSwitchElement(int element)
8817 static int belt_move_dir[3] =
8824 int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(element);
8826 return belt_move_dir[belt_dir_nr];
8829 int getBeltElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
8831 static int belt_base_element[4] =
8833 EL_CONVEYOR_BELT_1_LEFT,
8834 EL_CONVEYOR_BELT_2_LEFT,
8835 EL_CONVEYOR_BELT_3_LEFT,
8836 EL_CONVEYOR_BELT_4_LEFT
8839 return belt_base_element[belt_nr] + belt_dir_nr;
8842 int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
8844 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
8846 return getBeltElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
8849 int getBeltSwitchElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
8851 static int belt_base_element[4] =
8853 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
8854 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
8855 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
8856 EL_CONVEYOR_BELT_4_SWITCH_LEFT
8859 return belt_base_element[belt_nr] + belt_dir_nr;
8862 int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
8864 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
8866 return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
8870 boolean getTeamMode_EM()
8872 return game.team_mode;
8875 int getNumActivePlayers_EM()
8878 int num_players = 0;
8882 return (setup.team_mode ? MAX_PLAYERS : 1);
8884 for (i = 0; i < MAX_PLAYERS; i++)
8885 if (tape.player_participates[i])
8888 return (num_players > 1 ? MAX_PLAYERS : 1);
8892 int num_players = 0;
8895 /* when recording game, activate all connected players */
8899 for (i = 0; i < MAX_PLAYERS; i++)
8900 if (tape.player_participates[i])
8908 int getGameFrameDelay_EM(int native_em_game_frame_delay)
8910 int game_frame_delay_value;
8912 game_frame_delay_value =
8913 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
8914 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
8917 if (tape.playing && tape.warp_forward && !tape.pausing)
8918 game_frame_delay_value = 0;
8920 return game_frame_delay_value;
8923 unsigned int InitRND(int seed)
8925 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
8926 return InitEngineRandom_EM(seed);
8927 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
8928 return InitEngineRandom_SP(seed);
8930 return InitEngineRandom_RND(seed);
8934 static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
8935 static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
8938 inline static int get_effective_element_EM(int tile, int frame_em)
8940 int element = object_mapping[tile].element_rnd;
8941 int action = object_mapping[tile].action;
8942 boolean is_backside = object_mapping[tile].is_backside;
8943 boolean action_removing = (action == ACTION_DIGGING ||
8944 action == ACTION_SNAPPING ||
8945 action == ACTION_COLLECTING);
8951 case Yacid_splash_eB:
8952 case Yacid_splash_wB:
8953 return (frame_em > 5 ? EL_EMPTY : element);
8957 case Ydiamond_stone:
8958 // if (!game.use_native_emc_graphics_engine)
8966 else /* frame_em == 7 */
8970 case Yacid_splash_eB:
8971 case Yacid_splash_wB:
8974 case Yemerald_stone:
8977 case Ydiamond_stone:
8981 case Xdrip_stretchB:
9000 case Xsand_stonein_1:
9001 case Xsand_stonein_2:
9002 case Xsand_stonein_3:
9003 case Xsand_stonein_4:
9007 return (is_backside || action_removing ? EL_EMPTY : element);
9012 inline static boolean check_linear_animation_EM(int tile)
9016 case Xsand_stonesand_1:
9017 case Xsand_stonesand_quickout_1:
9018 case Xsand_sandstone_1:
9019 case Xsand_stonein_1:
9020 case Xsand_stoneout_1:
9040 case Yacid_splash_eB:
9041 case Yacid_splash_wB:
9042 case Yemerald_stone:
9050 inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
9051 boolean has_crumbled_graphics,
9052 int crumbled, int sync_frame)
9054 /* if element can be crumbled, but certain action graphics are just empty
9055 space (like instantly snapping sand to empty space in 1 frame), do not
9056 treat these empty space graphics as crumbled graphics in EMC engine */
9057 if (crumbled == IMG_EMPTY_SPACE)
9058 has_crumbled_graphics = FALSE;
9060 if (has_crumbled_graphics)
9062 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9063 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
9064 g_crumbled->anim_delay,
9065 g_crumbled->anim_mode,
9066 g_crumbled->anim_start_frame,
9069 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
9070 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
9072 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
9074 g_em->has_crumbled_graphics = TRUE;
9078 g_em->crumbled_bitmap = NULL;
9079 g_em->crumbled_src_x = 0;
9080 g_em->crumbled_src_y = 0;
9081 g_em->crumbled_border_size = 0;
9083 g_em->has_crumbled_graphics = FALSE;
9087 void ResetGfxAnimation_EM(int x, int y, int tile)
9092 void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
9093 int tile, int frame_em, int x, int y)
9095 int action = object_mapping[tile].action;
9097 int direction = object_mapping[tile].direction;
9098 int effective_element = get_effective_element_EM(tile, frame_em);
9099 int graphic = (direction == MV_NONE ?
9100 el_act2img(effective_element, action) :
9101 el_act_dir2img(effective_element, action, direction));
9102 struct GraphicInfo *g = &graphic_info[graphic];
9105 boolean action_removing = (action == ACTION_DIGGING ||
9106 action == ACTION_SNAPPING ||
9107 action == ACTION_COLLECTING);
9108 boolean action_moving = (action == ACTION_FALLING ||
9109 action == ACTION_MOVING ||
9110 action == ACTION_PUSHING ||
9111 action == ACTION_EATING ||
9112 action == ACTION_FILLING ||
9113 action == ACTION_EMPTYING);
9114 boolean action_falling = (action == ACTION_FALLING ||
9115 action == ACTION_FILLING ||
9116 action == ACTION_EMPTYING);
9118 /* special case: graphic uses "2nd movement tile" and has defined
9119 7 frames for movement animation (or less) => use default graphic
9120 for last (8th) frame which ends the movement animation */
9121 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9123 action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
9124 graphic = (direction == MV_NONE ?
9125 el_act2img(effective_element, action) :
9126 el_act_dir2img(effective_element, action, direction));
9128 g = &graphic_info[graphic];
9132 if (tile == Xsand_stonesand_1 ||
9133 tile == Xsand_stonesand_2 ||
9134 tile == Xsand_stonesand_3 ||
9135 tile == Xsand_stonesand_4)
9136 printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9140 if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
9144 // printf("::: resetting... [%d]\n", tile);
9147 if (action_removing || check_linear_animation_EM(tile))
9149 GfxFrame[x][y] = frame_em;
9151 // printf("::: resetting... [%d]\n", tile);
9154 else if (action_moving)
9156 boolean is_backside = object_mapping[tile].is_backside;
9160 int direction = object_mapping[tile].direction;
9161 int move_dir = (action_falling ? MV_DOWN : direction);
9166 /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
9167 if (g->double_movement && frame_em == 0)
9171 // printf("::: resetting... [%d]\n", tile);
9175 if (move_dir == MV_LEFT)
9176 GfxFrame[x - 1][y] = GfxFrame[x][y];
9177 else if (move_dir == MV_RIGHT)
9178 GfxFrame[x + 1][y] = GfxFrame[x][y];
9179 else if (move_dir == MV_UP)
9180 GfxFrame[x][y - 1] = GfxFrame[x][y];
9181 else if (move_dir == MV_DOWN)
9182 GfxFrame[x][y + 1] = GfxFrame[x][y];
9189 /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
9190 if (tile == Xsand_stonesand_quickout_1 ||
9191 tile == Xsand_stonesand_quickout_2)
9196 if (tile == Xsand_stonesand_1 ||
9197 tile == Xsand_stonesand_2 ||
9198 tile == Xsand_stonesand_3 ||
9199 tile == Xsand_stonesand_4)
9200 printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9204 if (graphic_info[graphic].anim_global_sync)
9205 sync_frame = FrameCounter;
9206 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9207 sync_frame = GfxFrame[x][y];
9209 sync_frame = 0; /* playfield border (pseudo steel) */
9211 SetRandomAnimationValue(x, y);
9213 int frame = getAnimationFrame(g->anim_frames,
9216 g->anim_start_frame,
9219 g_em->unique_identifier =
9220 (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
9224 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
9225 int tile, int frame_em, int x, int y)
9227 int action = object_mapping[tile].action;
9228 int direction = object_mapping[tile].direction;
9229 boolean is_backside = object_mapping[tile].is_backside;
9230 int effective_element = get_effective_element_EM(tile, frame_em);
9232 int effective_action = action;
9234 int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
9236 int graphic = (direction == MV_NONE ?
9237 el_act2img(effective_element, effective_action) :
9238 el_act_dir2img(effective_element, effective_action,
9240 int crumbled = (direction == MV_NONE ?
9241 el_act2crm(effective_element, effective_action) :
9242 el_act_dir2crm(effective_element, effective_action,
9244 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
9245 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
9246 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
9247 struct GraphicInfo *g = &graphic_info[graphic];
9249 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9253 /* special case: graphic uses "2nd movement tile" and has defined
9254 7 frames for movement animation (or less) => use default graphic
9255 for last (8th) frame which ends the movement animation */
9256 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9258 effective_action = ACTION_DEFAULT;
9259 graphic = (direction == MV_NONE ?
9260 el_act2img(effective_element, effective_action) :
9261 el_act_dir2img(effective_element, effective_action,
9263 crumbled = (direction == MV_NONE ?
9264 el_act2crm(effective_element, effective_action) :
9265 el_act_dir2crm(effective_element, effective_action,
9268 g = &graphic_info[graphic];
9278 if (frame_em == 0) /* reset animation frame for certain elements */
9280 if (check_linear_animation_EM(tile))
9285 if (graphic_info[graphic].anim_global_sync)
9286 sync_frame = FrameCounter;
9287 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9288 sync_frame = GfxFrame[x][y];
9290 sync_frame = 0; /* playfield border (pseudo steel) */
9292 SetRandomAnimationValue(x, y);
9297 int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
9298 i == Xdrip_stretchB ? 7 :
9299 i == Ydrip_s2 ? j + 8 :
9300 i == Ydrip_s2B ? j + 8 :
9309 i == Xfake_acid_1 ? 0 :
9310 i == Xfake_acid_2 ? 10 :
9311 i == Xfake_acid_3 ? 20 :
9312 i == Xfake_acid_4 ? 30 :
9313 i == Xfake_acid_5 ? 40 :
9314 i == Xfake_acid_6 ? 50 :
9315 i == Xfake_acid_7 ? 60 :
9316 i == Xfake_acid_8 ? 70 :
9318 i == Xball_2B ? j + 8 :
9319 i == Yball_eat ? j + 1 :
9320 i == Ykey_1_eat ? j + 1 :
9321 i == Ykey_2_eat ? j + 1 :
9322 i == Ykey_3_eat ? j + 1 :
9323 i == Ykey_4_eat ? j + 1 :
9324 i == Ykey_5_eat ? j + 1 :
9325 i == Ykey_6_eat ? j + 1 :
9326 i == Ykey_7_eat ? j + 1 :
9327 i == Ykey_8_eat ? j + 1 :
9328 i == Ylenses_eat ? j + 1 :
9329 i == Ymagnify_eat ? j + 1 :
9330 i == Ygrass_eat ? j + 1 :
9331 i == Ydirt_eat ? j + 1 :
9332 i == Xamoeba_1 ? 0 :
9333 i == Xamoeba_2 ? 1 :
9334 i == Xamoeba_3 ? 2 :
9335 i == Xamoeba_4 ? 3 :
9336 i == Xamoeba_5 ? 0 :
9337 i == Xamoeba_6 ? 1 :
9338 i == Xamoeba_7 ? 2 :
9339 i == Xamoeba_8 ? 3 :
9340 i == Xexit_2 ? j + 8 :
9341 i == Xexit_3 ? j + 16 :
9342 i == Xdynamite_1 ? 0 :
9343 i == Xdynamite_2 ? 8 :
9344 i == Xdynamite_3 ? 16 :
9345 i == Xdynamite_4 ? 24 :
9346 i == Xsand_stonein_1 ? j + 1 :
9347 i == Xsand_stonein_2 ? j + 9 :
9348 i == Xsand_stonein_3 ? j + 17 :
9349 i == Xsand_stonein_4 ? j + 25 :
9350 i == Xsand_stoneout_1 && j == 0 ? 0 :
9351 i == Xsand_stoneout_1 && j == 1 ? 0 :
9352 i == Xsand_stoneout_1 && j == 2 ? 1 :
9353 i == Xsand_stoneout_1 && j == 3 ? 2 :
9354 i == Xsand_stoneout_1 && j == 4 ? 2 :
9355 i == Xsand_stoneout_1 && j == 5 ? 3 :
9356 i == Xsand_stoneout_1 && j == 6 ? 4 :
9357 i == Xsand_stoneout_1 && j == 7 ? 4 :
9358 i == Xsand_stoneout_2 && j == 0 ? 5 :
9359 i == Xsand_stoneout_2 && j == 1 ? 6 :
9360 i == Xsand_stoneout_2 && j == 2 ? 7 :
9361 i == Xsand_stoneout_2 && j == 3 ? 8 :
9362 i == Xsand_stoneout_2 && j == 4 ? 9 :
9363 i == Xsand_stoneout_2 && j == 5 ? 11 :
9364 i == Xsand_stoneout_2 && j == 6 ? 13 :
9365 i == Xsand_stoneout_2 && j == 7 ? 15 :
9366 i == Xboom_bug && j == 1 ? 2 :
9367 i == Xboom_bug && j == 2 ? 2 :
9368 i == Xboom_bug && j == 3 ? 4 :
9369 i == Xboom_bug && j == 4 ? 4 :
9370 i == Xboom_bug && j == 5 ? 2 :
9371 i == Xboom_bug && j == 6 ? 2 :
9372 i == Xboom_bug && j == 7 ? 0 :
9373 i == Xboom_bomb && j == 1 ? 2 :
9374 i == Xboom_bomb && j == 2 ? 2 :
9375 i == Xboom_bomb && j == 3 ? 4 :
9376 i == Xboom_bomb && j == 4 ? 4 :
9377 i == Xboom_bomb && j == 5 ? 2 :
9378 i == Xboom_bomb && j == 6 ? 2 :
9379 i == Xboom_bomb && j == 7 ? 0 :
9380 i == Xboom_android && j == 7 ? 6 :
9381 i == Xboom_1 && j == 1 ? 2 :
9382 i == Xboom_1 && j == 2 ? 2 :
9383 i == Xboom_1 && j == 3 ? 4 :
9384 i == Xboom_1 && j == 4 ? 4 :
9385 i == Xboom_1 && j == 5 ? 6 :
9386 i == Xboom_1 && j == 6 ? 6 :
9387 i == Xboom_1 && j == 7 ? 8 :
9388 i == Xboom_2 && j == 0 ? 8 :
9389 i == Xboom_2 && j == 1 ? 8 :
9390 i == Xboom_2 && j == 2 ? 10 :
9391 i == Xboom_2 && j == 3 ? 10 :
9392 i == Xboom_2 && j == 4 ? 10 :
9393 i == Xboom_2 && j == 5 ? 12 :
9394 i == Xboom_2 && j == 6 ? 12 :
9395 i == Xboom_2 && j == 7 ? 12 :
9397 special_animation && j == 4 ? 3 :
9398 effective_action != action ? 0 :
9404 int xxx_effective_action;
9405 int xxx_has_action_graphics;
9408 int element = object_mapping[i].element_rnd;
9409 int action = object_mapping[i].action;
9410 int direction = object_mapping[i].direction;
9411 boolean is_backside = object_mapping[i].is_backside;
9413 boolean action_removing = (action == ACTION_DIGGING ||
9414 action == ACTION_SNAPPING ||
9415 action == ACTION_COLLECTING);
9417 boolean action_exploding = ((action == ACTION_EXPLODING ||
9418 action == ACTION_SMASHED_BY_ROCK ||
9419 action == ACTION_SMASHED_BY_SPRING) &&
9420 element != EL_DIAMOND);
9421 boolean action_active = (action == ACTION_ACTIVE);
9422 boolean action_other = (action == ACTION_OTHER);
9426 int effective_element = get_effective_element_EM(i, j);
9428 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
9429 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
9431 i == Xdrip_stretch ? element :
9432 i == Xdrip_stretchB ? element :
9433 i == Ydrip_s1 ? element :
9434 i == Ydrip_s1B ? element :
9435 i == Xball_1B ? element :
9436 i == Xball_2 ? element :
9437 i == Xball_2B ? element :
9438 i == Yball_eat ? element :
9439 i == Ykey_1_eat ? element :
9440 i == Ykey_2_eat ? element :
9441 i == Ykey_3_eat ? element :
9442 i == Ykey_4_eat ? element :
9443 i == Ykey_5_eat ? element :
9444 i == Ykey_6_eat ? element :
9445 i == Ykey_7_eat ? element :
9446 i == Ykey_8_eat ? element :
9447 i == Ylenses_eat ? element :
9448 i == Ymagnify_eat ? element :
9449 i == Ygrass_eat ? element :
9450 i == Ydirt_eat ? element :
9451 i == Yemerald_stone ? EL_EMERALD :
9452 i == Ydiamond_stone ? EL_ROCK :
9453 i == Xsand_stonein_1 ? element :
9454 i == Xsand_stonein_2 ? element :
9455 i == Xsand_stonein_3 ? element :
9456 i == Xsand_stonein_4 ? element :
9457 is_backside ? EL_EMPTY :
9458 action_removing ? EL_EMPTY :
9461 int effective_action = (j < 7 ? action :
9462 i == Xdrip_stretch ? action :
9463 i == Xdrip_stretchB ? action :
9464 i == Ydrip_s1 ? action :
9465 i == Ydrip_s1B ? action :
9466 i == Xball_1B ? action :
9467 i == Xball_2 ? action :
9468 i == Xball_2B ? action :
9469 i == Yball_eat ? action :
9470 i == Ykey_1_eat ? action :
9471 i == Ykey_2_eat ? action :
9472 i == Ykey_3_eat ? action :
9473 i == Ykey_4_eat ? action :
9474 i == Ykey_5_eat ? action :
9475 i == Ykey_6_eat ? action :
9476 i == Ykey_7_eat ? action :
9477 i == Ykey_8_eat ? action :
9478 i == Ylenses_eat ? action :
9479 i == Ymagnify_eat ? action :
9480 i == Ygrass_eat ? action :
9481 i == Ydirt_eat ? action :
9482 i == Xsand_stonein_1 ? action :
9483 i == Xsand_stonein_2 ? action :
9484 i == Xsand_stonein_3 ? action :
9485 i == Xsand_stonein_4 ? action :
9486 i == Xsand_stoneout_1 ? action :
9487 i == Xsand_stoneout_2 ? action :
9488 i == Xboom_android ? ACTION_EXPLODING :
9489 action_exploding ? ACTION_EXPLODING :
9490 action_active ? action :
9491 action_other ? action :
9493 int graphic = (el_act_dir2img(effective_element, effective_action,
9495 int crumbled = (el_act_dir2crm(effective_element, effective_action,
9497 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
9498 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
9499 boolean has_action_graphics = (graphic != base_graphic);
9500 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
9501 struct GraphicInfo *g = &graphic_info[graphic];
9503 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9505 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
9508 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
9509 boolean special_animation = (action != ACTION_DEFAULT &&
9510 g->anim_frames == 3 &&
9511 g->anim_delay == 2 &&
9512 g->anim_mode & ANIM_LINEAR);
9513 xxx_sync_frame = (i == Xdrip_stretch ? 7 :
9514 i == Xdrip_stretchB ? 7 :
9515 i == Ydrip_s2 ? j + 8 :
9516 i == Ydrip_s2B ? j + 8 :
9525 i == Xfake_acid_1 ? 0 :
9526 i == Xfake_acid_2 ? 10 :
9527 i == Xfake_acid_3 ? 20 :
9528 i == Xfake_acid_4 ? 30 :
9529 i == Xfake_acid_5 ? 40 :
9530 i == Xfake_acid_6 ? 50 :
9531 i == Xfake_acid_7 ? 60 :
9532 i == Xfake_acid_8 ? 70 :
9534 i == Xball_2B ? j + 8 :
9535 i == Yball_eat ? j + 1 :
9536 i == Ykey_1_eat ? j + 1 :
9537 i == Ykey_2_eat ? j + 1 :
9538 i == Ykey_3_eat ? j + 1 :
9539 i == Ykey_4_eat ? j + 1 :
9540 i == Ykey_5_eat ? j + 1 :
9541 i == Ykey_6_eat ? j + 1 :
9542 i == Ykey_7_eat ? j + 1 :
9543 i == Ykey_8_eat ? j + 1 :
9544 i == Ylenses_eat ? j + 1 :
9545 i == Ymagnify_eat ? j + 1 :
9546 i == Ygrass_eat ? j + 1 :
9547 i == Ydirt_eat ? j + 1 :
9548 i == Xamoeba_1 ? 0 :
9549 i == Xamoeba_2 ? 1 :
9550 i == Xamoeba_3 ? 2 :
9551 i == Xamoeba_4 ? 3 :
9552 i == Xamoeba_5 ? 0 :
9553 i == Xamoeba_6 ? 1 :
9554 i == Xamoeba_7 ? 2 :
9555 i == Xamoeba_8 ? 3 :
9556 i == Xexit_2 ? j + 8 :
9557 i == Xexit_3 ? j + 16 :
9558 i == Xdynamite_1 ? 0 :
9559 i == Xdynamite_2 ? 8 :
9560 i == Xdynamite_3 ? 16 :
9561 i == Xdynamite_4 ? 24 :
9562 i == Xsand_stonein_1 ? j + 1 :
9563 i == Xsand_stonein_2 ? j + 9 :
9564 i == Xsand_stonein_3 ? j + 17 :
9565 i == Xsand_stonein_4 ? j + 25 :
9566 i == Xsand_stoneout_1 && j == 0 ? 0 :
9567 i == Xsand_stoneout_1 && j == 1 ? 0 :
9568 i == Xsand_stoneout_1 && j == 2 ? 1 :
9569 i == Xsand_stoneout_1 && j == 3 ? 2 :
9570 i == Xsand_stoneout_1 && j == 4 ? 2 :
9571 i == Xsand_stoneout_1 && j == 5 ? 3 :
9572 i == Xsand_stoneout_1 && j == 6 ? 4 :
9573 i == Xsand_stoneout_1 && j == 7 ? 4 :
9574 i == Xsand_stoneout_2 && j == 0 ? 5 :
9575 i == Xsand_stoneout_2 && j == 1 ? 6 :
9576 i == Xsand_stoneout_2 && j == 2 ? 7 :
9577 i == Xsand_stoneout_2 && j == 3 ? 8 :
9578 i == Xsand_stoneout_2 && j == 4 ? 9 :
9579 i == Xsand_stoneout_2 && j == 5 ? 11 :
9580 i == Xsand_stoneout_2 && j == 6 ? 13 :
9581 i == Xsand_stoneout_2 && j == 7 ? 15 :
9582 i == Xboom_bug && j == 1 ? 2 :
9583 i == Xboom_bug && j == 2 ? 2 :
9584 i == Xboom_bug && j == 3 ? 4 :
9585 i == Xboom_bug && j == 4 ? 4 :
9586 i == Xboom_bug && j == 5 ? 2 :
9587 i == Xboom_bug && j == 6 ? 2 :
9588 i == Xboom_bug && j == 7 ? 0 :
9589 i == Xboom_bomb && j == 1 ? 2 :
9590 i == Xboom_bomb && j == 2 ? 2 :
9591 i == Xboom_bomb && j == 3 ? 4 :
9592 i == Xboom_bomb && j == 4 ? 4 :
9593 i == Xboom_bomb && j == 5 ? 2 :
9594 i == Xboom_bomb && j == 6 ? 2 :
9595 i == Xboom_bomb && j == 7 ? 0 :
9596 i == Xboom_android && j == 7 ? 6 :
9597 i == Xboom_1 && j == 1 ? 2 :
9598 i == Xboom_1 && j == 2 ? 2 :
9599 i == Xboom_1 && j == 3 ? 4 :
9600 i == Xboom_1 && j == 4 ? 4 :
9601 i == Xboom_1 && j == 5 ? 6 :
9602 i == Xboom_1 && j == 6 ? 6 :
9603 i == Xboom_1 && j == 7 ? 8 :
9604 i == Xboom_2 && j == 0 ? 8 :
9605 i == Xboom_2 && j == 1 ? 8 :
9606 i == Xboom_2 && j == 2 ? 10 :
9607 i == Xboom_2 && j == 3 ? 10 :
9608 i == Xboom_2 && j == 4 ? 10 :
9609 i == Xboom_2 && j == 5 ? 12 :
9610 i == Xboom_2 && j == 6 ? 12 :
9611 i == Xboom_2 && j == 7 ? 12 :
9612 special_animation && j == 4 ? 3 :
9613 effective_action != action ? 0 :
9616 xxx_effective_action = effective_action;
9617 xxx_has_action_graphics = has_action_graphics;
9622 int frame = getAnimationFrame(g->anim_frames,
9625 g->anim_start_frame,
9639 int old_src_x = g_em->src_x;
9640 int old_src_y = g_em->src_y;
9644 getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
9645 g->double_movement && is_backside);
9647 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
9648 &g_em->src_x, &g_em->src_y, FALSE);
9653 if (tile == Ydiamond_stone)
9654 printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n",
9659 g->anim_start_frame,
9662 g_em->src_x, g_em->src_y,
9663 g_em->src_offset_x, g_em->src_offset_y,
9664 g_em->dst_offset_x, g_em->dst_offset_y,
9676 if (graphic == IMG_BUG_MOVING_RIGHT)
9677 printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
9678 g->double_movement, is_backside,
9679 old_src_x, old_src_y, g_em->src_x, g_em->src_y);
9687 g_em->src_offset_x = 0;
9688 g_em->src_offset_y = 0;
9689 g_em->dst_offset_x = 0;
9690 g_em->dst_offset_y = 0;
9691 g_em->width = TILEX;
9692 g_em->height = TILEY;
9694 g_em->preserve_background = FALSE;
9697 /* (updating the "crumbled" graphic definitions is probably not really needed,
9698 as animations for crumbled graphics can't be longer than one EMC cycle) */
9700 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
9705 g_em->crumbled_bitmap = NULL;
9706 g_em->crumbled_src_x = 0;
9707 g_em->crumbled_src_y = 0;
9709 g_em->has_crumbled_graphics = FALSE;
9711 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
9713 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
9714 g_crumbled->anim_delay,
9715 g_crumbled->anim_mode,
9716 g_crumbled->anim_start_frame,
9719 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
9720 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
9722 g_em->has_crumbled_graphics = TRUE;
9728 int effective_action = xxx_effective_action;
9729 int has_action_graphics = xxx_has_action_graphics;
9731 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
9732 effective_action == ACTION_MOVING ||
9733 effective_action == ACTION_PUSHING ||
9734 effective_action == ACTION_EATING)) ||
9735 (!has_action_graphics && (effective_action == ACTION_FILLING ||
9736 effective_action == ACTION_EMPTYING)))
9739 (effective_action == ACTION_FALLING ||
9740 effective_action == ACTION_FILLING ||
9741 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
9742 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
9743 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
9744 int num_steps = (i == Ydrip_s1 ? 16 :
9745 i == Ydrip_s1B ? 16 :
9746 i == Ydrip_s2 ? 16 :
9747 i == Ydrip_s2B ? 16 :
9748 i == Xsand_stonein_1 ? 32 :
9749 i == Xsand_stonein_2 ? 32 :
9750 i == Xsand_stonein_3 ? 32 :
9751 i == Xsand_stonein_4 ? 32 :
9752 i == Xsand_stoneout_1 ? 16 :
9753 i == Xsand_stoneout_2 ? 16 : 8);
9754 int cx = ABS(dx) * (TILEX / num_steps);
9755 int cy = ABS(dy) * (TILEY / num_steps);
9756 int step_frame = (i == Ydrip_s2 ? j + 8 :
9757 i == Ydrip_s2B ? j + 8 :
9758 i == Xsand_stonein_2 ? j + 8 :
9759 i == Xsand_stonein_3 ? j + 16 :
9760 i == Xsand_stonein_4 ? j + 24 :
9761 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
9762 int step = (is_backside ? step_frame : num_steps - step_frame);
9764 if (is_backside) /* tile where movement starts */
9766 if (dx < 0 || dy < 0)
9768 g_em->src_offset_x = cx * step;
9769 g_em->src_offset_y = cy * step;
9773 g_em->dst_offset_x = cx * step;
9774 g_em->dst_offset_y = cy * step;
9777 else /* tile where movement ends */
9779 if (dx < 0 || dy < 0)
9781 g_em->dst_offset_x = cx * step;
9782 g_em->dst_offset_y = cy * step;
9786 g_em->src_offset_x = cx * step;
9787 g_em->src_offset_y = cy * step;
9791 g_em->width = TILEX - cx * step;
9792 g_em->height = TILEY - cy * step;
9795 /* create unique graphic identifier to decide if tile must be redrawn */
9796 /* bit 31 - 16 (16 bit): EM style graphic
9797 bit 15 - 12 ( 4 bit): EM style frame
9798 bit 11 - 6 ( 6 bit): graphic width
9799 bit 5 - 0 ( 6 bit): graphic height */
9800 g_em->unique_identifier =
9801 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
9807 void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
9808 int player_nr, int anim, int frame_em)
9810 int element = player_mapping[player_nr][anim].element_rnd;
9811 int action = player_mapping[player_nr][anim].action;
9812 int direction = player_mapping[player_nr][anim].direction;
9813 int graphic = (direction == MV_NONE ?
9814 el_act2img(element, action) :
9815 el_act_dir2img(element, action, direction));
9816 struct GraphicInfo *g = &graphic_info[graphic];
9819 InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
9821 stored_player[player_nr].StepFrame = frame_em;
9823 sync_frame = stored_player[player_nr].Frame;
9825 int frame = getAnimationFrame(g->anim_frames,
9828 g->anim_start_frame,
9831 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
9832 &g_em->src_x, &g_em->src_y, FALSE);
9835 printf("::: %d: %d, %d [%d]\n",
9837 stored_player[player_nr].Frame,
9838 stored_player[player_nr].StepFrame,
9843 void InitGraphicInfo_EM(void)
9846 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
9847 struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
9852 int num_em_gfx_errors = 0;
9854 if (graphic_info_em_object[0][0].bitmap == NULL)
9856 /* EM graphics not yet initialized in em_open_all() */
9861 printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
9864 /* always start with reliable default values */
9865 for (i = 0; i < TILE_MAX; i++)
9867 object_mapping[i].element_rnd = EL_UNKNOWN;
9868 object_mapping[i].is_backside = FALSE;
9869 object_mapping[i].action = ACTION_DEFAULT;
9870 object_mapping[i].direction = MV_NONE;
9873 /* always start with reliable default values */
9874 for (p = 0; p < MAX_PLAYERS; p++)
9876 for (i = 0; i < SPR_MAX; i++)
9878 player_mapping[p][i].element_rnd = EL_UNKNOWN;
9879 player_mapping[p][i].action = ACTION_DEFAULT;
9880 player_mapping[p][i].direction = MV_NONE;
9884 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
9886 int e = em_object_mapping_list[i].element_em;
9888 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
9889 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
9891 if (em_object_mapping_list[i].action != -1)
9892 object_mapping[e].action = em_object_mapping_list[i].action;
9894 if (em_object_mapping_list[i].direction != -1)
9895 object_mapping[e].direction =
9896 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
9899 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
9901 int a = em_player_mapping_list[i].action_em;
9902 int p = em_player_mapping_list[i].player_nr;
9904 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
9906 if (em_player_mapping_list[i].action != -1)
9907 player_mapping[p][a].action = em_player_mapping_list[i].action;
9909 if (em_player_mapping_list[i].direction != -1)
9910 player_mapping[p][a].direction =
9911 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
9914 for (i = 0; i < TILE_MAX; i++)
9916 int element = object_mapping[i].element_rnd;
9917 int action = object_mapping[i].action;
9918 int direction = object_mapping[i].direction;
9919 boolean is_backside = object_mapping[i].is_backside;
9921 boolean action_removing = (action == ACTION_DIGGING ||
9922 action == ACTION_SNAPPING ||
9923 action == ACTION_COLLECTING);
9925 boolean action_exploding = ((action == ACTION_EXPLODING ||
9926 action == ACTION_SMASHED_BY_ROCK ||
9927 action == ACTION_SMASHED_BY_SPRING) &&
9928 element != EL_DIAMOND);
9929 boolean action_active = (action == ACTION_ACTIVE);
9930 boolean action_other = (action == ACTION_OTHER);
9932 for (j = 0; j < 8; j++)
9935 int effective_element = get_effective_element_EM(i, j);
9937 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
9938 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
9940 i == Xdrip_stretch ? element :
9941 i == Xdrip_stretchB ? element :
9942 i == Ydrip_s1 ? element :
9943 i == Ydrip_s1B ? element :
9944 i == Xball_1B ? element :
9945 i == Xball_2 ? element :
9946 i == Xball_2B ? element :
9947 i == Yball_eat ? element :
9948 i == Ykey_1_eat ? element :
9949 i == Ykey_2_eat ? element :
9950 i == Ykey_3_eat ? element :
9951 i == Ykey_4_eat ? element :
9952 i == Ykey_5_eat ? element :
9953 i == Ykey_6_eat ? element :
9954 i == Ykey_7_eat ? element :
9955 i == Ykey_8_eat ? element :
9956 i == Ylenses_eat ? element :
9957 i == Ymagnify_eat ? element :
9958 i == Ygrass_eat ? element :
9959 i == Ydirt_eat ? element :
9960 i == Yemerald_stone ? EL_EMERALD :
9961 i == Ydiamond_stone ? EL_ROCK :
9962 i == Xsand_stonein_1 ? element :
9963 i == Xsand_stonein_2 ? element :
9964 i == Xsand_stonein_3 ? element :
9965 i == Xsand_stonein_4 ? element :
9966 is_backside ? EL_EMPTY :
9967 action_removing ? EL_EMPTY :
9970 int effective_action = (j < 7 ? action :
9971 i == Xdrip_stretch ? action :
9972 i == Xdrip_stretchB ? action :
9973 i == Ydrip_s1 ? action :
9974 i == Ydrip_s1B ? action :
9975 i == Xball_1B ? action :
9976 i == Xball_2 ? action :
9977 i == Xball_2B ? action :
9978 i == Yball_eat ? action :
9979 i == Ykey_1_eat ? action :
9980 i == Ykey_2_eat ? action :
9981 i == Ykey_3_eat ? action :
9982 i == Ykey_4_eat ? action :
9983 i == Ykey_5_eat ? action :
9984 i == Ykey_6_eat ? action :
9985 i == Ykey_7_eat ? action :
9986 i == Ykey_8_eat ? action :
9987 i == Ylenses_eat ? action :
9988 i == Ymagnify_eat ? action :
9989 i == Ygrass_eat ? action :
9990 i == Ydirt_eat ? action :
9991 i == Xsand_stonein_1 ? action :
9992 i == Xsand_stonein_2 ? action :
9993 i == Xsand_stonein_3 ? action :
9994 i == Xsand_stonein_4 ? action :
9995 i == Xsand_stoneout_1 ? action :
9996 i == Xsand_stoneout_2 ? action :
9997 i == Xboom_android ? ACTION_EXPLODING :
9998 action_exploding ? ACTION_EXPLODING :
9999 action_active ? action :
10000 action_other ? action :
10002 int graphic = (el_act_dir2img(effective_element, effective_action,
10004 int crumbled = (el_act_dir2crm(effective_element, effective_action,
10006 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
10007 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
10008 boolean has_action_graphics = (graphic != base_graphic);
10009 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
10010 struct GraphicInfo *g = &graphic_info[graphic];
10012 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
10014 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10015 Bitmap *src_bitmap;
10017 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
10018 boolean special_animation = (action != ACTION_DEFAULT &&
10019 g->anim_frames == 3 &&
10020 g->anim_delay == 2 &&
10021 g->anim_mode & ANIM_LINEAR);
10022 int sync_frame = (i == Xdrip_stretch ? 7 :
10023 i == Xdrip_stretchB ? 7 :
10024 i == Ydrip_s2 ? j + 8 :
10025 i == Ydrip_s2B ? j + 8 :
10027 i == Xacid_2 ? 10 :
10028 i == Xacid_3 ? 20 :
10029 i == Xacid_4 ? 30 :
10030 i == Xacid_5 ? 40 :
10031 i == Xacid_6 ? 50 :
10032 i == Xacid_7 ? 60 :
10033 i == Xacid_8 ? 70 :
10034 i == Xfake_acid_1 ? 0 :
10035 i == Xfake_acid_2 ? 10 :
10036 i == Xfake_acid_3 ? 20 :
10037 i == Xfake_acid_4 ? 30 :
10038 i == Xfake_acid_5 ? 40 :
10039 i == Xfake_acid_6 ? 50 :
10040 i == Xfake_acid_7 ? 60 :
10041 i == Xfake_acid_8 ? 70 :
10043 i == Xball_2B ? j + 8 :
10044 i == Yball_eat ? j + 1 :
10045 i == Ykey_1_eat ? j + 1 :
10046 i == Ykey_2_eat ? j + 1 :
10047 i == Ykey_3_eat ? j + 1 :
10048 i == Ykey_4_eat ? j + 1 :
10049 i == Ykey_5_eat ? j + 1 :
10050 i == Ykey_6_eat ? j + 1 :
10051 i == Ykey_7_eat ? j + 1 :
10052 i == Ykey_8_eat ? j + 1 :
10053 i == Ylenses_eat ? j + 1 :
10054 i == Ymagnify_eat ? j + 1 :
10055 i == Ygrass_eat ? j + 1 :
10056 i == Ydirt_eat ? j + 1 :
10057 i == Xamoeba_1 ? 0 :
10058 i == Xamoeba_2 ? 1 :
10059 i == Xamoeba_3 ? 2 :
10060 i == Xamoeba_4 ? 3 :
10061 i == Xamoeba_5 ? 0 :
10062 i == Xamoeba_6 ? 1 :
10063 i == Xamoeba_7 ? 2 :
10064 i == Xamoeba_8 ? 3 :
10065 i == Xexit_2 ? j + 8 :
10066 i == Xexit_3 ? j + 16 :
10067 i == Xdynamite_1 ? 0 :
10068 i == Xdynamite_2 ? 8 :
10069 i == Xdynamite_3 ? 16 :
10070 i == Xdynamite_4 ? 24 :
10071 i == Xsand_stonein_1 ? j + 1 :
10072 i == Xsand_stonein_2 ? j + 9 :
10073 i == Xsand_stonein_3 ? j + 17 :
10074 i == Xsand_stonein_4 ? j + 25 :
10075 i == Xsand_stoneout_1 && j == 0 ? 0 :
10076 i == Xsand_stoneout_1 && j == 1 ? 0 :
10077 i == Xsand_stoneout_1 && j == 2 ? 1 :
10078 i == Xsand_stoneout_1 && j == 3 ? 2 :
10079 i == Xsand_stoneout_1 && j == 4 ? 2 :
10080 i == Xsand_stoneout_1 && j == 5 ? 3 :
10081 i == Xsand_stoneout_1 && j == 6 ? 4 :
10082 i == Xsand_stoneout_1 && j == 7 ? 4 :
10083 i == Xsand_stoneout_2 && j == 0 ? 5 :
10084 i == Xsand_stoneout_2 && j == 1 ? 6 :
10085 i == Xsand_stoneout_2 && j == 2 ? 7 :
10086 i == Xsand_stoneout_2 && j == 3 ? 8 :
10087 i == Xsand_stoneout_2 && j == 4 ? 9 :
10088 i == Xsand_stoneout_2 && j == 5 ? 11 :
10089 i == Xsand_stoneout_2 && j == 6 ? 13 :
10090 i == Xsand_stoneout_2 && j == 7 ? 15 :
10091 i == Xboom_bug && j == 1 ? 2 :
10092 i == Xboom_bug && j == 2 ? 2 :
10093 i == Xboom_bug && j == 3 ? 4 :
10094 i == Xboom_bug && j == 4 ? 4 :
10095 i == Xboom_bug && j == 5 ? 2 :
10096 i == Xboom_bug && j == 6 ? 2 :
10097 i == Xboom_bug && j == 7 ? 0 :
10098 i == Xboom_bomb && j == 1 ? 2 :
10099 i == Xboom_bomb && j == 2 ? 2 :
10100 i == Xboom_bomb && j == 3 ? 4 :
10101 i == Xboom_bomb && j == 4 ? 4 :
10102 i == Xboom_bomb && j == 5 ? 2 :
10103 i == Xboom_bomb && j == 6 ? 2 :
10104 i == Xboom_bomb && j == 7 ? 0 :
10105 i == Xboom_android && j == 7 ? 6 :
10106 i == Xboom_1 && j == 1 ? 2 :
10107 i == Xboom_1 && j == 2 ? 2 :
10108 i == Xboom_1 && j == 3 ? 4 :
10109 i == Xboom_1 && j == 4 ? 4 :
10110 i == Xboom_1 && j == 5 ? 6 :
10111 i == Xboom_1 && j == 6 ? 6 :
10112 i == Xboom_1 && j == 7 ? 8 :
10113 i == Xboom_2 && j == 0 ? 8 :
10114 i == Xboom_2 && j == 1 ? 8 :
10115 i == Xboom_2 && j == 2 ? 10 :
10116 i == Xboom_2 && j == 3 ? 10 :
10117 i == Xboom_2 && j == 4 ? 10 :
10118 i == Xboom_2 && j == 5 ? 12 :
10119 i == Xboom_2 && j == 6 ? 12 :
10120 i == Xboom_2 && j == 7 ? 12 :
10121 special_animation && j == 4 ? 3 :
10122 effective_action != action ? 0 :
10126 Bitmap *debug_bitmap = g_em->bitmap;
10127 int debug_src_x = g_em->src_x;
10128 int debug_src_y = g_em->src_y;
10131 int frame = getAnimationFrame(g->anim_frames,
10134 g->anim_start_frame,
10137 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
10138 g->double_movement && is_backside);
10140 g_em->bitmap = src_bitmap;
10141 g_em->src_x = src_x;
10142 g_em->src_y = src_y;
10143 g_em->src_offset_x = 0;
10144 g_em->src_offset_y = 0;
10145 g_em->dst_offset_x = 0;
10146 g_em->dst_offset_y = 0;
10147 g_em->width = TILEX;
10148 g_em->height = TILEY;
10150 g_em->preserve_background = FALSE;
10153 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10158 g_em->crumbled_bitmap = NULL;
10159 g_em->crumbled_src_x = 0;
10160 g_em->crumbled_src_y = 0;
10161 g_em->crumbled_border_size = 0;
10163 g_em->has_crumbled_graphics = FALSE;
10166 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
10167 printf("::: empty crumbled: %d [%s], %d, %d\n",
10168 effective_element, element_info[effective_element].token_name,
10169 effective_action, direction);
10172 /* if element can be crumbled, but certain action graphics are just empty
10173 space (like instantly snapping sand to empty space in 1 frame), do not
10174 treat these empty space graphics as crumbled graphics in EMC engine */
10175 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10177 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10178 g_crumbled->anim_delay,
10179 g_crumbled->anim_mode,
10180 g_crumbled->anim_start_frame,
10183 getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
10185 g_em->has_crumbled_graphics = TRUE;
10186 g_em->crumbled_bitmap = src_bitmap;
10187 g_em->crumbled_src_x = src_x;
10188 g_em->crumbled_src_y = src_y;
10189 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
10193 if (g_em == &graphic_info_em_object[207][0])
10194 printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
10195 graphic_info_em_object[207][0].crumbled_src_x,
10196 graphic_info_em_object[207][0].crumbled_src_y,
10198 crumbled, frame, src_x, src_y,
10203 g->anim_start_frame,
10205 gfx.anim_random_frame,
10210 printf("::: EMC tile %d is crumbled\n", i);
10216 if (element == EL_ROCK &&
10217 effective_action == ACTION_FILLING)
10218 printf("::: has_action_graphics == %d\n", has_action_graphics);
10221 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10222 effective_action == ACTION_MOVING ||
10223 effective_action == ACTION_PUSHING ||
10224 effective_action == ACTION_EATING)) ||
10225 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10226 effective_action == ACTION_EMPTYING)))
10229 (effective_action == ACTION_FALLING ||
10230 effective_action == ACTION_FILLING ||
10231 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10232 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10233 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10234 int num_steps = (i == Ydrip_s1 ? 16 :
10235 i == Ydrip_s1B ? 16 :
10236 i == Ydrip_s2 ? 16 :
10237 i == Ydrip_s2B ? 16 :
10238 i == Xsand_stonein_1 ? 32 :
10239 i == Xsand_stonein_2 ? 32 :
10240 i == Xsand_stonein_3 ? 32 :
10241 i == Xsand_stonein_4 ? 32 :
10242 i == Xsand_stoneout_1 ? 16 :
10243 i == Xsand_stoneout_2 ? 16 : 8);
10244 int cx = ABS(dx) * (TILEX / num_steps);
10245 int cy = ABS(dy) * (TILEY / num_steps);
10246 int step_frame = (i == Ydrip_s2 ? j + 8 :
10247 i == Ydrip_s2B ? j + 8 :
10248 i == Xsand_stonein_2 ? j + 8 :
10249 i == Xsand_stonein_3 ? j + 16 :
10250 i == Xsand_stonein_4 ? j + 24 :
10251 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10252 int step = (is_backside ? step_frame : num_steps - step_frame);
10254 if (is_backside) /* tile where movement starts */
10256 if (dx < 0 || dy < 0)
10258 g_em->src_offset_x = cx * step;
10259 g_em->src_offset_y = cy * step;
10263 g_em->dst_offset_x = cx * step;
10264 g_em->dst_offset_y = cy * step;
10267 else /* tile where movement ends */
10269 if (dx < 0 || dy < 0)
10271 g_em->dst_offset_x = cx * step;
10272 g_em->dst_offset_y = cy * step;
10276 g_em->src_offset_x = cx * step;
10277 g_em->src_offset_y = cy * step;
10281 g_em->width = TILEX - cx * step;
10282 g_em->height = TILEY - cy * step;
10285 /* create unique graphic identifier to decide if tile must be redrawn */
10286 /* bit 31 - 16 (16 bit): EM style graphic
10287 bit 15 - 12 ( 4 bit): EM style frame
10288 bit 11 - 6 ( 6 bit): graphic width
10289 bit 5 - 0 ( 6 bit): graphic height */
10290 g_em->unique_identifier =
10291 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10295 /* skip check for EMC elements not contained in original EMC artwork */
10296 if (element == EL_EMC_FAKE_ACID)
10299 if (g_em->bitmap != debug_bitmap ||
10300 g_em->src_x != debug_src_x ||
10301 g_em->src_y != debug_src_y ||
10302 g_em->src_offset_x != 0 ||
10303 g_em->src_offset_y != 0 ||
10304 g_em->dst_offset_x != 0 ||
10305 g_em->dst_offset_y != 0 ||
10306 g_em->width != TILEX ||
10307 g_em->height != TILEY)
10309 static int last_i = -1;
10317 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
10318 i, element, element_info[element].token_name,
10319 element_action_info[effective_action].suffix, direction);
10321 if (element != effective_element)
10322 printf(" [%d ('%s')]",
10324 element_info[effective_element].token_name);
10328 if (g_em->bitmap != debug_bitmap)
10329 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
10330 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
10332 if (g_em->src_x != debug_src_x ||
10333 g_em->src_y != debug_src_y)
10334 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
10335 j, (is_backside ? 'B' : 'F'),
10336 g_em->src_x, g_em->src_y,
10337 g_em->src_x / 32, g_em->src_y / 32,
10338 debug_src_x, debug_src_y,
10339 debug_src_x / 32, debug_src_y / 32);
10341 if (g_em->src_offset_x != 0 ||
10342 g_em->src_offset_y != 0 ||
10343 g_em->dst_offset_x != 0 ||
10344 g_em->dst_offset_y != 0)
10345 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
10347 g_em->src_offset_x, g_em->src_offset_y,
10348 g_em->dst_offset_x, g_em->dst_offset_y);
10350 if (g_em->width != TILEX ||
10351 g_em->height != TILEY)
10352 printf(" %d (%d): size %d,%d should be %d,%d\n",
10354 g_em->width, g_em->height, TILEX, TILEY);
10356 num_em_gfx_errors++;
10363 for (i = 0; i < TILE_MAX; i++)
10365 for (j = 0; j < 8; j++)
10367 int element = object_mapping[i].element_rnd;
10368 int action = object_mapping[i].action;
10369 int direction = object_mapping[i].direction;
10370 boolean is_backside = object_mapping[i].is_backside;
10371 int graphic_action = el_act_dir2img(element, action, direction);
10372 int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
10374 if ((action == ACTION_SMASHED_BY_ROCK ||
10375 action == ACTION_SMASHED_BY_SPRING ||
10376 action == ACTION_EATING) &&
10377 graphic_action == graphic_default)
10379 int e = (action == ACTION_SMASHED_BY_ROCK ? Ystone_s :
10380 action == ACTION_SMASHED_BY_SPRING ? Yspring_s :
10381 direction == MV_LEFT ? (is_backside? Yspring_wB: Yspring_w) :
10382 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
10385 /* no separate animation for "smashed by rock" -- use rock instead */
10386 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10387 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
10389 g_em->bitmap = g_xx->bitmap;
10390 g_em->src_x = g_xx->src_x;
10391 g_em->src_y = g_xx->src_y;
10392 g_em->src_offset_x = g_xx->src_offset_x;
10393 g_em->src_offset_y = g_xx->src_offset_y;
10394 g_em->dst_offset_x = g_xx->dst_offset_x;
10395 g_em->dst_offset_y = g_xx->dst_offset_y;
10396 g_em->width = g_xx->width;
10397 g_em->height = g_xx->height;
10398 g_em->unique_identifier = g_xx->unique_identifier;
10401 g_em->preserve_background = TRUE;
10406 for (p = 0; p < MAX_PLAYERS; p++)
10408 for (i = 0; i < SPR_MAX; i++)
10410 int element = player_mapping[p][i].element_rnd;
10411 int action = player_mapping[p][i].action;
10412 int direction = player_mapping[p][i].direction;
10414 for (j = 0; j < 8; j++)
10416 int effective_element = element;
10417 int effective_action = action;
10418 int graphic = (direction == MV_NONE ?
10419 el_act2img(effective_element, effective_action) :
10420 el_act_dir2img(effective_element, effective_action,
10422 struct GraphicInfo *g = &graphic_info[graphic];
10423 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
10424 Bitmap *src_bitmap;
10426 int sync_frame = j;
10429 Bitmap *debug_bitmap = g_em->bitmap;
10430 int debug_src_x = g_em->src_x;
10431 int debug_src_y = g_em->src_y;
10434 int frame = getAnimationFrame(g->anim_frames,
10437 g->anim_start_frame,
10440 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
10442 g_em->bitmap = src_bitmap;
10443 g_em->src_x = src_x;
10444 g_em->src_y = src_y;
10445 g_em->src_offset_x = 0;
10446 g_em->src_offset_y = 0;
10447 g_em->dst_offset_x = 0;
10448 g_em->dst_offset_y = 0;
10449 g_em->width = TILEX;
10450 g_em->height = TILEY;
10454 /* skip check for EMC elements not contained in original EMC artwork */
10455 if (element == EL_PLAYER_3 ||
10456 element == EL_PLAYER_4)
10459 if (g_em->bitmap != debug_bitmap ||
10460 g_em->src_x != debug_src_x ||
10461 g_em->src_y != debug_src_y)
10463 static int last_i = -1;
10471 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
10472 p, i, element, element_info[element].token_name,
10473 element_action_info[effective_action].suffix, direction);
10475 if (element != effective_element)
10476 printf(" [%d ('%s')]",
10478 element_info[effective_element].token_name);
10482 if (g_em->bitmap != debug_bitmap)
10483 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
10484 j, (int)(g_em->bitmap), (int)(debug_bitmap));
10486 if (g_em->src_x != debug_src_x ||
10487 g_em->src_y != debug_src_y)
10488 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
10490 g_em->src_x, g_em->src_y,
10491 g_em->src_x / 32, g_em->src_y / 32,
10492 debug_src_x, debug_src_y,
10493 debug_src_x / 32, debug_src_y / 32);
10495 num_em_gfx_errors++;
10505 printf("::: [%d errors found]\n", num_em_gfx_errors);
10511 void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
10512 boolean any_player_moving,
10513 boolean player_is_dropping)
10515 if (tape.single_step && tape.recording && !tape.pausing)
10518 boolean active_players = FALSE;
10521 for (i = 0; i < MAX_PLAYERS; i++)
10522 if (action[i] != JOY_NO_ACTION)
10523 active_players = TRUE;
10527 if (frame == 0 && !player_is_dropping)
10528 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
10532 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
10533 boolean murphy_is_dropping)
10536 printf("::: waiting: %d, dropping: %d\n",
10537 murphy_is_waiting, murphy_is_dropping);
10540 if (tape.single_step && tape.recording && !tape.pausing)
10542 // if (murphy_is_waiting || murphy_is_dropping)
10543 if (murphy_is_waiting)
10546 printf("::: murphy is waiting -> pause mode\n");
10549 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
10554 void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
10555 int graphic, int sync_frame, int x, int y)
10557 int frame = getGraphicAnimationFrame(graphic, sync_frame);
10559 getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
10562 boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
10564 return (IS_NEXT_FRAME(sync_frame, graphic));
10567 int getGraphicInfo_Delay(int graphic)
10569 return graphic_info[graphic].anim_delay;
10572 void PlayMenuSoundExt(int sound)
10574 if (sound == SND_UNDEFINED)
10577 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
10578 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
10581 if (IS_LOOP_SOUND(sound))
10582 PlaySoundLoop(sound);
10587 void PlayMenuSound()
10589 PlayMenuSoundExt(menu.sound[game_status]);
10592 void PlayMenuSoundStereo(int sound, int stereo_position)
10594 if (sound == SND_UNDEFINED)
10597 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
10598 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
10601 if (IS_LOOP_SOUND(sound))
10602 PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP);
10604 PlaySoundStereo(sound, stereo_position);
10607 void PlayMenuSoundIfLoopExt(int sound)
10609 if (sound == SND_UNDEFINED)
10612 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
10613 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
10616 if (IS_LOOP_SOUND(sound))
10617 PlaySoundLoop(sound);
10620 void PlayMenuSoundIfLoop()
10622 PlayMenuSoundIfLoopExt(menu.sound[game_status]);
10625 void PlayMenuMusicExt(int music)
10627 if (music == MUS_UNDEFINED)
10630 if (!setup.sound_music)
10636 void PlayMenuMusic()
10638 PlayMenuMusicExt(menu.music[game_status]);
10641 void PlaySoundActivating()
10644 PlaySound(SND_MENU_ITEM_ACTIVATING);
10648 void PlaySoundSelecting()
10651 PlaySound(SND_MENU_ITEM_SELECTING);
10655 void ToggleFullscreenOrChangeWindowScalingIfNeeded()
10657 boolean change_fullscreen = (setup.fullscreen !=
10658 video.fullscreen_enabled);
10659 boolean change_fullscreen_mode = (video.fullscreen_enabled &&
10660 !strEqual(setup.fullscreen_mode,
10661 video.fullscreen_mode_current));
10662 boolean change_window_scaling_percent = (!video.fullscreen_enabled &&
10663 setup.window_scaling_percent !=
10664 video.window_scaling_percent);
10666 if (change_window_scaling_percent && video.fullscreen_enabled)
10669 if (!change_window_scaling_percent && !video.fullscreen_available)
10672 #if defined(TARGET_SDL2)
10673 if (change_window_scaling_percent)
10675 SDLSetWindowScaling(setup.window_scaling_percent);
10679 else if (change_fullscreen)
10681 SDLSetWindowFullscreen(setup.fullscreen);
10683 /* set setup value according to successfully changed fullscreen mode */
10684 setup.fullscreen = video.fullscreen_enabled;
10690 if (change_fullscreen ||
10691 change_fullscreen_mode ||
10692 change_window_scaling_percent)
10694 Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
10696 /* save backbuffer content which gets lost when toggling fullscreen mode */
10697 BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
10699 if (change_fullscreen_mode)
10701 /* keep fullscreen, but change fullscreen mode (screen resolution) */
10702 video.fullscreen_enabled = FALSE; /* force new fullscreen mode */
10705 if (change_window_scaling_percent)
10707 /* keep window mode, but change window scaling */
10708 video.fullscreen_enabled = TRUE; /* force new window scaling */
10711 /* toggle fullscreen */
10712 ChangeVideoModeIfNeeded(setup.fullscreen);
10714 /* set setup value according to successfully changed fullscreen mode */
10715 setup.fullscreen = video.fullscreen_enabled;
10717 /* restore backbuffer content from temporary backbuffer backup bitmap */
10718 BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
10720 FreeBitmap(tmp_backbuffer);
10723 /* update visible window/screen */
10724 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
10726 redraw_mask = REDRAW_ALL;
10731 void ChangeViewportPropertiesIfNeeded()
10734 int *door_1_x = &DX;
10735 int *door_1_y = &DY;
10736 int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
10737 int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
10739 int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
10740 game_status == GAME_MODE_EDITOR ? game_status :
10742 int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
10744 struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
10745 struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
10746 struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode2];
10747 struct RectWithBorder *vp_door_3 = &viewport.door_2[GAME_MODE_EDITOR];
10748 int border_size = vp_playfield->border_size;
10749 int new_sx = vp_playfield->x + border_size;
10750 int new_sy = vp_playfield->y + border_size;
10751 int new_sxsize = vp_playfield->width - 2 * border_size;
10752 int new_sysize = vp_playfield->height - 2 * border_size;
10753 int new_real_sx = vp_playfield->x;
10754 int new_real_sy = vp_playfield->y;
10755 int new_full_sxsize = vp_playfield->width;
10756 int new_full_sysize = vp_playfield->height;
10757 int new_dx = vp_door_1->x;
10758 int new_dy = vp_door_1->y;
10759 int new_dxsize = vp_door_1->width;
10760 int new_dysize = vp_door_1->height;
10761 int new_vx = vp_door_2->x;
10762 int new_vy = vp_door_2->y;
10763 int new_vxsize = vp_door_2->width;
10764 int new_vysize = vp_door_2->height;
10765 int new_ex = vp_door_3->x;
10766 int new_ey = vp_door_3->y;
10767 int new_exsize = vp_door_3->width;
10768 int new_eysize = vp_door_3->height;
10770 int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
10771 int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
10772 gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
10773 int new_scr_fieldx = new_sxsize / tilesize;
10774 int new_scr_fieldy = new_sysize / tilesize;
10775 int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var;
10776 int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
10778 int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE;
10779 int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE;
10781 boolean init_gfx_buffers = FALSE;
10782 boolean init_video_buffer = FALSE;
10783 boolean init_gadgets_and_toons = FALSE;
10786 /* !!! TEST ONLY !!! */
10787 // InitGfxBuffers();
10791 if (viewport.window.width != WIN_XSIZE ||
10792 viewport.window.height != WIN_YSIZE)
10794 WIN_XSIZE = viewport.window.width;
10795 WIN_YSIZE = viewport.window.height;
10798 init_video_buffer = TRUE;
10799 init_gfx_buffers = TRUE;
10801 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
10805 SetDrawDeactivationMask(REDRAW_NONE);
10806 SetDrawBackgroundMask(REDRAW_FIELD);
10808 // RedrawBackground();
10812 // printf("::: video: init_video_buffer, init_gfx_buffers\n");
10815 if (new_scr_fieldx != SCR_FIELDX ||
10816 new_scr_fieldy != SCR_FIELDY)
10818 /* this always toggles between MAIN and GAME when using small tile size */
10820 SCR_FIELDX = new_scr_fieldx;
10821 SCR_FIELDY = new_scr_fieldy;
10823 // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
10827 if (new_tilesize_var != TILESIZE_VAR &&
10828 gfx_game_mode == GAME_MODE_PLAYING)
10830 /* doing this outside GAME_MODE_PLAYING would give wrong playfield size */
10832 TILESIZE_VAR = new_tilesize_var;
10834 init_gfx_buffers = TRUE;
10836 // printf("::: tilesize: init_gfx_buffers\n");
10840 if (new_sx != SX ||
10848 new_sxsize != SXSIZE ||
10849 new_sysize != SYSIZE ||
10850 new_dxsize != DXSIZE ||
10851 new_dysize != DYSIZE ||
10852 new_vxsize != VXSIZE ||
10853 new_vysize != VYSIZE ||
10854 new_exsize != EXSIZE ||
10855 new_eysize != EYSIZE ||
10856 new_real_sx != REAL_SX ||
10857 new_real_sy != REAL_SY ||
10858 new_full_sxsize != FULL_SXSIZE ||
10859 new_full_sysize != FULL_SYSIZE ||
10860 new_tilesize_var != TILESIZE_VAR
10863 vp_door_1->x != *door_1_x ||
10864 vp_door_1->y != *door_1_y ||
10865 vp_door_2->x != *door_2_x ||
10866 vp_door_2->y != *door_2_y
10878 SXSIZE = new_sxsize;
10879 SYSIZE = new_sysize;
10880 DXSIZE = new_dxsize;
10881 DYSIZE = new_dysize;
10882 VXSIZE = new_vxsize;
10883 VYSIZE = new_vysize;
10884 EXSIZE = new_exsize;
10885 EYSIZE = new_eysize;
10886 REAL_SX = new_real_sx;
10887 REAL_SY = new_real_sy;
10888 FULL_SXSIZE = new_full_sxsize;
10889 FULL_SYSIZE = new_full_sysize;
10890 TILESIZE_VAR = new_tilesize_var;
10893 printf("::: %d, %d, %d [%d]\n",
10894 SCR_FIELDX, SCR_FIELDY, TILESIZE_VAR,
10895 setup.small_game_graphics);
10899 *door_1_x = vp_door_1->x;
10900 *door_1_y = vp_door_1->y;
10901 *door_2_x = vp_door_2->x;
10902 *door_2_y = vp_door_2->y;
10906 init_gfx_buffers = TRUE;
10908 // printf("::: viewports: init_gfx_buffers\n");
10913 if (gfx_game_mode == GAME_MODE_MAIN)
10916 init_gadgets_and_toons = TRUE;
10918 // printf("::: viewports: init_gadgets_and_toons\n");
10926 if (init_gfx_buffers)
10928 // printf("::: init_gfx_buffers\n");
10930 SCR_FIELDX = new_scr_fieldx_buffers;
10931 SCR_FIELDY = new_scr_fieldy_buffers;
10935 SCR_FIELDX = new_scr_fieldx;
10936 SCR_FIELDY = new_scr_fieldy;
10939 if (init_video_buffer)
10941 // printf("::: init_video_buffer\n");
10943 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
10945 SetDrawDeactivationMask(REDRAW_NONE);
10946 SetDrawBackgroundMask(REDRAW_FIELD);
10949 if (init_gadgets_and_toons)
10951 // printf("::: init_gadgets_and_toons\n");
10958 printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status);