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 ***********************************************************/
16 #include "libgame/libgame.h"
28 /* select level set with EMC X11 graphics before activating EM GFX debugging */
29 #define DEBUG_EM_GFX 0
31 /* tool button identifiers */
32 #define TOOL_CTRL_ID_YES 0
33 #define TOOL_CTRL_ID_NO 1
34 #define TOOL_CTRL_ID_CONFIRM 2
35 #define TOOL_CTRL_ID_PLAYER_1 3
36 #define TOOL_CTRL_ID_PLAYER_2 4
37 #define TOOL_CTRL_ID_PLAYER_3 5
38 #define TOOL_CTRL_ID_PLAYER_4 6
40 #define NUM_TOOL_BUTTONS 7
42 /* constants for number of doors and door parts */
44 #define NUM_PANELS NUM_DOORS
45 // #define NUM_PANELS 0
46 #define MAX_PARTS_PER_DOOR 8
47 #define MAX_DOOR_PARTS (NUM_DOORS * MAX_PARTS_PER_DOOR + NUM_PANELS)
48 #define DOOR_PART_IS_PANEL(i) ((i) >= NUM_DOORS * MAX_PARTS_PER_DOOR)
51 struct DoorPartOrderInfo
57 static struct DoorPartOrderInfo door_part_order[MAX_DOOR_PARTS];
59 struct DoorPartControlInfo
63 struct DoorPartPosInfo *pos;
66 static struct DoorPartControlInfo door_part_controls[] =
70 IMG_DOOR_1_GFX_PART_1,
75 IMG_DOOR_1_GFX_PART_2,
80 IMG_DOOR_1_GFX_PART_3,
85 IMG_DOOR_1_GFX_PART_4,
90 IMG_DOOR_1_GFX_PART_5,
95 IMG_DOOR_1_GFX_PART_6,
100 IMG_DOOR_1_GFX_PART_7,
105 IMG_DOOR_1_GFX_PART_8,
111 IMG_DOOR_2_GFX_PART_1,
116 IMG_DOOR_2_GFX_PART_2,
121 IMG_DOOR_2_GFX_PART_3,
126 IMG_DOOR_2_GFX_PART_4,
131 IMG_DOOR_2_GFX_PART_5,
136 IMG_DOOR_2_GFX_PART_6,
141 IMG_DOOR_2_GFX_PART_7,
146 IMG_DOOR_2_GFX_PART_8,
152 IMG_BACKGROUND_PANEL,
169 /* forward declaration for internal use */
170 static void UnmapToolButtons();
171 static void HandleToolButtons(struct GadgetInfo *);
172 static int el_act_dir2crm(int, int, int);
173 static int el_act2crm(int, int);
175 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
176 static int request_gadget_id = -1;
178 static char *print_if_not_empty(int element)
180 static char *s = NULL;
181 char *token_name = element_info[element].token_name;
186 s = checked_malloc(strlen(token_name) + 10 + 1);
188 if (element != EL_EMPTY)
189 sprintf(s, "%d\t['%s']", element, token_name);
191 sprintf(s, "%d", element);
196 void DumpTile(int x, int y)
201 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
207 printf_line("-", 79);
208 printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
209 printf_line("-", 79);
211 if (!IN_LEV_FIELD(x, y))
213 printf("(not in level field)\n");
219 printf(" Feld: %d\t['%s']\n", Feld[x][y],
220 element_info[Feld[x][y]].token_name);
221 printf(" Back: %s\n", print_if_not_empty(Back[x][y]));
222 printf(" Store: %s\n", print_if_not_empty(Store[x][y]));
223 printf(" Store2: %s\n", print_if_not_empty(Store2[x][y]));
224 printf(" StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
225 printf(" MovPos: %d\n", MovPos[x][y]);
226 printf(" MovDir: %d\n", MovDir[x][y]);
227 printf(" MovDelay: %d\n", MovDelay[x][y]);
228 printf(" ChangeDelay: %d\n", ChangeDelay[x][y]);
229 printf(" CustomValue: %d\n", CustomValue[x][y]);
230 printf(" GfxElement: %d\n", GfxElement[x][y]);
231 printf(" GfxAction: %d\n", GfxAction[x][y]);
232 printf(" GfxFrame: %d\n", GfxFrame[x][y]);
236 void SetDrawtoField(int mode)
238 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
246 BX2 = SCR_FIELDX + 1;
247 BY2 = SCR_FIELDY + 1;
266 BX2 = SCR_FIELDX + 1;
267 BY2 = SCR_FIELDY + 1;
282 drawto_field = fieldbuffer;
284 else /* DRAW_BACKBUFFER */
290 BX2 = SCR_FIELDX - 1;
291 BY2 = SCR_FIELDY - 1;
295 drawto_field = backbuffer;
299 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
301 if (game_status == GAME_MODE_PLAYING &&
302 level.game_engine_type == GAME_ENGINE_TYPE_EM)
304 /* currently there is no partial redraw -- always redraw whole playfield */
305 RedrawPlayfield_EM(TRUE);
307 /* blit playfield from scroll buffer to normal back buffer for fading in */
308 BlitScreenToBitmap_EM(backbuffer);
310 else if (game_status == GAME_MODE_PLAYING &&
311 level.game_engine_type == GAME_ENGINE_TYPE_SP)
313 /* currently there is no partial redraw -- always redraw whole playfield */
314 RedrawPlayfield_SP(TRUE);
316 /* blit playfield from scroll buffer to normal back buffer for fading in */
317 BlitScreenToBitmap_SP(backbuffer);
319 else if (game_status == GAME_MODE_PLAYING &&
320 !game.envelope_active)
326 width = gfx.sxsize + 2 * TILEX;
327 height = gfx.sysize + 2 * TILEY;
333 int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
334 int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
336 for (xx = BX1; xx <= BX2; xx++)
337 for (yy = BY1; yy <= BY2; yy++)
338 if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
339 DrawScreenField(xx, yy);
343 if (setup.soft_scrolling)
345 int fx = FX, fy = FY;
347 fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
348 fy += (ScreenMovDir & (MV_UP|MV_DOWN) ? ScreenGfxPos : 0);
350 BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
362 BlitBitmap(drawto, window, x, y, width, height, x, y);
365 void DrawMaskedBorder_Rect(int x, int y, int width, int height)
367 Bitmap *bitmap = graphic_info[IMG_GLOBAL_BORDER].bitmap;
369 SetClipOrigin(bitmap, bitmap->stored_clip_gc, 0, 0);
370 BlitBitmapMasked(bitmap, backbuffer, x, y, width, height, x, y);
373 void DrawMaskedBorder_FIELD()
375 if (global.border_status >= GAME_MODE_TITLE &&
376 global.border_status <= GAME_MODE_PLAYING &&
377 border.draw_masked[global.border_status])
378 DrawMaskedBorder_Rect(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
381 void DrawMaskedBorder_DOOR_1()
383 if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
384 (global.border_status != GAME_MODE_EDITOR ||
385 border.draw_masked[GFX_SPECIAL_ARG_EDITOR]))
386 DrawMaskedBorder_Rect(DX, DY, DXSIZE, DYSIZE);
389 void DrawMaskedBorder_DOOR_2()
391 if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] &&
392 global.border_status != GAME_MODE_EDITOR)
393 DrawMaskedBorder_Rect(VX, VY, VXSIZE, VYSIZE);
396 void DrawMaskedBorder_DOOR_3()
398 /* currently not available */
401 void DrawMaskedBorder_ALL()
403 DrawMaskedBorder_FIELD();
404 DrawMaskedBorder_DOOR_1();
405 DrawMaskedBorder_DOOR_2();
406 DrawMaskedBorder_DOOR_3();
409 void DrawMaskedBorder(int redraw_mask)
411 /* never draw masked screen borders on borderless screens */
412 if (effectiveGameStatus() == GAME_MODE_LOADING ||
413 effectiveGameStatus() == GAME_MODE_TITLE)
416 /* never draw masked screen borders when displaying request outside door */
417 if (effectiveGameStatus() == GAME_MODE_PSEUDO_DOOR &&
418 global.use_envelope_request)
421 if (redraw_mask & REDRAW_ALL)
422 DrawMaskedBorder_ALL();
425 if (redraw_mask & REDRAW_FIELD)
426 DrawMaskedBorder_FIELD();
427 if (redraw_mask & REDRAW_DOOR_1)
428 DrawMaskedBorder_DOOR_1();
429 if (redraw_mask & REDRAW_DOOR_2)
430 DrawMaskedBorder_DOOR_2();
431 if (redraw_mask & REDRAW_DOOR_3)
432 DrawMaskedBorder_DOOR_3();
436 void BlitScreenToBitmap(Bitmap *target_bitmap)
438 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
439 int fx = FX, fy = FY;
442 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
443 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
444 int dx_var = dx * TILESIZE_VAR / TILESIZE;
445 int dy_var = dy * TILESIZE_VAR / TILESIZE;
448 // fx += dx * TILESIZE_VAR / TILESIZE;
449 // fy += dy * TILESIZE_VAR / TILESIZE;
451 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
452 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
455 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
456 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
458 if (EVEN(SCR_FIELDX))
460 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
461 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
463 fx += (dx_var > 0 ? TILEX_VAR : 0);
470 if (EVEN(SCR_FIELDY))
472 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
473 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
475 fy += (dy_var > 0 ? TILEY_VAR : 0);
483 printf("::: (%d, %d) [(%d / %d, %d / %d)] => %d, %d\n",
486 SBY_Upper, SBY_Lower,
490 if (border.draw_masked[GAME_MODE_PLAYING])
492 if (buffer != backbuffer)
494 /* copy playfield buffer to backbuffer to add masked border */
495 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
496 DrawMaskedBorder(REDRAW_FIELD);
499 BlitBitmap(backbuffer, target_bitmap,
500 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
505 BlitBitmap(buffer, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY);
512 DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
515 printf("::: TILES TO REFRESH: %d\n", redraw_tiles);
516 for (x = 0; x < SCR_FIELDX; x++)
517 for (y = 0 ; y < SCR_FIELDY; y++)
518 if (redraw[redraw_x1 + x][redraw_y1 + y])
519 printf("::: - %d, %d [%s]\n",
520 LEVELX(x), LEVELY(y),
521 EL_NAME(Feld[LEVELX(x)][LEVELY(y)]));
524 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
525 redraw_mask |= REDRAW_FIELD;
528 // never redraw single tiles, always redraw the whole field
529 // (redrawing single tiles up to a certain threshold was faster on old,
530 // now legacy graphics, but slows things down on modern graphics now)
531 // UPDATE: this is now globally defined by value of REDRAWTILES_THRESHOLD
532 if (redraw_mask & REDRAW_TILES)
533 redraw_mask |= REDRAW_FIELD;
537 /* !!! TEST ONLY !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
538 /* (force full redraw) */
539 if (game_status == GAME_MODE_PLAYING)
540 redraw_mask |= REDRAW_FIELD;
543 if (redraw_mask & REDRAW_FIELD)
544 redraw_mask &= ~REDRAW_TILES;
546 if (redraw_mask == REDRAW_NONE)
551 if (redraw_mask & REDRAW_ALL)
552 printf("[REDRAW_ALL]");
553 if (redraw_mask & REDRAW_FIELD)
554 printf("[REDRAW_FIELD]");
555 if (redraw_mask & REDRAW_TILES)
556 printf("[REDRAW_TILES]");
557 if (redraw_mask & REDRAW_DOOR_1)
558 printf("[REDRAW_DOOR_1]");
559 if (redraw_mask & REDRAW_DOOR_2)
560 printf("[REDRAW_DOOR_2]");
561 if (redraw_mask & REDRAW_FROM_BACKBUFFER)
562 printf("[REDRAW_FROM_BACKBUFFER]");
563 printf(" [%d]\n", FrameCounter);
566 if (redraw_mask & REDRAW_TILES &&
567 game_status == GAME_MODE_PLAYING &&
568 border.draw_masked[GAME_MODE_PLAYING])
569 redraw_mask |= REDRAW_FIELD;
571 if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
573 static boolean last_frame_skipped = FALSE;
574 boolean skip_even_when_not_scrolling = TRUE;
575 boolean just_scrolling = (ScreenMovDir != 0);
576 boolean verbose = FALSE;
578 if (global.fps_slowdown_factor > 1 &&
579 (FrameCounter % global.fps_slowdown_factor) &&
580 (just_scrolling || skip_even_when_not_scrolling))
582 redraw_mask &= ~REDRAW_MAIN;
584 last_frame_skipped = TRUE;
587 printf("FRAME SKIPPED\n");
591 if (last_frame_skipped)
592 redraw_mask |= REDRAW_FIELD;
594 last_frame_skipped = FALSE;
597 printf("frame not skipped\n");
601 /* synchronize X11 graphics at this point; if we would synchronize the
602 display immediately after the buffer switching (after the XFlush),
603 this could mean that we have to wait for the graphics to complete,
604 although we could go on doing calculations for the next frame */
608 /* never draw masked border to backbuffer when using playfield buffer */
609 if (game_status != GAME_MODE_PLAYING ||
610 redraw_mask & REDRAW_FROM_BACKBUFFER ||
611 buffer == backbuffer)
612 DrawMaskedBorder(redraw_mask);
614 DrawMaskedBorder(redraw_mask & REDRAW_DOORS);
616 if (redraw_mask & REDRAW_ALL)
618 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
620 redraw_mask = REDRAW_NONE;
623 if (redraw_mask & REDRAW_FIELD)
626 printf("::: REDRAW_FIELD\n");
629 if (game_status != GAME_MODE_PLAYING ||
630 redraw_mask & REDRAW_FROM_BACKBUFFER)
632 BlitBitmap(backbuffer, window,
633 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
638 BlitScreenToBitmap(window);
640 int fx = FX, fy = FY;
643 int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
644 int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
645 int dx_var = dx * TILESIZE_VAR / TILESIZE;
646 int dy_var = dy * TILESIZE_VAR / TILESIZE;
649 // fx += dx * TILESIZE_VAR / TILESIZE;
650 // fy += dy * TILESIZE_VAR / TILESIZE;
652 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
653 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
656 /* !!! THIS WORKS !!! */
658 printf("::: %d, %d\n", scroll_x, scroll_y);
660 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
661 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
663 if (EVEN(SCR_FIELDX))
665 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
666 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
668 fx += (dx > 0 ? TILEX_VAR : 0);
675 if (EVEN(SCR_FIELDY))
677 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
678 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
680 fy += (dy > 0 ? TILEY_VAR : 0);
687 if (border.draw_masked[GAME_MODE_PLAYING])
689 if (buffer != backbuffer)
691 /* copy playfield buffer to backbuffer to add masked border */
692 BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY);
693 DrawMaskedBorder(REDRAW_FIELD);
696 BlitBitmap(backbuffer, window,
697 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
702 BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
708 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
710 (setup.soft_scrolling ?
711 "setup.soft_scrolling" :
712 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
713 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
714 ABS(ScreenGfxPos) == ScrollStepSize ?
715 "ABS(ScreenGfxPos) == ScrollStepSize" :
716 "redraw_tiles > REDRAWTILES_THRESHOLD"));
721 redraw_mask &= ~REDRAW_MAIN;
724 if (redraw_mask & REDRAW_DOORS)
726 if (redraw_mask & REDRAW_DOOR_1)
727 BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
729 if (redraw_mask & REDRAW_DOOR_2)
730 BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
732 if (redraw_mask & REDRAW_DOOR_3)
733 BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
735 redraw_mask &= ~REDRAW_DOORS;
738 if (redraw_mask & REDRAW_MICROLEVEL)
740 BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
741 SX, SY + 10 * TILEY);
743 redraw_mask &= ~REDRAW_MICROLEVEL;
746 if (redraw_mask & REDRAW_TILES)
749 printf("::: REDRAW_TILES\n");
755 InitGfxClipRegion(TRUE, SX, SY, SXSIZE, SYSIZE);
758 int sx = SX; // - (EVEN(SCR_FIELDX) ? TILEX_VAR / 2 : 0);
759 int sy = SY; // + (EVEN(SCR_FIELDY) ? TILEY_VAR / 2 : 0);
762 int dx_var = dx * TILESIZE_VAR / TILESIZE;
763 int dy_var = dy * TILESIZE_VAR / TILESIZE;
765 int fx = FX, fy = FY;
767 int scr_fieldx = SCR_FIELDX + (EVEN(SCR_FIELDX) ? 2 : 0);
768 int scr_fieldy = SCR_FIELDY + (EVEN(SCR_FIELDY) ? 2 : 0);
770 ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var;
771 ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var;
773 if (EVEN(SCR_FIELDX))
775 if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR)
777 fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR;
786 fx += (dx_var > 0 ? TILEX_VAR : 0);
790 if (EVEN(SCR_FIELDY))
792 if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR)
794 fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR;
803 fy += (dy_var > 0 ? TILEY_VAR : 0);
808 printf("::: %d, %d, %d, %d\n", sx, sy, SCR_FIELDX, SCR_FIELDY);
811 for (x = 0; x < scr_fieldx; x++)
812 for (y = 0 ; y < scr_fieldy; y++)
813 if (redraw[redraw_x1 + x][redraw_y1 + y])
814 BlitBitmap(buffer, window,
815 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
816 TILEX_VAR, TILEY_VAR,
817 sx + x * TILEX_VAR, sy + y * TILEY_VAR);
820 InitGfxClipRegion(FALSE, -1, -1, -1, -1);
822 for (x = 0; x < SCR_FIELDX; x++)
823 for (y = 0 ; y < SCR_FIELDY; y++)
824 if (redraw[redraw_x1 + x][redraw_y1 + y])
825 BlitBitmap(buffer, window,
826 FX + x * TILEX_VAR, FY + y * TILEY_VAR,
827 TILEX_VAR, TILEY_VAR,
828 SX + x * TILEX_VAR, SY + y * TILEY_VAR);
832 for (x = 0; x < SCR_FIELDX; x++)
833 for (y = 0 ; y < SCR_FIELDY; y++)
834 if (redraw[redraw_x1 + x][redraw_y1 + y])
835 BlitBitmap(buffer, window,
836 FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
837 SX + x * TILEX, SY + y * TILEY);
841 if (redraw_mask & REDRAW_FPS) /* display frames per second */
846 sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
847 if (!global.fps_slowdown)
850 sprintf(text, "%04.1f fps%s", global.frames_per_second, info1);
852 DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE);
854 DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
860 for (x = 0; x < MAX_BUF_XSIZE; x++)
861 for (y = 0; y < MAX_BUF_YSIZE; y++)
864 redraw_mask = REDRAW_NONE;
867 static void FadeCrossSaveBackbuffer()
869 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
872 static void FadeExt(int fade_mask, int fade_mode, int fade_type)
874 static int fade_type_skip = FADE_TYPE_NONE;
875 void (*draw_border_function)(void) = NULL;
876 Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL);
877 int x, y, width, height;
878 int fade_delay, post_delay;
880 if (fade_type == FADE_TYPE_FADE_OUT)
882 if (fade_type_skip != FADE_TYPE_NONE)
885 printf("::: skipping %d ... [%d] (X)\n", fade_mode, fade_type_skip);
888 /* skip all fade operations until specified fade operation */
889 if (fade_type & fade_type_skip)
890 fade_type_skip = FADE_TYPE_NONE;
895 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
897 FadeCrossSaveBackbuffer();
903 redraw_mask |= fade_mask;
905 if (fade_type == FADE_TYPE_SKIP)
908 printf("::: will skip %d ... [%d]\n", fade_mode, fade_type_skip);
911 fade_type_skip = fade_mode;
917 printf("::: !!! FADING %d ... [%d] [%d]\n", fade_mode, fade_type,
922 fade_delay = fading.fade_delay;
923 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
926 if (fade_type_skip != FADE_TYPE_NONE)
929 printf("::: skipping %d ... [%d]\n", fade_mode, fade_type_skip);
932 /* skip all fade operations until specified fade operation */
933 if (fade_type & fade_type_skip)
934 fade_type_skip = FADE_TYPE_NONE;
944 if (global.autoplay_leveldir)
946 // fading.fade_mode = FADE_MODE_NONE;
953 if (fading.fade_mode == FADE_MODE_NONE)
961 /* !!! what about fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */
964 printf("::: NOW FADING %d ... [%d]\n", fade_mode, fade_type);
968 if (fade_mask == REDRAW_NONE)
969 fade_mask = REDRAW_FIELD;
972 // if (fade_mask & REDRAW_FIELD)
973 if (fade_mask == REDRAW_FIELD)
978 height = FULL_SYSIZE;
981 fade_delay = fading.fade_delay;
982 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
985 if (border.draw_masked_when_fading)
986 draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */
988 DrawMaskedBorder_FIELD(); /* draw once */
990 else /* REDRAW_ALL */
998 fade_delay = fading.fade_delay;
999 post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0);
1004 if (!setup.fade_screens ||
1006 fading.fade_mode == FADE_MODE_NONE)
1008 if (!setup.fade_screens || fade_delay == 0)
1011 if (fade_mode == FADE_MODE_FADE_OUT)
1015 if (fade_mode == FADE_MODE_FADE_OUT &&
1016 fading.fade_mode != FADE_MODE_NONE)
1017 ClearRectangle(backbuffer, x, y, width, height);
1021 BlitBitmap(backbuffer, window, x, y, width, height, x, y);
1022 redraw_mask = REDRAW_NONE;
1030 FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay,
1031 draw_border_function);
1033 redraw_mask &= ~fade_mask;
1036 void FadeIn(int fade_mask)
1038 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
1039 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN);
1041 FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN);
1044 void FadeOut(int fade_mask)
1046 if (fading.fade_mode & FADE_TYPE_TRANSFORM)
1047 FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_OUT);
1049 FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT);
1051 global.border_status = game_status;
1054 static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set)
1056 static struct TitleFadingInfo fading_leave_stored;
1059 fading_leave_stored = fading_leave;
1061 fading = fading_leave_stored;
1064 void FadeSetEnterMenu()
1066 fading = menu.enter_menu;
1069 printf("::: storing enter_menu\n");
1072 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1075 void FadeSetLeaveMenu()
1077 fading = menu.leave_menu;
1080 printf("::: storing leave_menu\n");
1083 FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1086 void FadeSetEnterScreen()
1088 fading = menu.enter_screen[game_status];
1091 printf("::: storing leave_screen[%d]\n", game_status);
1094 FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */
1097 void FadeSetNextScreen()
1099 fading = menu.next_screen;
1102 printf("::: storing next_screen\n");
1105 // (do not overwrite fade mode set by FadeSetEnterScreen)
1106 // FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */
1109 void FadeSetLeaveScreen()
1112 printf("::: recalling last stored value\n");
1115 FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */
1118 void FadeSetFromType(int type)
1120 if (type & TYPE_ENTER_SCREEN)
1121 FadeSetEnterScreen();
1122 else if (type & TYPE_ENTER)
1124 else if (type & TYPE_LEAVE)
1128 void FadeSetDisabled()
1130 static struct TitleFadingInfo fading_none = { FADE_MODE_NONE, -1, -1, -1 };
1132 fading = fading_none;
1135 void FadeSkipNextFadeIn()
1137 FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP);
1140 void FadeSkipNextFadeOut()
1142 FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
1145 void SetWindowBackgroundImageIfDefined(int graphic)
1147 if (graphic_info[graphic].bitmap)
1148 SetWindowBackgroundBitmap(graphic_info[graphic].bitmap);
1151 void SetMainBackgroundImageIfDefined(int graphic)
1153 if (graphic_info[graphic].bitmap)
1154 SetMainBackgroundBitmap(graphic_info[graphic].bitmap);
1157 void SetDoorBackgroundImageIfDefined(int graphic)
1159 if (graphic_info[graphic].bitmap)
1160 SetDoorBackgroundBitmap(graphic_info[graphic].bitmap);
1163 void SetWindowBackgroundImage(int graphic)
1165 SetWindowBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1166 graphic_info[graphic].bitmap ?
1167 graphic_info[graphic].bitmap :
1168 graphic_info[IMG_BACKGROUND].bitmap);
1171 void SetMainBackgroundImage(int graphic)
1173 SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1174 graphic_info[graphic].bitmap ?
1175 graphic_info[graphic].bitmap :
1176 graphic_info[IMG_BACKGROUND].bitmap);
1179 void SetDoorBackgroundImage(int graphic)
1181 SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
1182 graphic_info[graphic].bitmap ?
1183 graphic_info[graphic].bitmap :
1184 graphic_info[IMG_BACKGROUND].bitmap);
1187 void SetPanelBackground()
1190 struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL];
1193 BlitBitmapTiled(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1194 gfx->width, gfx->height, 0, 0, DXSIZE, DYSIZE);
1196 /* (ClearRectangle() only needed if panel bitmap is smaller than panel) */
1197 ClearRectangle(bitmap_db_panel, DX, DY, DXSIZE, DYSIZE);
1198 BlitBitmap(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y,
1199 MIN(gfx->width, DXSIZE), MIN(gfx->height, DYSIZE), 0, 0);
1202 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, bitmap_db_panel,
1203 DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, 0, 0);
1206 SetDoorBackgroundBitmap(bitmap_db_panel);
1209 void DrawBackground(int x, int y, int width, int height)
1211 /* !!! "drawto" might still point to playfield buffer here (see below) !!! */
1212 /* (when entering hall of fame after playing) */
1214 ClearRectangleOnBackground(drawto, x, y, width, height);
1216 ClearRectangleOnBackground(backbuffer, x, y, width, height);
1222 if (IN_GFX_FIELD_FULL(x, y))
1223 redraw_mask |= REDRAW_FIELD;
1224 else if (IN_GFX_DOOR_1(x, y))
1225 redraw_mask |= REDRAW_DOOR_1;
1226 else if (IN_GFX_DOOR_2(x, y))
1227 redraw_mask |= REDRAW_DOOR_2;
1228 else if (IN_GFX_DOOR_3(x, y))
1229 redraw_mask |= REDRAW_DOOR_3;
1231 /* (this only works for the current arrangement of playfield and panels) */
1233 redraw_mask |= REDRAW_FIELD;
1234 else if (y < gfx.vy)
1235 redraw_mask |= REDRAW_DOOR_1;
1237 redraw_mask |= REDRAW_DOOR_2;
1241 /* (this is just wrong (when drawing to one of the two door panel areas)) */
1242 redraw_mask |= REDRAW_FIELD;
1246 void DrawBackgroundForFont(int x, int y, int width, int height, int font_nr)
1248 struct FontBitmapInfo *font = getFontBitmapInfo(font_nr);
1250 if (font->bitmap == NULL)
1253 DrawBackground(x, y, width, height);
1256 void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic)
1258 struct GraphicInfo *g = &graphic_info[graphic];
1260 if (g->bitmap == NULL)
1263 DrawBackground(x, y, width, height);
1268 /* !!! "drawto" might still point to playfield buffer here (see above) !!! */
1269 /* (when entering hall of fame after playing) */
1270 DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
1272 /* !!! maybe this should be done before clearing the background !!! */
1273 if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
1275 ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
1276 SetDrawtoField(DRAW_BUFFERED);
1279 SetDrawtoField(DRAW_BACKBUFFER);
1282 void MarkTileDirty(int x, int y)
1284 int xx = redraw_x1 + x;
1285 int yy = redraw_y1 + y;
1287 if (!redraw[xx][yy])
1290 redraw[xx][yy] = TRUE;
1291 redraw_mask |= REDRAW_TILES;
1294 void SetBorderElement()
1298 BorderElement = EL_EMPTY;
1300 for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
1302 for (x = 0; x < lev_fieldx; x++)
1304 if (!IS_INDESTRUCTIBLE(Feld[x][y]))
1305 BorderElement = EL_STEELWALL;
1307 if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
1313 void FloodFillLevel(int from_x, int from_y, int fill_element,
1314 short field[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
1315 int max_fieldx, int max_fieldy)
1319 static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
1320 static int safety = 0;
1322 /* check if starting field still has the desired content */
1323 if (field[from_x][from_y] == fill_element)
1328 if (safety > max_fieldx * max_fieldy)
1329 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
1331 old_element = field[from_x][from_y];
1332 field[from_x][from_y] = fill_element;
1334 for (i = 0; i < 4; i++)
1336 x = from_x + check[i][0];
1337 y = from_y + check[i][1];
1339 if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
1340 FloodFillLevel(x, y, fill_element, field, max_fieldx, max_fieldy);
1346 void SetRandomAnimationValue(int x, int y)
1348 gfx.anim_random_frame = GfxRandom[x][y];
1351 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
1353 /* animation synchronized with global frame counter, not move position */
1354 if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
1355 sync_frame = FrameCounter;
1357 return getAnimationFrame(graphic_info[graphic].anim_frames,
1358 graphic_info[graphic].anim_delay,
1359 graphic_info[graphic].anim_mode,
1360 graphic_info[graphic].anim_start_frame,
1364 void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw,
1365 Bitmap **bitmap, int *x, int *y,
1366 boolean get_backside)
1370 int width_mult, width_div;
1371 int height_mult, height_div;
1375 { 15, 16, 2, 3 }, /* 1 x 1 */
1376 { 7, 8, 2, 3 }, /* 2 x 2 */
1377 { 3, 4, 2, 3 }, /* 4 x 4 */
1378 { 1, 2, 2, 3 }, /* 8 x 8 */
1379 { 0, 1, 2, 3 }, /* 16 x 16 */
1380 { 0, 1, 0, 1 }, /* 32 x 32 */
1382 struct GraphicInfo *g = &graphic_info[graphic];
1383 Bitmap *src_bitmap = g->bitmap;
1384 int tilesize = MIN(MAX(1, tilesize_raw), TILESIZE);
1385 int offset_calc_pos = log_2(tilesize);
1386 int width_mult = offset_calc[offset_calc_pos].width_mult;
1387 int width_div = offset_calc[offset_calc_pos].width_div;
1388 int height_mult = offset_calc[offset_calc_pos].height_mult;
1389 int height_div = offset_calc[offset_calc_pos].height_div;
1390 int startx = src_bitmap->width * width_mult / width_div;
1391 int starty = src_bitmap->height * height_mult / height_div;
1393 int src_x = (g->src_x + (get_backside ? g->offset2_x : 0)) *
1394 tilesize / TILESIZE;
1395 int src_y = (g->src_y + (get_backside ? g->offset2_y : 0)) *
1396 tilesize / TILESIZE;
1398 int src_x = g->src_x * tilesize / TILESIZE;
1399 int src_y = g->src_y * tilesize / TILESIZE;
1401 int width = g->width * tilesize / TILESIZE;
1402 int height = g->height * tilesize / TILESIZE;
1403 int offset_x = g->offset_x * tilesize / TILESIZE;
1404 int offset_y = g->offset_y * tilesize / TILESIZE;
1406 if (g->offset_y == 0) /* frames are ordered horizontally */
1408 int max_width = g->anim_frames_per_line * width;
1409 int pos = (src_y / height) * max_width + src_x + frame * offset_x;
1411 src_x = pos % max_width;
1412 src_y = src_y % height + pos / max_width * height;
1414 else if (g->offset_x == 0) /* frames are ordered vertically */
1416 int max_height = g->anim_frames_per_line * height;
1417 int pos = (src_x / width) * max_height + src_y + frame * offset_y;
1419 src_x = src_x % width + pos / max_height * width;
1420 src_y = pos % max_height;
1422 else /* frames are ordered diagonally */
1424 src_x = src_x + frame * offset_x;
1425 src_y = src_y + frame * offset_y;
1428 *bitmap = src_bitmap;
1429 *x = startx + src_x;
1430 *y = starty + src_y;
1433 void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1434 int *x, int *y, boolean get_backside)
1436 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y,
1440 void getSizedGraphicSource(int graphic, int frame, int tilesize_raw,
1441 Bitmap **bitmap, int *x, int *y)
1443 getSizedGraphicSourceExt(graphic, frame, tilesize_raw, bitmap, x, y, FALSE);
1446 void getFixedGraphicSource(int graphic, int frame,
1447 Bitmap **bitmap, int *x, int *y)
1449 getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y, FALSE);
1452 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1455 getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
1457 struct GraphicInfo *g = &graphic_info[graphic];
1458 int mini_startx = 0;
1459 int mini_starty = g->bitmap->height * 2 / 3;
1461 *bitmap = g->bitmap;
1462 *x = mini_startx + g->src_x / 2;
1463 *y = mini_starty + g->src_y / 2;
1467 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
1468 int *x, int *y, boolean get_backside)
1470 struct GraphicInfo *g = &graphic_info[graphic];
1471 int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
1472 int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
1475 if (TILESIZE_VAR != TILESIZE)
1476 return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y,
1480 *bitmap = g->bitmap;
1482 if (g->offset_y == 0) /* frames are ordered horizontally */
1484 int max_width = g->anim_frames_per_line * g->width;
1485 int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
1487 *x = pos % max_width;
1488 *y = src_y % g->height + pos / max_width * g->height;
1490 else if (g->offset_x == 0) /* frames are ordered vertically */
1492 int max_height = g->anim_frames_per_line * g->height;
1493 int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
1495 *x = src_x % g->width + pos / max_height * g->width;
1496 *y = pos % max_height;
1498 else /* frames are ordered diagonally */
1500 *x = src_x + frame * g->offset_x;
1501 *y = src_y + frame * g->offset_y;
1505 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
1507 getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
1510 void DrawGraphic(int x, int y, int graphic, int frame)
1513 if (!IN_SCR_FIELD(x, y))
1515 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1516 printf("DrawGraphic(): This should never happen!\n");
1522 DrawGraphicExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR, graphic,
1525 DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
1527 MarkTileDirty(x, y);
1530 void DrawFixedGraphic(int x, int y, int graphic, int frame)
1533 if (!IN_SCR_FIELD(x, y))
1535 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
1536 printf("DrawGraphic(): This should never happen!\n");
1541 DrawFixedGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1543 MarkTileDirty(x, y);
1546 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1552 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1554 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX_VAR, TILEY_VAR, x, y);
1556 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1560 void DrawFixedGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
1566 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1567 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
1570 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
1573 if (!IN_SCR_FIELD(x, y))
1575 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1576 printf("DrawGraphicThruMask(): This should never happen!\n");
1582 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
1585 DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic,
1588 MarkTileDirty(x, y);
1591 void DrawFixedGraphicThruMask(int x, int y, int graphic, int frame)
1594 if (!IN_SCR_FIELD(x, y))
1596 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
1597 printf("DrawGraphicThruMask(): This should never happen!\n");
1602 DrawFixedGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1604 MarkTileDirty(x, y);
1607 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
1613 getGraphicSource(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);
1618 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX_VAR, TILEY_VAR,
1621 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1625 void DrawFixedGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y,
1626 int graphic, int frame)
1631 getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1633 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1634 dst_x - src_x, dst_y - src_y);
1635 BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
1638 void DrawSizedGraphic(int x, int y, int graphic, int frame, int tilesize)
1640 DrawSizedGraphicExt(drawto, SX + x * tilesize, SY + y * tilesize, graphic,
1642 MarkTileDirty(x / tilesize, y / tilesize);
1645 void DrawSizedGraphicExt(DrawBuffer *d, int x, int y, int graphic, int frame,
1651 getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
1652 BlitBitmap(src_bitmap, d, src_x, src_y, tilesize, tilesize, x, y);
1655 void DrawMiniGraphic(int x, int y, int graphic)
1657 DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
1658 MarkTileDirty(x / 2, y / 2);
1661 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
1666 getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1667 BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
1670 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
1671 int graphic, int frame,
1672 int cut_mode, int mask_mode)
1677 int width = TILEX, height = TILEY;
1680 if (dx || dy) /* shifted graphic */
1682 if (x < BX1) /* object enters playfield from the left */
1689 else if (x > BX2) /* object enters playfield from the right */
1695 else if (x==BX1 && dx < 0) /* object leaves playfield to the left */
1701 else if (x==BX2 && dx > 0) /* object leaves playfield to the right */
1703 else if (dx) /* general horizontal movement */
1704 MarkTileDirty(x + SIGN(dx), y);
1706 if (y < BY1) /* object enters playfield from the top */
1708 if (cut_mode==CUT_BELOW) /* object completely above top border */
1716 else if (y > BY2) /* object enters playfield from the bottom */
1722 else if (y==BY1 && dy < 0) /* object leaves playfield to the top */
1728 else if (dy > 0 && cut_mode == CUT_ABOVE)
1730 if (y == BY2) /* object completely above bottom border */
1736 MarkTileDirty(x, y + 1);
1737 } /* object leaves playfield to the bottom */
1738 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1740 else if (dy) /* general vertical movement */
1741 MarkTileDirty(x, y + SIGN(dy));
1745 if (!IN_SCR_FIELD(x, y))
1747 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1748 printf("DrawGraphicShifted(): This should never happen!\n");
1754 width = width * TILESIZE_VAR / TILESIZE;
1755 height = height * TILESIZE_VAR / TILESIZE;
1756 cx = cx * TILESIZE_VAR / TILESIZE;
1757 cy = cy * TILESIZE_VAR / TILESIZE;
1758 dx = dx * TILESIZE_VAR / TILESIZE;
1759 dy = dy * TILESIZE_VAR / TILESIZE;
1762 if (width > 0 && height > 0)
1764 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1770 dst_x = FX + x * TILEX_VAR + dx;
1771 dst_y = FY + y * TILEY_VAR + dy;
1773 dst_x = FX + x * TILEX + dx;
1774 dst_y = FY + y * TILEY + dy;
1777 if (mask_mode == USE_MASKING)
1779 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1780 dst_x - src_x, dst_y - src_y);
1781 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1785 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1788 MarkTileDirty(x, y);
1792 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
1793 int graphic, int frame,
1794 int cut_mode, int mask_mode)
1800 int width = TILEX_VAR, height = TILEY_VAR;
1802 int width = TILEX, height = TILEY;
1806 int x2 = x + SIGN(dx);
1807 int y2 = y + SIGN(dy);
1809 /* !!! DOES NOT WORK FOR SLOW MOVEMENT !!! */
1810 int sync_frame = GfxFrame[LEVELX(x)][LEVELY(y)];
1812 /* movement with two-tile animations must be sync'ed with movement position,
1813 not with current GfxFrame (which can be higher when using slow movement) */
1814 int anim_pos = (dx ? ABS(dx) : ABS(dy));
1815 int anim_frames = graphic_info[graphic].anim_frames;
1817 /* (we also need anim_delay here for movement animations with less frames) */
1818 int anim_delay = graphic_info[graphic].anim_delay;
1819 int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE;
1821 int sync_frame = anim_pos * anim_frames / TILESIZE;
1824 boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */
1825 boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */
1827 /* re-calculate animation frame for two-tile movement animation */
1828 frame = getGraphicAnimationFrame(graphic, sync_frame);
1832 printf("::: %d, %d, %d => %d [%d]\n",
1833 anim_pos, anim_frames, anim_delay, sync_frame, graphic);
1835 printf("::: %d, %d => %d\n",
1836 anim_pos, anim_frames, sync_frame);
1841 printf("::: %d [%d, %d] [%d] [%d]\n", frame, sync_frame, dy,
1842 GfxFrame[LEVELX(x)][LEVELY(y)], mask_mode);
1845 /* check if movement start graphic inside screen area and should be drawn */
1846 if (draw_start_tile && IN_SCR_FIELD(x1, y1))
1848 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
1851 dst_x = FX + x1 * TILEX_VAR;
1852 dst_y = FY + y1 * TILEY_VAR;
1854 dst_x = FX + x1 * TILEX;
1855 dst_y = FY + y1 * TILEY;
1858 if (mask_mode == USE_MASKING)
1860 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1861 dst_x - src_x, dst_y - src_y);
1862 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1866 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1869 MarkTileDirty(x1, y1);
1872 /* check if movement end graphic inside screen area and should be drawn */
1873 if (draw_end_tile && IN_SCR_FIELD(x2, y2))
1875 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
1878 dst_x = FX + x2 * TILEX_VAR;
1879 dst_y = FY + y2 * TILEY_VAR;
1881 dst_x = FX + x2 * TILEX;
1882 dst_y = FY + y2 * TILEY;
1885 if (mask_mode == USE_MASKING)
1887 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1888 dst_x - src_x, dst_y - src_y);
1889 BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
1893 BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
1896 MarkTileDirty(x2, y2);
1900 static void DrawGraphicShifted(int x, int y, int dx, int dy,
1901 int graphic, int frame,
1902 int cut_mode, int mask_mode)
1906 DrawGraphic(x, y, graphic, frame);
1911 if (graphic_info[graphic].double_movement) /* EM style movement images */
1912 DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1914 DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
1917 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
1918 int frame, int cut_mode)
1920 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
1923 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1924 int cut_mode, int mask_mode)
1926 int lx = LEVELX(x), ly = LEVELY(y);
1930 if (IN_LEV_FIELD(lx, ly))
1932 SetRandomAnimationValue(lx, ly);
1934 graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
1935 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1937 /* do not use double (EM style) movement graphic when not moving */
1938 if (graphic_info[graphic].double_movement && !dx && !dy)
1940 graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
1941 frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
1944 else /* border element */
1946 graphic = el2img(element);
1947 frame = getGraphicAnimationFrame(graphic, -1);
1950 if (element == EL_EXPANDABLE_WALL)
1952 boolean left_stopped = FALSE, right_stopped = FALSE;
1954 if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
1955 left_stopped = TRUE;
1956 if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
1957 right_stopped = TRUE;
1959 if (left_stopped && right_stopped)
1961 else if (left_stopped)
1963 graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
1964 frame = graphic_info[graphic].anim_frames - 1;
1966 else if (right_stopped)
1968 graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
1969 frame = graphic_info[graphic].anim_frames - 1;
1974 DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
1975 else if (mask_mode == USE_MASKING)
1976 DrawGraphicThruMask(x, y, graphic, frame);
1978 DrawGraphic(x, y, graphic, frame);
1981 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1982 int cut_mode, int mask_mode)
1984 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1985 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1986 cut_mode, mask_mode);
1989 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1992 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1995 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1998 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
2001 void DrawLevelElementThruMask(int x, int y, int element)
2003 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
2006 void DrawLevelFieldThruMask(int x, int y)
2008 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
2011 /* !!! implementation of quicksand is totally broken !!! */
2012 #define IS_CRUMBLED_TILE(x, y, e) \
2013 (GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) || \
2014 !IS_MOVING(x, y) || \
2015 (e) == EL_QUICKSAND_EMPTYING || \
2016 (e) == EL_QUICKSAND_FAST_EMPTYING))
2018 static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy,
2023 int width, height, cx, cy;
2024 int sx = SCREENX(x), sy = SCREENY(y);
2025 int crumbled_border_size = graphic_info[graphic].border_size;
2028 getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2030 for (i = 1; i < 4; i++)
2032 int dxx = (i & 1 ? dx : 0);
2033 int dyy = (i & 2 ? dy : 0);
2036 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2039 /* check if neighbour field is of same crumble type */
2040 boolean same = (IS_CRUMBLED_TILE(xx, yy, element) &&
2041 graphic_info[graphic].class ==
2042 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class);
2044 /* return if check prevents inner corner */
2045 if (same == (dxx == dx && dyy == dy))
2049 /* if we reach this point, we have an inner corner */
2051 getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y);
2054 width = crumbled_border_size * TILESIZE_VAR / TILESIZE;
2055 height = crumbled_border_size * TILESIZE_VAR / TILESIZE;
2056 cx = (dx > 0 ? TILEX - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
2057 cy = (dy > 0 ? TILEY - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE;
2059 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2060 width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
2062 width = crumbled_border_size;
2063 height = crumbled_border_size;
2064 cx = (dx > 0 ? TILEX - crumbled_border_size : 0);
2065 cy = (dy > 0 ? TILEY - crumbled_border_size : 0);
2067 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2068 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2072 static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
2077 int width, height, bx, by, cx, cy;
2078 int sx = SCREENX(x), sy = SCREENY(y);
2079 int crumbled_border_size = graphic_info[graphic].border_size;
2082 getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
2084 /* draw simple, sloppy, non-corner-accurate crumbled border */
2087 width = (dir == 1 || dir == 2 ? crumbled_border_size : TILEX);
2088 height = (dir == 0 || dir == 3 ? crumbled_border_size : TILEY);
2089 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2090 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2092 if (dir == 1 || dir == 2) /* left or right crumbled border */
2094 width = crumbled_border_size;
2096 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2099 else /* top or bottom crumbled border */
2102 height = crumbled_border_size;
2104 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2109 BlitBitmap(src_bitmap, drawto_field,
2110 src_x + cx * TILESIZE_VAR / TILESIZE,
2111 src_y + cy * TILESIZE_VAR / TILESIZE,
2112 width * TILESIZE_VAR / TILESIZE,
2113 height * TILESIZE_VAR / TILESIZE,
2114 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
2115 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
2117 BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
2118 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2121 /* (remaining middle border part must be at least as big as corner part) */
2122 if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
2123 crumbled_border_size >= TILESIZE / 3)
2126 /* correct corners of crumbled border, if needed */
2129 for (i = -1; i <= 1; i+=2)
2131 int xx = x + (dir == 0 || dir == 3 ? i : 0);
2132 int yy = y + (dir == 1 || dir == 2 ? i : 0);
2133 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2136 /* check if neighbour field is of same crumble type */
2137 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2138 graphic_info[graphic].class ==
2139 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2141 /* no crumbled corner, but continued crumbled border */
2143 int c1 = (dir == 2 || dir == 3 ? TILESIZE - crumbled_border_size : 0);
2144 int c2 = (i == 1 ? TILESIZE - crumbled_border_size : 0);
2145 int b1 = (i == 1 ? crumbled_border_size :
2146 TILESIZE - 2 * crumbled_border_size);
2148 width = crumbled_border_size;
2149 height = crumbled_border_size;
2151 if (dir == 1 || dir == 2)
2167 BlitBitmap(src_bitmap, drawto_field,
2168 src_x + bx * TILESIZE_VAR / TILESIZE,
2169 src_y + by * TILESIZE_VAR / TILESIZE,
2170 width * TILESIZE_VAR / TILESIZE,
2171 height * TILESIZE_VAR / TILESIZE,
2172 FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE,
2173 FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE);
2175 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2176 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2181 if (dir == 1 || dir == 2) /* left or right crumbled border */
2183 for (i = -1; i <= 1; i+=2)
2187 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2190 /* check if neighbour field is of same crumble type */
2191 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2192 graphic_info[graphic].class ==
2193 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2195 /* no crumbled corner, but continued crumbled border */
2197 width = crumbled_border_size;
2198 height = crumbled_border_size;
2199 cx = (dir == 2 ? TILEX - crumbled_border_size : 0);
2200 cy = (i == 1 ? TILEY - crumbled_border_size : 0);
2202 by = (i == 1 ? crumbled_border_size :
2203 TILEY - 2 * crumbled_border_size);
2205 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2206 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2210 else /* top or bottom crumbled border */
2212 for (i = -1; i <= 1; i+=2)
2216 int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2219 /* check if neighbour field is of same crumble type */
2220 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2221 graphic_info[graphic].class ==
2222 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2224 /* no crumbled corner, but continued crumbled border */
2226 width = crumbled_border_size;
2227 height = crumbled_border_size;
2228 cx = (i == 1 ? TILEX - crumbled_border_size : 0);
2229 cy = (dir == 3 ? TILEY - crumbled_border_size : 0);
2230 bx = (i == 1 ? crumbled_border_size :
2231 TILEX - 2 * crumbled_border_size);
2234 BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
2235 width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
2242 static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame)
2244 int sx = SCREENX(x), sy = SCREENY(y);
2247 static int xy[4][2] =
2255 if (!IN_LEV_FIELD(x, y))
2258 element = TILE_GFX_ELEMENT(x, y);
2260 /* crumble field itself */
2261 if (IS_CRUMBLED_TILE(x, y, element))
2263 if (!IN_SCR_FIELD(sx, sy))
2266 for (i = 0; i < 4; i++)
2268 int xx = x + xy[i][0];
2269 int yy = y + xy[i][1];
2271 element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
2274 /* check if neighbour field is of same crumble type */
2276 if (IS_CRUMBLED_TILE(xx, yy, element) &&
2277 graphic_info[graphic].class ==
2278 graphic_info[el_act2crm(element, ACTION_DEFAULT)].class)
2281 if (IS_CRUMBLED_TILE(xx, yy, element))
2285 DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i);
2288 if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) &&
2289 graphic_info[graphic].anim_frames == 2)
2291 for (i = 0; i < 4; i++)
2293 int dx = (i & 1 ? +1 : -1);
2294 int dy = (i & 2 ? +1 : -1);
2296 DrawLevelFieldCrumbledInnerCorners(x, y, dx, dy, graphic);
2300 MarkTileDirty(sx, sy);
2302 else /* center field not crumbled -- crumble neighbour fields */
2304 for (i = 0; i < 4; i++)
2306 int xx = x + xy[i][0];
2307 int yy = y + xy[i][1];
2308 int sxx = sx + xy[i][0];
2309 int syy = sy + xy[i][1];
2311 if (!IN_LEV_FIELD(xx, yy) ||
2312 !IN_SCR_FIELD(sxx, syy))
2315 if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
2318 element = TILE_GFX_ELEMENT(xx, yy);
2320 if (!IS_CRUMBLED_TILE(xx, yy, element))
2323 graphic = el_act2crm(element, ACTION_DEFAULT);
2325 DrawLevelFieldCrumbledBorders(xx, yy, graphic, 0, 3 - i);
2327 MarkTileDirty(sxx, syy);
2332 void DrawLevelFieldCrumbled(int x, int y)
2336 if (!IN_LEV_FIELD(x, y))
2340 /* !!! CHECK THIS !!! */
2343 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2344 GFX_CRUMBLED(GfxElement[x][y]))
2347 if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
2348 GfxElement[x][y] != EL_UNDEFINED &&
2349 GFX_CRUMBLED(GfxElement[x][y]))
2351 DrawLevelFieldCrumbledDigging(x, y, GfxDir[x][y], GfxFrame[x][y]);
2358 graphic = el_act2crm(TILE_GFX_ELEMENT(x, y), ACTION_DEFAULT);
2360 graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
2363 DrawLevelFieldCrumbledExt(x, y, graphic, 0);
2366 void DrawLevelFieldCrumbledDigging(int x, int y, int direction,
2369 int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
2370 int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
2371 int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
2372 int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
2373 int sx = SCREENX(x), sy = SCREENY(y);
2375 DrawGraphic(sx, sy, graphic1, frame1);
2376 DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
2379 void DrawLevelFieldCrumbledNeighbours(int x, int y)
2381 int sx = SCREENX(x), sy = SCREENY(y);
2382 static int xy[4][2] =
2391 for (i = 0; i < 4; i++)
2393 int xx = x + xy[i][0];
2394 int yy = y + xy[i][1];
2395 int sxx = sx + xy[i][0];
2396 int syy = sy + xy[i][1];
2398 if (!IN_LEV_FIELD(xx, yy) ||
2399 !IN_SCR_FIELD(sxx, syy) ||
2400 !GFX_CRUMBLED(Feld[xx][yy]) ||
2404 DrawLevelField(xx, yy);
2408 static int getBorderElement(int x, int y)
2412 { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
2413 { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
2414 { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
2415 { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
2416 { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
2417 { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
2418 { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
2420 int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
2421 int steel_position = (x == -1 && y == -1 ? 0 :
2422 x == lev_fieldx && y == -1 ? 1 :
2423 x == -1 && y == lev_fieldy ? 2 :
2424 x == lev_fieldx && y == lev_fieldy ? 3 :
2425 x == -1 || x == lev_fieldx ? 4 :
2426 y == -1 || y == lev_fieldy ? 5 : 6);
2428 return border[steel_position][steel_type];
2431 void DrawScreenElement(int x, int y, int element)
2433 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
2434 DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
2437 void DrawLevelElement(int x, int y, int element)
2439 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2440 DrawScreenElement(SCREENX(x), SCREENY(y), element);
2443 void DrawScreenField(int x, int y)
2445 int lx = LEVELX(x), ly = LEVELY(y);
2446 int element, content;
2448 if (!IN_LEV_FIELD(lx, ly))
2450 if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
2453 element = getBorderElement(lx, ly);
2455 DrawScreenElement(x, y, element);
2460 element = Feld[lx][ly];
2461 content = Store[lx][ly];
2463 if (IS_MOVING(lx, ly))
2465 int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
2466 boolean cut_mode = NO_CUTTING;
2468 if (element == EL_QUICKSAND_EMPTYING ||
2469 element == EL_QUICKSAND_FAST_EMPTYING ||
2470 element == EL_MAGIC_WALL_EMPTYING ||
2471 element == EL_BD_MAGIC_WALL_EMPTYING ||
2472 element == EL_DC_MAGIC_WALL_EMPTYING ||
2473 element == EL_AMOEBA_DROPPING)
2474 cut_mode = CUT_ABOVE;
2475 else if (element == EL_QUICKSAND_FILLING ||
2476 element == EL_QUICKSAND_FAST_FILLING ||
2477 element == EL_MAGIC_WALL_FILLING ||
2478 element == EL_BD_MAGIC_WALL_FILLING ||
2479 element == EL_DC_MAGIC_WALL_FILLING)
2480 cut_mode = CUT_BELOW;
2483 if (lx == 9 && ly == 1)
2484 printf("::: %s [%d] [%d, %d] [%d]\n",
2485 EL_NAME(TILE_GFX_ELEMENT(lx, ly)),
2486 el_act2crm(TILE_GFX_ELEMENT(lx, ly), ACTION_DEFAULT),
2487 element_info[EL_QUICKSAND_EMPTYING].graphic[ACTION_DEFAULT],
2488 element_info[EL_QUICKSAND_EMPTYING].crumbled[ACTION_DEFAULT],
2489 GFX_CRUMBLED(TILE_GFX_ELEMENT(lx, ly)));
2492 if (cut_mode == CUT_ABOVE)
2494 DrawScreenElement(x, y, element);
2496 DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
2499 DrawScreenElement(x, y, EL_EMPTY);
2502 DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
2503 else if (cut_mode == NO_CUTTING)
2504 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
2507 DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
2510 if (cut_mode == CUT_BELOW &&
2511 IN_LEV_FIELD(lx, ly + 1) && IN_SCR_FIELD(x, y + 1))
2512 DrawLevelElement(lx, ly + 1, element);
2516 if (content == EL_ACID)
2518 int dir = MovDir[lx][ly];
2519 int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
2520 int newly = ly + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
2522 DrawLevelElementThruMask(newlx, newly, EL_ACID);
2525 else if (IS_BLOCKED(lx, ly))
2530 boolean cut_mode = NO_CUTTING;
2531 int element_old, content_old;
2533 Blocked2Moving(lx, ly, &oldx, &oldy);
2536 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
2537 MovDir[oldx][oldy] == MV_RIGHT);
2539 element_old = Feld[oldx][oldy];
2540 content_old = Store[oldx][oldy];
2542 if (element_old == EL_QUICKSAND_EMPTYING ||
2543 element_old == EL_QUICKSAND_FAST_EMPTYING ||
2544 element_old == EL_MAGIC_WALL_EMPTYING ||
2545 element_old == EL_BD_MAGIC_WALL_EMPTYING ||
2546 element_old == EL_DC_MAGIC_WALL_EMPTYING ||
2547 element_old == EL_AMOEBA_DROPPING)
2548 cut_mode = CUT_ABOVE;
2550 DrawScreenElement(x, y, EL_EMPTY);
2553 DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
2555 else if (cut_mode == NO_CUTTING)
2556 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
2559 DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
2562 else if (IS_DRAWABLE(element))
2563 DrawScreenElement(x, y, element);
2565 DrawScreenElement(x, y, EL_EMPTY);
2568 void DrawLevelField(int x, int y)
2570 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
2571 DrawScreenField(SCREENX(x), SCREENY(y));
2572 else if (IS_MOVING(x, y))
2576 Moving2Blocked(x, y, &newx, &newy);
2577 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
2578 DrawScreenField(SCREENX(newx), SCREENY(newy));
2580 else if (IS_BLOCKED(x, y))
2584 Blocked2Moving(x, y, &oldx, &oldy);
2585 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
2586 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
2590 void DrawMiniElement(int x, int y, int element)
2594 graphic = el2edimg(element);
2595 DrawMiniGraphic(x, y, graphic);
2598 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
2600 int x = sx + scroll_x, y = sy + scroll_y;
2602 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
2603 DrawMiniElement(sx, sy, EL_EMPTY);
2604 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
2605 DrawMiniElement(sx, sy, Feld[x][y]);
2607 DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
2610 void DrawEnvelopeBackgroundTiles(int graphic, int startx, int starty,
2611 int x, int y, int xsize, int ysize,
2612 int tile_width, int tile_height)
2616 int dst_x = startx + x * tile_width;
2617 int dst_y = starty + y * tile_height;
2618 int width = graphic_info[graphic].width;
2619 int height = graphic_info[graphic].height;
2620 int inner_width_raw = MAX(width - 2 * tile_width, tile_width);
2621 int inner_height_raw = MAX(height - 2 * tile_height, tile_height);
2622 int inner_width = inner_width_raw - (inner_width_raw % tile_width);
2623 int inner_height = inner_height_raw - (inner_height_raw % tile_height);
2624 int inner_sx = (width >= 3 * tile_width ? tile_width : 0);
2625 int inner_sy = (height >= 3 * tile_height ? tile_height : 0);
2626 boolean draw_masked = graphic_info[graphic].draw_masked;
2628 getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
2630 if (src_bitmap == NULL || width < tile_width || height < tile_height)
2632 ClearRectangle(drawto, dst_x, dst_y, tile_width, tile_height);
2636 src_x += (x == 0 ? 0 : x == xsize - 1 ? width - tile_width :
2637 inner_sx + (x - 1) * tile_width % inner_width);
2638 src_y += (y == 0 ? 0 : y == ysize - 1 ? height - tile_height :
2639 inner_sy + (y - 1) * tile_height % inner_height);
2643 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
2644 dst_x - src_x, dst_y - src_y);
2645 BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
2649 BlitBitmap(src_bitmap, drawto, src_x, src_y, tile_width, tile_height,
2653 void DrawEnvelopeBackground(int graphic, int startx, int starty,
2654 int x, int y, int xsize, int ysize, int font_nr)
2656 int font_width = getFontWidth(font_nr);
2657 int font_height = getFontHeight(font_nr);
2659 DrawEnvelopeBackgroundTiles(graphic, startx, starty, x, y, xsize, ysize,
2660 font_width, font_height);
2663 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
2665 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2666 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2667 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2668 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2669 boolean no_delay = (tape.warp_forward);
2670 unsigned int anim_delay = 0;
2671 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
2672 int anim_delay_value = (no_delay ? 0 : frame_delay_value);
2673 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
2674 int font_width = getFontWidth(font_nr);
2675 int font_height = getFontHeight(font_nr);
2676 int max_xsize = level.envelope[envelope_nr].xsize;
2677 int max_ysize = level.envelope[envelope_nr].ysize;
2678 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
2679 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
2680 int xend = max_xsize;
2681 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
2682 int xstep = (xstart < xend ? 1 : 0);
2683 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2686 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2688 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2689 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2690 int sx = SX + (SXSIZE - xsize * font_width) / 2;
2691 int sy = SY + (SYSIZE - ysize * font_height) / 2;
2694 SetDrawtoField(DRAW_BUFFERED);
2697 BlitScreenToBitmap(backbuffer);
2699 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
2702 SetDrawtoField(DRAW_BACKBUFFER);
2704 for (yy = 0; yy < ysize; yy++)
2705 for (xx = 0; xx < xsize; xx++)
2706 DrawEnvelopeBackground(graphic, sx, sy, xx, yy, xsize, ysize, font_nr);
2709 DrawTextBuffer(sx + font_width, sy + font_height,
2710 level.envelope[envelope_nr].text, font_nr, max_xsize,
2711 xsize - 2, ysize - 2, 0, mask_mode,
2712 level.envelope[envelope_nr].autowrap,
2713 level.envelope[envelope_nr].centered, FALSE);
2715 DrawTextToTextArea(sx + font_width, sy + font_height,
2716 level.envelope[envelope_nr].text, font_nr, max_xsize,
2717 xsize - 2, ysize - 2, mask_mode);
2720 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2723 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2727 void ShowEnvelope(int envelope_nr)
2729 int element = EL_ENVELOPE_1 + envelope_nr;
2730 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
2731 int sound_opening = element_info[element].sound[ACTION_OPENING];
2732 int sound_closing = element_info[element].sound[ACTION_CLOSING];
2733 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2734 boolean no_delay = (tape.warp_forward);
2735 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
2736 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
2737 int anim_mode = graphic_info[graphic].anim_mode;
2738 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
2739 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
2741 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
2743 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
2745 if (anim_mode == ANIM_DEFAULT)
2746 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
2748 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
2751 Delay(wait_delay_value);
2753 WaitForEventToContinue();
2755 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
2757 if (anim_mode != ANIM_NONE)
2758 AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
2760 if (anim_mode == ANIM_DEFAULT)
2761 AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
2763 game.envelope_active = FALSE;
2765 SetDrawtoField(DRAW_BUFFERED);
2767 redraw_mask |= REDRAW_FIELD;
2771 static void setRequestPosition(int *x, int *y, boolean add_border_size)
2773 int border_size = request.border_size;
2774 int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2);
2775 int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2);
2776 int sx = sx_center - request.width / 2;
2777 int sy = sy_center - request.height / 2;
2779 if (add_border_size)
2789 void DrawEnvelopeRequest(char *text)
2791 char *text_final = text;
2792 char *text_door_style = NULL;
2793 int graphic = IMG_BACKGROUND_REQUEST;
2794 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
2795 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
2796 int font_nr = FONT_REQUEST;
2797 int font_width = getFontWidth(font_nr);
2798 int font_height = getFontHeight(font_nr);
2799 int border_size = request.border_size;
2800 int line_spacing = request.line_spacing;
2801 int line_height = font_height + line_spacing;
2802 int text_width = request.width - 2 * border_size;
2803 int text_height = request.height - 2 * border_size;
2804 int line_length = text_width / font_width;
2805 int max_lines = text_height / line_height;
2806 int width = request.width;
2807 int height = request.height;
2808 int tile_size = request.step_offset;
2809 int x_steps = width / tile_size;
2810 int y_steps = height / tile_size;
2814 if (request.wrap_single_words)
2816 char *src_text_ptr, *dst_text_ptr;
2818 text_door_style = checked_malloc(2 * strlen(text) + 1);
2820 src_text_ptr = text;
2821 dst_text_ptr = text_door_style;
2823 while (*src_text_ptr)
2825 if (*src_text_ptr == ' ' ||
2826 *src_text_ptr == '?' ||
2827 *src_text_ptr == '!')
2828 *dst_text_ptr++ = '\n';
2830 if (*src_text_ptr != ' ')
2831 *dst_text_ptr++ = *src_text_ptr;
2836 *dst_text_ptr = '\0';
2838 text_final = text_door_style;
2841 setRequestPosition(&sx, &sy, FALSE);
2843 ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
2845 for (y = 0; y < y_steps; y++)
2846 for (x = 0; x < x_steps; x++)
2847 DrawEnvelopeBackgroundTiles(graphic, sx, sy,
2848 x, y, x_steps, y_steps,
2849 tile_size, tile_size);
2851 DrawTextBuffer(sx + border_size, sy + border_size, text_final, font_nr,
2852 line_length, -1, max_lines, line_spacing, mask_mode,
2853 request.autowrap, request.centered, FALSE);
2855 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2856 RedrawGadget(tool_gadget[i]);
2858 // store readily prepared envelope request for later use when animating
2859 BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2863 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2864 BlitBitmap(bitmap_db_cross, backbuffer, sx, sy, width, height, sx, sy);
2866 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2871 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2873 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2879 if (text_door_style)
2880 free(text_door_style);
2885 void AnimateEnvelopeRequest(int anim_mode, int action)
2887 int graphic = IMG_BACKGROUND_REQUEST;
2888 boolean draw_masked = graphic_info[graphic].draw_masked;
2890 int delay_value_normal = request.step_delay;
2891 int delay_value_fast = delay_value_normal / 2;
2893 int delay_value_normal = GameFrameDelay;
2894 int delay_value_fast = FfwdFrameDelay;
2896 boolean ffwd_delay = (tape.playing && tape.fast_forward);
2897 boolean no_delay = (tape.warp_forward);
2898 int delay_value = (ffwd_delay ? delay_value_fast : delay_value_normal);
2899 int anim_delay_value = (no_delay ? 0 : delay_value + 500 * 0);
2900 unsigned int anim_delay = 0;
2902 int width = request.width;
2903 int height = request.height;
2904 int tile_size = request.step_offset;
2905 int max_xsize = width / tile_size;
2906 int max_ysize = height / tile_size;
2907 int max_xsize_inner = max_xsize - 2;
2908 int max_ysize_inner = max_ysize - 2;
2910 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize_inner : 0);
2911 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize_inner : 0);
2912 int xend = max_xsize_inner;
2913 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize_inner : 0);
2914 int xstep = (xstart < xend ? 1 : 0);
2915 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
2918 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
2920 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
2921 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
2922 int sx_center = (request.x != -1 ? request.x : SX + SXSIZE / 2);
2923 int sy_center = (request.y != -1 ? request.y : SY + SYSIZE / 2);
2924 int src_x = sx_center - width / 2;
2925 int src_y = sy_center - height / 2;
2926 int dst_x = sx_center - xsize * tile_size / 2;
2927 int dst_y = sy_center - ysize * tile_size / 2;
2928 int xsize_size_left = (xsize - 1) * tile_size;
2929 int ysize_size_top = (ysize - 1) * tile_size;
2930 int max_xsize_pos = (max_xsize - 1) * tile_size;
2931 int max_ysize_pos = (max_ysize - 1) * tile_size;
2934 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2937 for (yy = 0; yy < 2; yy++)
2939 for (xx = 0; xx < 2; xx++)
2941 int src_xx = src_x + xx * max_xsize_pos;
2942 int src_yy = src_y + yy * max_ysize_pos;
2943 int dst_xx = dst_x + xx * xsize_size_left;
2944 int dst_yy = dst_y + yy * ysize_size_top;
2945 int xx_size = (xx ? tile_size : xsize_size_left);
2946 int yy_size = (yy ? tile_size : ysize_size_top);
2949 BlitBitmapMasked(bitmap_db_cross, backbuffer,
2950 src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
2952 BlitBitmap(bitmap_db_cross, backbuffer,
2953 src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy);
2957 BlitBitmap(bitmap_db_cross, backbuffer,
2959 xsize_size_left, ysize_size_top,
2961 BlitBitmap(bitmap_db_cross, backbuffer,
2962 src_x + max_xsize_pos, src_y,
2963 tile_size, ysize_size_top,
2964 dst_x + xsize_size_left, dst_y);
2965 BlitBitmap(bitmap_db_cross, backbuffer,
2966 src_x, src_y + max_ysize_pos,
2967 xsize_size_left, tile_size,
2968 dst_x, dst_y + ysize_size_top);
2969 BlitBitmap(bitmap_db_cross, backbuffer,
2970 src_x + max_xsize_pos, src_y + max_ysize_pos,
2971 tile_size, tile_size,
2972 dst_x + xsize_size_left, dst_y + ysize_size_top);
2976 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2977 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
2979 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
2989 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
2995 void AnimateEnvelopeRequest(char *text, int anim_mode, int action)
2998 int envelope_nr = 0;
3001 int graphic = IMG_BACKGROUND_REQUEST;
3003 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
3005 Bitmap *src_bitmap = graphic_info[graphic].bitmap;
3006 int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
3007 boolean ffwd_delay = (tape.playing && tape.fast_forward);
3008 boolean no_delay = (tape.warp_forward);
3009 unsigned int anim_delay = 0;
3010 int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
3011 int anim_delay_value = (no_delay ? 0 : frame_delay_value + 500 * 0);
3013 int max_word_len = maxWordLengthInString(text);
3014 int font_nr = (max_word_len > 7 ? FONT_TEXT_1 : FONT_TEXT_2);
3016 int font_nr = FONT_ENVELOPE_1 + envelope_nr;
3018 int font_width = getFontWidth(font_nr);
3019 int font_height = getFontHeight(font_nr);
3020 int line_spacing = 2 * 1;
3024 int max_xsize = DXSIZE / font_width;
3025 // int max_ysize = DYSIZE / font_height;
3026 int max_ysize = DYSIZE / (font_height + line_spacing);
3028 int max_xsize = 7; /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
3029 int max_ysize = 13; /* tools.c: MAX_REQUEST_LINES == 13 */
3033 int max_xsize = level.envelope[envelope_nr].xsize;
3034 int max_ysize = level.envelope[envelope_nr].ysize;
3036 int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
3037 int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
3038 int xend = max_xsize;
3039 int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
3040 int xstep = (xstart < xend ? 1 : 0);
3041 int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
3046 char *text_copy = getStringCopy(text);
3049 font_nr = FONT_TEXT_2;
3051 if (maxWordLengthInString(text) > 7) /* MAX_REQUEST_LINE_FONT1_LEN == 7 */
3053 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
3054 font_nr = FONT_TEXT_1;
3057 int max_word_len = 0;
3059 char *text_copy = getStringCopy(text);
3061 font_nr = FONT_TEXT_2;
3063 for (text_ptr = text; *text_ptr; text_ptr++)
3065 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
3067 if (max_word_len > 7) /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */
3069 max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */
3070 font_nr = FONT_TEXT_1;
3079 for (text_ptr = text_copy; *text_ptr; text_ptr++)
3080 if (*text_ptr == ' ')
3085 dDX = SX + (SXSIZE - DXSIZE) / 2 - DX;
3086 dDY = SY + (SYSIZE - DYSIZE) / 2 - DY;
3088 dDX = SX + SXSIZE / 2 - max_xsize * font_width / 2 - DX;
3089 dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY;
3092 for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
3094 int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
3095 int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
3096 int sx = SX + (SXSIZE - xsize * font_width) / 2;
3097 // int sy = SX + (SYSIZE - ysize * font_height) / 2;
3098 int sy = SY + (SYSIZE - ysize * (font_height + line_spacing)) / 2;
3102 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3104 SetDrawtoField(DRAW_BUFFERED);
3107 BlitScreenToBitmap(backbuffer);
3109 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
3112 SetDrawtoField(DRAW_BACKBUFFER);
3115 for (yy = 0; yy < ysize; yy++)
3116 for (xx = 0; xx < xsize; xx++)
3117 DrawEnvelopeBackgroundTiles(graphic, sx, sy, xx, yy, xsize, ysize,
3118 getFontWidth(font_nr),
3119 getFontHeight(font_nr) + line_spacing);
3124 DrawTextBuffer(sx + font_width, sy + font_height + 8,
3125 text_copy, font_nr, max_xsize,
3126 xsize - 2, ysize - 2, line_spacing, mask_mode,
3127 FALSE, TRUE, FALSE);
3129 DrawTextBuffer(sx + font_width, sy + font_height,
3130 level.envelope[envelope_nr].text, font_nr, max_xsize,
3131 xsize - 2, ysize - 2, 0, mask_mode,
3132 level.envelope[envelope_nr].autowrap,
3133 level.envelope[envelope_nr].centered, FALSE);
3137 DrawTextToTextArea(sx + font_width, sy + font_height,
3138 level.envelope[envelope_nr].text, font_nr, max_xsize,
3139 xsize - 2, ysize - 2, mask_mode);
3142 /* copy request gadgets to door backbuffer */
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));
3154 if ((ysize - 2) > 13)
3155 BlitBitmap(bitmap_db_door, drawto,
3156 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3157 DOOR_GFX_PAGEY1 + 11 * (font_height + line_spacing * 0),
3158 (xsize - 2) * font_width,
3159 (ysize - 2 - 13) * (font_height + line_spacing),
3161 sy + (font_height + line_spacing) * (1 + 13));
3163 if ((ysize - 2) > 13)
3164 BlitBitmap(bitmap_db_door, drawto,
3165 DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2,
3166 DOOR_GFX_PAGEY1 + 13 * font_height,
3167 (xsize - 2) * font_width,
3168 (ysize - 2 - 13) * font_height,
3170 sy + font_height * (1 + 13));
3174 redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3175 // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER;
3177 redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
3187 WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
3197 void ShowEnvelopeRequest(char *text, unsigned int req_state, int action)
3200 int last_game_status = game_status; /* save current game status */
3201 // int last_draw_background_mask = gfx.draw_background_mask;
3204 int graphic = IMG_BACKGROUND_REQUEST;
3205 int sound_opening = SND_REQUEST_OPENING;
3206 int sound_closing = SND_REQUEST_CLOSING;
3208 int envelope_nr = 0;
3209 int element = EL_ENVELOPE_1 + envelope_nr;
3210 int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
3211 int sound_opening = element_info[element].sound[ACTION_OPENING];
3212 int sound_closing = element_info[element].sound[ACTION_CLOSING];
3215 boolean ffwd_delay = (tape.playing && tape.fast_forward);
3216 boolean no_delay = (tape.warp_forward);
3217 int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
3218 int wait_delay_value = (no_delay ? 0 : normal_delay_value);
3220 int anim_mode = graphic_info[graphic].anim_mode;
3221 int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
3222 anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
3224 char *text_copy = getStringCopy(text);
3227 for (text_ptr = text_copy; *text_ptr; text_ptr++)
3228 if (*text_ptr == ' ')
3233 if (game_status == GAME_MODE_PLAYING)
3235 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
3236 BlitScreenToBitmap_EM(backbuffer);
3237 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
3238 BlitScreenToBitmap_SP(backbuffer);
3241 BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
3245 SetDrawtoField(DRAW_BACKBUFFER);
3247 // SetDrawBackgroundMask(REDRAW_NONE);
3249 if (action == ACTION_OPENING)
3251 BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3254 if (req_state & REQ_ASK)
3256 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
3257 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
3259 else if (req_state & REQ_CONFIRM)
3261 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
3263 else if (req_state & REQ_PLAYER)
3265 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
3266 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
3267 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
3268 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
3273 DrawEnvelopeRequest(text);
3275 DrawEnvelopeRequest(text_copy);
3278 if (game_status != GAME_MODE_MAIN)
3282 /* force DOOR font inside door area */
3283 game_status = GAME_MODE_PSEUDO_DOOR;
3286 game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */
3288 if (action == ACTION_OPENING)
3290 PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
3292 if (anim_mode == ANIM_DEFAULT)
3293 AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_OPENING);
3295 AnimateEnvelopeRequest(main_anim_mode, ACTION_OPENING);
3299 Delay(wait_delay_value);
3301 WaitForEventToContinue();
3306 PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
3308 if (anim_mode != ANIM_NONE)
3309 AnimateEnvelopeRequest(main_anim_mode, ACTION_CLOSING);
3311 if (anim_mode == ANIM_DEFAULT)
3312 AnimateEnvelopeRequest(ANIM_DEFAULT, ACTION_CLOSING);
3315 game.envelope_active = FALSE;
3318 // game_status = last_game_status; /* restore current game status */
3320 if (action == ACTION_CLOSING)
3322 if (game_status != GAME_MODE_MAIN)
3325 BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3328 SetDrawtoField(DRAW_BUFFERED);
3331 // SetDrawBackgroundMask(last_draw_background_mask);
3334 redraw_mask = REDRAW_FIELD;
3335 // redraw_mask |= REDRAW_ALL;
3337 redraw_mask |= REDRAW_FIELD;
3341 if (game_status == GAME_MODE_MAIN)
3346 /* (important: after "BackToFront()", but before "SetDrawtoField()") */
3347 game_status = last_game_status; /* restore current game status */
3350 if (action == ACTION_CLOSING &&
3351 game_status == GAME_MODE_PLAYING &&
3352 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3353 SetDrawtoField(DRAW_BUFFERED);
3355 if (game_status == GAME_MODE_PLAYING &&
3356 level.game_engine_type == GAME_ENGINE_TYPE_RND)
3357 SetDrawtoField(DRAW_BUFFERED);
3369 void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize)
3373 int graphic = el2preimg(element);
3375 getSizedGraphicSource(graphic, 0, tilesize, &src_bitmap, &src_x, &src_y);
3376 BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y);
3384 SetMainBackgroundImage(IMG_BACKGROUND_PLAYING);
3385 SetDrawBackgroundMask(REDRAW_FIELD);
3387 SetDrawBackgroundMask(REDRAW_NONE);
3392 for (x = BX1; x <= BX2; x++)
3393 for (y = BY1; y <= BY2; y++)
3394 DrawScreenField(x, y);
3396 redraw_mask |= REDRAW_FIELD;
3399 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
3403 for (x = 0; x < size_x; x++)
3404 for (y = 0; y < size_y; y++)
3405 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
3407 redraw_mask |= REDRAW_FIELD;
3410 static void DrawPreviewLevelPlayfieldExt(int from_x, int from_y)
3412 boolean show_level_border = (BorderElement != EL_EMPTY);
3413 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3414 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3415 int tile_size = preview.tile_size;
3416 int preview_width = preview.xsize * tile_size;
3417 int preview_height = preview.ysize * tile_size;
3418 int real_preview_xsize = MIN(level_xsize, preview.xsize);
3419 int real_preview_ysize = MIN(level_ysize, preview.ysize);
3420 int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
3421 int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
3424 DrawBackground(dst_x, dst_y, preview_width, preview_height);
3426 dst_x += (preview_width - real_preview_xsize * tile_size) / 2;
3427 dst_y += (preview_height - real_preview_ysize * tile_size) / 2;
3429 for (x = 0; x < real_preview_xsize; x++)
3431 for (y = 0; y < real_preview_ysize; y++)
3433 int lx = from_x + x + (show_level_border ? -1 : 0);
3434 int ly = from_y + y + (show_level_border ? -1 : 0);
3435 int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
3436 getBorderElement(lx, ly));
3438 DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size,
3439 element, tile_size);
3443 redraw_mask |= REDRAW_MICROLEVEL;
3446 #define MICROLABEL_EMPTY 0
3447 #define MICROLABEL_LEVEL_NAME 1
3448 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
3449 #define MICROLABEL_LEVEL_AUTHOR 3
3450 #define MICROLABEL_IMPORTED_FROM_HEAD 4
3451 #define MICROLABEL_IMPORTED_FROM 5
3452 #define MICROLABEL_IMPORTED_BY_HEAD 6
3453 #define MICROLABEL_IMPORTED_BY 7
3455 static int getMaxTextLength(struct TextPosInfo *pos, int font_nr)
3457 int max_text_width = SXSIZE;
3458 int font_width = getFontWidth(font_nr);
3460 if (pos->align == ALIGN_CENTER)
3461 max_text_width = (pos->x < SXSIZE / 2 ? pos->x * 2 : (SXSIZE - pos->x) * 2);
3462 else if (pos->align == ALIGN_RIGHT)
3463 max_text_width = pos->x;
3465 max_text_width = SXSIZE - pos->x;
3467 return max_text_width / font_width;
3470 static void DrawPreviewLevelLabelExt(int mode)
3472 struct TextPosInfo *pos = &menu.main.text.level_info_2;
3473 char label_text[MAX_OUTPUT_LINESIZE + 1];
3474 int max_len_label_text;
3476 int font_nr = pos->font;
3479 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3480 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3481 mode == MICROLABEL_IMPORTED_BY_HEAD)
3482 font_nr = pos->font_alt;
3484 int font_nr = FONT_TEXT_2;
3487 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3488 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3489 mode == MICROLABEL_IMPORTED_BY_HEAD)
3490 font_nr = FONT_TEXT_3;
3494 max_len_label_text = getMaxTextLength(pos, font_nr);
3496 max_len_label_text = SXSIZE / getFontWidth(font_nr);
3500 if (pos->size != -1)
3501 max_len_label_text = pos->size;
3504 for (i = 0; i < max_len_label_text; i++)
3505 label_text[i] = ' ';
3506 label_text[max_len_label_text] = '\0';
3508 if (strlen(label_text) > 0)
3511 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3513 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3514 int lypos = MICROLABEL2_YPOS;
3516 DrawText(lxpos, lypos, label_text, font_nr);
3521 (mode == MICROLABEL_LEVEL_NAME ? level.name :
3522 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
3523 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
3524 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
3525 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
3526 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
3527 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
3528 max_len_label_text);
3529 label_text[max_len_label_text] = '\0';
3531 if (strlen(label_text) > 0)
3534 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3536 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3537 int lypos = MICROLABEL2_YPOS;
3539 DrawText(lxpos, lypos, label_text, font_nr);
3543 redraw_mask |= REDRAW_MICROLEVEL;
3546 static void DrawPreviewLevelExt(boolean restart)
3548 static unsigned int scroll_delay = 0;
3549 static unsigned int label_delay = 0;
3550 static int from_x, from_y, scroll_direction;
3551 static int label_state, label_counter;
3552 unsigned int scroll_delay_value = preview.step_delay;
3553 boolean show_level_border = (BorderElement != EL_EMPTY);
3554 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3555 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3556 int last_game_status = game_status; /* save current game status */
3559 /* force PREVIEW font on preview level */
3560 game_status = GAME_MODE_PSEUDO_PREVIEW;
3568 if (preview.anim_mode == ANIM_CENTERED)
3570 if (level_xsize > preview.xsize)
3571 from_x = (level_xsize - preview.xsize) / 2;
3572 if (level_ysize > preview.ysize)
3573 from_y = (level_ysize - preview.ysize) / 2;
3576 from_x += preview.xoffset;
3577 from_y += preview.yoffset;
3579 scroll_direction = MV_RIGHT;
3583 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3584 DrawPreviewLevelLabelExt(label_state);
3586 /* initialize delay counters */
3587 DelayReached(&scroll_delay, 0);
3588 DelayReached(&label_delay, 0);
3590 if (leveldir_current->name)
3592 struct TextPosInfo *pos = &menu.main.text.level_info_1;
3593 char label_text[MAX_OUTPUT_LINESIZE + 1];
3595 int font_nr = pos->font;
3597 int font_nr = FONT_TEXT_1;
3600 int max_len_label_text = getMaxTextLength(pos, font_nr);
3602 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
3610 if (pos->size != -1)
3611 max_len_label_text = pos->size;
3614 strncpy(label_text, leveldir_current->name, max_len_label_text);
3615 label_text[max_len_label_text] = '\0';
3618 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3620 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3621 lypos = SY + MICROLABEL1_YPOS;
3623 DrawText(lxpos, lypos, label_text, font_nr);
3627 game_status = last_game_status; /* restore current game status */
3632 /* scroll preview level, if needed */
3633 if (preview.anim_mode != ANIM_NONE &&
3634 (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
3635 DelayReached(&scroll_delay, scroll_delay_value))
3637 switch (scroll_direction)
3642 from_x -= preview.step_offset;
3643 from_x = (from_x < 0 ? 0 : from_x);
3646 scroll_direction = MV_UP;
3650 if (from_x < level_xsize - preview.xsize)
3652 from_x += preview.step_offset;
3653 from_x = (from_x > level_xsize - preview.xsize ?
3654 level_xsize - preview.xsize : from_x);
3657 scroll_direction = MV_DOWN;
3663 from_y -= preview.step_offset;
3664 from_y = (from_y < 0 ? 0 : from_y);
3667 scroll_direction = MV_RIGHT;
3671 if (from_y < level_ysize - preview.ysize)
3673 from_y += preview.step_offset;
3674 from_y = (from_y > level_ysize - preview.ysize ?
3675 level_ysize - preview.ysize : from_y);
3678 scroll_direction = MV_LEFT;
3685 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3688 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
3689 /* redraw micro level label, if needed */
3690 if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
3691 !strEqual(level.author, ANONYMOUS_NAME) &&
3692 !strEqual(level.author, leveldir_current->name) &&
3693 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
3695 int max_label_counter = 23;
3697 if (leveldir_current->imported_from != NULL &&
3698 strlen(leveldir_current->imported_from) > 0)
3699 max_label_counter += 14;
3700 if (leveldir_current->imported_by != NULL &&
3701 strlen(leveldir_current->imported_by) > 0)
3702 max_label_counter += 14;
3704 label_counter = (label_counter + 1) % max_label_counter;
3705 label_state = (label_counter >= 0 && label_counter <= 7 ?
3706 MICROLABEL_LEVEL_NAME :
3707 label_counter >= 9 && label_counter <= 12 ?
3708 MICROLABEL_LEVEL_AUTHOR_HEAD :
3709 label_counter >= 14 && label_counter <= 21 ?
3710 MICROLABEL_LEVEL_AUTHOR :
3711 label_counter >= 23 && label_counter <= 26 ?
3712 MICROLABEL_IMPORTED_FROM_HEAD :
3713 label_counter >= 28 && label_counter <= 35 ?
3714 MICROLABEL_IMPORTED_FROM :
3715 label_counter >= 37 && label_counter <= 40 ?
3716 MICROLABEL_IMPORTED_BY_HEAD :
3717 label_counter >= 42 && label_counter <= 49 ?
3718 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
3720 if (leveldir_current->imported_from == NULL &&
3721 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
3722 label_state == MICROLABEL_IMPORTED_FROM))
3723 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
3724 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
3726 DrawPreviewLevelLabelExt(label_state);
3729 game_status = last_game_status; /* restore current game status */
3732 void DrawPreviewLevelInitial()
3734 DrawPreviewLevelExt(TRUE);
3737 void DrawPreviewLevelAnimation()
3739 DrawPreviewLevelExt(FALSE);
3742 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3743 int graphic, int sync_frame, int mask_mode)
3745 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3747 if (mask_mode == USE_MASKING)
3748 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3750 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
3753 inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3754 int graphic, int sync_frame,
3757 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3759 if (mask_mode == USE_MASKING)
3760 DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3762 DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
3765 inline void DrawGraphicAnimation(int x, int y, int graphic)
3767 int lx = LEVELX(x), ly = LEVELY(y);
3769 if (!IN_SCR_FIELD(x, y))
3773 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
3774 graphic, GfxFrame[lx][ly], NO_MASKING);
3776 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3777 graphic, GfxFrame[lx][ly], NO_MASKING);
3779 MarkTileDirty(x, y);
3782 inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
3784 int lx = LEVELX(x), ly = LEVELY(y);
3786 if (!IN_SCR_FIELD(x, y))
3789 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3790 graphic, GfxFrame[lx][ly], NO_MASKING);
3791 MarkTileDirty(x, y);
3794 void DrawLevelGraphicAnimation(int x, int y, int graphic)
3796 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3799 void DrawLevelElementAnimation(int x, int y, int element)
3801 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3803 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3806 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
3808 int sx = SCREENX(x), sy = SCREENY(y);
3810 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3813 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3816 DrawGraphicAnimation(sx, sy, graphic);
3819 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
3820 DrawLevelFieldCrumbled(x, y);
3822 if (GFX_CRUMBLED(Feld[x][y]))
3823 DrawLevelFieldCrumbled(x, y);
3827 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
3829 int sx = SCREENX(x), sy = SCREENY(y);
3832 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3835 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3837 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3840 DrawGraphicAnimation(sx, sy, graphic);
3842 if (GFX_CRUMBLED(element))
3843 DrawLevelFieldCrumbled(x, y);
3846 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
3848 if (player->use_murphy)
3850 /* this works only because currently only one player can be "murphy" ... */
3851 static int last_horizontal_dir = MV_LEFT;
3852 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
3854 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3855 last_horizontal_dir = move_dir;
3857 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
3859 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
3861 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
3867 return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
3870 static boolean equalGraphics(int graphic1, int graphic2)
3872 struct GraphicInfo *g1 = &graphic_info[graphic1];
3873 struct GraphicInfo *g2 = &graphic_info[graphic2];
3875 return (g1->bitmap == g2->bitmap &&
3876 g1->src_x == g2->src_x &&
3877 g1->src_y == g2->src_y &&
3878 g1->anim_frames == g2->anim_frames &&
3879 g1->anim_delay == g2->anim_delay &&
3880 g1->anim_mode == g2->anim_mode);
3883 void DrawAllPlayers()
3887 for (i = 0; i < MAX_PLAYERS; i++)
3888 if (stored_player[i].active)
3889 DrawPlayer(&stored_player[i]);
3892 void DrawPlayerField(int x, int y)
3894 if (!IS_PLAYER(x, y))
3897 DrawPlayer(PLAYERINFO(x, y));
3900 #define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
3902 void DrawPlayer(struct PlayerInfo *player)
3904 int jx = player->jx;
3905 int jy = player->jy;
3906 int move_dir = player->MovDir;
3907 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
3908 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
3909 int last_jx = (player->is_moving ? jx - dx : jx);
3910 int last_jy = (player->is_moving ? jy - dy : jy);
3911 int next_jx = jx + dx;
3912 int next_jy = jy + dy;
3913 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
3914 boolean player_is_opaque = FALSE;
3915 int sx = SCREENX(jx), sy = SCREENY(jy);
3916 int sxx = 0, syy = 0;
3917 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
3919 int action = ACTION_DEFAULT;
3920 int last_player_graphic = getPlayerGraphic(player, move_dir);
3921 int last_player_frame = player->Frame;
3924 /* GfxElement[][] is set to the element the player is digging or collecting;
3925 remove also for off-screen player if the player is not moving anymore */
3926 if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
3927 GfxElement[jx][jy] = EL_UNDEFINED;
3929 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
3933 if (!IN_LEV_FIELD(jx, jy))
3935 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
3936 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
3937 printf("DrawPlayerField(): This should never happen!\n");
3942 if (element == EL_EXPLOSION)
3945 action = (player->is_pushing ? ACTION_PUSHING :
3946 player->is_digging ? ACTION_DIGGING :
3947 player->is_collecting ? ACTION_COLLECTING :
3948 player->is_moving ? ACTION_MOVING :
3949 player->is_snapping ? ACTION_SNAPPING :
3950 player->is_dropping ? ACTION_DROPPING :
3951 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
3953 if (player->is_waiting)
3954 move_dir = player->dir_waiting;
3956 InitPlayerGfxAnimation(player, action, move_dir);
3958 /* ----------------------------------------------------------------------- */
3959 /* draw things in the field the player is leaving, if needed */
3960 /* ----------------------------------------------------------------------- */
3962 if (player->is_moving)
3964 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
3966 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
3968 if (last_element == EL_DYNAMITE_ACTIVE ||
3969 last_element == EL_EM_DYNAMITE_ACTIVE ||
3970 last_element == EL_SP_DISK_RED_ACTIVE)
3971 DrawDynamite(last_jx, last_jy);
3973 DrawLevelFieldThruMask(last_jx, last_jy);
3975 else if (last_element == EL_DYNAMITE_ACTIVE ||
3976 last_element == EL_EM_DYNAMITE_ACTIVE ||
3977 last_element == EL_SP_DISK_RED_ACTIVE)
3978 DrawDynamite(last_jx, last_jy);
3980 /* !!! this is not enough to prevent flickering of players which are
3981 moving next to each others without a free tile between them -- this
3982 can only be solved by drawing all players layer by layer (first the
3983 background, then the foreground etc.) !!! => TODO */
3984 else if (!IS_PLAYER(last_jx, last_jy))
3985 DrawLevelField(last_jx, last_jy);
3988 DrawLevelField(last_jx, last_jy);
3991 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
3992 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
3995 if (!IN_SCR_FIELD(sx, sy))
3998 /* ----------------------------------------------------------------------- */
3999 /* draw things behind the player, if needed */
4000 /* ----------------------------------------------------------------------- */
4003 DrawLevelElement(jx, jy, Back[jx][jy]);
4004 else if (IS_ACTIVE_BOMB(element))
4005 DrawLevelElement(jx, jy, EL_EMPTY);
4008 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
4010 int old_element = GfxElement[jx][jy];
4011 int old_graphic = el_act_dir2img(old_element, action, move_dir);
4012 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
4014 if (GFX_CRUMBLED(old_element))
4015 DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
4017 DrawGraphic(sx, sy, old_graphic, frame);
4019 if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
4020 player_is_opaque = TRUE;
4024 GfxElement[jx][jy] = EL_UNDEFINED;
4026 /* make sure that pushed elements are drawn with correct frame rate */
4028 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4030 if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
4031 GfxFrame[jx][jy] = player->StepFrame;
4033 if (player->is_pushing && player->is_moving)
4034 GfxFrame[jx][jy] = player->StepFrame;
4037 DrawLevelField(jx, jy);
4041 #if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
4042 /* ----------------------------------------------------------------------- */
4043 /* draw player himself */
4044 /* ----------------------------------------------------------------------- */
4046 graphic = getPlayerGraphic(player, move_dir);
4048 /* in the case of changed player action or direction, prevent the current
4049 animation frame from being restarted for identical animations */
4050 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4051 player->Frame = last_player_frame;
4053 frame = getGraphicAnimationFrame(graphic, player->Frame);
4057 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4058 sxx = player->GfxPos;
4060 syy = player->GfxPos;
4063 if (!setup.soft_scrolling && ScreenMovPos)
4066 if (player_is_opaque)
4067 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4069 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4071 if (SHIELD_ON(player))
4073 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4074 IMG_SHIELD_NORMAL_ACTIVE);
4075 int frame = getGraphicAnimationFrame(graphic, -1);
4077 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4081 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4084 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4085 sxx = player->GfxPos;
4087 syy = player->GfxPos;
4091 /* ----------------------------------------------------------------------- */
4092 /* draw things the player is pushing, if needed */
4093 /* ----------------------------------------------------------------------- */
4096 printf("::: %d, %d [%d, %d] [%d]\n",
4097 player->is_pushing, player_is_moving, player->GfxAction,
4098 player->is_moving, player_is_moving);
4102 if (player->is_pushing && player->is_moving)
4104 int px = SCREENX(jx), py = SCREENY(jy);
4105 int pxx = (TILEX - ABS(sxx)) * dx;
4106 int pyy = (TILEY - ABS(syy)) * dy;
4107 int gfx_frame = GfxFrame[jx][jy];
4113 if (!IS_MOVING(jx, jy)) /* push movement already finished */
4115 element = Feld[next_jx][next_jy];
4116 gfx_frame = GfxFrame[next_jx][next_jy];
4119 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4122 sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
4123 frame = getGraphicAnimationFrame(graphic, sync_frame);
4125 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
4128 /* draw background element under pushed element (like the Sokoban field) */
4130 if (game.use_masked_pushing && IS_MOVING(jx, jy))
4132 /* this allows transparent pushing animation over non-black background */
4135 DrawLevelElement(jx, jy, Back[jx][jy]);
4137 DrawLevelElement(jx, jy, EL_EMPTY);
4139 if (Back[next_jx][next_jy])
4140 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4142 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4144 else if (Back[next_jx][next_jy])
4145 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4147 if (Back[next_jx][next_jy])
4148 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4152 printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
4153 jx, px, player->GfxPos, player->StepFrame,
4158 GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
4162 /* do not draw (EM style) pushing animation when pushing is finished */
4163 /* (two-tile animations usually do not contain start and end frame) */
4164 if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
4165 DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
4167 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4169 /* masked drawing is needed for EMC style (double) movement graphics */
4170 /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
4171 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4176 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4177 /* ----------------------------------------------------------------------- */
4178 /* draw player himself */
4179 /* ----------------------------------------------------------------------- */
4181 graphic = getPlayerGraphic(player, move_dir);
4183 /* in the case of changed player action or direction, prevent the current
4184 animation frame from being restarted for identical animations */
4185 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4186 player->Frame = last_player_frame;
4188 frame = getGraphicAnimationFrame(graphic, player->Frame);
4192 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4193 sxx = player->GfxPos;
4195 syy = player->GfxPos;
4198 if (!setup.soft_scrolling && ScreenMovPos)
4201 if (player_is_opaque)
4202 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4204 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4206 if (SHIELD_ON(player))
4208 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4209 IMG_SHIELD_NORMAL_ACTIVE);
4210 int frame = getGraphicAnimationFrame(graphic, -1);
4212 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4216 /* ----------------------------------------------------------------------- */
4217 /* draw things in front of player (active dynamite or dynabombs) */
4218 /* ----------------------------------------------------------------------- */
4220 if (IS_ACTIVE_BOMB(element))
4222 graphic = el2img(element);
4223 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
4225 if (game.emulation == EMU_SUPAPLEX)
4226 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
4228 DrawGraphicThruMask(sx, sy, graphic, frame);
4231 if (player_is_moving && last_element == EL_EXPLOSION)
4233 int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
4234 GfxElement[last_jx][last_jy] : EL_EMPTY);
4235 int graphic = el_act2img(element, ACTION_EXPLODING);
4236 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
4237 int phase = ExplodePhase[last_jx][last_jy] - 1;
4238 int frame = getGraphicAnimationFrame(graphic, phase - delay);
4241 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
4244 /* ----------------------------------------------------------------------- */
4245 /* draw elements the player is just walking/passing through/under */
4246 /* ----------------------------------------------------------------------- */
4248 if (player_is_moving)
4250 /* handle the field the player is leaving ... */
4251 if (IS_ACCESSIBLE_INSIDE(last_element))
4252 DrawLevelField(last_jx, last_jy);
4253 else if (IS_ACCESSIBLE_UNDER(last_element))
4254 DrawLevelFieldThruMask(last_jx, last_jy);
4257 /* do not redraw accessible elements if the player is just pushing them */
4258 if (!player_is_moving || !player->is_pushing)
4260 /* ... and the field the player is entering */
4261 if (IS_ACCESSIBLE_INSIDE(element))
4262 DrawLevelField(jx, jy);
4263 else if (IS_ACCESSIBLE_UNDER(element))
4264 DrawLevelFieldThruMask(jx, jy);
4267 MarkTileDirty(sx, sy);
4270 /* ------------------------------------------------------------------------- */
4272 void WaitForEventToContinue()
4274 boolean still_wait = TRUE;
4276 /* simulate releasing mouse button over last gadget, if still pressed */
4278 HandleGadgets(-1, -1, 0);
4280 button_status = MB_RELEASED;
4296 case EVENT_BUTTONPRESS:
4297 case EVENT_KEYPRESS:
4301 case EVENT_KEYRELEASE:
4302 ClearPlayerAction();
4306 HandleOtherEvents(&event);
4310 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4317 /* don't eat all CPU time */
4322 #define MAX_REQUEST_LINES 13
4323 #define MAX_REQUEST_LINE_FONT1_LEN 7
4324 #define MAX_REQUEST_LINE_FONT2_LEN 10
4328 static int RequestHandleEvents(unsigned int req_state)
4330 int last_game_status = game_status; /* save current game status */
4334 button_status = MB_RELEASED;
4336 request_gadget_id = -1;
4349 case EVENT_BUTTONPRESS:
4350 case EVENT_BUTTONRELEASE:
4351 case EVENT_MOTIONNOTIFY:
4353 if (event.type == EVENT_MOTIONNOTIFY)
4355 if (!PointerInWindow(window))
4356 continue; /* window and pointer are on different screens */
4361 motion_status = TRUE;
4362 mx = ((MotionEvent *) &event)->x;
4363 my = ((MotionEvent *) &event)->y;
4367 motion_status = FALSE;
4368 mx = ((ButtonEvent *) &event)->x;
4369 my = ((ButtonEvent *) &event)->y;
4370 if (event.type == EVENT_BUTTONPRESS)
4371 button_status = ((ButtonEvent *) &event)->button;
4373 button_status = MB_RELEASED;
4376 /* this sets 'request_gadget_id' */
4377 HandleGadgets(mx, my, button_status);
4379 switch (request_gadget_id)
4381 case TOOL_CTRL_ID_YES:
4384 case TOOL_CTRL_ID_NO:
4387 case TOOL_CTRL_ID_CONFIRM:
4388 result = TRUE | FALSE;
4391 case TOOL_CTRL_ID_PLAYER_1:
4394 case TOOL_CTRL_ID_PLAYER_2:
4397 case TOOL_CTRL_ID_PLAYER_3:
4400 case TOOL_CTRL_ID_PLAYER_4:
4411 case EVENT_KEYPRESS:
4412 switch (GetEventKey((KeyEvent *)&event, TRUE))
4415 if (req_state & REQ_CONFIRM)
4424 #if defined(TARGET_SDL2)
4434 if (req_state & REQ_PLAYER)
4438 case EVENT_KEYRELEASE:
4439 ClearPlayerAction();
4443 HandleOtherEvents(&event);
4447 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4449 int joy = AnyJoystick();
4451 if (joy & JOY_BUTTON_1)
4453 else if (joy & JOY_BUTTON_2)
4459 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
4461 HandleGameActions();
4467 if (!PendingEvent()) /* delay only if no pending events */
4472 game_status = GAME_MODE_PSEUDO_DOOR;
4478 game_status = last_game_status; /* restore current game status */
4486 if (!PendingEvent()) /* delay only if no pending events */
4489 /* don't eat all CPU time */
4499 static boolean RequestDoor(char *text, unsigned int req_state)
4501 unsigned int old_door_state;
4502 int last_game_status = game_status; /* save current game status */
4503 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4504 int font_nr = FONT_TEXT_2;
4509 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4511 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4512 font_nr = FONT_TEXT_1;
4515 if (game_status == GAME_MODE_PLAYING)
4517 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4518 BlitScreenToBitmap_EM(backbuffer);
4519 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4520 BlitScreenToBitmap_SP(backbuffer);
4523 /* disable deactivated drawing when quick-loading level tape recording */
4524 if (tape.playing && tape.deactivate_display)
4525 TapeDeactivateDisplayOff(TRUE);
4527 SetMouseCursor(CURSOR_DEFAULT);
4529 #if defined(NETWORK_AVALIABLE)
4530 /* pause network game while waiting for request to answer */
4531 if (options.network &&
4532 game_status == GAME_MODE_PLAYING &&
4533 req_state & REQUEST_WAIT_FOR_INPUT)
4534 SendToServer_PausePlaying();
4537 old_door_state = GetDoorState();
4539 /* simulate releasing mouse button over last gadget, if still pressed */
4541 HandleGadgets(-1, -1, 0);
4545 /* draw released gadget before proceeding */
4548 if (old_door_state & DOOR_OPEN_1)
4550 CloseDoor(DOOR_CLOSE_1);
4552 /* save old door content */
4553 BlitBitmap(bitmap_db_door, bitmap_db_door,
4554 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4555 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
4558 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4559 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4561 /* clear door drawing field */
4562 DrawBackground(DX, DY, DXSIZE, DYSIZE);
4564 /* force DOOR font inside door area */
4565 game_status = GAME_MODE_PSEUDO_DOOR;
4567 /* write text for request */
4568 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
4570 char text_line[max_request_line_len + 1];
4576 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
4578 tc = *(text_ptr + tx);
4579 // if (!tc || tc == ' ')
4580 if (!tc || tc == ' ' || tc == '?' || tc == '!')
4584 if ((tc == '?' || tc == '!') && tl == 0)
4594 strncpy(text_line, text_ptr, tl);
4597 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
4598 DY + 8 + ty * (getFontHeight(font_nr) + 2),
4599 text_line, font_nr);
4601 text_ptr += tl + (tc == ' ' ? 1 : 0);
4602 // text_ptr += tl + (tc == ' ' || tc == '?' || tc == '!' ? 1 : 0);
4605 game_status = last_game_status; /* restore current game status */
4607 if (req_state & REQ_ASK)
4609 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4610 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4612 else if (req_state & REQ_CONFIRM)
4614 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4616 else if (req_state & REQ_PLAYER)
4618 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4619 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4620 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4621 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4624 /* copy request gadgets to door backbuffer */
4625 BlitBitmap(drawto, bitmap_db_door,
4626 DX, DY, DXSIZE, DYSIZE,
4627 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4629 OpenDoor(DOOR_OPEN_1);
4631 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4633 if (game_status == GAME_MODE_PLAYING)
4635 SetPanelBackground();
4636 SetDrawBackgroundMask(REDRAW_DOOR_1);
4640 SetDrawBackgroundMask(REDRAW_FIELD);
4646 if (game_status != GAME_MODE_MAIN)
4649 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4651 // ---------- handle request buttons ----------
4652 result = RequestHandleEvents(req_state);
4654 if (game_status != GAME_MODE_MAIN)
4659 if (!(req_state & REQ_STAY_OPEN))
4661 CloseDoor(DOOR_CLOSE_1);
4663 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
4664 (req_state & REQ_REOPEN))
4665 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
4670 if (game_status == GAME_MODE_PLAYING)
4672 SetPanelBackground();
4673 SetDrawBackgroundMask(REDRAW_DOOR_1);
4677 SetDrawBackgroundMask(REDRAW_FIELD);
4680 #if defined(NETWORK_AVALIABLE)
4681 /* continue network game after request */
4682 if (options.network &&
4683 game_status == GAME_MODE_PLAYING &&
4684 req_state & REQUEST_WAIT_FOR_INPUT)
4685 SendToServer_ContinuePlaying();
4688 /* restore deactivated drawing when quick-loading level tape recording */
4689 if (tape.playing && tape.deactivate_display)
4690 TapeDeactivateDisplayOn();
4695 static boolean RequestEnvelope(char *text, unsigned int req_state)
4702 if (game_status == GAME_MODE_PLAYING)
4704 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4705 BlitScreenToBitmap_EM(backbuffer);
4706 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4707 BlitScreenToBitmap_SP(backbuffer);
4710 /* disable deactivated drawing when quick-loading level tape recording */
4711 if (tape.playing && tape.deactivate_display)
4712 TapeDeactivateDisplayOff(TRUE);
4714 SetMouseCursor(CURSOR_DEFAULT);
4716 #if defined(NETWORK_AVALIABLE)
4717 /* pause network game while waiting for request to answer */
4718 if (options.network &&
4719 game_status == GAME_MODE_PLAYING &&
4720 req_state & REQUEST_WAIT_FOR_INPUT)
4721 SendToServer_PausePlaying();
4724 /* simulate releasing mouse button over last gadget, if still pressed */
4726 HandleGadgets(-1, -1, 0);
4730 // (replace with setting corresponding request background)
4731 // SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4732 // SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4734 /* clear door drawing field */
4735 // DrawBackground(DX, DY, DXSIZE, DYSIZE);
4738 if (global.use_envelope_request)
4742 CreateToolButtons();
4748 if (req_state & REQ_ASK)
4750 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_YES], FALSE);
4751 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_NO], FALSE);
4753 else if (req_state & REQ_CONFIRM)
4755 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_CONFIRM], FALSE);
4757 else if (req_state & REQ_PLAYER)
4759 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_1], FALSE);
4760 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_2], FALSE);
4761 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_3], FALSE);
4762 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_4], FALSE);
4765 if (req_state & REQ_ASK)
4767 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4768 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4770 else if (req_state & REQ_CONFIRM)
4772 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4774 else if (req_state & REQ_PLAYER)
4776 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4777 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4778 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4779 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4784 ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
4787 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4789 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
4790 i == TOOL_CTRL_ID_NO)) ||
4791 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
4792 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
4793 i == TOOL_CTRL_ID_PLAYER_2 &&
4794 i == TOOL_CTRL_ID_PLAYER_3 &&
4795 i == TOOL_CTRL_ID_PLAYER_4)))
4797 int x = tool_gadget[i]->x + dDX;
4798 int y = tool_gadget[i]->y + dDY;
4800 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
4805 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4807 if (game_status == GAME_MODE_PLAYING)
4809 SetPanelBackground();
4810 SetDrawBackgroundMask(REDRAW_DOOR_1);
4814 SetDrawBackgroundMask(REDRAW_FIELD);
4821 if (game_status != GAME_MODE_MAIN)
4825 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4827 // ---------- handle request buttons ----------
4828 result = RequestHandleEvents(req_state);
4830 if (game_status != GAME_MODE_MAIN)
4835 ShowEnvelopeRequest(text, req_state, ACTION_CLOSING);
4839 if (game_status == GAME_MODE_PLAYING)
4841 SetPanelBackground();
4842 SetDrawBackgroundMask(REDRAW_DOOR_1);
4846 SetDrawBackgroundMask(REDRAW_FIELD);
4849 #if defined(NETWORK_AVALIABLE)
4850 /* continue network game after request */
4851 if (options.network &&
4852 game_status == GAME_MODE_PLAYING &&
4853 req_state & REQUEST_WAIT_FOR_INPUT)
4854 SendToServer_ContinuePlaying();
4857 /* restore deactivated drawing when quick-loading level tape recording */
4858 if (tape.playing && tape.deactivate_display)
4859 TapeDeactivateDisplayOn();
4864 boolean Request(char *text, unsigned int req_state)
4866 if (global.use_envelope_request)
4867 return RequestEnvelope(text, req_state);
4869 return RequestDoor(text, req_state);
4872 #else // =====================================================================
4874 boolean Request(char *text, unsigned int req_state)
4876 int mx, my, ty, result = -1;
4877 unsigned int old_door_state;
4878 int last_game_status = game_status; /* save current game status */
4879 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4880 int font_nr = FONT_TEXT_2;
4882 int max_word_len = 0;
4888 global.use_envelope_request = 1;
4892 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4894 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4895 font_nr = FONT_TEXT_1;
4898 for (text_ptr = text; *text_ptr; text_ptr++)
4900 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
4902 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
4904 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4906 font_nr = FONT_TEXT_1;
4908 font_nr = FONT_LEVEL_NUMBER;
4916 if (game_status == GAME_MODE_PLAYING)
4918 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4919 BlitScreenToBitmap_EM(backbuffer);
4920 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4921 BlitScreenToBitmap_SP(backbuffer);
4924 /* disable deactivated drawing when quick-loading level tape recording */
4925 if (tape.playing && tape.deactivate_display)
4926 TapeDeactivateDisplayOff(TRUE);
4928 SetMouseCursor(CURSOR_DEFAULT);
4930 #if defined(NETWORK_AVALIABLE)
4931 /* pause network game while waiting for request to answer */
4932 if (options.network &&
4933 game_status == GAME_MODE_PLAYING &&
4934 req_state & REQUEST_WAIT_FOR_INPUT)
4935 SendToServer_PausePlaying();
4938 old_door_state = GetDoorState();
4940 /* simulate releasing mouse button over last gadget, if still pressed */
4942 HandleGadgets(-1, -1, 0);
4946 /* draw released gadget before proceeding */
4950 if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request)
4952 if (old_door_state & DOOR_OPEN_1)
4956 if (!global.use_envelope_request)
4957 CloseDoor(DOOR_CLOSE_1);
4959 CloseDoor(DOOR_CLOSE_1);
4962 /* save old door content */
4963 BlitBitmap(bitmap_db_door, bitmap_db_door,
4964 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4965 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
4969 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4972 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4974 /* clear door drawing field */
4975 DrawBackground(DX, DY, DXSIZE, DYSIZE);
4977 /* force DOOR font inside door area */
4978 game_status = GAME_MODE_PSEUDO_DOOR;
4980 /* write text for request */
4981 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
4983 char text_line[max_request_line_len + 1];
4989 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
4991 tc = *(text_ptr + tx);
4992 if (!tc || tc == ' ')
5003 strncpy(text_line, text_ptr, tl);
5006 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
5007 DY + 8 + ty * (getFontHeight(font_nr) + 2),
5008 text_line, font_nr);
5010 text_ptr += tl + (tc == ' ' ? 1 : 0);
5013 game_status = last_game_status; /* restore current game status */
5016 if (global.use_envelope_request)
5020 CreateToolButtons();
5024 if (req_state & REQ_ASK)
5026 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
5027 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
5029 else if (req_state & REQ_CONFIRM)
5031 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
5033 else if (req_state & REQ_PLAYER)
5035 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
5036 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
5037 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
5038 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
5041 /* copy request gadgets to door backbuffer */
5042 BlitBitmap(drawto, bitmap_db_door,
5043 DX, DY, DXSIZE, DYSIZE,
5044 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5047 if (global.use_envelope_request)
5049 ShowEnvelopeRequest(text, ACTION_OPENING);
5051 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
5053 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
5054 i == TOOL_CTRL_ID_NO)) ||
5055 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
5056 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
5057 i == TOOL_CTRL_ID_PLAYER_2 &&
5058 i == TOOL_CTRL_ID_PLAYER_3 &&
5059 i == TOOL_CTRL_ID_PLAYER_4)))
5061 int x = tool_gadget[i]->x + dDX;
5062 int y = tool_gadget[i]->y + dDY;
5064 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
5071 if (!global.use_envelope_request)
5072 OpenDoor(DOOR_OPEN_1);
5074 OpenDoor(DOOR_OPEN_1);
5077 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
5079 if (game_status == GAME_MODE_PLAYING)
5081 SetPanelBackground();
5082 SetDrawBackgroundMask(REDRAW_DOOR_1);
5086 SetDrawBackgroundMask(REDRAW_FIELD);
5093 if (game_status != GAME_MODE_MAIN && !global.use_envelope_request)
5096 if (game_status != GAME_MODE_MAIN)
5100 button_status = MB_RELEASED;
5102 request_gadget_id = -1;
5104 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
5116 case EVENT_BUTTONPRESS:
5117 case EVENT_BUTTONRELEASE:
5118 case EVENT_MOTIONNOTIFY:
5120 if (event.type == EVENT_MOTIONNOTIFY)
5122 if (!PointerInWindow(window))
5123 continue; /* window and pointer are on different screens */
5128 motion_status = TRUE;
5129 mx = ((MotionEvent *) &event)->x;
5130 my = ((MotionEvent *) &event)->y;
5134 motion_status = FALSE;
5135 mx = ((ButtonEvent *) &event)->x;
5136 my = ((ButtonEvent *) &event)->y;
5137 if (event.type == EVENT_BUTTONPRESS)
5138 button_status = ((ButtonEvent *) &event)->button;
5140 button_status = MB_RELEASED;
5143 /* this sets 'request_gadget_id' */
5144 HandleGadgets(mx, my, button_status);
5146 switch (request_gadget_id)
5148 case TOOL_CTRL_ID_YES:
5151 case TOOL_CTRL_ID_NO:
5154 case TOOL_CTRL_ID_CONFIRM:
5155 result = TRUE | FALSE;
5158 case TOOL_CTRL_ID_PLAYER_1:
5161 case TOOL_CTRL_ID_PLAYER_2:
5164 case TOOL_CTRL_ID_PLAYER_3:
5167 case TOOL_CTRL_ID_PLAYER_4:
5178 case EVENT_KEYPRESS:
5179 switch (GetEventKey((KeyEvent *)&event, TRUE))
5182 if (req_state & REQ_CONFIRM)
5191 #if defined(TARGET_SDL2)
5201 if (req_state & REQ_PLAYER)
5205 case EVENT_KEYRELEASE:
5206 ClearPlayerAction();
5210 HandleOtherEvents(&event);
5214 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
5216 int joy = AnyJoystick();
5218 if (joy & JOY_BUTTON_1)
5220 else if (joy & JOY_BUTTON_2)
5226 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
5228 HandleGameActions();
5234 if (!PendingEvent()) /* delay only if no pending events */
5239 game_status = GAME_MODE_PSEUDO_DOOR;
5245 game_status = last_game_status; /* restore current game status */
5253 if (!PendingEvent()) /* delay only if no pending events */
5256 /* don't eat all CPU time */
5263 if (game_status != GAME_MODE_MAIN)
5269 if (global.use_envelope_request)
5270 ShowEnvelopeRequest(text, ACTION_CLOSING);
5274 if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request)
5276 if (!(req_state & REQ_STAY_OPEN))
5279 CloseDoor(DOOR_CLOSE_1);
5281 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
5282 (req_state & REQ_REOPEN))
5283 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
5288 if (game_status == GAME_MODE_PLAYING)
5290 SetPanelBackground();
5291 SetDrawBackgroundMask(REDRAW_DOOR_1);
5295 SetDrawBackgroundMask(REDRAW_FIELD);
5298 #if defined(NETWORK_AVALIABLE)
5299 /* continue network game after request */
5300 if (options.network &&
5301 game_status == GAME_MODE_PLAYING &&
5302 req_state & REQUEST_WAIT_FOR_INPUT)
5303 SendToServer_ContinuePlaying();
5306 /* restore deactivated drawing when quick-loading level tape recording */
5307 if (tape.playing && tape.deactivate_display)
5308 TapeDeactivateDisplayOn();
5315 static int compareDoorPartOrderInfo(const void *object1, const void *object2)
5317 const struct DoorPartOrderInfo *dpo1 = (struct DoorPartOrderInfo *)object1;
5318 const struct DoorPartOrderInfo *dpo2 = (struct DoorPartOrderInfo *)object2;
5321 if (dpo1->sort_priority != dpo2->sort_priority)
5322 compare_result = dpo1->sort_priority - dpo2->sort_priority;
5324 compare_result = dpo1->nr - dpo2->nr;
5326 return compare_result;
5329 void InitGraphicCompatibilityInfo_Doors()
5335 struct DoorInfo *door;
5339 { DOOR_1, IMG_DOOR_1_GFX_PART_1, IMG_DOOR_1_GFX_PART_8, &door_1 },
5340 { DOOR_2, IMG_DOOR_2_GFX_PART_1, IMG_DOOR_2_GFX_PART_8, &door_2 },
5342 { -1, -1, -1, NULL }
5344 struct Rect door_rect_list[] =
5346 { DX, DY, DXSIZE, DYSIZE },
5347 { VX, VY, VXSIZE, VYSIZE }
5351 for (i = 0; doors[i].door_token != -1; i++)
5353 int door_token = doors[i].door_token;
5354 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5355 int part_1 = doors[i].part_1;
5356 int part_8 = doors[i].part_8;
5357 int part_2 = part_1 + 1;
5358 int part_3 = part_1 + 2;
5359 struct DoorInfo *door = doors[i].door;
5360 struct Rect *door_rect = &door_rect_list[door_index];
5361 boolean door_gfx_redefined = FALSE;
5363 /* check if any door part graphic definitions have been redefined */
5365 for (j = 0; door_part_controls[j].door_token != -1; j++)
5367 struct DoorPartControlInfo *dpc = &door_part_controls[j];
5368 struct FileInfo *fi = getImageListEntryFromImageID(dpc->graphic);
5370 if (dpc->door_token == door_token && fi->redefined)
5371 door_gfx_redefined = TRUE;
5374 /* check for old-style door graphic/animation modifications */
5376 if (!door_gfx_redefined)
5378 if (door->anim_mode & ANIM_STATIC_PANEL)
5380 door->panel.step_xoffset = 0;
5381 door->panel.step_yoffset = 0;
5384 if (door->anim_mode & (ANIM_HORIZONTAL | ANIM_VERTICAL))
5386 struct GraphicInfo *g_part_1 = &graphic_info[part_1];
5387 struct GraphicInfo *g_part_2 = &graphic_info[part_2];
5388 int num_door_steps, num_panel_steps;
5390 /* remove door part graphics other than the two default wings */
5392 for (j = 0; door_part_controls[j].door_token != -1; j++)
5394 struct DoorPartControlInfo *dpc = &door_part_controls[j];
5395 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5397 if (dpc->graphic >= part_3 &&
5398 dpc->graphic <= part_8)
5402 /* set graphics and screen positions of the default wings */
5404 g_part_1->width = door_rect->width;
5405 g_part_1->height = door_rect->height;
5406 g_part_2->width = door_rect->width;
5407 g_part_2->height = door_rect->height;
5408 g_part_2->src_x = door_rect->width;
5409 g_part_2->src_y = g_part_1->src_y;
5411 door->part_2.x = door->part_1.x;
5412 door->part_2.y = door->part_1.y;
5414 if (door->width != -1)
5416 g_part_1->width = door->width;
5417 g_part_2->width = door->width;
5419 // special treatment for graphics and screen position of right wing
5420 g_part_2->src_x += door_rect->width - door->width;
5421 door->part_2.x += door_rect->width - door->width;
5424 if (door->height != -1)
5426 g_part_1->height = door->height;
5427 g_part_2->height = door->height;
5429 // special treatment for graphics and screen position of bottom wing
5430 g_part_2->src_y += door_rect->height - door->height;
5431 door->part_2.y += door_rect->height - door->height;
5434 /* set animation delays for the default wings and panels */
5436 door->part_1.step_delay = door->step_delay;
5437 door->part_2.step_delay = door->step_delay;
5438 door->panel.step_delay = door->step_delay;
5440 /* set animation draw order for the default wings */
5442 door->part_1.sort_priority = 2; /* draw left wing over ... */
5443 door->part_2.sort_priority = 1; /* ... right wing */
5445 /* set animation draw offset for the default wings */
5447 if (door->anim_mode & ANIM_HORIZONTAL)
5449 door->part_1.step_xoffset = door->step_offset;
5450 door->part_1.step_yoffset = 0;
5451 door->part_2.step_xoffset = door->step_offset * -1;
5452 door->part_2.step_yoffset = 0;
5454 num_door_steps = g_part_1->width / door->step_offset;
5456 else // ANIM_VERTICAL
5458 door->part_1.step_xoffset = 0;
5459 door->part_1.step_yoffset = door->step_offset;
5460 door->part_2.step_xoffset = 0;
5461 door->part_2.step_yoffset = door->step_offset * -1;
5463 num_door_steps = g_part_1->height / door->step_offset;
5466 /* set animation draw offset for the default panels */
5468 if (door->step_offset > 1)
5470 num_panel_steps = 2 * door_rect->height / door->step_offset;
5471 door->panel.start_step = num_panel_steps - num_door_steps;
5475 num_panel_steps = door_rect->height / door->step_offset;
5476 door->panel.start_step = num_panel_steps - num_door_steps / 2;
5477 door->panel.step_delay *= 2;
5488 for (i = 0; door_part_controls[i].door_token != -1; i++)
5490 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5491 struct DoorPartOrderInfo *dpo = &door_part_order[i];
5493 /* initialize "start_step_opening" and "start_step_closing", if needed */
5494 if (dpc->pos->start_step_opening == 0 &&
5495 dpc->pos->start_step_closing == 0)
5497 // dpc->pos->start_step_opening = dpc->pos->start_step;
5498 dpc->pos->start_step_closing = dpc->pos->start_step;
5501 /* fill structure for door part draw order (sorted below) */
5503 dpo->sort_priority = dpc->pos->sort_priority;
5506 struct DoorPartPosInfo *pos = dpc->pos;
5508 printf(":0: step_xoffset == %d, step_yoffset == %d\n",
5509 pos->step_xoffset, pos->step_yoffset);
5513 /* sort door part controls according to sort_priority and graphic number */
5514 qsort(door_part_order, MAX_DOOR_PARTS,
5515 sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo);
5518 unsigned int OpenDoor(unsigned int door_state)
5520 if (door_state & DOOR_COPY_BACK)
5522 if (door_state & DOOR_OPEN_1)
5523 BlitBitmap(bitmap_db_door, bitmap_db_door,
5524 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
5525 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5527 if (door_state & DOOR_OPEN_2)
5528 BlitBitmap(bitmap_db_door, bitmap_db_door,
5529 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
5530 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5532 door_state &= ~DOOR_COPY_BACK;
5535 return MoveDoor(door_state);
5538 unsigned int CloseDoor(unsigned int door_state)
5540 unsigned int old_door_state = GetDoorState();
5542 if (!(door_state & DOOR_NO_COPY_BACK))
5544 if (old_door_state & DOOR_OPEN_1)
5545 BlitBitmap(backbuffer, bitmap_db_door,
5546 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5548 if (old_door_state & DOOR_OPEN_2)
5549 BlitBitmap(backbuffer, bitmap_db_door,
5550 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5552 door_state &= ~DOOR_NO_COPY_BACK;
5555 return MoveDoor(door_state);
5558 unsigned int GetDoorState()
5560 return MoveDoor(DOOR_GET_STATE);
5563 unsigned int SetDoorState(unsigned int door_state)
5565 return MoveDoor(door_state | DOOR_SET_STATE);
5570 // ========== TEST 1 ===========================================================
5572 int euclid(int a, int b)
5574 return (b ? euclid(b, a % b) : a);
5577 unsigned int MoveDoor(unsigned int door_state)
5579 struct XY panel_pos_list[] =
5581 { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 },
5582 { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 },
5584 struct Rect door_rect_list[] =
5586 { DX, DY, DXSIZE, DYSIZE },
5587 { VX, VY, VXSIZE, VYSIZE }
5589 static int door1 = DOOR_OPEN_1;
5590 static int door2 = DOOR_CLOSE_2;
5591 unsigned int door_delay = 0;
5592 unsigned int door_delay_value;
5596 if (door_1.width < 0 || door_1.width > DXSIZE)
5597 door_1.width = DXSIZE;
5598 if (door_1.height < 0 || door_1.height > DYSIZE)
5599 door_1.height = DYSIZE;
5600 if (door_2.width < 0 || door_2.width > VXSIZE)
5601 door_2.width = VXSIZE;
5602 if (door_2.height < 0 || door_2.height > VYSIZE)
5603 door_2.height = VYSIZE;
5606 if (door_state == DOOR_GET_STATE)
5607 return (door1 | door2);
5609 if (door_state & DOOR_SET_STATE)
5611 if (door_state & DOOR_ACTION_1)
5612 door1 = door_state & DOOR_ACTION_1;
5613 if (door_state & DOOR_ACTION_2)
5614 door2 = door_state & DOOR_ACTION_2;
5616 return (door1 | door2);
5619 if (!(door_state & DOOR_FORCE_REDRAW))
5621 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
5622 door_state &= ~DOOR_OPEN_1;
5623 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
5624 door_state &= ~DOOR_CLOSE_1;
5625 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
5626 door_state &= ~DOOR_OPEN_2;
5627 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
5628 door_state &= ~DOOR_CLOSE_2;
5632 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
5635 if (setup.quick_doors)
5637 stepsize = 20; /* must be chosen to always draw last frame */
5638 door_delay_value = 0;
5642 if (global.autoplay_leveldir)
5644 door_state |= DOOR_NO_DELAY;
5645 door_state &= ~DOOR_CLOSE_ALL;
5649 if (game_status == GAME_MODE_EDITOR)
5650 door_state |= DOOR_NO_DELAY;
5653 if (door_state & DOOR_ACTION)
5655 boolean door_panel_drawn[NUM_DOORS];
5656 boolean door_part_skip[MAX_DOOR_PARTS];
5657 boolean door_part_done[MAX_DOOR_PARTS];
5658 boolean door_part_done_all;
5659 int num_steps[MAX_DOOR_PARTS];
5660 int max_move_delay = 0; // delay for complete animations of all doors
5661 int max_step_delay = 0; // delay (ms) between two animation frames
5662 int num_move_steps = 0; // number of animation steps for all doors
5663 int current_move_delay = 0;
5666 for (i = 0; i < MAX_DOOR_PARTS; i++)
5668 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5669 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5670 int door_token = dpc->door_token;
5672 door_part_done[i] = FALSE;
5673 door_part_skip[i] = (!(door_state & door_token) ||
5678 for (i = 0; i < MAX_DOOR_PARTS; i++)
5680 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5681 struct DoorPartPosInfo *pos = dpc->pos;
5682 int start_step = pos->start_step;
5684 printf("::: ---> %d: start_step == %d [%d]\n",
5685 i, start_step, door_part_done[i]);
5689 for (i = 0; i < MAX_DOOR_PARTS; i++)
5691 int nr = door_part_order[i].nr;
5692 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5693 struct DoorPartPosInfo *pos = dpc->pos;
5694 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5695 int door_token = dpc->door_token;
5696 boolean is_panel = DOOR_PART_IS_PANEL(nr);
5697 int step_xoffset = ABS(pos->step_xoffset);
5698 int step_yoffset = ABS(pos->step_yoffset);
5699 int step_delay = pos->step_delay;
5700 int current_door_state = door_state & door_token;
5701 boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
5702 boolean door_closing = ((current_door_state & DOOR_CLOSE) != 0);
5703 boolean part_opening = (is_panel ? door_closing : door_opening);
5704 int start_step = (part_opening ? pos->start_step_opening :
5705 pos->start_step_closing);
5706 float move_xsize = (step_xoffset ? g->width : 0);
5707 float move_ysize = (step_yoffset ? g->height : 0);
5708 int move_xsteps = (step_xoffset ? ceil(move_xsize / step_xoffset) : 0);
5709 int move_ysteps = (step_yoffset ? ceil(move_ysize / step_yoffset) : 0);
5710 int move_steps = (move_xsteps && move_ysteps ?
5711 MIN(move_xsteps, move_ysteps) :
5712 move_xsteps ? move_xsteps : move_ysteps) - start_step;
5713 int move_delay = move_steps * step_delay;
5715 if (door_part_skip[nr])
5718 max_move_delay = MAX(max_move_delay, move_delay);
5719 max_step_delay = (max_step_delay == 0 ? step_delay :
5720 euclid(max_step_delay, step_delay));
5721 num_steps[nr] = move_steps;
5725 printf("::: %d: move_delay == %d, start_step == %d [%d]\n",
5726 i, move_delay, start_step, door_part_order[i].nr);
5728 if (DOOR_PART_IS_PANEL(i))
5729 printf("::: %d: move_delay == %d, start_step == %d\n",
5730 i, move_delay, start_step);
5735 num_move_steps = max_move_delay / max_step_delay;
5737 door_delay_value = max_step_delay;
5740 door_delay_value *= 10;
5744 printf("::: num_move_steps == %d, max_move_delay == %d, max_step_delay == %d\n", num_move_steps, max_move_delay, max_step_delay);
5747 for (k = 0; k < num_move_steps; k++)
5749 door_part_done_all = TRUE;
5751 for (i = 0; i < NUM_DOORS; i++)
5752 door_panel_drawn[i] = FALSE;
5754 for (i = 0; i < MAX_DOOR_PARTS; i++)
5756 int nr = door_part_order[i].nr;
5757 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5758 struct DoorPartPosInfo *pos = dpc->pos;
5759 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5760 int door_token = dpc->door_token;
5761 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5762 boolean is_panel = DOOR_PART_IS_PANEL(nr);
5763 struct XY *panel_pos = &panel_pos_list[door_index];
5764 struct Rect *door_rect = &door_rect_list[door_index];
5765 Bitmap *bitmap = (is_panel ? bitmap_db_door : g->bitmap);
5766 int current_door_state = door_state & door_token;
5767 boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
5768 boolean door_closing = !door_opening;
5769 boolean part_opening = (is_panel ? door_closing : door_opening);
5770 boolean part_closing = !part_opening;
5771 int start_step = (part_opening ? pos->start_step_opening :
5772 pos->start_step_closing);
5773 int step_delay = pos->step_delay;
5774 int step_factor = step_delay / max_step_delay;
5775 int k1 = (step_factor ? k / step_factor + 1 : k);
5776 int k2 = (part_opening ? k1 + start_step : num_steps[nr] - k1);
5777 int kk = (k2 < 0 ? 0 : k2);
5778 int src_x, src_y, src_xx, src_yy;
5779 int dst_x, dst_y, dst_xx, dst_yy;
5783 if (DOOR_PART_IS_PANEL(nr))
5785 int start_step = pos->start_step;
5787 k2 = (door_closing ? k1 : num_steps[nr] - k1);// - start_step;
5788 kk = (k2 < 0 ? 0 : k2);
5794 if (nr != 16 && nr != 0)
5805 if (door_part_skip[nr])
5809 if (!(door_state & door_token))
5816 if (current_move_delay % step_delay)
5822 if (!door_panel_drawn[door_index])
5825 ClearRectangle(drawto, door_rect->x, door_rect->y,
5826 door_rect->width, door_rect->height);
5828 BlitBitmap(bitmap_db_door, drawto, panel_pos->x, panel_pos->y,
5829 door_rect->width, door_rect->height,
5830 door_rect->x, door_rect->y);
5833 door_panel_drawn[door_index] = TRUE;
5836 // draw opening or closing door parts
5838 if (pos->step_xoffset < 0) // door part on right side
5841 dst_xx = pos->x + ABS(kk * pos->step_xoffset);
5844 if (dst_xx + width > door_rect->width)
5845 width = door_rect->width - dst_xx;
5847 else // door part on left side
5850 dst_xx = pos->x - kk * pos->step_xoffset;
5854 src_xx = ABS(dst_xx);
5858 width = g->width - src_xx;
5860 // printf("::: k == %d [%d] \n", k, start_step);
5863 if (pos->step_yoffset < 0) // door part on bottom side
5866 dst_yy = pos->y + ABS(kk * pos->step_yoffset);
5869 if (dst_yy + height > door_rect->height)
5870 height = door_rect->height - dst_yy;
5872 else // door part on top side
5875 dst_yy = pos->y - kk * pos->step_yoffset;
5879 src_yy = ABS(dst_yy);
5883 height = g->height - src_yy;
5888 src_x = panel_pos->x + src_xx;
5889 src_y = panel_pos->y + src_yy;
5893 src_x = g->src_x + src_xx;
5894 src_y = g->src_y + src_yy;
5897 dst_x = door_rect->x + dst_xx;
5898 dst_y = door_rect->y + dst_yy;
5901 if (DOOR_PART_IS_PANEL(nr))
5903 printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
5904 width, height, g->width, g->height, src_x, src_y);
5908 if (width >= 0 && width <= g->width &&
5909 height >= 0 && height <= g->height)
5911 if (is_panel || !pos->draw_masked)
5912 BlitBitmap(bitmap, drawto, src_x, src_y, width, height,
5915 BlitBitmapMasked(bitmap, drawto, src_x, src_y, width, height,
5920 if (DOOR_PART_IS_PANEL(nr))
5922 bitmap = bitmap_db_door;
5923 src_x = panel_pos->x + src_xx;
5924 src_y = panel_pos->y + src_yy;
5926 printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
5927 width, height, g->width, g->height, src_x, src_y);
5929 if (width >= 0 && width <= g->width &&
5930 height >= 0 && height <= g->height)
5931 BlitBitmap(bitmap, drawto, src_x, src_y,
5937 redraw_mask |= REDRAW_DOOR_FROM_TOKEN(door_token);
5940 if ((part_opening && (width < 0 || height < 0)) ||
5941 (part_closing && (width >= g->width && height >= g->height)))
5942 door_part_done[nr] = TRUE;
5944 if ((door_opening && (width < 0 || height < 0)) ||
5945 (door_closing && (width >= g->width && height >= g->height)))
5946 door_part_done[nr] = TRUE;
5949 // continue door part animations, but not panel after door has closed
5950 if (!door_part_done[nr] && !(is_panel && door_closing))
5951 door_part_done_all = FALSE;
5954 if (!door_part_done[nr])
5955 printf("::: k == %d, nr == %d\n", k, nr);
5959 if (!(door_state & DOOR_NO_DELAY))
5963 if (game_status == GAME_MODE_MAIN)
5966 WaitUntilDelayReached(&door_delay, door_delay_value);
5968 current_move_delay += max_step_delay;
5972 door_part_done_all = TRUE;
5974 for (i = 0; i < MAX_DOOR_PARTS; i++)
5975 if (!door_part_done[i] &&
5976 !(DOOR_PART_IS_PANEL(i) && door_closing))
5977 door_part_done_all = FALSE;
5980 if (door_part_done_all)
5986 if (door_state & DOOR_ACTION_1)
5987 door1 = door_state & DOOR_ACTION_1;
5988 if (door_state & DOOR_ACTION_2)
5989 door2 = door_state & DOOR_ACTION_2;
5992 printf("::: DOORS DONE %08x\n", door_state);
5994 printf("::: GO!\n");
5997 return (door1 | door2);
6002 // ========== OLD ==============================================================
6004 unsigned int MoveDoor(unsigned int door_state)
6006 static int door1 = DOOR_OPEN_1;
6007 static int door2 = DOOR_CLOSE_2;
6008 unsigned int door_delay = 0;
6009 unsigned int door_delay_value;
6013 if (door_1.width < 0 || door_1.width > DXSIZE)
6014 door_1.width = DXSIZE;
6015 if (door_1.height < 0 || door_1.height > DYSIZE)
6016 door_1.height = DYSIZE;
6017 if (door_2.width < 0 || door_2.width > VXSIZE)
6018 door_2.width = VXSIZE;
6019 if (door_2.height < 0 || door_2.height > VYSIZE)
6020 door_2.height = VYSIZE;
6023 if (door_state == DOOR_GET_STATE)
6024 return (door1 | door2);
6026 if (door_state & DOOR_SET_STATE)
6028 if (door_state & DOOR_ACTION_1)
6029 door1 = door_state & DOOR_ACTION_1;
6030 if (door_state & DOOR_ACTION_2)
6031 door2 = door_state & DOOR_ACTION_2;
6033 return (door1 | door2);
6036 if (!(door_state & DOOR_FORCE_REDRAW))
6038 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
6039 door_state &= ~DOOR_OPEN_1;
6040 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
6041 door_state &= ~DOOR_CLOSE_1;
6042 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
6043 door_state &= ~DOOR_OPEN_2;
6044 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
6045 door_state &= ~DOOR_CLOSE_2;
6048 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
6051 // door_delay_value *= 4; // !!! TEST ONLY !!!
6053 if (setup.quick_doors)
6055 stepsize = 20; /* must be chosen to always draw last frame */
6056 door_delay_value = 0;
6059 if (global.autoplay_leveldir)
6061 door_state |= DOOR_NO_DELAY;
6062 door_state &= ~DOOR_CLOSE_ALL;
6066 if (game_status == GAME_MODE_EDITOR)
6067 door_state |= DOOR_NO_DELAY;
6070 if (door_state & DOOR_ACTION)
6073 struct GraphicInfo *g1_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
6074 struct GraphicInfo *g1_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
6075 struct GraphicInfo *g2_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
6076 struct GraphicInfo *g2_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
6077 int door_1_left_width = g1_left->width;
6078 int door_1_left_height = g1_left->height;
6079 int door_1_right_width = g1_right->width;
6080 int door_1_right_height = g1_right->height;
6081 int door_2_left_width = g2_left->width;
6082 int door_2_left_height = g2_left->height;
6083 int door_2_right_width = g2_right->width;
6084 int door_2_right_height = g2_right->height;
6085 int door_1_width = MAX(door_1_left_width, door_1_right_width);
6086 int door_1_height = MAX(door_1_left_height, door_1_right_height);
6087 int door_2_width = MAX(door_2_left_width, door_2_right_width);
6088 int door_2_height = MAX(door_2_left_height, door_2_right_height);
6090 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
6091 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
6092 boolean door_1_done = (!handle_door_1);
6093 boolean door_2_done = (!handle_door_2);
6094 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
6095 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
6098 int door_size_1 = (door_1_vertical ? door_1_height : door_1_width);
6099 int door_size_2 = (door_2_vertical ? door_2_height : door_2_width);
6101 int door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
6102 int door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
6105 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
6106 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
6108 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
6109 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
6110 // int door_size = (handle_door_1 ? door_size_1 : door_size_2);
6111 int door_size = (handle_door_2 ? door_size_2 : door_size_1);
6112 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
6113 int door_skip = max_door_size - door_size;
6114 int end = door_size;
6115 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
6118 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
6120 /* opening door sound has priority over simultaneously closing door */
6121 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
6122 PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
6123 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
6124 PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
6127 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
6131 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6132 GC gc = bitmap->stored_clip_gc;
6135 if (door_state & DOOR_ACTION_1 &&
6136 x * door_1.step_offset <= door_size_1)
6138 int a = MIN(x * door_1.step_offset, end);
6139 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
6143 int i = p + door_skip;
6147 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
6148 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
6149 Bitmap *bm_left = g_left->bitmap;
6150 Bitmap *bm_right = g_right->bitmap;
6151 GC gc_left = bm_left->stored_clip_gc;
6152 GC gc_right = bm_right->stored_clip_gc;
6155 int classic_dxsize = 100;
6156 int classic_dysize = 280;
6157 boolean classic_door_1_size = (DXSIZE == classic_dxsize &&
6158 DYSIZE == classic_dysize);
6160 if (door_1.anim_mode & ANIM_STATIC_PANEL)
6162 BlitBitmap(bitmap_db_door, drawto,
6163 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
6164 DXSIZE, DYSIZE, DX, DY);
6168 BlitBitmap(bitmap_db_door, drawto,
6169 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
6170 DXSIZE, DYSIZE - p / 2, DX, DY);
6173 // printf("::: p == %d\n", p);
6174 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
6178 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
6181 int src1_x = g_right->src_x;
6182 int src1_y = g_right->src_y;
6183 int src2_x = g_left->src_x + g_left->width - i;
6184 int src2_y = g_left->src_y;
6185 int dst1_x = DX + DXSIZE - i;
6190 int height = DYSIZE;
6192 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6193 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6196 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6197 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6200 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6201 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
6202 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
6203 int dst2_x = DX, dst2_y = DY;
6204 int width = i, height = DYSIZE;
6206 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6207 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6210 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6211 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6215 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
6218 int src1_x = g_right->src_x;
6219 int src1_y = g_right->src_y;
6220 int src2_x = g_left->src_x;
6221 int src2_y = g_left->src_y + g_left->height - i;
6223 int dst1_y = DY + DYSIZE - i;
6229 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6230 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6233 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6234 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6237 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6238 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
6239 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
6240 int dst2_x = DX, dst2_y = DY;
6241 int width = DXSIZE, height = i;
6243 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6244 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6247 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6248 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6252 else if (classic_door_1_size && x <= DXSIZE) /* ANIM_DEFAULT */
6254 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
6257 int src1_x = g_right->src_x;
6258 int src1_y = g_right->src_y;
6259 int src2_x = g_left->src_x + g_left->width - i;
6260 int src2_y = g_left->src_y;
6261 int dst1_x = DX + DXSIZE - i;
6266 int height1 = 63, height2 = DYSIZE / 2 - height1;
6267 int ypos1 = 0, ypos2 = height2;
6268 int ypos3 = DYSIZE / 2, ypos4 = DYSIZE - height2;
6270 SetClipOrigin(bm_right, gc_right,
6271 dst1_x - src1_x, dst1_y - src1_y + j);
6272 BlitBitmapMasked(bm_right, drawto,
6273 src1_x, src1_y + ypos1, width, height2,
6274 dst1_x, dst1_y + ypos1 + j);
6275 BlitBitmapMasked(bm_right, drawto,
6276 src1_x, src1_y + ypos3, width, height1,
6277 dst1_x, dst1_y + ypos3 + j);
6278 SetClipOrigin(bm_left, gc_left,
6279 dst2_x - src2_x, dst2_y - src2_y - j);
6280 BlitBitmapMasked(bm_left, drawto,
6281 src2_x, src2_y + ypos1 + j, width, height2 - j,
6282 dst2_x, dst2_y + ypos1);
6283 BlitBitmapMasked(bm_left, drawto,
6284 src2_x, src2_y + ypos3, width, height1,
6285 dst2_x, dst2_y + ypos3 - j);
6287 SetClipOrigin(bm_left, gc_left,
6288 dst2_x - src2_x, dst2_y - src2_y - j);
6289 BlitBitmapMasked(bm_left, drawto,
6290 src2_x, src2_y + ypos2, width, height1,
6291 dst2_x, dst2_y + ypos2 - j);
6292 BlitBitmapMasked(bm_left, drawto,
6293 src2_x, src2_y + ypos4, width, height2,
6294 dst2_x, dst2_y + ypos4 - j);
6295 SetClipOrigin(bm_right, gc_right,
6296 dst1_x - src1_x, dst1_y - src1_y + j);
6297 BlitBitmapMasked(bm_right, drawto,
6298 src1_x, src1_y + ypos2, width, height1,
6299 dst1_x, dst1_y + ypos2 + j);
6300 BlitBitmapMasked(bm_right, drawto,
6301 src1_x, src1_y + ypos4, width, height2 - j,
6302 dst1_x, dst1_y + ypos4 + j);
6305 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6306 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
6307 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
6308 int dst2_x = DX, dst2_y = DY;
6309 int width = i, height = DYSIZE;
6310 int ypos1 = 63, ypos2 = 77, ypos3 = 140, ypos4 = 203;
6312 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6313 BlitBitmapMasked(bitmap, drawto,
6314 src1_x, src1_y, width, ypos2,
6315 dst1_x, dst1_y + j);
6316 BlitBitmapMasked(bitmap, drawto,
6317 src1_x, src1_y + ypos3, width, ypos1,
6318 dst1_x, dst1_y + ypos3 + j);
6319 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
6320 BlitBitmapMasked(bitmap, drawto,
6321 src2_x, src2_y + j, width, ypos2 - j,
6323 BlitBitmapMasked(bitmap, drawto,
6324 src2_x, src2_y + ypos3, width, ypos1,
6325 dst2_x, dst2_y + ypos3 - j);
6327 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
6328 BlitBitmapMasked(bitmap, drawto,
6329 src2_x, src2_y + ypos2, width, ypos1,
6330 dst2_x, dst2_y + ypos2 - j);
6331 BlitBitmapMasked(bitmap, drawto,
6332 src2_x, src2_y + ypos4, width, ypos2,
6333 dst2_x, dst2_y + ypos4 - j);
6334 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6335 BlitBitmapMasked(bitmap, drawto,
6336 src1_x, src1_y + ypos2, width, ypos1,
6337 dst1_x, dst1_y + ypos2 + j);
6338 BlitBitmapMasked(bitmap, drawto,
6339 src1_x, src1_y + ypos4, width, ypos2 - j,
6340 dst1_x, dst1_y + ypos4 + j);
6343 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
6344 BlitBitmapMasked(bitmap, drawto,
6345 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
6346 DX + DXSIZE - i, DY + j);
6347 BlitBitmapMasked(bitmap, drawto,
6348 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
6349 DX + DXSIZE - i, DY + 140 + j);
6350 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
6351 DY - (DOOR_GFX_PAGEY1 + j));
6352 BlitBitmapMasked(bitmap, drawto,
6353 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
6355 BlitBitmapMasked(bitmap, drawto,
6356 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
6359 BlitBitmapMasked(bitmap, drawto,
6360 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
6362 BlitBitmapMasked(bitmap, drawto,
6363 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
6365 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
6366 BlitBitmapMasked(bitmap, drawto,
6367 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
6368 DX + DXSIZE - i, DY + 77 + j);
6369 BlitBitmapMasked(bitmap, drawto,
6370 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
6371 DX + DXSIZE - i, DY + 203 + j);
6376 redraw_mask |= REDRAW_DOOR_1;
6377 door_1_done = (a == end);
6380 if (door_state & DOOR_ACTION_2 &&
6381 x * door_2.step_offset <= door_size_2)
6383 int a = MIN(x * door_2.step_offset, door_size);
6384 int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
6385 int i = p + door_skip;
6388 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
6389 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
6390 Bitmap *bm_left = g_left->bitmap;
6391 Bitmap *bm_right = g_right->bitmap;
6392 GC gc_left = bm_left->stored_clip_gc;
6393 GC gc_right = bm_right->stored_clip_gc;
6396 int classic_vxsize = 100;
6397 int classic_vysize = 100;
6398 boolean classic_door_2_size = (VXSIZE == classic_vxsize &&
6399 VYSIZE == classic_vysize);
6401 if (door_2.anim_mode & ANIM_STATIC_PANEL)
6403 BlitBitmap(bitmap_db_door, drawto,
6404 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
6405 VXSIZE, VYSIZE, VX, VY);
6407 else if (x <= VYSIZE)
6409 BlitBitmap(bitmap_db_door, drawto,
6410 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
6411 VXSIZE, VYSIZE - p / 2, VX, VY);
6413 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
6416 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
6419 int src1_x = g_right->src_x;
6420 int src1_y = g_right->src_y;
6421 int src2_x = g_left->src_x + g_left->width - i;
6422 int src2_y = g_left->src_y;
6423 int dst1_x = VX + VXSIZE - i;
6428 int height = VYSIZE;
6430 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6431 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6434 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6435 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6438 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6439 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6440 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6441 int dst2_x = VX, dst2_y = VY;
6442 int width = i, height = VYSIZE;
6444 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6445 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6448 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6449 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6453 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
6456 int src1_x = g_right->src_x;
6457 int src1_y = g_right->src_y;
6458 int src2_x = g_left->src_x;
6459 int src2_y = g_left->src_y + g_left->height - i;
6461 int dst1_y = VY + VYSIZE - i;
6467 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6468 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6471 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6472 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6475 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6476 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
6477 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
6478 int dst2_x = VX, dst2_y = VY;
6479 int width = VXSIZE, height = i;
6481 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6482 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6485 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6486 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6490 else if (classic_door_2_size && x <= VXSIZE) /* ANIM_DEFAULT */
6492 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
6495 int src1_x = g_right->src_x;
6496 int src1_y = g_right->src_y;
6497 int src2_x = g_left->src_x + g_left->width - i;
6498 int src2_y = g_left->src_y;
6499 int dst1_x = VX + VXSIZE - i;
6504 int height = VYSIZE / 2;
6505 int ypos1 = 0, ypos2 = VYSIZE / 2;
6507 SetClipOrigin(bm_right, gc_right,
6508 dst1_x - src1_x, dst1_y - src1_y + j);
6509 BlitBitmapMasked(bm_right, drawto,
6510 src1_x, src1_y + ypos1, width, height,
6511 dst1_x, dst1_y + ypos1 + j);
6512 SetClipOrigin(bm_left, gc_left,
6513 dst2_x - src2_x, dst2_y - src2_y - j);
6514 BlitBitmapMasked(bm_left, drawto,
6515 src2_x, src2_y + ypos1 + j, width, height - j,
6516 dst2_x, dst2_y + ypos1);
6518 SetClipOrigin(bm_left, gc_left,
6519 dst2_x - src2_x, dst2_y - src2_y - j);
6520 BlitBitmapMasked(bm_left, drawto,
6521 src2_x, src2_y + ypos2, width, height,
6522 dst2_x, dst2_y + ypos2 - j);
6523 SetClipOrigin(bm_right, gc_right,
6524 dst1_x - src1_x, dst1_y - src1_y + j);
6525 BlitBitmapMasked(bm_right, drawto,
6526 src1_x, src1_y + ypos2, width, height - j,
6527 dst1_x, dst1_y + ypos2 + j);
6529 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6530 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6531 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6532 int dst2_x = VX, dst2_y = VY;
6533 int width = i, height = VYSIZE;
6534 int ypos = VYSIZE / 2;
6536 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6537 BlitBitmapMasked(bitmap, drawto,
6538 src1_x, src1_y, width, ypos,
6539 dst1_x, dst1_y + j);
6540 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6541 BlitBitmapMasked(bitmap, drawto,
6542 src2_x, src2_y + j, width, ypos - j,
6545 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6546 BlitBitmapMasked(bitmap, drawto,
6547 src2_x, src2_y + ypos, width, ypos,
6548 dst2_x, dst2_y + ypos - j);
6549 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6550 BlitBitmapMasked(bitmap, drawto,
6551 src1_x, src1_y + ypos, width, ypos - j,
6552 dst1_x, dst1_y + ypos + j);
6555 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6556 BlitBitmapMasked(bitmap, drawto,
6557 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
6558 VX + VXSIZE - i, VY + j);
6559 SetClipOrigin(bitmap, gc,
6560 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
6561 BlitBitmapMasked(bitmap, drawto,
6562 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
6565 BlitBitmapMasked(bitmap, drawto,
6566 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6567 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
6568 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6569 BlitBitmapMasked(bitmap, drawto,
6570 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6572 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
6577 redraw_mask |= REDRAW_DOOR_2;
6578 door_2_done = (a == VXSIZE);
6581 if (!(door_state & DOOR_NO_DELAY))
6585 if (game_status == GAME_MODE_MAIN)
6588 WaitUntilDelayReached(&door_delay, door_delay_value);
6593 if (door_state & DOOR_ACTION_1)
6594 door1 = door_state & DOOR_ACTION_1;
6595 if (door_state & DOOR_ACTION_2)
6596 door2 = door_state & DOOR_ACTION_2;
6598 return (door1 | door2);
6603 void DrawSpecialEditorDoor()
6606 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6607 int top_border_width = gfx1->width;
6608 int top_border_height = gfx1->height;
6609 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6610 int ex = EX - outer_border;
6611 int ey = EY - outer_border;
6612 int vy = VY - outer_border;
6613 int exsize = EXSIZE + 2 * outer_border;
6615 CloseDoor(DOOR_CLOSE_2);
6617 /* draw bigger level editor toolbox window */
6618 BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
6619 top_border_width, top_border_height, ex, ey - top_border_height);
6620 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
6621 exsize, EYSIZE - VYSIZE + outer_border, ex, ey);
6623 /* draw bigger level editor toolbox window */
6624 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
6625 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
6627 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6628 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
6632 redraw_mask |= REDRAW_ALL;
6635 void UndrawSpecialEditorDoor()
6638 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6639 int top_border_width = gfx1->width;
6640 int top_border_height = gfx1->height;
6641 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6642 int ex = EX - outer_border;
6643 int ey = EY - outer_border;
6644 int ey_top = ey - top_border_height;
6645 int exsize = EXSIZE + 2 * outer_border;
6646 int eysize = EYSIZE + 2 * outer_border;
6648 /* draw normal tape recorder window */
6649 if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
6651 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6652 ex, ey_top, top_border_width, top_border_height,
6654 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6655 ex, ey, exsize, eysize, ex, ey);
6659 // if screen background is set to "[NONE]", clear editor toolbox window
6660 ClearRectangle(drawto, ex, ey_top, top_border_width, top_border_height);
6661 ClearRectangle(drawto, ex, ey, exsize, eysize);
6664 /* draw normal tape recorder window */
6665 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6666 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
6670 redraw_mask |= REDRAW_ALL;
6674 /* ---------- new tool button stuff ---------------------------------------- */
6681 struct TextPosInfo *pos;
6684 } toolbutton_info[NUM_TOOL_BUTTONS] =
6687 IMG_REQUEST_BUTTON_GFX_YES, &request.button.yes,
6688 TOOL_CTRL_ID_YES, "yes"
6691 IMG_REQUEST_BUTTON_GFX_NO, &request.button.no,
6692 TOOL_CTRL_ID_NO, "no"
6695 IMG_REQUEST_BUTTON_GFX_CONFIRM, &request.button.confirm,
6696 TOOL_CTRL_ID_CONFIRM, "confirm"
6699 IMG_REQUEST_BUTTON_GFX_PLAYER_1, &request.button.player_1,
6700 TOOL_CTRL_ID_PLAYER_1, "player 1"
6703 IMG_REQUEST_BUTTON_GFX_PLAYER_2, &request.button.player_2,
6704 TOOL_CTRL_ID_PLAYER_2, "player 2"
6707 IMG_REQUEST_BUTTON_GFX_PLAYER_3, &request.button.player_3,
6708 TOOL_CTRL_ID_PLAYER_3, "player 3"
6711 IMG_REQUEST_BUTTON_GFX_PLAYER_4, &request.button.player_4,
6712 TOOL_CTRL_ID_PLAYER_4, "player 4"
6716 void CreateToolButtons()
6720 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6722 struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
6723 struct TextPosInfo *pos = toolbutton_info[i].pos;
6724 struct GadgetInfo *gi;
6725 Bitmap *deco_bitmap = None;
6726 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6727 unsigned int event_mask = GD_EVENT_RELEASED;
6730 int gd_x = gfx->src_x;
6731 int gd_y = gfx->src_y;
6732 int gd_xp = gfx->src_x + gfx->pressed_xoffset;
6733 int gd_yp = gfx->src_y + gfx->pressed_yoffset;
6736 if (global.use_envelope_request)
6737 setRequestPosition(&dx, &dy, TRUE);
6739 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
6741 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
6743 getSizedGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0,
6744 pos->size, &deco_bitmap, &deco_x, &deco_y);
6745 deco_xpos = (gfx->width - pos->size) / 2;
6746 deco_ypos = (gfx->height - pos->size) / 2;
6749 gi = CreateGadget(GDI_CUSTOM_ID, id,
6750 GDI_INFO_TEXT, toolbutton_info[i].infotext,
6751 GDI_X, dx + GDI_ACTIVE_POS(pos->x),
6752 GDI_Y, dy + GDI_ACTIVE_POS(pos->y),
6753 GDI_WIDTH, gfx->width,
6754 GDI_HEIGHT, gfx->height,
6755 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
6756 GDI_STATE, GD_BUTTON_UNPRESSED,
6757 GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y,
6758 GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp,
6759 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
6760 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
6761 GDI_DECORATION_SIZE, pos->size, pos->size,
6762 GDI_DECORATION_SHIFTING, 1, 1,
6763 GDI_DIRECT_DRAW, FALSE,
6764 GDI_EVENT_MASK, event_mask,
6765 GDI_CALLBACK_ACTION, HandleToolButtons,
6769 Error(ERR_EXIT, "cannot create gadget");
6771 tool_gadget[id] = gi;
6777 /* graphic position values for tool buttons */
6778 #define TOOL_BUTTON_YES_XPOS 2
6779 #define TOOL_BUTTON_YES_YPOS 250
6780 #define TOOL_BUTTON_YES_GFX_YPOS 0
6781 #define TOOL_BUTTON_YES_XSIZE 46
6782 #define TOOL_BUTTON_YES_YSIZE 28
6783 #define TOOL_BUTTON_NO_XPOS 52
6784 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
6785 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
6786 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
6787 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
6788 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
6789 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
6790 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
6791 #define TOOL_BUTTON_CONFIRM_XSIZE 96
6792 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
6793 #define TOOL_BUTTON_PLAYER_XSIZE 30
6794 #define TOOL_BUTTON_PLAYER_YSIZE 30
6795 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
6796 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
6797 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
6798 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
6799 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6800 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6801 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6802 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6803 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6804 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6805 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6806 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6807 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6808 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6809 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6810 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6811 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6812 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6813 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6814 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6823 } toolbutton_info[NUM_TOOL_BUTTONS] =
6826 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
6827 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
6828 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
6833 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
6834 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
6835 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
6840 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
6841 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
6842 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
6843 TOOL_CTRL_ID_CONFIRM,
6847 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6848 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
6849 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6850 TOOL_CTRL_ID_PLAYER_1,
6854 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6855 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
6856 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6857 TOOL_CTRL_ID_PLAYER_2,
6861 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6862 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
6863 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6864 TOOL_CTRL_ID_PLAYER_3,
6868 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6869 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
6870 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6871 TOOL_CTRL_ID_PLAYER_4,
6876 void CreateToolButtons()
6880 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6882 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6883 Bitmap *deco_bitmap = None;
6884 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6885 struct GadgetInfo *gi;
6886 unsigned int event_mask;
6887 int gd_xoffset, gd_yoffset;
6888 int gd_x1, gd_x2, gd_y;
6891 event_mask = GD_EVENT_RELEASED;
6893 gd_xoffset = toolbutton_info[i].xpos;
6894 gd_yoffset = toolbutton_info[i].ypos;
6895 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
6896 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
6897 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
6899 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
6901 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
6903 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
6904 &deco_bitmap, &deco_x, &deco_y);
6905 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
6906 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
6909 gi = CreateGadget(GDI_CUSTOM_ID, id,
6910 GDI_INFO_TEXT, toolbutton_info[i].infotext,
6911 GDI_X, DX + GDI_ACTIVE_POS(toolbutton_info[i].x),
6912 GDI_Y, DY + GDI_ACTIVE_POS(toolbutton_info[i].y),
6913 GDI_WIDTH, toolbutton_info[i].width,
6914 GDI_HEIGHT, toolbutton_info[i].height,
6915 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
6916 GDI_STATE, GD_BUTTON_UNPRESSED,
6917 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
6918 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
6919 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
6920 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
6921 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
6922 GDI_DECORATION_SHIFTING, 1, 1,
6923 GDI_DIRECT_DRAW, FALSE,
6924 GDI_EVENT_MASK, event_mask,
6925 GDI_CALLBACK_ACTION, HandleToolButtons,
6929 Error(ERR_EXIT, "cannot create gadget");
6931 tool_gadget[id] = gi;
6937 void FreeToolButtons()
6941 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6942 FreeGadget(tool_gadget[i]);
6945 static void UnmapToolButtons()
6949 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6950 UnmapGadget(tool_gadget[i]);
6953 static void HandleToolButtons(struct GadgetInfo *gi)
6955 request_gadget_id = gi->custom_id;
6958 static struct Mapping_EM_to_RND_object
6961 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
6962 boolean is_backside; /* backside of moving element */
6968 em_object_mapping_list[] =
6971 Xblank, TRUE, FALSE,
6975 Yacid_splash_eB, FALSE, FALSE,
6976 EL_ACID_SPLASH_RIGHT, -1, -1
6979 Yacid_splash_wB, FALSE, FALSE,
6980 EL_ACID_SPLASH_LEFT, -1, -1
6983 #ifdef EM_ENGINE_BAD_ROLL
6985 Xstone_force_e, FALSE, FALSE,
6986 EL_ROCK, -1, MV_BIT_RIGHT
6989 Xstone_force_w, FALSE, FALSE,
6990 EL_ROCK, -1, MV_BIT_LEFT
6993 Xnut_force_e, FALSE, FALSE,
6994 EL_NUT, -1, MV_BIT_RIGHT
6997 Xnut_force_w, FALSE, FALSE,
6998 EL_NUT, -1, MV_BIT_LEFT
7001 Xspring_force_e, FALSE, FALSE,
7002 EL_SPRING, -1, MV_BIT_RIGHT
7005 Xspring_force_w, FALSE, FALSE,
7006 EL_SPRING, -1, MV_BIT_LEFT
7009 Xemerald_force_e, FALSE, FALSE,
7010 EL_EMERALD, -1, MV_BIT_RIGHT
7013 Xemerald_force_w, FALSE, FALSE,
7014 EL_EMERALD, -1, MV_BIT_LEFT
7017 Xdiamond_force_e, FALSE, FALSE,
7018 EL_DIAMOND, -1, MV_BIT_RIGHT
7021 Xdiamond_force_w, FALSE, FALSE,
7022 EL_DIAMOND, -1, MV_BIT_LEFT
7025 Xbomb_force_e, FALSE, FALSE,
7026 EL_BOMB, -1, MV_BIT_RIGHT
7029 Xbomb_force_w, FALSE, FALSE,
7030 EL_BOMB, -1, MV_BIT_LEFT
7032 #endif /* EM_ENGINE_BAD_ROLL */
7035 Xstone, TRUE, FALSE,
7039 Xstone_pause, FALSE, FALSE,
7043 Xstone_fall, FALSE, FALSE,
7047 Ystone_s, FALSE, FALSE,
7048 EL_ROCK, ACTION_FALLING, -1
7051 Ystone_sB, FALSE, TRUE,
7052 EL_ROCK, ACTION_FALLING, -1
7055 Ystone_e, FALSE, FALSE,
7056 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
7059 Ystone_eB, FALSE, TRUE,
7060 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
7063 Ystone_w, FALSE, FALSE,
7064 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
7067 Ystone_wB, FALSE, TRUE,
7068 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
7075 Xnut_pause, FALSE, FALSE,
7079 Xnut_fall, FALSE, FALSE,
7083 Ynut_s, FALSE, FALSE,
7084 EL_NUT, ACTION_FALLING, -1
7087 Ynut_sB, FALSE, TRUE,
7088 EL_NUT, ACTION_FALLING, -1
7091 Ynut_e, FALSE, FALSE,
7092 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
7095 Ynut_eB, FALSE, TRUE,
7096 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
7099 Ynut_w, FALSE, FALSE,
7100 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
7103 Ynut_wB, FALSE, TRUE,
7104 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
7107 Xbug_n, TRUE, FALSE,
7111 Xbug_e, TRUE, FALSE,
7112 EL_BUG_RIGHT, -1, -1
7115 Xbug_s, TRUE, FALSE,
7119 Xbug_w, TRUE, FALSE,
7123 Xbug_gon, FALSE, FALSE,
7127 Xbug_goe, FALSE, FALSE,
7128 EL_BUG_RIGHT, -1, -1
7131 Xbug_gos, FALSE, FALSE,
7135 Xbug_gow, FALSE, FALSE,
7139 Ybug_n, FALSE, FALSE,
7140 EL_BUG, ACTION_MOVING, MV_BIT_UP
7143 Ybug_nB, FALSE, TRUE,
7144 EL_BUG, ACTION_MOVING, MV_BIT_UP
7147 Ybug_e, FALSE, FALSE,
7148 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
7151 Ybug_eB, FALSE, TRUE,
7152 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
7155 Ybug_s, FALSE, FALSE,
7156 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
7159 Ybug_sB, FALSE, TRUE,
7160 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
7163 Ybug_w, FALSE, FALSE,
7164 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
7167 Ybug_wB, FALSE, TRUE,
7168 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
7171 Ybug_w_n, FALSE, FALSE,
7172 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
7175 Ybug_n_e, FALSE, FALSE,
7176 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
7179 Ybug_e_s, FALSE, FALSE,
7180 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
7183 Ybug_s_w, FALSE, FALSE,
7184 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
7187 Ybug_e_n, FALSE, FALSE,
7188 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
7191 Ybug_s_e, FALSE, FALSE,
7192 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
7195 Ybug_w_s, FALSE, FALSE,
7196 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
7199 Ybug_n_w, FALSE, FALSE,
7200 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
7203 Ybug_stone, FALSE, FALSE,
7204 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
7207 Ybug_spring, FALSE, FALSE,
7208 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
7211 Xtank_n, TRUE, FALSE,
7212 EL_SPACESHIP_UP, -1, -1
7215 Xtank_e, TRUE, FALSE,
7216 EL_SPACESHIP_RIGHT, -1, -1
7219 Xtank_s, TRUE, FALSE,
7220 EL_SPACESHIP_DOWN, -1, -1
7223 Xtank_w, TRUE, FALSE,
7224 EL_SPACESHIP_LEFT, -1, -1
7227 Xtank_gon, FALSE, FALSE,
7228 EL_SPACESHIP_UP, -1, -1
7231 Xtank_goe, FALSE, FALSE,
7232 EL_SPACESHIP_RIGHT, -1, -1
7235 Xtank_gos, FALSE, FALSE,
7236 EL_SPACESHIP_DOWN, -1, -1
7239 Xtank_gow, FALSE, FALSE,
7240 EL_SPACESHIP_LEFT, -1, -1
7243 Ytank_n, FALSE, FALSE,
7244 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
7247 Ytank_nB, FALSE, TRUE,
7248 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
7251 Ytank_e, FALSE, FALSE,
7252 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
7255 Ytank_eB, FALSE, TRUE,
7256 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
7259 Ytank_s, FALSE, FALSE,
7260 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
7263 Ytank_sB, FALSE, TRUE,
7264 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
7267 Ytank_w, FALSE, FALSE,
7268 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
7271 Ytank_wB, FALSE, TRUE,
7272 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
7275 Ytank_w_n, FALSE, FALSE,
7276 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
7279 Ytank_n_e, FALSE, FALSE,
7280 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
7283 Ytank_e_s, FALSE, FALSE,
7284 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
7287 Ytank_s_w, FALSE, FALSE,
7288 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
7291 Ytank_e_n, FALSE, FALSE,
7292 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
7295 Ytank_s_e, FALSE, FALSE,
7296 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
7299 Ytank_w_s, FALSE, FALSE,
7300 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
7303 Ytank_n_w, FALSE, FALSE,
7304 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
7307 Ytank_stone, FALSE, FALSE,
7308 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
7311 Ytank_spring, FALSE, FALSE,
7312 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
7315 Xandroid, TRUE, FALSE,
7316 EL_EMC_ANDROID, ACTION_ACTIVE, -1
7319 Xandroid_1_n, FALSE, FALSE,
7320 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
7323 Xandroid_2_n, FALSE, FALSE,
7324 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
7327 Xandroid_1_e, FALSE, FALSE,
7328 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
7331 Xandroid_2_e, FALSE, FALSE,
7332 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
7335 Xandroid_1_w, FALSE, FALSE,
7336 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
7339 Xandroid_2_w, FALSE, FALSE,
7340 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
7343 Xandroid_1_s, FALSE, FALSE,
7344 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
7347 Xandroid_2_s, FALSE, FALSE,
7348 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
7351 Yandroid_n, FALSE, FALSE,
7352 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
7355 Yandroid_nB, FALSE, TRUE,
7356 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
7359 Yandroid_ne, FALSE, FALSE,
7360 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
7363 Yandroid_neB, FALSE, TRUE,
7364 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
7367 Yandroid_e, FALSE, FALSE,
7368 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
7371 Yandroid_eB, FALSE, TRUE,
7372 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
7375 Yandroid_se, FALSE, FALSE,
7376 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
7379 Yandroid_seB, FALSE, TRUE,
7380 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
7383 Yandroid_s, FALSE, FALSE,
7384 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
7387 Yandroid_sB, FALSE, TRUE,
7388 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
7391 Yandroid_sw, FALSE, FALSE,
7392 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
7395 Yandroid_swB, FALSE, TRUE,
7396 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
7399 Yandroid_w, FALSE, FALSE,
7400 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
7403 Yandroid_wB, FALSE, TRUE,
7404 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
7407 Yandroid_nw, FALSE, FALSE,
7408 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
7411 Yandroid_nwB, FALSE, TRUE,
7412 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
7415 Xspring, TRUE, FALSE,
7419 Xspring_pause, FALSE, FALSE,
7423 Xspring_e, FALSE, FALSE,
7427 Xspring_w, FALSE, FALSE,
7431 Xspring_fall, FALSE, FALSE,
7435 Yspring_s, FALSE, FALSE,
7436 EL_SPRING, ACTION_FALLING, -1
7439 Yspring_sB, FALSE, TRUE,
7440 EL_SPRING, ACTION_FALLING, -1
7443 Yspring_e, FALSE, FALSE,
7444 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
7447 Yspring_eB, FALSE, TRUE,
7448 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
7451 Yspring_w, FALSE, FALSE,
7452 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
7455 Yspring_wB, FALSE, TRUE,
7456 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
7459 Yspring_kill_e, FALSE, FALSE,
7460 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
7463 Yspring_kill_eB, FALSE, TRUE,
7464 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
7467 Yspring_kill_w, FALSE, FALSE,
7468 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7471 Yspring_kill_wB, FALSE, TRUE,
7472 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7475 Xeater_n, TRUE, FALSE,
7476 EL_YAMYAM_UP, -1, -1
7479 Xeater_e, TRUE, FALSE,
7480 EL_YAMYAM_RIGHT, -1, -1
7483 Xeater_w, TRUE, FALSE,
7484 EL_YAMYAM_LEFT, -1, -1
7487 Xeater_s, TRUE, FALSE,
7488 EL_YAMYAM_DOWN, -1, -1
7491 Yeater_n, FALSE, FALSE,
7492 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7495 Yeater_nB, FALSE, TRUE,
7496 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7499 Yeater_e, FALSE, FALSE,
7500 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7503 Yeater_eB, FALSE, TRUE,
7504 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7507 Yeater_s, FALSE, FALSE,
7508 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7511 Yeater_sB, FALSE, TRUE,
7512 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7515 Yeater_w, FALSE, FALSE,
7516 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7519 Yeater_wB, FALSE, TRUE,
7520 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7523 Yeater_stone, FALSE, FALSE,
7524 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
7527 Yeater_spring, FALSE, FALSE,
7528 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
7531 Xalien, TRUE, FALSE,
7535 Xalien_pause, FALSE, FALSE,
7539 Yalien_n, FALSE, FALSE,
7540 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7543 Yalien_nB, FALSE, TRUE,
7544 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7547 Yalien_e, FALSE, FALSE,
7548 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7551 Yalien_eB, FALSE, TRUE,
7552 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7555 Yalien_s, FALSE, FALSE,
7556 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7559 Yalien_sB, FALSE, TRUE,
7560 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7563 Yalien_w, FALSE, FALSE,
7564 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7567 Yalien_wB, FALSE, TRUE,
7568 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7571 Yalien_stone, FALSE, FALSE,
7572 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
7575 Yalien_spring, FALSE, FALSE,
7576 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
7579 Xemerald, TRUE, FALSE,
7583 Xemerald_pause, FALSE, FALSE,
7587 Xemerald_fall, FALSE, FALSE,
7591 Xemerald_shine, FALSE, FALSE,
7592 EL_EMERALD, ACTION_TWINKLING, -1
7595 Yemerald_s, FALSE, FALSE,
7596 EL_EMERALD, ACTION_FALLING, -1
7599 Yemerald_sB, FALSE, TRUE,
7600 EL_EMERALD, ACTION_FALLING, -1
7603 Yemerald_e, FALSE, FALSE,
7604 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7607 Yemerald_eB, FALSE, TRUE,
7608 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7611 Yemerald_w, FALSE, FALSE,
7612 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7615 Yemerald_wB, FALSE, TRUE,
7616 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7619 Yemerald_eat, FALSE, FALSE,
7620 EL_EMERALD, ACTION_COLLECTING, -1
7623 Yemerald_stone, FALSE, FALSE,
7624 EL_NUT, ACTION_BREAKING, -1
7627 Xdiamond, TRUE, FALSE,
7631 Xdiamond_pause, FALSE, FALSE,
7635 Xdiamond_fall, FALSE, FALSE,
7639 Xdiamond_shine, FALSE, FALSE,
7640 EL_DIAMOND, ACTION_TWINKLING, -1
7643 Ydiamond_s, FALSE, FALSE,
7644 EL_DIAMOND, ACTION_FALLING, -1
7647 Ydiamond_sB, FALSE, TRUE,
7648 EL_DIAMOND, ACTION_FALLING, -1
7651 Ydiamond_e, FALSE, FALSE,
7652 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7655 Ydiamond_eB, FALSE, TRUE,
7656 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7659 Ydiamond_w, FALSE, FALSE,
7660 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7663 Ydiamond_wB, FALSE, TRUE,
7664 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7667 Ydiamond_eat, FALSE, FALSE,
7668 EL_DIAMOND, ACTION_COLLECTING, -1
7671 Ydiamond_stone, FALSE, FALSE,
7672 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
7675 Xdrip_fall, TRUE, FALSE,
7676 EL_AMOEBA_DROP, -1, -1
7679 Xdrip_stretch, FALSE, FALSE,
7680 EL_AMOEBA_DROP, ACTION_FALLING, -1
7683 Xdrip_stretchB, FALSE, TRUE,
7684 EL_AMOEBA_DROP, ACTION_FALLING, -1
7687 Xdrip_eat, FALSE, FALSE,
7688 EL_AMOEBA_DROP, ACTION_GROWING, -1
7691 Ydrip_s1, FALSE, FALSE,
7692 EL_AMOEBA_DROP, ACTION_FALLING, -1
7695 Ydrip_s1B, FALSE, TRUE,
7696 EL_AMOEBA_DROP, ACTION_FALLING, -1
7699 Ydrip_s2, FALSE, FALSE,
7700 EL_AMOEBA_DROP, ACTION_FALLING, -1
7703 Ydrip_s2B, FALSE, TRUE,
7704 EL_AMOEBA_DROP, ACTION_FALLING, -1
7711 Xbomb_pause, FALSE, FALSE,
7715 Xbomb_fall, FALSE, FALSE,
7719 Ybomb_s, FALSE, FALSE,
7720 EL_BOMB, ACTION_FALLING, -1
7723 Ybomb_sB, FALSE, TRUE,
7724 EL_BOMB, ACTION_FALLING, -1
7727 Ybomb_e, FALSE, FALSE,
7728 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7731 Ybomb_eB, FALSE, TRUE,
7732 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7735 Ybomb_w, FALSE, FALSE,
7736 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7739 Ybomb_wB, FALSE, TRUE,
7740 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7743 Ybomb_eat, FALSE, FALSE,
7744 EL_BOMB, ACTION_ACTIVATING, -1
7747 Xballoon, TRUE, FALSE,
7751 Yballoon_n, FALSE, FALSE,
7752 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7755 Yballoon_nB, FALSE, TRUE,
7756 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7759 Yballoon_e, FALSE, FALSE,
7760 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7763 Yballoon_eB, FALSE, TRUE,
7764 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7767 Yballoon_s, FALSE, FALSE,
7768 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7771 Yballoon_sB, FALSE, TRUE,
7772 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7775 Yballoon_w, FALSE, FALSE,
7776 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7779 Yballoon_wB, FALSE, TRUE,
7780 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7783 Xgrass, TRUE, FALSE,
7784 EL_EMC_GRASS, -1, -1
7787 Ygrass_nB, FALSE, FALSE,
7788 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
7791 Ygrass_eB, FALSE, FALSE,
7792 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
7795 Ygrass_sB, FALSE, FALSE,
7796 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
7799 Ygrass_wB, FALSE, FALSE,
7800 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
7807 Ydirt_nB, FALSE, FALSE,
7808 EL_SAND, ACTION_DIGGING, MV_BIT_UP
7811 Ydirt_eB, FALSE, FALSE,
7812 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
7815 Ydirt_sB, FALSE, FALSE,
7816 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
7819 Ydirt_wB, FALSE, FALSE,
7820 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
7823 Xacid_ne, TRUE, FALSE,
7824 EL_ACID_POOL_TOPRIGHT, -1, -1
7827 Xacid_se, TRUE, FALSE,
7828 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
7831 Xacid_s, TRUE, FALSE,
7832 EL_ACID_POOL_BOTTOM, -1, -1
7835 Xacid_sw, TRUE, FALSE,
7836 EL_ACID_POOL_BOTTOMLEFT, -1, -1
7839 Xacid_nw, TRUE, FALSE,
7840 EL_ACID_POOL_TOPLEFT, -1, -1
7843 Xacid_1, TRUE, FALSE,
7847 Xacid_2, FALSE, FALSE,
7851 Xacid_3, FALSE, FALSE,
7855 Xacid_4, FALSE, FALSE,
7859 Xacid_5, FALSE, FALSE,
7863 Xacid_6, FALSE, FALSE,
7867 Xacid_7, FALSE, FALSE,
7871 Xacid_8, FALSE, FALSE,
7875 Xball_1, TRUE, FALSE,
7876 EL_EMC_MAGIC_BALL, -1, -1
7879 Xball_1B, FALSE, FALSE,
7880 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7883 Xball_2, FALSE, FALSE,
7884 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7887 Xball_2B, FALSE, FALSE,
7888 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7891 Yball_eat, FALSE, FALSE,
7892 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
7895 Ykey_1_eat, FALSE, FALSE,
7896 EL_EM_KEY_1, ACTION_COLLECTING, -1
7899 Ykey_2_eat, FALSE, FALSE,
7900 EL_EM_KEY_2, ACTION_COLLECTING, -1
7903 Ykey_3_eat, FALSE, FALSE,
7904 EL_EM_KEY_3, ACTION_COLLECTING, -1
7907 Ykey_4_eat, FALSE, FALSE,
7908 EL_EM_KEY_4, ACTION_COLLECTING, -1
7911 Ykey_5_eat, FALSE, FALSE,
7912 EL_EMC_KEY_5, ACTION_COLLECTING, -1
7915 Ykey_6_eat, FALSE, FALSE,
7916 EL_EMC_KEY_6, ACTION_COLLECTING, -1
7919 Ykey_7_eat, FALSE, FALSE,
7920 EL_EMC_KEY_7, ACTION_COLLECTING, -1
7923 Ykey_8_eat, FALSE, FALSE,
7924 EL_EMC_KEY_8, ACTION_COLLECTING, -1
7927 Ylenses_eat, FALSE, FALSE,
7928 EL_EMC_LENSES, ACTION_COLLECTING, -1
7931 Ymagnify_eat, FALSE, FALSE,
7932 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
7935 Ygrass_eat, FALSE, FALSE,
7936 EL_EMC_GRASS, ACTION_SNAPPING, -1
7939 Ydirt_eat, FALSE, FALSE,
7940 EL_SAND, ACTION_SNAPPING, -1
7943 Xgrow_ns, TRUE, FALSE,
7944 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
7947 Ygrow_ns_eat, FALSE, FALSE,
7948 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
7951 Xgrow_ew, TRUE, FALSE,
7952 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
7955 Ygrow_ew_eat, FALSE, FALSE,
7956 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
7959 Xwonderwall, TRUE, FALSE,
7960 EL_MAGIC_WALL, -1, -1
7963 XwonderwallB, FALSE, FALSE,
7964 EL_MAGIC_WALL, ACTION_ACTIVE, -1
7967 Xamoeba_1, TRUE, FALSE,
7968 EL_AMOEBA_DRY, ACTION_OTHER, -1
7971 Xamoeba_2, FALSE, FALSE,
7972 EL_AMOEBA_DRY, ACTION_OTHER, -1
7975 Xamoeba_3, FALSE, FALSE,
7976 EL_AMOEBA_DRY, ACTION_OTHER, -1
7979 Xamoeba_4, FALSE, FALSE,
7980 EL_AMOEBA_DRY, ACTION_OTHER, -1
7983 Xamoeba_5, TRUE, FALSE,
7984 EL_AMOEBA_WET, ACTION_OTHER, -1
7987 Xamoeba_6, FALSE, FALSE,
7988 EL_AMOEBA_WET, ACTION_OTHER, -1
7991 Xamoeba_7, FALSE, FALSE,
7992 EL_AMOEBA_WET, ACTION_OTHER, -1
7995 Xamoeba_8, FALSE, FALSE,
7996 EL_AMOEBA_WET, ACTION_OTHER, -1
7999 Xdoor_1, TRUE, FALSE,
8000 EL_EM_GATE_1, -1, -1
8003 Xdoor_2, TRUE, FALSE,
8004 EL_EM_GATE_2, -1, -1
8007 Xdoor_3, TRUE, FALSE,
8008 EL_EM_GATE_3, -1, -1
8011 Xdoor_4, TRUE, FALSE,
8012 EL_EM_GATE_4, -1, -1
8015 Xdoor_5, TRUE, FALSE,
8016 EL_EMC_GATE_5, -1, -1
8019 Xdoor_6, TRUE, FALSE,
8020 EL_EMC_GATE_6, -1, -1
8023 Xdoor_7, TRUE, FALSE,
8024 EL_EMC_GATE_7, -1, -1
8027 Xdoor_8, TRUE, FALSE,
8028 EL_EMC_GATE_8, -1, -1
8031 Xkey_1, TRUE, FALSE,
8035 Xkey_2, TRUE, FALSE,
8039 Xkey_3, TRUE, FALSE,
8043 Xkey_4, TRUE, FALSE,
8047 Xkey_5, TRUE, FALSE,
8048 EL_EMC_KEY_5, -1, -1
8051 Xkey_6, TRUE, FALSE,
8052 EL_EMC_KEY_6, -1, -1
8055 Xkey_7, TRUE, FALSE,
8056 EL_EMC_KEY_7, -1, -1
8059 Xkey_8, TRUE, FALSE,
8060 EL_EMC_KEY_8, -1, -1
8063 Xwind_n, TRUE, FALSE,
8064 EL_BALLOON_SWITCH_UP, -1, -1
8067 Xwind_e, TRUE, FALSE,
8068 EL_BALLOON_SWITCH_RIGHT, -1, -1
8071 Xwind_s, TRUE, FALSE,
8072 EL_BALLOON_SWITCH_DOWN, -1, -1
8075 Xwind_w, TRUE, FALSE,
8076 EL_BALLOON_SWITCH_LEFT, -1, -1
8079 Xwind_nesw, TRUE, FALSE,
8080 EL_BALLOON_SWITCH_ANY, -1, -1
8083 Xwind_stop, TRUE, FALSE,
8084 EL_BALLOON_SWITCH_NONE, -1, -1
8088 EL_EM_EXIT_CLOSED, -1, -1
8091 Xexit_1, TRUE, FALSE,
8092 EL_EM_EXIT_OPEN, -1, -1
8095 Xexit_2, FALSE, FALSE,
8096 EL_EM_EXIT_OPEN, -1, -1
8099 Xexit_3, FALSE, FALSE,
8100 EL_EM_EXIT_OPEN, -1, -1
8103 Xdynamite, TRUE, FALSE,
8104 EL_EM_DYNAMITE, -1, -1
8107 Ydynamite_eat, FALSE, FALSE,
8108 EL_EM_DYNAMITE, ACTION_COLLECTING, -1
8111 Xdynamite_1, TRUE, FALSE,
8112 EL_EM_DYNAMITE_ACTIVE, -1, -1
8115 Xdynamite_2, FALSE, FALSE,
8116 EL_EM_DYNAMITE_ACTIVE, -1, -1
8119 Xdynamite_3, FALSE, FALSE,
8120 EL_EM_DYNAMITE_ACTIVE, -1, -1
8123 Xdynamite_4, FALSE, FALSE,
8124 EL_EM_DYNAMITE_ACTIVE, -1, -1
8127 Xbumper, TRUE, FALSE,
8128 EL_EMC_SPRING_BUMPER, -1, -1
8131 XbumperB, FALSE, FALSE,
8132 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
8135 Xwheel, TRUE, FALSE,
8136 EL_ROBOT_WHEEL, -1, -1
8139 XwheelB, FALSE, FALSE,
8140 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
8143 Xswitch, TRUE, FALSE,
8144 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
8147 XswitchB, FALSE, FALSE,
8148 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
8152 EL_QUICKSAND_EMPTY, -1, -1
8155 Xsand_stone, TRUE, FALSE,
8156 EL_QUICKSAND_FULL, -1, -1
8159 Xsand_stonein_1, FALSE, TRUE,
8160 EL_ROCK, ACTION_FILLING, -1
8163 Xsand_stonein_2, FALSE, TRUE,
8164 EL_ROCK, ACTION_FILLING, -1
8167 Xsand_stonein_3, FALSE, TRUE,
8168 EL_ROCK, ACTION_FILLING, -1
8171 Xsand_stonein_4, FALSE, TRUE,
8172 EL_ROCK, ACTION_FILLING, -1
8176 Xsand_stonesand_1, FALSE, FALSE,
8177 EL_QUICKSAND_EMPTYING, -1, -1
8180 Xsand_stonesand_2, FALSE, FALSE,
8181 EL_QUICKSAND_EMPTYING, -1, -1
8184 Xsand_stonesand_3, FALSE, FALSE,
8185 EL_QUICKSAND_EMPTYING, -1, -1
8188 Xsand_stonesand_4, FALSE, FALSE,
8189 EL_QUICKSAND_EMPTYING, -1, -1
8192 Xsand_stonesand_quickout_1, FALSE, FALSE,
8193 EL_QUICKSAND_EMPTYING, -1, -1
8196 Xsand_stonesand_quickout_2, FALSE, FALSE,
8197 EL_QUICKSAND_EMPTYING, -1, -1
8201 Xsand_stonesand_1, FALSE, FALSE,
8202 EL_QUICKSAND_FULL, -1, -1
8205 Xsand_stonesand_2, FALSE, FALSE,
8206 EL_QUICKSAND_FULL, -1, -1
8209 Xsand_stonesand_3, FALSE, FALSE,
8210 EL_QUICKSAND_FULL, -1, -1
8213 Xsand_stonesand_4, FALSE, FALSE,
8214 EL_QUICKSAND_FULL, -1, -1
8218 Xsand_stoneout_1, FALSE, FALSE,
8219 EL_ROCK, ACTION_EMPTYING, -1
8222 Xsand_stoneout_2, FALSE, FALSE,
8223 EL_ROCK, ACTION_EMPTYING, -1
8227 Xsand_sandstone_1, FALSE, FALSE,
8228 EL_QUICKSAND_FILLING, -1, -1
8231 Xsand_sandstone_2, FALSE, FALSE,
8232 EL_QUICKSAND_FILLING, -1, -1
8235 Xsand_sandstone_3, FALSE, FALSE,
8236 EL_QUICKSAND_FILLING, -1, -1
8239 Xsand_sandstone_4, FALSE, FALSE,
8240 EL_QUICKSAND_FILLING, -1, -1
8244 Xsand_sandstone_1, FALSE, FALSE,
8245 EL_QUICKSAND_FULL, -1, -1
8248 Xsand_sandstone_2, FALSE, FALSE,
8249 EL_QUICKSAND_FULL, -1, -1
8252 Xsand_sandstone_3, FALSE, FALSE,
8253 EL_QUICKSAND_FULL, -1, -1
8256 Xsand_sandstone_4, FALSE, FALSE,
8257 EL_QUICKSAND_FULL, -1, -1
8261 Xplant, TRUE, FALSE,
8262 EL_EMC_PLANT, -1, -1
8265 Yplant, FALSE, FALSE,
8266 EL_EMC_PLANT, -1, -1
8269 Xlenses, TRUE, FALSE,
8270 EL_EMC_LENSES, -1, -1
8273 Xmagnify, TRUE, FALSE,
8274 EL_EMC_MAGNIFIER, -1, -1
8277 Xdripper, TRUE, FALSE,
8278 EL_EMC_DRIPPER, -1, -1
8281 XdripperB, FALSE, FALSE,
8282 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
8285 Xfake_blank, TRUE, FALSE,
8286 EL_INVISIBLE_WALL, -1, -1
8289 Xfake_blankB, FALSE, FALSE,
8290 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
8293 Xfake_grass, TRUE, FALSE,
8294 EL_EMC_FAKE_GRASS, -1, -1
8297 Xfake_grassB, FALSE, FALSE,
8298 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
8301 Xfake_door_1, TRUE, FALSE,
8302 EL_EM_GATE_1_GRAY, -1, -1
8305 Xfake_door_2, TRUE, FALSE,
8306 EL_EM_GATE_2_GRAY, -1, -1
8309 Xfake_door_3, TRUE, FALSE,
8310 EL_EM_GATE_3_GRAY, -1, -1
8313 Xfake_door_4, TRUE, FALSE,
8314 EL_EM_GATE_4_GRAY, -1, -1
8317 Xfake_door_5, TRUE, FALSE,
8318 EL_EMC_GATE_5_GRAY, -1, -1
8321 Xfake_door_6, TRUE, FALSE,
8322 EL_EMC_GATE_6_GRAY, -1, -1
8325 Xfake_door_7, TRUE, FALSE,
8326 EL_EMC_GATE_7_GRAY, -1, -1
8329 Xfake_door_8, TRUE, FALSE,
8330 EL_EMC_GATE_8_GRAY, -1, -1
8333 Xfake_acid_1, TRUE, FALSE,
8334 EL_EMC_FAKE_ACID, -1, -1
8337 Xfake_acid_2, FALSE, FALSE,
8338 EL_EMC_FAKE_ACID, -1, -1
8341 Xfake_acid_3, FALSE, FALSE,
8342 EL_EMC_FAKE_ACID, -1, -1
8345 Xfake_acid_4, FALSE, FALSE,
8346 EL_EMC_FAKE_ACID, -1, -1
8349 Xfake_acid_5, FALSE, FALSE,
8350 EL_EMC_FAKE_ACID, -1, -1
8353 Xfake_acid_6, FALSE, FALSE,
8354 EL_EMC_FAKE_ACID, -1, -1
8357 Xfake_acid_7, FALSE, FALSE,
8358 EL_EMC_FAKE_ACID, -1, -1
8361 Xfake_acid_8, FALSE, FALSE,
8362 EL_EMC_FAKE_ACID, -1, -1
8365 Xsteel_1, TRUE, FALSE,
8366 EL_STEELWALL, -1, -1
8369 Xsteel_2, TRUE, FALSE,
8370 EL_EMC_STEELWALL_2, -1, -1
8373 Xsteel_3, TRUE, FALSE,
8374 EL_EMC_STEELWALL_3, -1, -1
8377 Xsteel_4, TRUE, FALSE,
8378 EL_EMC_STEELWALL_4, -1, -1
8381 Xwall_1, TRUE, FALSE,
8385 Xwall_2, TRUE, FALSE,
8386 EL_EMC_WALL_14, -1, -1
8389 Xwall_3, TRUE, FALSE,
8390 EL_EMC_WALL_15, -1, -1
8393 Xwall_4, TRUE, FALSE,
8394 EL_EMC_WALL_16, -1, -1
8397 Xround_wall_1, TRUE, FALSE,
8398 EL_WALL_SLIPPERY, -1, -1
8401 Xround_wall_2, TRUE, FALSE,
8402 EL_EMC_WALL_SLIPPERY_2, -1, -1
8405 Xround_wall_3, TRUE, FALSE,
8406 EL_EMC_WALL_SLIPPERY_3, -1, -1
8409 Xround_wall_4, TRUE, FALSE,
8410 EL_EMC_WALL_SLIPPERY_4, -1, -1
8413 Xdecor_1, TRUE, FALSE,
8414 EL_EMC_WALL_8, -1, -1
8417 Xdecor_2, TRUE, FALSE,
8418 EL_EMC_WALL_6, -1, -1
8421 Xdecor_3, TRUE, FALSE,
8422 EL_EMC_WALL_4, -1, -1
8425 Xdecor_4, TRUE, FALSE,
8426 EL_EMC_WALL_7, -1, -1
8429 Xdecor_5, TRUE, FALSE,
8430 EL_EMC_WALL_5, -1, -1
8433 Xdecor_6, TRUE, FALSE,
8434 EL_EMC_WALL_9, -1, -1
8437 Xdecor_7, TRUE, FALSE,
8438 EL_EMC_WALL_10, -1, -1
8441 Xdecor_8, TRUE, FALSE,
8442 EL_EMC_WALL_1, -1, -1
8445 Xdecor_9, TRUE, FALSE,
8446 EL_EMC_WALL_2, -1, -1
8449 Xdecor_10, TRUE, FALSE,
8450 EL_EMC_WALL_3, -1, -1
8453 Xdecor_11, TRUE, FALSE,
8454 EL_EMC_WALL_11, -1, -1
8457 Xdecor_12, TRUE, FALSE,
8458 EL_EMC_WALL_12, -1, -1
8461 Xalpha_0, TRUE, FALSE,
8462 EL_CHAR('0'), -1, -1
8465 Xalpha_1, TRUE, FALSE,
8466 EL_CHAR('1'), -1, -1
8469 Xalpha_2, TRUE, FALSE,
8470 EL_CHAR('2'), -1, -1
8473 Xalpha_3, TRUE, FALSE,
8474 EL_CHAR('3'), -1, -1
8477 Xalpha_4, TRUE, FALSE,
8478 EL_CHAR('4'), -1, -1
8481 Xalpha_5, TRUE, FALSE,
8482 EL_CHAR('5'), -1, -1
8485 Xalpha_6, TRUE, FALSE,
8486 EL_CHAR('6'), -1, -1
8489 Xalpha_7, TRUE, FALSE,
8490 EL_CHAR('7'), -1, -1
8493 Xalpha_8, TRUE, FALSE,
8494 EL_CHAR('8'), -1, -1
8497 Xalpha_9, TRUE, FALSE,
8498 EL_CHAR('9'), -1, -1
8501 Xalpha_excla, TRUE, FALSE,
8502 EL_CHAR('!'), -1, -1
8505 Xalpha_quote, TRUE, FALSE,
8506 EL_CHAR('"'), -1, -1
8509 Xalpha_comma, TRUE, FALSE,
8510 EL_CHAR(','), -1, -1
8513 Xalpha_minus, TRUE, FALSE,
8514 EL_CHAR('-'), -1, -1
8517 Xalpha_perio, TRUE, FALSE,
8518 EL_CHAR('.'), -1, -1
8521 Xalpha_colon, TRUE, FALSE,
8522 EL_CHAR(':'), -1, -1
8525 Xalpha_quest, TRUE, FALSE,
8526 EL_CHAR('?'), -1, -1
8529 Xalpha_a, TRUE, FALSE,
8530 EL_CHAR('A'), -1, -1
8533 Xalpha_b, TRUE, FALSE,
8534 EL_CHAR('B'), -1, -1
8537 Xalpha_c, TRUE, FALSE,
8538 EL_CHAR('C'), -1, -1
8541 Xalpha_d, TRUE, FALSE,
8542 EL_CHAR('D'), -1, -1
8545 Xalpha_e, TRUE, FALSE,
8546 EL_CHAR('E'), -1, -1
8549 Xalpha_f, TRUE, FALSE,
8550 EL_CHAR('F'), -1, -1
8553 Xalpha_g, TRUE, FALSE,
8554 EL_CHAR('G'), -1, -1
8557 Xalpha_h, TRUE, FALSE,
8558 EL_CHAR('H'), -1, -1
8561 Xalpha_i, TRUE, FALSE,
8562 EL_CHAR('I'), -1, -1
8565 Xalpha_j, TRUE, FALSE,
8566 EL_CHAR('J'), -1, -1
8569 Xalpha_k, TRUE, FALSE,
8570 EL_CHAR('K'), -1, -1
8573 Xalpha_l, TRUE, FALSE,
8574 EL_CHAR('L'), -1, -1
8577 Xalpha_m, TRUE, FALSE,
8578 EL_CHAR('M'), -1, -1
8581 Xalpha_n, TRUE, FALSE,
8582 EL_CHAR('N'), -1, -1
8585 Xalpha_o, TRUE, FALSE,
8586 EL_CHAR('O'), -1, -1
8589 Xalpha_p, TRUE, FALSE,
8590 EL_CHAR('P'), -1, -1
8593 Xalpha_q, TRUE, FALSE,
8594 EL_CHAR('Q'), -1, -1
8597 Xalpha_r, TRUE, FALSE,
8598 EL_CHAR('R'), -1, -1
8601 Xalpha_s, TRUE, FALSE,
8602 EL_CHAR('S'), -1, -1
8605 Xalpha_t, TRUE, FALSE,
8606 EL_CHAR('T'), -1, -1
8609 Xalpha_u, TRUE, FALSE,
8610 EL_CHAR('U'), -1, -1
8613 Xalpha_v, TRUE, FALSE,
8614 EL_CHAR('V'), -1, -1
8617 Xalpha_w, TRUE, FALSE,
8618 EL_CHAR('W'), -1, -1
8621 Xalpha_x, TRUE, FALSE,
8622 EL_CHAR('X'), -1, -1
8625 Xalpha_y, TRUE, FALSE,
8626 EL_CHAR('Y'), -1, -1
8629 Xalpha_z, TRUE, FALSE,
8630 EL_CHAR('Z'), -1, -1
8633 Xalpha_arrow_e, TRUE, FALSE,
8634 EL_CHAR('>'), -1, -1
8637 Xalpha_arrow_w, TRUE, FALSE,
8638 EL_CHAR('<'), -1, -1
8641 Xalpha_copyr, TRUE, FALSE,
8642 EL_CHAR('©'), -1, -1
8646 Xboom_bug, FALSE, FALSE,
8647 EL_BUG, ACTION_EXPLODING, -1
8650 Xboom_bomb, FALSE, FALSE,
8651 EL_BOMB, ACTION_EXPLODING, -1
8654 Xboom_android, FALSE, FALSE,
8655 EL_EMC_ANDROID, ACTION_OTHER, -1
8658 Xboom_1, FALSE, FALSE,
8659 EL_DEFAULT, ACTION_EXPLODING, -1
8662 Xboom_2, FALSE, FALSE,
8663 EL_DEFAULT, ACTION_EXPLODING, -1
8666 Znormal, FALSE, FALSE,
8670 Zdynamite, FALSE, FALSE,
8674 Zplayer, FALSE, FALSE,
8678 ZBORDER, FALSE, FALSE,
8688 static struct Mapping_EM_to_RND_player
8697 em_player_mapping_list[] =
8701 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
8705 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
8709 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
8713 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
8717 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
8721 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
8725 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
8729 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
8733 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
8737 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
8741 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
8745 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
8749 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
8753 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
8757 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
8761 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
8765 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
8769 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
8773 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
8777 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
8781 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
8785 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
8789 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
8793 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
8797 EL_PLAYER_1, ACTION_DEFAULT, -1,
8801 EL_PLAYER_2, ACTION_DEFAULT, -1,
8805 EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
8809 EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
8813 EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
8817 EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
8821 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
8825 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
8829 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
8833 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
8837 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
8841 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
8845 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
8849 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
8853 EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
8857 EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
8861 EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
8865 EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
8869 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
8873 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
8877 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
8881 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
8885 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
8889 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
8893 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
8897 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
8901 EL_PLAYER_3, ACTION_DEFAULT, -1,
8905 EL_PLAYER_4, ACTION_DEFAULT, -1,
8914 int map_element_RND_to_EM(int element_rnd)
8916 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
8917 static boolean mapping_initialized = FALSE;
8919 if (!mapping_initialized)
8923 /* return "Xalpha_quest" for all undefined elements in mapping array */
8924 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
8925 mapping_RND_to_EM[i] = Xalpha_quest;
8927 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
8928 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
8929 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
8930 em_object_mapping_list[i].element_em;
8932 mapping_initialized = TRUE;
8935 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
8936 return mapping_RND_to_EM[element_rnd];
8938 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
8943 int map_element_EM_to_RND(int element_em)
8945 static unsigned short mapping_EM_to_RND[TILE_MAX];
8946 static boolean mapping_initialized = FALSE;
8948 if (!mapping_initialized)
8952 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
8953 for (i = 0; i < TILE_MAX; i++)
8954 mapping_EM_to_RND[i] = EL_UNKNOWN;
8956 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
8957 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
8958 em_object_mapping_list[i].element_rnd;
8960 mapping_initialized = TRUE;
8963 if (element_em >= 0 && element_em < TILE_MAX)
8964 return mapping_EM_to_RND[element_em];
8966 Error(ERR_WARN, "invalid EM level element %d", element_em);
8971 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
8973 struct LevelInfo_EM *level_em = level->native_em_level;
8974 struct LEVEL *lev = level_em->lev;
8977 for (i = 0; i < TILE_MAX; i++)
8978 lev->android_array[i] = Xblank;
8980 for (i = 0; i < level->num_android_clone_elements; i++)
8982 int element_rnd = level->android_clone_element[i];
8983 int element_em = map_element_RND_to_EM(element_rnd);
8985 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
8986 if (em_object_mapping_list[j].element_rnd == element_rnd)
8987 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
8991 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
8993 struct LevelInfo_EM *level_em = level->native_em_level;
8994 struct LEVEL *lev = level_em->lev;
8997 level->num_android_clone_elements = 0;
8999 for (i = 0; i < TILE_MAX; i++)
9001 int element_em = lev->android_array[i];
9003 boolean element_found = FALSE;
9005 if (element_em == Xblank)
9008 element_rnd = map_element_EM_to_RND(element_em);
9010 for (j = 0; j < level->num_android_clone_elements; j++)
9011 if (level->android_clone_element[j] == element_rnd)
9012 element_found = TRUE;
9016 level->android_clone_element[level->num_android_clone_elements++] =
9019 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
9024 if (level->num_android_clone_elements == 0)
9026 level->num_android_clone_elements = 1;
9027 level->android_clone_element[0] = EL_EMPTY;
9031 int map_direction_RND_to_EM(int direction)
9033 return (direction == MV_UP ? 0 :
9034 direction == MV_RIGHT ? 1 :
9035 direction == MV_DOWN ? 2 :
9036 direction == MV_LEFT ? 3 :
9040 int map_direction_EM_to_RND(int direction)
9042 return (direction == 0 ? MV_UP :
9043 direction == 1 ? MV_RIGHT :
9044 direction == 2 ? MV_DOWN :
9045 direction == 3 ? MV_LEFT :
9049 int map_element_RND_to_SP(int element_rnd)
9051 int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
9053 if (element_rnd >= EL_SP_START &&
9054 element_rnd <= EL_SP_END)
9055 element_sp = element_rnd - EL_SP_START;
9056 else if (element_rnd == EL_EMPTY_SPACE)
9058 else if (element_rnd == EL_INVISIBLE_WALL)
9064 int map_element_SP_to_RND(int element_sp)
9066 int element_rnd = EL_UNKNOWN;
9068 if (element_sp >= 0x00 &&
9070 element_rnd = EL_SP_START + element_sp;
9071 else if (element_sp == 0x28)
9072 element_rnd = EL_INVISIBLE_WALL;
9077 int map_action_SP_to_RND(int action_sp)
9081 case actActive: return ACTION_ACTIVE;
9082 case actImpact: return ACTION_IMPACT;
9083 case actExploding: return ACTION_EXPLODING;
9084 case actDigging: return ACTION_DIGGING;
9085 case actSnapping: return ACTION_SNAPPING;
9086 case actCollecting: return ACTION_COLLECTING;
9087 case actPassing: return ACTION_PASSING;
9088 case actPushing: return ACTION_PUSHING;
9089 case actDropping: return ACTION_DROPPING;
9091 default: return ACTION_DEFAULT;
9095 int get_next_element(int element)
9099 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
9100 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
9101 case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL;
9102 case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY;
9103 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
9104 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
9105 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
9106 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
9107 case EL_DC_MAGIC_WALL_FILLING: return EL_DC_MAGIC_WALL_FULL;
9108 case EL_DC_MAGIC_WALL_EMPTYING: return EL_DC_MAGIC_WALL_ACTIVE;
9109 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
9111 default: return element;
9116 int el_act_dir2img(int element, int action, int direction)
9118 element = GFX_ELEMENT(element);
9120 if (direction == MV_NONE)
9121 return element_info[element].graphic[action];
9123 direction = MV_DIR_TO_BIT(direction);
9125 return element_info[element].direction_graphic[action][direction];
9128 int el_act_dir2img(int element, int action, int direction)
9130 element = GFX_ELEMENT(element);
9131 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
9133 /* direction_graphic[][] == graphic[] for undefined direction graphics */
9134 return element_info[element].direction_graphic[action][direction];
9139 static int el_act_dir2crm(int element, int action, int direction)
9141 element = GFX_ELEMENT(element);
9143 if (direction == MV_NONE)
9144 return element_info[element].crumbled[action];
9146 direction = MV_DIR_TO_BIT(direction);
9148 return element_info[element].direction_crumbled[action][direction];
9151 static int el_act_dir2crm(int element, int action, int direction)
9153 element = GFX_ELEMENT(element);
9154 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
9156 /* direction_graphic[][] == graphic[] for undefined direction graphics */
9157 return element_info[element].direction_crumbled[action][direction];
9161 int el_act2img(int element, int action)
9163 element = GFX_ELEMENT(element);
9165 return element_info[element].graphic[action];
9168 int el_act2crm(int element, int action)
9170 element = GFX_ELEMENT(element);
9172 return element_info[element].crumbled[action];
9175 int el_dir2img(int element, int direction)
9177 element = GFX_ELEMENT(element);
9179 return el_act_dir2img(element, ACTION_DEFAULT, direction);
9182 int el2baseimg(int element)
9184 return element_info[element].graphic[ACTION_DEFAULT];
9187 int el2img(int element)
9189 element = GFX_ELEMENT(element);
9191 return element_info[element].graphic[ACTION_DEFAULT];
9194 int el2edimg(int element)
9196 element = GFX_ELEMENT(element);
9198 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
9201 int el2preimg(int element)
9203 element = GFX_ELEMENT(element);
9205 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
9208 int el2panelimg(int element)
9210 element = GFX_ELEMENT(element);
9212 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PANEL];
9215 int font2baseimg(int font_nr)
9217 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
9220 int getBeltNrFromBeltElement(int element)
9222 return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 :
9223 element < EL_CONVEYOR_BELT_3_LEFT ? 1 :
9224 element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3);
9227 int getBeltNrFromBeltActiveElement(int element)
9229 return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 :
9230 element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 :
9231 element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3);
9234 int getBeltNrFromBeltSwitchElement(int element)
9236 return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 :
9237 element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 :
9238 element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3);
9241 int getBeltDirNrFromBeltElement(int element)
9243 static int belt_base_element[4] =
9245 EL_CONVEYOR_BELT_1_LEFT,
9246 EL_CONVEYOR_BELT_2_LEFT,
9247 EL_CONVEYOR_BELT_3_LEFT,
9248 EL_CONVEYOR_BELT_4_LEFT
9251 int belt_nr = getBeltNrFromBeltElement(element);
9252 int belt_dir_nr = element - belt_base_element[belt_nr];
9254 return (belt_dir_nr % 3);
9257 int getBeltDirNrFromBeltSwitchElement(int element)
9259 static int belt_base_element[4] =
9261 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
9262 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
9263 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
9264 EL_CONVEYOR_BELT_4_SWITCH_LEFT
9267 int belt_nr = getBeltNrFromBeltSwitchElement(element);
9268 int belt_dir_nr = element - belt_base_element[belt_nr];
9270 return (belt_dir_nr % 3);
9273 int getBeltDirFromBeltElement(int element)
9275 static int belt_move_dir[3] =
9282 int belt_dir_nr = getBeltDirNrFromBeltElement(element);
9284 return belt_move_dir[belt_dir_nr];
9287 int getBeltDirFromBeltSwitchElement(int element)
9289 static int belt_move_dir[3] =
9296 int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(element);
9298 return belt_move_dir[belt_dir_nr];
9301 int getBeltElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
9303 static int belt_base_element[4] =
9305 EL_CONVEYOR_BELT_1_LEFT,
9306 EL_CONVEYOR_BELT_2_LEFT,
9307 EL_CONVEYOR_BELT_3_LEFT,
9308 EL_CONVEYOR_BELT_4_LEFT
9311 return belt_base_element[belt_nr] + belt_dir_nr;
9314 int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
9316 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
9318 return getBeltElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
9321 int getBeltSwitchElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
9323 static int belt_base_element[4] =
9325 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
9326 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
9327 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
9328 EL_CONVEYOR_BELT_4_SWITCH_LEFT
9331 return belt_base_element[belt_nr] + belt_dir_nr;
9334 int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
9336 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
9338 return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
9342 boolean getTeamMode_EM()
9344 return game.team_mode;
9347 int getNumActivePlayers_EM()
9350 int num_players = 0;
9354 return (setup.team_mode ? MAX_PLAYERS : 1);
9356 for (i = 0; i < MAX_PLAYERS; i++)
9357 if (tape.player_participates[i])
9360 return (num_players > 1 ? MAX_PLAYERS : 1);
9364 int num_players = 0;
9367 /* when recording game, activate all connected players */
9371 for (i = 0; i < MAX_PLAYERS; i++)
9372 if (tape.player_participates[i])
9380 int getGameFrameDelay_EM(int native_em_game_frame_delay)
9382 int game_frame_delay_value;
9384 game_frame_delay_value =
9385 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
9386 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
9389 if (tape.playing && tape.warp_forward && !tape.pausing)
9390 game_frame_delay_value = 0;
9392 return game_frame_delay_value;
9395 unsigned int InitRND(int seed)
9397 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
9398 return InitEngineRandom_EM(seed);
9399 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
9400 return InitEngineRandom_SP(seed);
9402 return InitEngineRandom_RND(seed);
9406 static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
9407 static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
9410 inline static int get_effective_element_EM(int tile, int frame_em)
9412 int element = object_mapping[tile].element_rnd;
9413 int action = object_mapping[tile].action;
9414 boolean is_backside = object_mapping[tile].is_backside;
9415 boolean action_removing = (action == ACTION_DIGGING ||
9416 action == ACTION_SNAPPING ||
9417 action == ACTION_COLLECTING);
9423 case Yacid_splash_eB:
9424 case Yacid_splash_wB:
9425 return (frame_em > 5 ? EL_EMPTY : element);
9429 case Ydiamond_stone:
9430 // if (!game.use_native_emc_graphics_engine)
9438 else /* frame_em == 7 */
9442 case Yacid_splash_eB:
9443 case Yacid_splash_wB:
9446 case Yemerald_stone:
9449 case Ydiamond_stone:
9453 case Xdrip_stretchB:
9472 case Xsand_stonein_1:
9473 case Xsand_stonein_2:
9474 case Xsand_stonein_3:
9475 case Xsand_stonein_4:
9479 return (is_backside || action_removing ? EL_EMPTY : element);
9484 inline static boolean check_linear_animation_EM(int tile)
9488 case Xsand_stonesand_1:
9489 case Xsand_stonesand_quickout_1:
9490 case Xsand_sandstone_1:
9491 case Xsand_stonein_1:
9492 case Xsand_stoneout_1:
9512 case Yacid_splash_eB:
9513 case Yacid_splash_wB:
9514 case Yemerald_stone:
9522 inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
9523 boolean has_crumbled_graphics,
9524 int crumbled, int sync_frame)
9526 /* if element can be crumbled, but certain action graphics are just empty
9527 space (like instantly snapping sand to empty space in 1 frame), do not
9528 treat these empty space graphics as crumbled graphics in EMC engine */
9529 if (crumbled == IMG_EMPTY_SPACE)
9530 has_crumbled_graphics = FALSE;
9532 if (has_crumbled_graphics)
9534 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9535 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
9536 g_crumbled->anim_delay,
9537 g_crumbled->anim_mode,
9538 g_crumbled->anim_start_frame,
9541 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
9542 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
9544 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
9546 g_em->has_crumbled_graphics = TRUE;
9550 g_em->crumbled_bitmap = NULL;
9551 g_em->crumbled_src_x = 0;
9552 g_em->crumbled_src_y = 0;
9553 g_em->crumbled_border_size = 0;
9555 g_em->has_crumbled_graphics = FALSE;
9559 void ResetGfxAnimation_EM(int x, int y, int tile)
9564 void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
9565 int tile, int frame_em, int x, int y)
9567 int action = object_mapping[tile].action;
9569 int direction = object_mapping[tile].direction;
9570 int effective_element = get_effective_element_EM(tile, frame_em);
9571 int graphic = (direction == MV_NONE ?
9572 el_act2img(effective_element, action) :
9573 el_act_dir2img(effective_element, action, direction));
9574 struct GraphicInfo *g = &graphic_info[graphic];
9577 boolean action_removing = (action == ACTION_DIGGING ||
9578 action == ACTION_SNAPPING ||
9579 action == ACTION_COLLECTING);
9580 boolean action_moving = (action == ACTION_FALLING ||
9581 action == ACTION_MOVING ||
9582 action == ACTION_PUSHING ||
9583 action == ACTION_EATING ||
9584 action == ACTION_FILLING ||
9585 action == ACTION_EMPTYING);
9586 boolean action_falling = (action == ACTION_FALLING ||
9587 action == ACTION_FILLING ||
9588 action == ACTION_EMPTYING);
9590 /* special case: graphic uses "2nd movement tile" and has defined
9591 7 frames for movement animation (or less) => use default graphic
9592 for last (8th) frame which ends the movement animation */
9593 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9595 action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
9596 graphic = (direction == MV_NONE ?
9597 el_act2img(effective_element, action) :
9598 el_act_dir2img(effective_element, action, direction));
9600 g = &graphic_info[graphic];
9604 if (tile == Xsand_stonesand_1 ||
9605 tile == Xsand_stonesand_2 ||
9606 tile == Xsand_stonesand_3 ||
9607 tile == Xsand_stonesand_4)
9608 printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9612 if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
9616 // printf("::: resetting... [%d]\n", tile);
9619 if (action_removing || check_linear_animation_EM(tile))
9621 GfxFrame[x][y] = frame_em;
9623 // printf("::: resetting... [%d]\n", tile);
9626 else if (action_moving)
9628 boolean is_backside = object_mapping[tile].is_backside;
9632 int direction = object_mapping[tile].direction;
9633 int move_dir = (action_falling ? MV_DOWN : direction);
9638 /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
9639 if (g->double_movement && frame_em == 0)
9643 // printf("::: resetting... [%d]\n", tile);
9647 if (move_dir == MV_LEFT)
9648 GfxFrame[x - 1][y] = GfxFrame[x][y];
9649 else if (move_dir == MV_RIGHT)
9650 GfxFrame[x + 1][y] = GfxFrame[x][y];
9651 else if (move_dir == MV_UP)
9652 GfxFrame[x][y - 1] = GfxFrame[x][y];
9653 else if (move_dir == MV_DOWN)
9654 GfxFrame[x][y + 1] = GfxFrame[x][y];
9661 /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
9662 if (tile == Xsand_stonesand_quickout_1 ||
9663 tile == Xsand_stonesand_quickout_2)
9668 if (tile == Xsand_stonesand_1 ||
9669 tile == Xsand_stonesand_2 ||
9670 tile == Xsand_stonesand_3 ||
9671 tile == Xsand_stonesand_4)
9672 printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9676 if (graphic_info[graphic].anim_global_sync)
9677 sync_frame = FrameCounter;
9678 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9679 sync_frame = GfxFrame[x][y];
9681 sync_frame = 0; /* playfield border (pseudo steel) */
9683 SetRandomAnimationValue(x, y);
9685 int frame = getAnimationFrame(g->anim_frames,
9688 g->anim_start_frame,
9691 g_em->unique_identifier =
9692 (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
9696 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
9697 int tile, int frame_em, int x, int y)
9699 int action = object_mapping[tile].action;
9700 int direction = object_mapping[tile].direction;
9701 boolean is_backside = object_mapping[tile].is_backside;
9702 int effective_element = get_effective_element_EM(tile, frame_em);
9704 int effective_action = action;
9706 int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
9708 int graphic = (direction == MV_NONE ?
9709 el_act2img(effective_element, effective_action) :
9710 el_act_dir2img(effective_element, effective_action,
9712 int crumbled = (direction == MV_NONE ?
9713 el_act2crm(effective_element, effective_action) :
9714 el_act_dir2crm(effective_element, effective_action,
9716 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
9717 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
9718 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
9719 struct GraphicInfo *g = &graphic_info[graphic];
9721 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9725 /* special case: graphic uses "2nd movement tile" and has defined
9726 7 frames for movement animation (or less) => use default graphic
9727 for last (8th) frame which ends the movement animation */
9728 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9730 effective_action = ACTION_DEFAULT;
9731 graphic = (direction == MV_NONE ?
9732 el_act2img(effective_element, effective_action) :
9733 el_act_dir2img(effective_element, effective_action,
9735 crumbled = (direction == MV_NONE ?
9736 el_act2crm(effective_element, effective_action) :
9737 el_act_dir2crm(effective_element, effective_action,
9740 g = &graphic_info[graphic];
9750 if (frame_em == 0) /* reset animation frame for certain elements */
9752 if (check_linear_animation_EM(tile))
9757 if (graphic_info[graphic].anim_global_sync)
9758 sync_frame = FrameCounter;
9759 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9760 sync_frame = GfxFrame[x][y];
9762 sync_frame = 0; /* playfield border (pseudo steel) */
9764 SetRandomAnimationValue(x, y);
9769 int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
9770 i == Xdrip_stretchB ? 7 :
9771 i == Ydrip_s2 ? j + 8 :
9772 i == Ydrip_s2B ? j + 8 :
9781 i == Xfake_acid_1 ? 0 :
9782 i == Xfake_acid_2 ? 10 :
9783 i == Xfake_acid_3 ? 20 :
9784 i == Xfake_acid_4 ? 30 :
9785 i == Xfake_acid_5 ? 40 :
9786 i == Xfake_acid_6 ? 50 :
9787 i == Xfake_acid_7 ? 60 :
9788 i == Xfake_acid_8 ? 70 :
9790 i == Xball_2B ? j + 8 :
9791 i == Yball_eat ? j + 1 :
9792 i == Ykey_1_eat ? j + 1 :
9793 i == Ykey_2_eat ? j + 1 :
9794 i == Ykey_3_eat ? j + 1 :
9795 i == Ykey_4_eat ? j + 1 :
9796 i == Ykey_5_eat ? j + 1 :
9797 i == Ykey_6_eat ? j + 1 :
9798 i == Ykey_7_eat ? j + 1 :
9799 i == Ykey_8_eat ? j + 1 :
9800 i == Ylenses_eat ? j + 1 :
9801 i == Ymagnify_eat ? j + 1 :
9802 i == Ygrass_eat ? j + 1 :
9803 i == Ydirt_eat ? j + 1 :
9804 i == Xamoeba_1 ? 0 :
9805 i == Xamoeba_2 ? 1 :
9806 i == Xamoeba_3 ? 2 :
9807 i == Xamoeba_4 ? 3 :
9808 i == Xamoeba_5 ? 0 :
9809 i == Xamoeba_6 ? 1 :
9810 i == Xamoeba_7 ? 2 :
9811 i == Xamoeba_8 ? 3 :
9812 i == Xexit_2 ? j + 8 :
9813 i == Xexit_3 ? j + 16 :
9814 i == Xdynamite_1 ? 0 :
9815 i == Xdynamite_2 ? 8 :
9816 i == Xdynamite_3 ? 16 :
9817 i == Xdynamite_4 ? 24 :
9818 i == Xsand_stonein_1 ? j + 1 :
9819 i == Xsand_stonein_2 ? j + 9 :
9820 i == Xsand_stonein_3 ? j + 17 :
9821 i == Xsand_stonein_4 ? j + 25 :
9822 i == Xsand_stoneout_1 && j == 0 ? 0 :
9823 i == Xsand_stoneout_1 && j == 1 ? 0 :
9824 i == Xsand_stoneout_1 && j == 2 ? 1 :
9825 i == Xsand_stoneout_1 && j == 3 ? 2 :
9826 i == Xsand_stoneout_1 && j == 4 ? 2 :
9827 i == Xsand_stoneout_1 && j == 5 ? 3 :
9828 i == Xsand_stoneout_1 && j == 6 ? 4 :
9829 i == Xsand_stoneout_1 && j == 7 ? 4 :
9830 i == Xsand_stoneout_2 && j == 0 ? 5 :
9831 i == Xsand_stoneout_2 && j == 1 ? 6 :
9832 i == Xsand_stoneout_2 && j == 2 ? 7 :
9833 i == Xsand_stoneout_2 && j == 3 ? 8 :
9834 i == Xsand_stoneout_2 && j == 4 ? 9 :
9835 i == Xsand_stoneout_2 && j == 5 ? 11 :
9836 i == Xsand_stoneout_2 && j == 6 ? 13 :
9837 i == Xsand_stoneout_2 && j == 7 ? 15 :
9838 i == Xboom_bug && j == 1 ? 2 :
9839 i == Xboom_bug && j == 2 ? 2 :
9840 i == Xboom_bug && j == 3 ? 4 :
9841 i == Xboom_bug && j == 4 ? 4 :
9842 i == Xboom_bug && j == 5 ? 2 :
9843 i == Xboom_bug && j == 6 ? 2 :
9844 i == Xboom_bug && j == 7 ? 0 :
9845 i == Xboom_bomb && j == 1 ? 2 :
9846 i == Xboom_bomb && j == 2 ? 2 :
9847 i == Xboom_bomb && j == 3 ? 4 :
9848 i == Xboom_bomb && j == 4 ? 4 :
9849 i == Xboom_bomb && j == 5 ? 2 :
9850 i == Xboom_bomb && j == 6 ? 2 :
9851 i == Xboom_bomb && j == 7 ? 0 :
9852 i == Xboom_android && j == 7 ? 6 :
9853 i == Xboom_1 && j == 1 ? 2 :
9854 i == Xboom_1 && j == 2 ? 2 :
9855 i == Xboom_1 && j == 3 ? 4 :
9856 i == Xboom_1 && j == 4 ? 4 :
9857 i == Xboom_1 && j == 5 ? 6 :
9858 i == Xboom_1 && j == 6 ? 6 :
9859 i == Xboom_1 && j == 7 ? 8 :
9860 i == Xboom_2 && j == 0 ? 8 :
9861 i == Xboom_2 && j == 1 ? 8 :
9862 i == Xboom_2 && j == 2 ? 10 :
9863 i == Xboom_2 && j == 3 ? 10 :
9864 i == Xboom_2 && j == 4 ? 10 :
9865 i == Xboom_2 && j == 5 ? 12 :
9866 i == Xboom_2 && j == 6 ? 12 :
9867 i == Xboom_2 && j == 7 ? 12 :
9869 special_animation && j == 4 ? 3 :
9870 effective_action != action ? 0 :
9876 int xxx_effective_action;
9877 int xxx_has_action_graphics;
9880 int element = object_mapping[i].element_rnd;
9881 int action = object_mapping[i].action;
9882 int direction = object_mapping[i].direction;
9883 boolean is_backside = object_mapping[i].is_backside;
9885 boolean action_removing = (action == ACTION_DIGGING ||
9886 action == ACTION_SNAPPING ||
9887 action == ACTION_COLLECTING);
9889 boolean action_exploding = ((action == ACTION_EXPLODING ||
9890 action == ACTION_SMASHED_BY_ROCK ||
9891 action == ACTION_SMASHED_BY_SPRING) &&
9892 element != EL_DIAMOND);
9893 boolean action_active = (action == ACTION_ACTIVE);
9894 boolean action_other = (action == ACTION_OTHER);
9898 int effective_element = get_effective_element_EM(i, j);
9900 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
9901 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
9903 i == Xdrip_stretch ? element :
9904 i == Xdrip_stretchB ? element :
9905 i == Ydrip_s1 ? element :
9906 i == Ydrip_s1B ? element :
9907 i == Xball_1B ? element :
9908 i == Xball_2 ? element :
9909 i == Xball_2B ? element :
9910 i == Yball_eat ? element :
9911 i == Ykey_1_eat ? element :
9912 i == Ykey_2_eat ? element :
9913 i == Ykey_3_eat ? element :
9914 i == Ykey_4_eat ? element :
9915 i == Ykey_5_eat ? element :
9916 i == Ykey_6_eat ? element :
9917 i == Ykey_7_eat ? element :
9918 i == Ykey_8_eat ? element :
9919 i == Ylenses_eat ? element :
9920 i == Ymagnify_eat ? element :
9921 i == Ygrass_eat ? element :
9922 i == Ydirt_eat ? element :
9923 i == Yemerald_stone ? EL_EMERALD :
9924 i == Ydiamond_stone ? EL_ROCK :
9925 i == Xsand_stonein_1 ? element :
9926 i == Xsand_stonein_2 ? element :
9927 i == Xsand_stonein_3 ? element :
9928 i == Xsand_stonein_4 ? element :
9929 is_backside ? EL_EMPTY :
9930 action_removing ? EL_EMPTY :
9933 int effective_action = (j < 7 ? action :
9934 i == Xdrip_stretch ? action :
9935 i == Xdrip_stretchB ? action :
9936 i == Ydrip_s1 ? action :
9937 i == Ydrip_s1B ? action :
9938 i == Xball_1B ? action :
9939 i == Xball_2 ? action :
9940 i == Xball_2B ? action :
9941 i == Yball_eat ? action :
9942 i == Ykey_1_eat ? action :
9943 i == Ykey_2_eat ? action :
9944 i == Ykey_3_eat ? action :
9945 i == Ykey_4_eat ? action :
9946 i == Ykey_5_eat ? action :
9947 i == Ykey_6_eat ? action :
9948 i == Ykey_7_eat ? action :
9949 i == Ykey_8_eat ? action :
9950 i == Ylenses_eat ? action :
9951 i == Ymagnify_eat ? action :
9952 i == Ygrass_eat ? action :
9953 i == Ydirt_eat ? action :
9954 i == Xsand_stonein_1 ? action :
9955 i == Xsand_stonein_2 ? action :
9956 i == Xsand_stonein_3 ? action :
9957 i == Xsand_stonein_4 ? action :
9958 i == Xsand_stoneout_1 ? action :
9959 i == Xsand_stoneout_2 ? action :
9960 i == Xboom_android ? ACTION_EXPLODING :
9961 action_exploding ? ACTION_EXPLODING :
9962 action_active ? action :
9963 action_other ? action :
9965 int graphic = (el_act_dir2img(effective_element, effective_action,
9967 int crumbled = (el_act_dir2crm(effective_element, effective_action,
9969 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
9970 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
9971 boolean has_action_graphics = (graphic != base_graphic);
9972 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
9973 struct GraphicInfo *g = &graphic_info[graphic];
9975 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9977 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
9980 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
9981 boolean special_animation = (action != ACTION_DEFAULT &&
9982 g->anim_frames == 3 &&
9983 g->anim_delay == 2 &&
9984 g->anim_mode & ANIM_LINEAR);
9985 xxx_sync_frame = (i == Xdrip_stretch ? 7 :
9986 i == Xdrip_stretchB ? 7 :
9987 i == Ydrip_s2 ? j + 8 :
9988 i == Ydrip_s2B ? j + 8 :
9997 i == Xfake_acid_1 ? 0 :
9998 i == Xfake_acid_2 ? 10 :
9999 i == Xfake_acid_3 ? 20 :
10000 i == Xfake_acid_4 ? 30 :
10001 i == Xfake_acid_5 ? 40 :
10002 i == Xfake_acid_6 ? 50 :
10003 i == Xfake_acid_7 ? 60 :
10004 i == Xfake_acid_8 ? 70 :
10006 i == Xball_2B ? j + 8 :
10007 i == Yball_eat ? j + 1 :
10008 i == Ykey_1_eat ? j + 1 :
10009 i == Ykey_2_eat ? j + 1 :
10010 i == Ykey_3_eat ? j + 1 :
10011 i == Ykey_4_eat ? j + 1 :
10012 i == Ykey_5_eat ? j + 1 :
10013 i == Ykey_6_eat ? j + 1 :
10014 i == Ykey_7_eat ? j + 1 :
10015 i == Ykey_8_eat ? j + 1 :
10016 i == Ylenses_eat ? j + 1 :
10017 i == Ymagnify_eat ? j + 1 :
10018 i == Ygrass_eat ? j + 1 :
10019 i == Ydirt_eat ? j + 1 :
10020 i == Xamoeba_1 ? 0 :
10021 i == Xamoeba_2 ? 1 :
10022 i == Xamoeba_3 ? 2 :
10023 i == Xamoeba_4 ? 3 :
10024 i == Xamoeba_5 ? 0 :
10025 i == Xamoeba_6 ? 1 :
10026 i == Xamoeba_7 ? 2 :
10027 i == Xamoeba_8 ? 3 :
10028 i == Xexit_2 ? j + 8 :
10029 i == Xexit_3 ? j + 16 :
10030 i == Xdynamite_1 ? 0 :
10031 i == Xdynamite_2 ? 8 :
10032 i == Xdynamite_3 ? 16 :
10033 i == Xdynamite_4 ? 24 :
10034 i == Xsand_stonein_1 ? j + 1 :
10035 i == Xsand_stonein_2 ? j + 9 :
10036 i == Xsand_stonein_3 ? j + 17 :
10037 i == Xsand_stonein_4 ? j + 25 :
10038 i == Xsand_stoneout_1 && j == 0 ? 0 :
10039 i == Xsand_stoneout_1 && j == 1 ? 0 :
10040 i == Xsand_stoneout_1 && j == 2 ? 1 :
10041 i == Xsand_stoneout_1 && j == 3 ? 2 :
10042 i == Xsand_stoneout_1 && j == 4 ? 2 :
10043 i == Xsand_stoneout_1 && j == 5 ? 3 :
10044 i == Xsand_stoneout_1 && j == 6 ? 4 :
10045 i == Xsand_stoneout_1 && j == 7 ? 4 :
10046 i == Xsand_stoneout_2 && j == 0 ? 5 :
10047 i == Xsand_stoneout_2 && j == 1 ? 6 :
10048 i == Xsand_stoneout_2 && j == 2 ? 7 :
10049 i == Xsand_stoneout_2 && j == 3 ? 8 :
10050 i == Xsand_stoneout_2 && j == 4 ? 9 :
10051 i == Xsand_stoneout_2 && j == 5 ? 11 :
10052 i == Xsand_stoneout_2 && j == 6 ? 13 :
10053 i == Xsand_stoneout_2 && j == 7 ? 15 :
10054 i == Xboom_bug && j == 1 ? 2 :
10055 i == Xboom_bug && j == 2 ? 2 :
10056 i == Xboom_bug && j == 3 ? 4 :
10057 i == Xboom_bug && j == 4 ? 4 :
10058 i == Xboom_bug && j == 5 ? 2 :
10059 i == Xboom_bug && j == 6 ? 2 :
10060 i == Xboom_bug && j == 7 ? 0 :
10061 i == Xboom_bomb && j == 1 ? 2 :
10062 i == Xboom_bomb && j == 2 ? 2 :
10063 i == Xboom_bomb && j == 3 ? 4 :
10064 i == Xboom_bomb && j == 4 ? 4 :
10065 i == Xboom_bomb && j == 5 ? 2 :
10066 i == Xboom_bomb && j == 6 ? 2 :
10067 i == Xboom_bomb && j == 7 ? 0 :
10068 i == Xboom_android && j == 7 ? 6 :
10069 i == Xboom_1 && j == 1 ? 2 :
10070 i == Xboom_1 && j == 2 ? 2 :
10071 i == Xboom_1 && j == 3 ? 4 :
10072 i == Xboom_1 && j == 4 ? 4 :
10073 i == Xboom_1 && j == 5 ? 6 :
10074 i == Xboom_1 && j == 6 ? 6 :
10075 i == Xboom_1 && j == 7 ? 8 :
10076 i == Xboom_2 && j == 0 ? 8 :
10077 i == Xboom_2 && j == 1 ? 8 :
10078 i == Xboom_2 && j == 2 ? 10 :
10079 i == Xboom_2 && j == 3 ? 10 :
10080 i == Xboom_2 && j == 4 ? 10 :
10081 i == Xboom_2 && j == 5 ? 12 :
10082 i == Xboom_2 && j == 6 ? 12 :
10083 i == Xboom_2 && j == 7 ? 12 :
10084 special_animation && j == 4 ? 3 :
10085 effective_action != action ? 0 :
10088 xxx_effective_action = effective_action;
10089 xxx_has_action_graphics = has_action_graphics;
10094 int frame = getAnimationFrame(g->anim_frames,
10097 g->anim_start_frame,
10111 int old_src_x = g_em->src_x;
10112 int old_src_y = g_em->src_y;
10116 getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
10117 g->double_movement && is_backside);
10119 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
10120 &g_em->src_x, &g_em->src_y, FALSE);
10125 if (tile == Ydiamond_stone)
10126 printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n",
10131 g->anim_start_frame,
10134 g_em->src_x, g_em->src_y,
10135 g_em->src_offset_x, g_em->src_offset_y,
10136 g_em->dst_offset_x, g_em->dst_offset_y,
10148 if (graphic == IMG_BUG_MOVING_RIGHT)
10149 printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
10150 g->double_movement, is_backside,
10151 old_src_x, old_src_y, g_em->src_x, g_em->src_y);
10159 g_em->src_offset_x = 0;
10160 g_em->src_offset_y = 0;
10161 g_em->dst_offset_x = 0;
10162 g_em->dst_offset_y = 0;
10163 g_em->width = TILEX;
10164 g_em->height = TILEY;
10166 g_em->preserve_background = FALSE;
10169 /* (updating the "crumbled" graphic definitions is probably not really needed,
10170 as animations for crumbled graphics can't be longer than one EMC cycle) */
10172 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10177 g_em->crumbled_bitmap = NULL;
10178 g_em->crumbled_src_x = 0;
10179 g_em->crumbled_src_y = 0;
10181 g_em->has_crumbled_graphics = FALSE;
10183 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10185 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10186 g_crumbled->anim_delay,
10187 g_crumbled->anim_mode,
10188 g_crumbled->anim_start_frame,
10191 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
10192 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
10194 g_em->has_crumbled_graphics = TRUE;
10200 int effective_action = xxx_effective_action;
10201 int has_action_graphics = xxx_has_action_graphics;
10203 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10204 effective_action == ACTION_MOVING ||
10205 effective_action == ACTION_PUSHING ||
10206 effective_action == ACTION_EATING)) ||
10207 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10208 effective_action == ACTION_EMPTYING)))
10211 (effective_action == ACTION_FALLING ||
10212 effective_action == ACTION_FILLING ||
10213 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10214 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10215 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10216 int num_steps = (i == Ydrip_s1 ? 16 :
10217 i == Ydrip_s1B ? 16 :
10218 i == Ydrip_s2 ? 16 :
10219 i == Ydrip_s2B ? 16 :
10220 i == Xsand_stonein_1 ? 32 :
10221 i == Xsand_stonein_2 ? 32 :
10222 i == Xsand_stonein_3 ? 32 :
10223 i == Xsand_stonein_4 ? 32 :
10224 i == Xsand_stoneout_1 ? 16 :
10225 i == Xsand_stoneout_2 ? 16 : 8);
10226 int cx = ABS(dx) * (TILEX / num_steps);
10227 int cy = ABS(dy) * (TILEY / num_steps);
10228 int step_frame = (i == Ydrip_s2 ? j + 8 :
10229 i == Ydrip_s2B ? j + 8 :
10230 i == Xsand_stonein_2 ? j + 8 :
10231 i == Xsand_stonein_3 ? j + 16 :
10232 i == Xsand_stonein_4 ? j + 24 :
10233 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10234 int step = (is_backside ? step_frame : num_steps - step_frame);
10236 if (is_backside) /* tile where movement starts */
10238 if (dx < 0 || dy < 0)
10240 g_em->src_offset_x = cx * step;
10241 g_em->src_offset_y = cy * step;
10245 g_em->dst_offset_x = cx * step;
10246 g_em->dst_offset_y = cy * step;
10249 else /* tile where movement ends */
10251 if (dx < 0 || dy < 0)
10253 g_em->dst_offset_x = cx * step;
10254 g_em->dst_offset_y = cy * step;
10258 g_em->src_offset_x = cx * step;
10259 g_em->src_offset_y = cy * step;
10263 g_em->width = TILEX - cx * step;
10264 g_em->height = TILEY - cy * step;
10267 /* create unique graphic identifier to decide if tile must be redrawn */
10268 /* bit 31 - 16 (16 bit): EM style graphic
10269 bit 15 - 12 ( 4 bit): EM style frame
10270 bit 11 - 6 ( 6 bit): graphic width
10271 bit 5 - 0 ( 6 bit): graphic height */
10272 g_em->unique_identifier =
10273 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10279 void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
10280 int player_nr, int anim, int frame_em)
10282 int element = player_mapping[player_nr][anim].element_rnd;
10283 int action = player_mapping[player_nr][anim].action;
10284 int direction = player_mapping[player_nr][anim].direction;
10285 int graphic = (direction == MV_NONE ?
10286 el_act2img(element, action) :
10287 el_act_dir2img(element, action, direction));
10288 struct GraphicInfo *g = &graphic_info[graphic];
10291 InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
10293 stored_player[player_nr].StepFrame = frame_em;
10295 sync_frame = stored_player[player_nr].Frame;
10297 int frame = getAnimationFrame(g->anim_frames,
10300 g->anim_start_frame,
10303 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
10304 &g_em->src_x, &g_em->src_y, FALSE);
10307 printf("::: %d: %d, %d [%d]\n",
10309 stored_player[player_nr].Frame,
10310 stored_player[player_nr].StepFrame,
10315 void InitGraphicInfo_EM(void)
10318 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
10319 struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
10324 int num_em_gfx_errors = 0;
10326 if (graphic_info_em_object[0][0].bitmap == NULL)
10328 /* EM graphics not yet initialized in em_open_all() */
10333 printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
10336 /* always start with reliable default values */
10337 for (i = 0; i < TILE_MAX; i++)
10339 object_mapping[i].element_rnd = EL_UNKNOWN;
10340 object_mapping[i].is_backside = FALSE;
10341 object_mapping[i].action = ACTION_DEFAULT;
10342 object_mapping[i].direction = MV_NONE;
10345 /* always start with reliable default values */
10346 for (p = 0; p < MAX_PLAYERS; p++)
10348 for (i = 0; i < SPR_MAX; i++)
10350 player_mapping[p][i].element_rnd = EL_UNKNOWN;
10351 player_mapping[p][i].action = ACTION_DEFAULT;
10352 player_mapping[p][i].direction = MV_NONE;
10356 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
10358 int e = em_object_mapping_list[i].element_em;
10360 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
10361 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
10363 if (em_object_mapping_list[i].action != -1)
10364 object_mapping[e].action = em_object_mapping_list[i].action;
10366 if (em_object_mapping_list[i].direction != -1)
10367 object_mapping[e].direction =
10368 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
10371 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
10373 int a = em_player_mapping_list[i].action_em;
10374 int p = em_player_mapping_list[i].player_nr;
10376 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
10378 if (em_player_mapping_list[i].action != -1)
10379 player_mapping[p][a].action = em_player_mapping_list[i].action;
10381 if (em_player_mapping_list[i].direction != -1)
10382 player_mapping[p][a].direction =
10383 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
10386 for (i = 0; i < TILE_MAX; i++)
10388 int element = object_mapping[i].element_rnd;
10389 int action = object_mapping[i].action;
10390 int direction = object_mapping[i].direction;
10391 boolean is_backside = object_mapping[i].is_backside;
10393 boolean action_removing = (action == ACTION_DIGGING ||
10394 action == ACTION_SNAPPING ||
10395 action == ACTION_COLLECTING);
10397 boolean action_exploding = ((action == ACTION_EXPLODING ||
10398 action == ACTION_SMASHED_BY_ROCK ||
10399 action == ACTION_SMASHED_BY_SPRING) &&
10400 element != EL_DIAMOND);
10401 boolean action_active = (action == ACTION_ACTIVE);
10402 boolean action_other = (action == ACTION_OTHER);
10404 for (j = 0; j < 8; j++)
10407 int effective_element = get_effective_element_EM(i, j);
10409 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
10410 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
10412 i == Xdrip_stretch ? element :
10413 i == Xdrip_stretchB ? element :
10414 i == Ydrip_s1 ? element :
10415 i == Ydrip_s1B ? element :
10416 i == Xball_1B ? element :
10417 i == Xball_2 ? element :
10418 i == Xball_2B ? element :
10419 i == Yball_eat ? element :
10420 i == Ykey_1_eat ? element :
10421 i == Ykey_2_eat ? element :
10422 i == Ykey_3_eat ? element :
10423 i == Ykey_4_eat ? element :
10424 i == Ykey_5_eat ? element :
10425 i == Ykey_6_eat ? element :
10426 i == Ykey_7_eat ? element :
10427 i == Ykey_8_eat ? element :
10428 i == Ylenses_eat ? element :
10429 i == Ymagnify_eat ? element :
10430 i == Ygrass_eat ? element :
10431 i == Ydirt_eat ? element :
10432 i == Yemerald_stone ? EL_EMERALD :
10433 i == Ydiamond_stone ? EL_ROCK :
10434 i == Xsand_stonein_1 ? element :
10435 i == Xsand_stonein_2 ? element :
10436 i == Xsand_stonein_3 ? element :
10437 i == Xsand_stonein_4 ? element :
10438 is_backside ? EL_EMPTY :
10439 action_removing ? EL_EMPTY :
10442 int effective_action = (j < 7 ? action :
10443 i == Xdrip_stretch ? action :
10444 i == Xdrip_stretchB ? action :
10445 i == Ydrip_s1 ? action :
10446 i == Ydrip_s1B ? action :
10447 i == Xball_1B ? action :
10448 i == Xball_2 ? action :
10449 i == Xball_2B ? action :
10450 i == Yball_eat ? action :
10451 i == Ykey_1_eat ? action :
10452 i == Ykey_2_eat ? action :
10453 i == Ykey_3_eat ? action :
10454 i == Ykey_4_eat ? action :
10455 i == Ykey_5_eat ? action :
10456 i == Ykey_6_eat ? action :
10457 i == Ykey_7_eat ? action :
10458 i == Ykey_8_eat ? action :
10459 i == Ylenses_eat ? action :
10460 i == Ymagnify_eat ? action :
10461 i == Ygrass_eat ? action :
10462 i == Ydirt_eat ? action :
10463 i == Xsand_stonein_1 ? action :
10464 i == Xsand_stonein_2 ? action :
10465 i == Xsand_stonein_3 ? action :
10466 i == Xsand_stonein_4 ? action :
10467 i == Xsand_stoneout_1 ? action :
10468 i == Xsand_stoneout_2 ? action :
10469 i == Xboom_android ? ACTION_EXPLODING :
10470 action_exploding ? ACTION_EXPLODING :
10471 action_active ? action :
10472 action_other ? action :
10474 int graphic = (el_act_dir2img(effective_element, effective_action,
10476 int crumbled = (el_act_dir2crm(effective_element, effective_action,
10478 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
10479 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
10480 boolean has_action_graphics = (graphic != base_graphic);
10481 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
10482 struct GraphicInfo *g = &graphic_info[graphic];
10484 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
10486 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10487 Bitmap *src_bitmap;
10489 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
10490 boolean special_animation = (action != ACTION_DEFAULT &&
10491 g->anim_frames == 3 &&
10492 g->anim_delay == 2 &&
10493 g->anim_mode & ANIM_LINEAR);
10494 int sync_frame = (i == Xdrip_stretch ? 7 :
10495 i == Xdrip_stretchB ? 7 :
10496 i == Ydrip_s2 ? j + 8 :
10497 i == Ydrip_s2B ? j + 8 :
10499 i == Xacid_2 ? 10 :
10500 i == Xacid_3 ? 20 :
10501 i == Xacid_4 ? 30 :
10502 i == Xacid_5 ? 40 :
10503 i == Xacid_6 ? 50 :
10504 i == Xacid_7 ? 60 :
10505 i == Xacid_8 ? 70 :
10506 i == Xfake_acid_1 ? 0 :
10507 i == Xfake_acid_2 ? 10 :
10508 i == Xfake_acid_3 ? 20 :
10509 i == Xfake_acid_4 ? 30 :
10510 i == Xfake_acid_5 ? 40 :
10511 i == Xfake_acid_6 ? 50 :
10512 i == Xfake_acid_7 ? 60 :
10513 i == Xfake_acid_8 ? 70 :
10515 i == Xball_2B ? j + 8 :
10516 i == Yball_eat ? j + 1 :
10517 i == Ykey_1_eat ? j + 1 :
10518 i == Ykey_2_eat ? j + 1 :
10519 i == Ykey_3_eat ? j + 1 :
10520 i == Ykey_4_eat ? j + 1 :
10521 i == Ykey_5_eat ? j + 1 :
10522 i == Ykey_6_eat ? j + 1 :
10523 i == Ykey_7_eat ? j + 1 :
10524 i == Ykey_8_eat ? j + 1 :
10525 i == Ylenses_eat ? j + 1 :
10526 i == Ymagnify_eat ? j + 1 :
10527 i == Ygrass_eat ? j + 1 :
10528 i == Ydirt_eat ? j + 1 :
10529 i == Xamoeba_1 ? 0 :
10530 i == Xamoeba_2 ? 1 :
10531 i == Xamoeba_3 ? 2 :
10532 i == Xamoeba_4 ? 3 :
10533 i == Xamoeba_5 ? 0 :
10534 i == Xamoeba_6 ? 1 :
10535 i == Xamoeba_7 ? 2 :
10536 i == Xamoeba_8 ? 3 :
10537 i == Xexit_2 ? j + 8 :
10538 i == Xexit_3 ? j + 16 :
10539 i == Xdynamite_1 ? 0 :
10540 i == Xdynamite_2 ? 8 :
10541 i == Xdynamite_3 ? 16 :
10542 i == Xdynamite_4 ? 24 :
10543 i == Xsand_stonein_1 ? j + 1 :
10544 i == Xsand_stonein_2 ? j + 9 :
10545 i == Xsand_stonein_3 ? j + 17 :
10546 i == Xsand_stonein_4 ? j + 25 :
10547 i == Xsand_stoneout_1 && j == 0 ? 0 :
10548 i == Xsand_stoneout_1 && j == 1 ? 0 :
10549 i == Xsand_stoneout_1 && j == 2 ? 1 :
10550 i == Xsand_stoneout_1 && j == 3 ? 2 :
10551 i == Xsand_stoneout_1 && j == 4 ? 2 :
10552 i == Xsand_stoneout_1 && j == 5 ? 3 :
10553 i == Xsand_stoneout_1 && j == 6 ? 4 :
10554 i == Xsand_stoneout_1 && j == 7 ? 4 :
10555 i == Xsand_stoneout_2 && j == 0 ? 5 :
10556 i == Xsand_stoneout_2 && j == 1 ? 6 :
10557 i == Xsand_stoneout_2 && j == 2 ? 7 :
10558 i == Xsand_stoneout_2 && j == 3 ? 8 :
10559 i == Xsand_stoneout_2 && j == 4 ? 9 :
10560 i == Xsand_stoneout_2 && j == 5 ? 11 :
10561 i == Xsand_stoneout_2 && j == 6 ? 13 :
10562 i == Xsand_stoneout_2 && j == 7 ? 15 :
10563 i == Xboom_bug && j == 1 ? 2 :
10564 i == Xboom_bug && j == 2 ? 2 :
10565 i == Xboom_bug && j == 3 ? 4 :
10566 i == Xboom_bug && j == 4 ? 4 :
10567 i == Xboom_bug && j == 5 ? 2 :
10568 i == Xboom_bug && j == 6 ? 2 :
10569 i == Xboom_bug && j == 7 ? 0 :
10570 i == Xboom_bomb && j == 1 ? 2 :
10571 i == Xboom_bomb && j == 2 ? 2 :
10572 i == Xboom_bomb && j == 3 ? 4 :
10573 i == Xboom_bomb && j == 4 ? 4 :
10574 i == Xboom_bomb && j == 5 ? 2 :
10575 i == Xboom_bomb && j == 6 ? 2 :
10576 i == Xboom_bomb && j == 7 ? 0 :
10577 i == Xboom_android && j == 7 ? 6 :
10578 i == Xboom_1 && j == 1 ? 2 :
10579 i == Xboom_1 && j == 2 ? 2 :
10580 i == Xboom_1 && j == 3 ? 4 :
10581 i == Xboom_1 && j == 4 ? 4 :
10582 i == Xboom_1 && j == 5 ? 6 :
10583 i == Xboom_1 && j == 6 ? 6 :
10584 i == Xboom_1 && j == 7 ? 8 :
10585 i == Xboom_2 && j == 0 ? 8 :
10586 i == Xboom_2 && j == 1 ? 8 :
10587 i == Xboom_2 && j == 2 ? 10 :
10588 i == Xboom_2 && j == 3 ? 10 :
10589 i == Xboom_2 && j == 4 ? 10 :
10590 i == Xboom_2 && j == 5 ? 12 :
10591 i == Xboom_2 && j == 6 ? 12 :
10592 i == Xboom_2 && j == 7 ? 12 :
10593 special_animation && j == 4 ? 3 :
10594 effective_action != action ? 0 :
10598 Bitmap *debug_bitmap = g_em->bitmap;
10599 int debug_src_x = g_em->src_x;
10600 int debug_src_y = g_em->src_y;
10603 int frame = getAnimationFrame(g->anim_frames,
10606 g->anim_start_frame,
10609 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
10610 g->double_movement && is_backside);
10612 g_em->bitmap = src_bitmap;
10613 g_em->src_x = src_x;
10614 g_em->src_y = src_y;
10615 g_em->src_offset_x = 0;
10616 g_em->src_offset_y = 0;
10617 g_em->dst_offset_x = 0;
10618 g_em->dst_offset_y = 0;
10619 g_em->width = TILEX;
10620 g_em->height = TILEY;
10622 g_em->preserve_background = FALSE;
10625 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10630 g_em->crumbled_bitmap = NULL;
10631 g_em->crumbled_src_x = 0;
10632 g_em->crumbled_src_y = 0;
10633 g_em->crumbled_border_size = 0;
10635 g_em->has_crumbled_graphics = FALSE;
10638 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
10639 printf("::: empty crumbled: %d [%s], %d, %d\n",
10640 effective_element, element_info[effective_element].token_name,
10641 effective_action, direction);
10644 /* if element can be crumbled, but certain action graphics are just empty
10645 space (like instantly snapping sand to empty space in 1 frame), do not
10646 treat these empty space graphics as crumbled graphics in EMC engine */
10647 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10649 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10650 g_crumbled->anim_delay,
10651 g_crumbled->anim_mode,
10652 g_crumbled->anim_start_frame,
10655 getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
10657 g_em->has_crumbled_graphics = TRUE;
10658 g_em->crumbled_bitmap = src_bitmap;
10659 g_em->crumbled_src_x = src_x;
10660 g_em->crumbled_src_y = src_y;
10661 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
10665 if (g_em == &graphic_info_em_object[207][0])
10666 printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
10667 graphic_info_em_object[207][0].crumbled_src_x,
10668 graphic_info_em_object[207][0].crumbled_src_y,
10670 crumbled, frame, src_x, src_y,
10675 g->anim_start_frame,
10677 gfx.anim_random_frame,
10682 printf("::: EMC tile %d is crumbled\n", i);
10688 if (element == EL_ROCK &&
10689 effective_action == ACTION_FILLING)
10690 printf("::: has_action_graphics == %d\n", has_action_graphics);
10693 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10694 effective_action == ACTION_MOVING ||
10695 effective_action == ACTION_PUSHING ||
10696 effective_action == ACTION_EATING)) ||
10697 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10698 effective_action == ACTION_EMPTYING)))
10701 (effective_action == ACTION_FALLING ||
10702 effective_action == ACTION_FILLING ||
10703 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10704 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10705 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10706 int num_steps = (i == Ydrip_s1 ? 16 :
10707 i == Ydrip_s1B ? 16 :
10708 i == Ydrip_s2 ? 16 :
10709 i == Ydrip_s2B ? 16 :
10710 i == Xsand_stonein_1 ? 32 :
10711 i == Xsand_stonein_2 ? 32 :
10712 i == Xsand_stonein_3 ? 32 :
10713 i == Xsand_stonein_4 ? 32 :
10714 i == Xsand_stoneout_1 ? 16 :
10715 i == Xsand_stoneout_2 ? 16 : 8);
10716 int cx = ABS(dx) * (TILEX / num_steps);
10717 int cy = ABS(dy) * (TILEY / num_steps);
10718 int step_frame = (i == Ydrip_s2 ? j + 8 :
10719 i == Ydrip_s2B ? j + 8 :
10720 i == Xsand_stonein_2 ? j + 8 :
10721 i == Xsand_stonein_3 ? j + 16 :
10722 i == Xsand_stonein_4 ? j + 24 :
10723 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10724 int step = (is_backside ? step_frame : num_steps - step_frame);
10726 if (is_backside) /* tile where movement starts */
10728 if (dx < 0 || dy < 0)
10730 g_em->src_offset_x = cx * step;
10731 g_em->src_offset_y = cy * step;
10735 g_em->dst_offset_x = cx * step;
10736 g_em->dst_offset_y = cy * step;
10739 else /* tile where movement ends */
10741 if (dx < 0 || dy < 0)
10743 g_em->dst_offset_x = cx * step;
10744 g_em->dst_offset_y = cy * step;
10748 g_em->src_offset_x = cx * step;
10749 g_em->src_offset_y = cy * step;
10753 g_em->width = TILEX - cx * step;
10754 g_em->height = TILEY - cy * step;
10757 /* create unique graphic identifier to decide if tile must be redrawn */
10758 /* bit 31 - 16 (16 bit): EM style graphic
10759 bit 15 - 12 ( 4 bit): EM style frame
10760 bit 11 - 6 ( 6 bit): graphic width
10761 bit 5 - 0 ( 6 bit): graphic height */
10762 g_em->unique_identifier =
10763 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10767 /* skip check for EMC elements not contained in original EMC artwork */
10768 if (element == EL_EMC_FAKE_ACID)
10771 if (g_em->bitmap != debug_bitmap ||
10772 g_em->src_x != debug_src_x ||
10773 g_em->src_y != debug_src_y ||
10774 g_em->src_offset_x != 0 ||
10775 g_em->src_offset_y != 0 ||
10776 g_em->dst_offset_x != 0 ||
10777 g_em->dst_offset_y != 0 ||
10778 g_em->width != TILEX ||
10779 g_em->height != TILEY)
10781 static int last_i = -1;
10789 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
10790 i, element, element_info[element].token_name,
10791 element_action_info[effective_action].suffix, direction);
10793 if (element != effective_element)
10794 printf(" [%d ('%s')]",
10796 element_info[effective_element].token_name);
10800 if (g_em->bitmap != debug_bitmap)
10801 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
10802 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
10804 if (g_em->src_x != debug_src_x ||
10805 g_em->src_y != debug_src_y)
10806 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
10807 j, (is_backside ? 'B' : 'F'),
10808 g_em->src_x, g_em->src_y,
10809 g_em->src_x / 32, g_em->src_y / 32,
10810 debug_src_x, debug_src_y,
10811 debug_src_x / 32, debug_src_y / 32);
10813 if (g_em->src_offset_x != 0 ||
10814 g_em->src_offset_y != 0 ||
10815 g_em->dst_offset_x != 0 ||
10816 g_em->dst_offset_y != 0)
10817 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
10819 g_em->src_offset_x, g_em->src_offset_y,
10820 g_em->dst_offset_x, g_em->dst_offset_y);
10822 if (g_em->width != TILEX ||
10823 g_em->height != TILEY)
10824 printf(" %d (%d): size %d,%d should be %d,%d\n",
10826 g_em->width, g_em->height, TILEX, TILEY);
10828 num_em_gfx_errors++;
10835 for (i = 0; i < TILE_MAX; i++)
10837 for (j = 0; j < 8; j++)
10839 int element = object_mapping[i].element_rnd;
10840 int action = object_mapping[i].action;
10841 int direction = object_mapping[i].direction;
10842 boolean is_backside = object_mapping[i].is_backside;
10843 int graphic_action = el_act_dir2img(element, action, direction);
10844 int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
10846 if ((action == ACTION_SMASHED_BY_ROCK ||
10847 action == ACTION_SMASHED_BY_SPRING ||
10848 action == ACTION_EATING) &&
10849 graphic_action == graphic_default)
10851 int e = (action == ACTION_SMASHED_BY_ROCK ? Ystone_s :
10852 action == ACTION_SMASHED_BY_SPRING ? Yspring_s :
10853 direction == MV_LEFT ? (is_backside? Yspring_wB: Yspring_w) :
10854 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
10857 /* no separate animation for "smashed by rock" -- use rock instead */
10858 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10859 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
10861 g_em->bitmap = g_xx->bitmap;
10862 g_em->src_x = g_xx->src_x;
10863 g_em->src_y = g_xx->src_y;
10864 g_em->src_offset_x = g_xx->src_offset_x;
10865 g_em->src_offset_y = g_xx->src_offset_y;
10866 g_em->dst_offset_x = g_xx->dst_offset_x;
10867 g_em->dst_offset_y = g_xx->dst_offset_y;
10868 g_em->width = g_xx->width;
10869 g_em->height = g_xx->height;
10870 g_em->unique_identifier = g_xx->unique_identifier;
10873 g_em->preserve_background = TRUE;
10878 for (p = 0; p < MAX_PLAYERS; p++)
10880 for (i = 0; i < SPR_MAX; i++)
10882 int element = player_mapping[p][i].element_rnd;
10883 int action = player_mapping[p][i].action;
10884 int direction = player_mapping[p][i].direction;
10886 for (j = 0; j < 8; j++)
10888 int effective_element = element;
10889 int effective_action = action;
10890 int graphic = (direction == MV_NONE ?
10891 el_act2img(effective_element, effective_action) :
10892 el_act_dir2img(effective_element, effective_action,
10894 struct GraphicInfo *g = &graphic_info[graphic];
10895 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
10896 Bitmap *src_bitmap;
10898 int sync_frame = j;
10901 Bitmap *debug_bitmap = g_em->bitmap;
10902 int debug_src_x = g_em->src_x;
10903 int debug_src_y = g_em->src_y;
10906 int frame = getAnimationFrame(g->anim_frames,
10909 g->anim_start_frame,
10912 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
10914 g_em->bitmap = src_bitmap;
10915 g_em->src_x = src_x;
10916 g_em->src_y = src_y;
10917 g_em->src_offset_x = 0;
10918 g_em->src_offset_y = 0;
10919 g_em->dst_offset_x = 0;
10920 g_em->dst_offset_y = 0;
10921 g_em->width = TILEX;
10922 g_em->height = TILEY;
10926 /* skip check for EMC elements not contained in original EMC artwork */
10927 if (element == EL_PLAYER_3 ||
10928 element == EL_PLAYER_4)
10931 if (g_em->bitmap != debug_bitmap ||
10932 g_em->src_x != debug_src_x ||
10933 g_em->src_y != debug_src_y)
10935 static int last_i = -1;
10943 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
10944 p, i, element, element_info[element].token_name,
10945 element_action_info[effective_action].suffix, direction);
10947 if (element != effective_element)
10948 printf(" [%d ('%s')]",
10950 element_info[effective_element].token_name);
10954 if (g_em->bitmap != debug_bitmap)
10955 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
10956 j, (int)(g_em->bitmap), (int)(debug_bitmap));
10958 if (g_em->src_x != debug_src_x ||
10959 g_em->src_y != debug_src_y)
10960 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
10962 g_em->src_x, g_em->src_y,
10963 g_em->src_x / 32, g_em->src_y / 32,
10964 debug_src_x, debug_src_y,
10965 debug_src_x / 32, debug_src_y / 32);
10967 num_em_gfx_errors++;
10977 printf("::: [%d errors found]\n", num_em_gfx_errors);
10983 void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
10984 boolean any_player_moving,
10985 boolean player_is_dropping)
10987 if (tape.single_step && tape.recording && !tape.pausing)
10990 boolean active_players = FALSE;
10993 for (i = 0; i < MAX_PLAYERS; i++)
10994 if (action[i] != JOY_NO_ACTION)
10995 active_players = TRUE;
10999 if (frame == 0 && !player_is_dropping)
11000 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
11004 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
11005 boolean murphy_is_dropping)
11008 printf("::: waiting: %d, dropping: %d\n",
11009 murphy_is_waiting, murphy_is_dropping);
11012 if (tape.single_step && tape.recording && !tape.pausing)
11014 // if (murphy_is_waiting || murphy_is_dropping)
11015 if (murphy_is_waiting)
11018 printf("::: murphy is waiting -> pause mode\n");
11021 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
11026 void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
11027 int graphic, int sync_frame, int x, int y)
11029 int frame = getGraphicAnimationFrame(graphic, sync_frame);
11031 getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
11034 boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
11036 return (IS_NEXT_FRAME(sync_frame, graphic));
11039 int getGraphicInfo_Delay(int graphic)
11041 return graphic_info[graphic].anim_delay;
11044 void PlayMenuSoundExt(int sound)
11046 if (sound == SND_UNDEFINED)
11049 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11050 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11053 if (IS_LOOP_SOUND(sound))
11054 PlaySoundLoop(sound);
11059 void PlayMenuSound()
11061 PlayMenuSoundExt(menu.sound[game_status]);
11064 void PlayMenuSoundStereo(int sound, int stereo_position)
11066 if (sound == SND_UNDEFINED)
11069 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11070 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11073 if (IS_LOOP_SOUND(sound))
11074 PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP);
11076 PlaySoundStereo(sound, stereo_position);
11079 void PlayMenuSoundIfLoopExt(int sound)
11081 if (sound == SND_UNDEFINED)
11084 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11085 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11088 if (IS_LOOP_SOUND(sound))
11089 PlaySoundLoop(sound);
11092 void PlayMenuSoundIfLoop()
11094 PlayMenuSoundIfLoopExt(menu.sound[game_status]);
11097 void PlayMenuMusicExt(int music)
11099 if (music == MUS_UNDEFINED)
11102 if (!setup.sound_music)
11108 void PlayMenuMusic()
11110 PlayMenuMusicExt(menu.music[game_status]);
11113 void PlaySoundActivating()
11116 PlaySound(SND_MENU_ITEM_ACTIVATING);
11120 void PlaySoundSelecting()
11123 PlaySound(SND_MENU_ITEM_SELECTING);
11127 void ToggleFullscreenOrChangeWindowScalingIfNeeded()
11129 boolean change_fullscreen = (setup.fullscreen !=
11130 video.fullscreen_enabled);
11131 boolean change_fullscreen_mode = (video.fullscreen_enabled &&
11132 !strEqual(setup.fullscreen_mode,
11133 video.fullscreen_mode_current));
11134 boolean change_window_scaling_percent = (!video.fullscreen_enabled &&
11135 setup.window_scaling_percent !=
11136 video.window_scaling_percent);
11138 if (change_window_scaling_percent && video.fullscreen_enabled)
11141 if (!change_window_scaling_percent && !video.fullscreen_available)
11144 #if defined(TARGET_SDL2)
11145 if (change_window_scaling_percent)
11147 SDLSetWindowScaling(setup.window_scaling_percent);
11151 else if (change_fullscreen)
11153 SDLSetWindowFullscreen(setup.fullscreen);
11155 /* set setup value according to successfully changed fullscreen mode */
11156 setup.fullscreen = video.fullscreen_enabled;
11162 if (change_fullscreen ||
11163 change_fullscreen_mode ||
11164 change_window_scaling_percent)
11166 Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
11168 /* save backbuffer content which gets lost when toggling fullscreen mode */
11169 BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11171 if (change_fullscreen_mode)
11173 /* keep fullscreen, but change fullscreen mode (screen resolution) */
11174 video.fullscreen_enabled = FALSE; /* force new fullscreen mode */
11177 if (change_window_scaling_percent)
11179 /* keep window mode, but change window scaling */
11180 video.fullscreen_enabled = TRUE; /* force new window scaling */
11183 /* toggle fullscreen */
11184 ChangeVideoModeIfNeeded(setup.fullscreen);
11186 /* set setup value according to successfully changed fullscreen mode */
11187 setup.fullscreen = video.fullscreen_enabled;
11189 /* restore backbuffer content from temporary backbuffer backup bitmap */
11190 BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11192 FreeBitmap(tmp_backbuffer);
11195 /* update visible window/screen */
11196 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11198 redraw_mask = REDRAW_ALL;
11203 void ChangeViewportPropertiesIfNeeded()
11206 int *door_1_x = &DX;
11207 int *door_1_y = &DY;
11208 int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
11209 int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
11211 int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
11212 game_status == GAME_MODE_EDITOR ? game_status :
11214 int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
11216 struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
11217 struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
11218 struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode2];
11219 struct RectWithBorder *vp_door_3 = &viewport.door_2[GAME_MODE_EDITOR];
11220 int border_size = vp_playfield->border_size;
11221 int new_sx = vp_playfield->x + border_size;
11222 int new_sy = vp_playfield->y + border_size;
11223 int new_sxsize = vp_playfield->width - 2 * border_size;
11224 int new_sysize = vp_playfield->height - 2 * border_size;
11225 int new_real_sx = vp_playfield->x;
11226 int new_real_sy = vp_playfield->y;
11227 int new_full_sxsize = vp_playfield->width;
11228 int new_full_sysize = vp_playfield->height;
11229 int new_dx = vp_door_1->x;
11230 int new_dy = vp_door_1->y;
11231 int new_dxsize = vp_door_1->width;
11232 int new_dysize = vp_door_1->height;
11233 int new_vx = vp_door_2->x;
11234 int new_vy = vp_door_2->y;
11235 int new_vxsize = vp_door_2->width;
11236 int new_vysize = vp_door_2->height;
11237 int new_ex = vp_door_3->x;
11238 int new_ey = vp_door_3->y;
11239 int new_exsize = vp_door_3->width;
11240 int new_eysize = vp_door_3->height;
11242 int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
11243 int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
11244 gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
11245 int new_scr_fieldx = new_sxsize / tilesize;
11246 int new_scr_fieldy = new_sysize / tilesize;
11247 int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var;
11248 int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
11250 int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE;
11251 int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE;
11253 boolean init_gfx_buffers = FALSE;
11254 boolean init_video_buffer = FALSE;
11255 boolean init_gadgets_and_toons = FALSE;
11258 /* !!! TEST ONLY !!! */
11259 // InitGfxBuffers();
11263 if (viewport.window.width != WIN_XSIZE ||
11264 viewport.window.height != WIN_YSIZE)
11266 WIN_XSIZE = viewport.window.width;
11267 WIN_YSIZE = viewport.window.height;
11270 init_video_buffer = TRUE;
11271 init_gfx_buffers = TRUE;
11273 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
11277 SetDrawDeactivationMask(REDRAW_NONE);
11278 SetDrawBackgroundMask(REDRAW_FIELD);
11280 // RedrawBackground();
11284 // printf("::: video: init_video_buffer, init_gfx_buffers\n");
11287 if (new_scr_fieldx != SCR_FIELDX ||
11288 new_scr_fieldy != SCR_FIELDY)
11290 /* this always toggles between MAIN and GAME when using small tile size */
11292 SCR_FIELDX = new_scr_fieldx;
11293 SCR_FIELDY = new_scr_fieldy;
11295 // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
11299 if (new_tilesize_var != TILESIZE_VAR &&
11300 gfx_game_mode == GAME_MODE_PLAYING)
11302 /* doing this outside GAME_MODE_PLAYING would give wrong playfield size */
11304 TILESIZE_VAR = new_tilesize_var;
11306 init_gfx_buffers = TRUE;
11308 // printf("::: tilesize: init_gfx_buffers\n");
11312 if (new_sx != SX ||
11320 new_sxsize != SXSIZE ||
11321 new_sysize != SYSIZE ||
11322 new_dxsize != DXSIZE ||
11323 new_dysize != DYSIZE ||
11324 new_vxsize != VXSIZE ||
11325 new_vysize != VYSIZE ||
11326 new_exsize != EXSIZE ||
11327 new_eysize != EYSIZE ||
11328 new_real_sx != REAL_SX ||
11329 new_real_sy != REAL_SY ||
11330 new_full_sxsize != FULL_SXSIZE ||
11331 new_full_sysize != FULL_SYSIZE ||
11332 new_tilesize_var != TILESIZE_VAR
11335 vp_door_1->x != *door_1_x ||
11336 vp_door_1->y != *door_1_y ||
11337 vp_door_2->x != *door_2_x ||
11338 vp_door_2->y != *door_2_y
11350 SXSIZE = new_sxsize;
11351 SYSIZE = new_sysize;
11352 DXSIZE = new_dxsize;
11353 DYSIZE = new_dysize;
11354 VXSIZE = new_vxsize;
11355 VYSIZE = new_vysize;
11356 EXSIZE = new_exsize;
11357 EYSIZE = new_eysize;
11358 REAL_SX = new_real_sx;
11359 REAL_SY = new_real_sy;
11360 FULL_SXSIZE = new_full_sxsize;
11361 FULL_SYSIZE = new_full_sysize;
11362 TILESIZE_VAR = new_tilesize_var;
11365 printf("::: %d, %d, %d [%d]\n",
11366 SCR_FIELDX, SCR_FIELDY, TILESIZE_VAR,
11367 setup.small_game_graphics);
11371 *door_1_x = vp_door_1->x;
11372 *door_1_y = vp_door_1->y;
11373 *door_2_x = vp_door_2->x;
11374 *door_2_y = vp_door_2->y;
11378 init_gfx_buffers = TRUE;
11380 // printf("::: viewports: init_gfx_buffers\n");
11386 if (gfx_game_mode == GAME_MODE_MAIN)
11390 init_gadgets_and_toons = TRUE;
11392 // printf("::: viewports: init_gadgets_and_toons\n");
11400 if (init_gfx_buffers)
11402 // printf("::: init_gfx_buffers\n");
11404 SCR_FIELDX = new_scr_fieldx_buffers;
11405 SCR_FIELDY = new_scr_fieldy_buffers;
11409 SCR_FIELDX = new_scr_fieldx;
11410 SCR_FIELDY = new_scr_fieldy;
11413 if (init_video_buffer)
11415 // printf("::: init_video_buffer\n");
11417 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
11419 SetDrawDeactivationMask(REDRAW_NONE);
11420 SetDrawBackgroundMask(REDRAW_FIELD);
11423 if (init_gadgets_and_toons)
11425 // printf("::: init_gadgets_and_toons\n");
11432 printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status);