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 real_preview_width = real_preview_xsize * tile_size;
3421 int real_preview_height = real_preview_ysize * tile_size;
3422 int dst_x = SX + ALIGNED_XPOS(preview.x, preview_width, preview.align);
3423 int dst_y = SY + ALIGNED_YPOS(preview.y, preview_height, preview.valign);
3427 if (!IN_GFX_FIELD_FULL(dst_x, dst_y + preview_height - 1))
3432 dst_x += (preview_width - real_preview_width) / 2;
3433 dst_y += (preview_height - real_preview_height) / 2;
3435 DrawBackground(dst_x, dst_y, real_preview_width, real_preview_height);
3437 DrawBackground(dst_x, dst_y, preview_width, preview_height);
3439 dst_x += (preview_width - real_preview_width) / 2;
3440 dst_y += (preview_height - real_preview_height) / 2;
3443 for (x = 0; x < real_preview_xsize; x++)
3445 for (y = 0; y < real_preview_ysize; y++)
3447 int lx = from_x + x + (show_level_border ? -1 : 0);
3448 int ly = from_y + y + (show_level_border ? -1 : 0);
3449 int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] :
3450 getBorderElement(lx, ly));
3452 DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size,
3453 element, tile_size);
3457 redraw_mask |= REDRAW_MICROLEVEL;
3460 #define MICROLABEL_EMPTY 0
3461 #define MICROLABEL_LEVEL_NAME 1
3462 #define MICROLABEL_LEVEL_AUTHOR_HEAD 2
3463 #define MICROLABEL_LEVEL_AUTHOR 3
3464 #define MICROLABEL_IMPORTED_FROM_HEAD 4
3465 #define MICROLABEL_IMPORTED_FROM 5
3466 #define MICROLABEL_IMPORTED_BY_HEAD 6
3467 #define MICROLABEL_IMPORTED_BY 7
3469 static int getMaxTextLength(struct TextPosInfo *pos, int font_nr)
3471 int max_text_width = SXSIZE;
3472 int font_width = getFontWidth(font_nr);
3474 if (pos->align == ALIGN_CENTER)
3475 max_text_width = (pos->x < SXSIZE / 2 ? pos->x * 2 : (SXSIZE - pos->x) * 2);
3476 else if (pos->align == ALIGN_RIGHT)
3477 max_text_width = pos->x;
3479 max_text_width = SXSIZE - pos->x;
3481 return max_text_width / font_width;
3484 static void DrawPreviewLevelLabelExt(int mode)
3486 struct TextPosInfo *pos = &menu.main.text.level_info_2;
3487 char label_text[MAX_OUTPUT_LINESIZE + 1];
3488 int max_len_label_text;
3490 int font_nr = pos->font;
3493 if (!IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
3496 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3497 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3498 mode == MICROLABEL_IMPORTED_BY_HEAD)
3499 font_nr = pos->font_alt;
3501 int font_nr = FONT_TEXT_2;
3504 if (mode == MICROLABEL_LEVEL_AUTHOR_HEAD ||
3505 mode == MICROLABEL_IMPORTED_FROM_HEAD ||
3506 mode == MICROLABEL_IMPORTED_BY_HEAD)
3507 font_nr = FONT_TEXT_3;
3511 max_len_label_text = getMaxTextLength(pos, font_nr);
3513 max_len_label_text = SXSIZE / getFontWidth(font_nr);
3517 if (pos->size != -1)
3518 max_len_label_text = pos->size;
3521 for (i = 0; i < max_len_label_text; i++)
3522 label_text[i] = ' ';
3523 label_text[max_len_label_text] = '\0';
3525 if (strlen(label_text) > 0)
3528 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3530 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3531 int lypos = MICROLABEL2_YPOS;
3533 DrawText(lxpos, lypos, label_text, font_nr);
3538 (mode == MICROLABEL_LEVEL_NAME ? level.name :
3539 mode == MICROLABEL_LEVEL_AUTHOR_HEAD ? "created by" :
3540 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
3541 mode == MICROLABEL_IMPORTED_FROM_HEAD ? "imported from" :
3542 mode == MICROLABEL_IMPORTED_FROM ? leveldir_current->imported_from :
3543 mode == MICROLABEL_IMPORTED_BY_HEAD ? "imported by" :
3544 mode == MICROLABEL_IMPORTED_BY ? leveldir_current->imported_by :""),
3545 max_len_label_text);
3546 label_text[max_len_label_text] = '\0';
3548 if (strlen(label_text) > 0)
3551 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3553 int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3554 int lypos = MICROLABEL2_YPOS;
3556 DrawText(lxpos, lypos, label_text, font_nr);
3560 redraw_mask |= REDRAW_MICROLEVEL;
3563 static void DrawPreviewLevelExt(boolean restart)
3565 static unsigned int scroll_delay = 0;
3566 static unsigned int label_delay = 0;
3567 static int from_x, from_y, scroll_direction;
3568 static int label_state, label_counter;
3569 unsigned int scroll_delay_value = preview.step_delay;
3570 boolean show_level_border = (BorderElement != EL_EMPTY);
3571 int level_xsize = lev_fieldx + (show_level_border ? 2 : 0);
3572 int level_ysize = lev_fieldy + (show_level_border ? 2 : 0);
3573 int last_game_status = game_status; /* save current game status */
3576 /* force PREVIEW font on preview level */
3577 game_status = GAME_MODE_PSEUDO_PREVIEW;
3585 if (preview.anim_mode == ANIM_CENTERED)
3587 if (level_xsize > preview.xsize)
3588 from_x = (level_xsize - preview.xsize) / 2;
3589 if (level_ysize > preview.ysize)
3590 from_y = (level_ysize - preview.ysize) / 2;
3593 from_x += preview.xoffset;
3594 from_y += preview.yoffset;
3596 scroll_direction = MV_RIGHT;
3600 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3601 DrawPreviewLevelLabelExt(label_state);
3603 /* initialize delay counters */
3604 DelayReached(&scroll_delay, 0);
3605 DelayReached(&label_delay, 0);
3607 if (leveldir_current->name)
3609 struct TextPosInfo *pos = &menu.main.text.level_info_1;
3610 char label_text[MAX_OUTPUT_LINESIZE + 1];
3612 int font_nr = pos->font;
3614 int font_nr = FONT_TEXT_1;
3617 int max_len_label_text = getMaxTextLength(pos, font_nr);
3619 int max_len_label_text = SXSIZE / getFontWidth(font_nr);
3627 if (pos->size != -1)
3628 max_len_label_text = pos->size;
3631 strncpy(label_text, leveldir_current->name, max_len_label_text);
3632 label_text[max_len_label_text] = '\0';
3635 if (IN_GFX_FIELD_FULL(pos->x, pos->y + getFontHeight(pos->font)))
3636 DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align);
3638 lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
3639 lypos = SY + MICROLABEL1_YPOS;
3641 DrawText(lxpos, lypos, label_text, font_nr);
3645 game_status = last_game_status; /* restore current game status */
3650 /* scroll preview level, if needed */
3651 if (preview.anim_mode != ANIM_NONE &&
3652 (level_xsize > preview.xsize || level_ysize > preview.ysize) &&
3653 DelayReached(&scroll_delay, scroll_delay_value))
3655 switch (scroll_direction)
3660 from_x -= preview.step_offset;
3661 from_x = (from_x < 0 ? 0 : from_x);
3664 scroll_direction = MV_UP;
3668 if (from_x < level_xsize - preview.xsize)
3670 from_x += preview.step_offset;
3671 from_x = (from_x > level_xsize - preview.xsize ?
3672 level_xsize - preview.xsize : from_x);
3675 scroll_direction = MV_DOWN;
3681 from_y -= preview.step_offset;
3682 from_y = (from_y < 0 ? 0 : from_y);
3685 scroll_direction = MV_RIGHT;
3689 if (from_y < level_ysize - preview.ysize)
3691 from_y += preview.step_offset;
3692 from_y = (from_y > level_ysize - preview.ysize ?
3693 level_ysize - preview.ysize : from_y);
3696 scroll_direction = MV_LEFT;
3703 DrawPreviewLevelPlayfieldExt(from_x, from_y);
3706 /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */
3707 /* redraw micro level label, if needed */
3708 if (!strEqual(level.name, NAMELESS_LEVEL_NAME) &&
3709 !strEqual(level.author, ANONYMOUS_NAME) &&
3710 !strEqual(level.author, leveldir_current->name) &&
3711 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
3713 int max_label_counter = 23;
3715 if (leveldir_current->imported_from != NULL &&
3716 strlen(leveldir_current->imported_from) > 0)
3717 max_label_counter += 14;
3718 if (leveldir_current->imported_by != NULL &&
3719 strlen(leveldir_current->imported_by) > 0)
3720 max_label_counter += 14;
3722 label_counter = (label_counter + 1) % max_label_counter;
3723 label_state = (label_counter >= 0 && label_counter <= 7 ?
3724 MICROLABEL_LEVEL_NAME :
3725 label_counter >= 9 && label_counter <= 12 ?
3726 MICROLABEL_LEVEL_AUTHOR_HEAD :
3727 label_counter >= 14 && label_counter <= 21 ?
3728 MICROLABEL_LEVEL_AUTHOR :
3729 label_counter >= 23 && label_counter <= 26 ?
3730 MICROLABEL_IMPORTED_FROM_HEAD :
3731 label_counter >= 28 && label_counter <= 35 ?
3732 MICROLABEL_IMPORTED_FROM :
3733 label_counter >= 37 && label_counter <= 40 ?
3734 MICROLABEL_IMPORTED_BY_HEAD :
3735 label_counter >= 42 && label_counter <= 49 ?
3736 MICROLABEL_IMPORTED_BY : MICROLABEL_EMPTY);
3738 if (leveldir_current->imported_from == NULL &&
3739 (label_state == MICROLABEL_IMPORTED_FROM_HEAD ||
3740 label_state == MICROLABEL_IMPORTED_FROM))
3741 label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ?
3742 MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY);
3744 DrawPreviewLevelLabelExt(label_state);
3747 game_status = last_game_status; /* restore current game status */
3750 void DrawPreviewLevelInitial()
3752 DrawPreviewLevelExt(TRUE);
3755 void DrawPreviewLevelAnimation()
3757 DrawPreviewLevelExt(FALSE);
3760 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3761 int graphic, int sync_frame, int mask_mode)
3763 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3765 if (mask_mode == USE_MASKING)
3766 DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3768 DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
3771 inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
3772 int graphic, int sync_frame,
3775 int frame = getGraphicAnimationFrame(graphic, sync_frame);
3777 if (mask_mode == USE_MASKING)
3778 DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
3780 DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame);
3783 inline void DrawGraphicAnimation(int x, int y, int graphic)
3785 int lx = LEVELX(x), ly = LEVELY(y);
3787 if (!IN_SCR_FIELD(x, y))
3791 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
3792 graphic, GfxFrame[lx][ly], NO_MASKING);
3794 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3795 graphic, GfxFrame[lx][ly], NO_MASKING);
3797 MarkTileDirty(x, y);
3800 inline void DrawFixedGraphicAnimation(int x, int y, int graphic)
3802 int lx = LEVELX(x), ly = LEVELY(y);
3804 if (!IN_SCR_FIELD(x, y))
3807 DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
3808 graphic, GfxFrame[lx][ly], NO_MASKING);
3809 MarkTileDirty(x, y);
3812 void DrawLevelGraphicAnimation(int x, int y, int graphic)
3814 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3817 void DrawLevelElementAnimation(int x, int y, int element)
3819 int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3821 DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
3824 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
3826 int sx = SCREENX(x), sy = SCREENY(y);
3828 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3831 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3834 DrawGraphicAnimation(sx, sy, graphic);
3837 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
3838 DrawLevelFieldCrumbled(x, y);
3840 if (GFX_CRUMBLED(Feld[x][y]))
3841 DrawLevelFieldCrumbled(x, y);
3845 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
3847 int sx = SCREENX(x), sy = SCREENY(y);
3850 if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
3853 graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
3855 if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
3858 DrawGraphicAnimation(sx, sy, graphic);
3860 if (GFX_CRUMBLED(element))
3861 DrawLevelFieldCrumbled(x, y);
3864 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
3866 if (player->use_murphy)
3868 /* this works only because currently only one player can be "murphy" ... */
3869 static int last_horizontal_dir = MV_LEFT;
3870 int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
3872 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
3873 last_horizontal_dir = move_dir;
3875 if (graphic == IMG_SP_MURPHY) /* undefined => use special graphic */
3877 int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
3879 graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
3885 return el_act_dir2img(player->artwork_element, player->GfxAction,move_dir);
3888 static boolean equalGraphics(int graphic1, int graphic2)
3890 struct GraphicInfo *g1 = &graphic_info[graphic1];
3891 struct GraphicInfo *g2 = &graphic_info[graphic2];
3893 return (g1->bitmap == g2->bitmap &&
3894 g1->src_x == g2->src_x &&
3895 g1->src_y == g2->src_y &&
3896 g1->anim_frames == g2->anim_frames &&
3897 g1->anim_delay == g2->anim_delay &&
3898 g1->anim_mode == g2->anim_mode);
3901 void DrawAllPlayers()
3905 for (i = 0; i < MAX_PLAYERS; i++)
3906 if (stored_player[i].active)
3907 DrawPlayer(&stored_player[i]);
3910 void DrawPlayerField(int x, int y)
3912 if (!IS_PLAYER(x, y))
3915 DrawPlayer(PLAYERINFO(x, y));
3918 #define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1
3920 void DrawPlayer(struct PlayerInfo *player)
3922 int jx = player->jx;
3923 int jy = player->jy;
3924 int move_dir = player->MovDir;
3925 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
3926 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? +1 : 0);
3927 int last_jx = (player->is_moving ? jx - dx : jx);
3928 int last_jy = (player->is_moving ? jy - dy : jy);
3929 int next_jx = jx + dx;
3930 int next_jy = jy + dy;
3931 boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
3932 boolean player_is_opaque = FALSE;
3933 int sx = SCREENX(jx), sy = SCREENY(jy);
3934 int sxx = 0, syy = 0;
3935 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
3937 int action = ACTION_DEFAULT;
3938 int last_player_graphic = getPlayerGraphic(player, move_dir);
3939 int last_player_frame = player->Frame;
3942 /* GfxElement[][] is set to the element the player is digging or collecting;
3943 remove also for off-screen player if the player is not moving anymore */
3944 if (IN_LEV_FIELD(jx, jy) && !player_is_moving)
3945 GfxElement[jx][jy] = EL_UNDEFINED;
3947 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
3951 if (!IN_LEV_FIELD(jx, jy))
3953 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
3954 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
3955 printf("DrawPlayerField(): This should never happen!\n");
3960 if (element == EL_EXPLOSION)
3963 action = (player->is_pushing ? ACTION_PUSHING :
3964 player->is_digging ? ACTION_DIGGING :
3965 player->is_collecting ? ACTION_COLLECTING :
3966 player->is_moving ? ACTION_MOVING :
3967 player->is_snapping ? ACTION_SNAPPING :
3968 player->is_dropping ? ACTION_DROPPING :
3969 player->is_waiting ? player->action_waiting : ACTION_DEFAULT);
3971 if (player->is_waiting)
3972 move_dir = player->dir_waiting;
3974 InitPlayerGfxAnimation(player, action, move_dir);
3976 /* ----------------------------------------------------------------------- */
3977 /* draw things in the field the player is leaving, if needed */
3978 /* ----------------------------------------------------------------------- */
3980 if (player->is_moving)
3982 if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
3984 DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
3986 if (last_element == EL_DYNAMITE_ACTIVE ||
3987 last_element == EL_EM_DYNAMITE_ACTIVE ||
3988 last_element == EL_SP_DISK_RED_ACTIVE)
3989 DrawDynamite(last_jx, last_jy);
3991 DrawLevelFieldThruMask(last_jx, last_jy);
3993 else if (last_element == EL_DYNAMITE_ACTIVE ||
3994 last_element == EL_EM_DYNAMITE_ACTIVE ||
3995 last_element == EL_SP_DISK_RED_ACTIVE)
3996 DrawDynamite(last_jx, last_jy);
3998 /* !!! this is not enough to prevent flickering of players which are
3999 moving next to each others without a free tile between them -- this
4000 can only be solved by drawing all players layer by layer (first the
4001 background, then the foreground etc.) !!! => TODO */
4002 else if (!IS_PLAYER(last_jx, last_jy))
4003 DrawLevelField(last_jx, last_jy);
4006 DrawLevelField(last_jx, last_jy);
4009 if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
4010 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4013 if (!IN_SCR_FIELD(sx, sy))
4016 /* ----------------------------------------------------------------------- */
4017 /* draw things behind the player, if needed */
4018 /* ----------------------------------------------------------------------- */
4021 DrawLevelElement(jx, jy, Back[jx][jy]);
4022 else if (IS_ACTIVE_BOMB(element))
4023 DrawLevelElement(jx, jy, EL_EMPTY);
4026 if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
4028 int old_element = GfxElement[jx][jy];
4029 int old_graphic = el_act_dir2img(old_element, action, move_dir);
4030 int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
4032 if (GFX_CRUMBLED(old_element))
4033 DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
4035 DrawGraphic(sx, sy, old_graphic, frame);
4037 if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
4038 player_is_opaque = TRUE;
4042 GfxElement[jx][jy] = EL_UNDEFINED;
4044 /* make sure that pushed elements are drawn with correct frame rate */
4046 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4048 if (player->is_pushing && player->is_moving && !IS_ANIM_MODE_CE(graphic))
4049 GfxFrame[jx][jy] = player->StepFrame;
4051 if (player->is_pushing && player->is_moving)
4052 GfxFrame[jx][jy] = player->StepFrame;
4055 DrawLevelField(jx, jy);
4059 #if !DRAW_PLAYER_OVER_PUSHED_ELEMENT
4060 /* ----------------------------------------------------------------------- */
4061 /* draw player himself */
4062 /* ----------------------------------------------------------------------- */
4064 graphic = getPlayerGraphic(player, move_dir);
4066 /* in the case of changed player action or direction, prevent the current
4067 animation frame from being restarted for identical animations */
4068 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4069 player->Frame = last_player_frame;
4071 frame = getGraphicAnimationFrame(graphic, player->Frame);
4075 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4076 sxx = player->GfxPos;
4078 syy = player->GfxPos;
4081 if (!setup.soft_scrolling && ScreenMovPos)
4084 if (player_is_opaque)
4085 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4087 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4089 if (SHIELD_ON(player))
4091 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4092 IMG_SHIELD_NORMAL_ACTIVE);
4093 int frame = getGraphicAnimationFrame(graphic, -1);
4095 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4099 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4102 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4103 sxx = player->GfxPos;
4105 syy = player->GfxPos;
4109 /* ----------------------------------------------------------------------- */
4110 /* draw things the player is pushing, if needed */
4111 /* ----------------------------------------------------------------------- */
4114 printf("::: %d, %d [%d, %d] [%d]\n",
4115 player->is_pushing, player_is_moving, player->GfxAction,
4116 player->is_moving, player_is_moving);
4120 if (player->is_pushing && player->is_moving)
4122 int px = SCREENX(jx), py = SCREENY(jy);
4123 int pxx = (TILEX - ABS(sxx)) * dx;
4124 int pyy = (TILEY - ABS(syy)) * dy;
4125 int gfx_frame = GfxFrame[jx][jy];
4131 if (!IS_MOVING(jx, jy)) /* push movement already finished */
4133 element = Feld[next_jx][next_jy];
4134 gfx_frame = GfxFrame[next_jx][next_jy];
4137 graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
4140 sync_frame = (IS_ANIM_MODE_CE(graphic) ? gfx_frame : player->StepFrame);
4141 frame = getGraphicAnimationFrame(graphic, sync_frame);
4143 frame = getGraphicAnimationFrame(graphic, player->StepFrame);
4146 /* draw background element under pushed element (like the Sokoban field) */
4148 if (game.use_masked_pushing && IS_MOVING(jx, jy))
4150 /* this allows transparent pushing animation over non-black background */
4153 DrawLevelElement(jx, jy, Back[jx][jy]);
4155 DrawLevelElement(jx, jy, EL_EMPTY);
4157 if (Back[next_jx][next_jy])
4158 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4160 DrawLevelElement(next_jx, next_jy, EL_EMPTY);
4162 else if (Back[next_jx][next_jy])
4163 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4165 if (Back[next_jx][next_jy])
4166 DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
4170 printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n",
4171 jx, px, player->GfxPos, player->StepFrame,
4176 GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]);
4180 /* do not draw (EM style) pushing animation when pushing is finished */
4181 /* (two-tile animations usually do not contain start and end frame) */
4182 if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
4183 DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
4185 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4187 /* masked drawing is needed for EMC style (double) movement graphics */
4188 /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */
4189 DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
4194 #if DRAW_PLAYER_OVER_PUSHED_ELEMENT
4195 /* ----------------------------------------------------------------------- */
4196 /* draw player himself */
4197 /* ----------------------------------------------------------------------- */
4199 graphic = getPlayerGraphic(player, move_dir);
4201 /* in the case of changed player action or direction, prevent the current
4202 animation frame from being restarted for identical animations */
4203 if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
4204 player->Frame = last_player_frame;
4206 frame = getGraphicAnimationFrame(graphic, player->Frame);
4210 if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
4211 sxx = player->GfxPos;
4213 syy = player->GfxPos;
4216 if (!setup.soft_scrolling && ScreenMovPos)
4219 if (player_is_opaque)
4220 DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING);
4222 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4224 if (SHIELD_ON(player))
4226 int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
4227 IMG_SHIELD_NORMAL_ACTIVE);
4228 int frame = getGraphicAnimationFrame(graphic, -1);
4230 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
4234 /* ----------------------------------------------------------------------- */
4235 /* draw things in front of player (active dynamite or dynabombs) */
4236 /* ----------------------------------------------------------------------- */
4238 if (IS_ACTIVE_BOMB(element))
4240 graphic = el2img(element);
4241 frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
4243 if (game.emulation == EMU_SUPAPLEX)
4244 DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
4246 DrawGraphicThruMask(sx, sy, graphic, frame);
4249 if (player_is_moving && last_element == EL_EXPLOSION)
4251 int element = (GfxElement[last_jx][last_jy] != EL_UNDEFINED ?
4252 GfxElement[last_jx][last_jy] : EL_EMPTY);
4253 int graphic = el_act2img(element, ACTION_EXPLODING);
4254 int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
4255 int phase = ExplodePhase[last_jx][last_jy] - 1;
4256 int frame = getGraphicAnimationFrame(graphic, phase - delay);
4259 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
4262 /* ----------------------------------------------------------------------- */
4263 /* draw elements the player is just walking/passing through/under */
4264 /* ----------------------------------------------------------------------- */
4266 if (player_is_moving)
4268 /* handle the field the player is leaving ... */
4269 if (IS_ACCESSIBLE_INSIDE(last_element))
4270 DrawLevelField(last_jx, last_jy);
4271 else if (IS_ACCESSIBLE_UNDER(last_element))
4272 DrawLevelFieldThruMask(last_jx, last_jy);
4275 /* do not redraw accessible elements if the player is just pushing them */
4276 if (!player_is_moving || !player->is_pushing)
4278 /* ... and the field the player is entering */
4279 if (IS_ACCESSIBLE_INSIDE(element))
4280 DrawLevelField(jx, jy);
4281 else if (IS_ACCESSIBLE_UNDER(element))
4282 DrawLevelFieldThruMask(jx, jy);
4285 MarkTileDirty(sx, sy);
4288 /* ------------------------------------------------------------------------- */
4290 void WaitForEventToContinue()
4292 boolean still_wait = TRUE;
4294 /* simulate releasing mouse button over last gadget, if still pressed */
4296 HandleGadgets(-1, -1, 0);
4298 button_status = MB_RELEASED;
4314 case EVENT_BUTTONPRESS:
4315 case EVENT_KEYPRESS:
4319 case EVENT_KEYRELEASE:
4320 ClearPlayerAction();
4324 HandleOtherEvents(&event);
4328 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4335 /* don't eat all CPU time */
4340 #define MAX_REQUEST_LINES 13
4341 #define MAX_REQUEST_LINE_FONT1_LEN 7
4342 #define MAX_REQUEST_LINE_FONT2_LEN 10
4346 static int RequestHandleEvents(unsigned int req_state)
4348 int last_game_status = game_status; /* save current game status */
4352 button_status = MB_RELEASED;
4354 request_gadget_id = -1;
4367 case EVENT_BUTTONPRESS:
4368 case EVENT_BUTTONRELEASE:
4369 case EVENT_MOTIONNOTIFY:
4371 if (event.type == EVENT_MOTIONNOTIFY)
4373 if (!PointerInWindow(window))
4374 continue; /* window and pointer are on different screens */
4379 motion_status = TRUE;
4380 mx = ((MotionEvent *) &event)->x;
4381 my = ((MotionEvent *) &event)->y;
4385 motion_status = FALSE;
4386 mx = ((ButtonEvent *) &event)->x;
4387 my = ((ButtonEvent *) &event)->y;
4388 if (event.type == EVENT_BUTTONPRESS)
4389 button_status = ((ButtonEvent *) &event)->button;
4391 button_status = MB_RELEASED;
4394 /* this sets 'request_gadget_id' */
4395 HandleGadgets(mx, my, button_status);
4397 switch (request_gadget_id)
4399 case TOOL_CTRL_ID_YES:
4402 case TOOL_CTRL_ID_NO:
4405 case TOOL_CTRL_ID_CONFIRM:
4406 result = TRUE | FALSE;
4409 case TOOL_CTRL_ID_PLAYER_1:
4412 case TOOL_CTRL_ID_PLAYER_2:
4415 case TOOL_CTRL_ID_PLAYER_3:
4418 case TOOL_CTRL_ID_PLAYER_4:
4429 case EVENT_KEYPRESS:
4430 switch (GetEventKey((KeyEvent *)&event, TRUE))
4433 if (req_state & REQ_CONFIRM)
4442 #if defined(TARGET_SDL2)
4452 if (req_state & REQ_PLAYER)
4456 case EVENT_KEYRELEASE:
4457 ClearPlayerAction();
4461 HandleOtherEvents(&event);
4465 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
4467 int joy = AnyJoystick();
4469 if (joy & JOY_BUTTON_1)
4471 else if (joy & JOY_BUTTON_2)
4477 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
4479 HandleGameActions();
4485 if (!PendingEvent()) /* delay only if no pending events */
4490 game_status = GAME_MODE_PSEUDO_DOOR;
4496 game_status = last_game_status; /* restore current game status */
4504 if (!PendingEvent()) /* delay only if no pending events */
4507 /* don't eat all CPU time */
4517 static boolean RequestDoor(char *text, unsigned int req_state)
4519 unsigned int old_door_state;
4520 int last_game_status = game_status; /* save current game status */
4521 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4522 int font_nr = FONT_TEXT_2;
4527 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4529 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4530 font_nr = FONT_TEXT_1;
4533 if (game_status == GAME_MODE_PLAYING)
4535 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4536 BlitScreenToBitmap_EM(backbuffer);
4537 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4538 BlitScreenToBitmap_SP(backbuffer);
4541 /* disable deactivated drawing when quick-loading level tape recording */
4542 if (tape.playing && tape.deactivate_display)
4543 TapeDeactivateDisplayOff(TRUE);
4545 SetMouseCursor(CURSOR_DEFAULT);
4547 #if defined(NETWORK_AVALIABLE)
4548 /* pause network game while waiting for request to answer */
4549 if (options.network &&
4550 game_status == GAME_MODE_PLAYING &&
4551 req_state & REQUEST_WAIT_FOR_INPUT)
4552 SendToServer_PausePlaying();
4555 old_door_state = GetDoorState();
4557 /* simulate releasing mouse button over last gadget, if still pressed */
4559 HandleGadgets(-1, -1, 0);
4563 /* draw released gadget before proceeding */
4566 if (old_door_state & DOOR_OPEN_1)
4568 CloseDoor(DOOR_CLOSE_1);
4570 /* save old door content */
4571 BlitBitmap(bitmap_db_door, bitmap_db_door,
4572 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4573 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
4576 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4577 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4579 /* clear door drawing field */
4580 DrawBackground(DX, DY, DXSIZE, DYSIZE);
4582 /* force DOOR font inside door area */
4583 game_status = GAME_MODE_PSEUDO_DOOR;
4585 /* write text for request */
4586 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
4588 char text_line[max_request_line_len + 1];
4594 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
4596 tc = *(text_ptr + tx);
4597 // if (!tc || tc == ' ')
4598 if (!tc || tc == ' ' || tc == '?' || tc == '!')
4602 if ((tc == '?' || tc == '!') && tl == 0)
4612 strncpy(text_line, text_ptr, tl);
4615 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
4616 DY + 8 + ty * (getFontHeight(font_nr) + 2),
4617 text_line, font_nr);
4619 text_ptr += tl + (tc == ' ' ? 1 : 0);
4620 // text_ptr += tl + (tc == ' ' || tc == '?' || tc == '!' ? 1 : 0);
4623 game_status = last_game_status; /* restore current game status */
4625 if (req_state & REQ_ASK)
4627 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4628 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4630 else if (req_state & REQ_CONFIRM)
4632 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4634 else if (req_state & REQ_PLAYER)
4636 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4637 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4638 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4639 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4642 /* copy request gadgets to door backbuffer */
4643 BlitBitmap(drawto, bitmap_db_door,
4644 DX, DY, DXSIZE, DYSIZE,
4645 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
4647 OpenDoor(DOOR_OPEN_1);
4649 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4651 if (game_status == GAME_MODE_PLAYING)
4653 SetPanelBackground();
4654 SetDrawBackgroundMask(REDRAW_DOOR_1);
4658 SetDrawBackgroundMask(REDRAW_FIELD);
4664 if (game_status != GAME_MODE_MAIN)
4667 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4669 // ---------- handle request buttons ----------
4670 result = RequestHandleEvents(req_state);
4672 if (game_status != GAME_MODE_MAIN)
4677 if (!(req_state & REQ_STAY_OPEN))
4679 CloseDoor(DOOR_CLOSE_1);
4681 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
4682 (req_state & REQ_REOPEN))
4683 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
4688 if (game_status == GAME_MODE_PLAYING)
4690 SetPanelBackground();
4691 SetDrawBackgroundMask(REDRAW_DOOR_1);
4695 SetDrawBackgroundMask(REDRAW_FIELD);
4698 #if defined(NETWORK_AVALIABLE)
4699 /* continue network game after request */
4700 if (options.network &&
4701 game_status == GAME_MODE_PLAYING &&
4702 req_state & REQUEST_WAIT_FOR_INPUT)
4703 SendToServer_ContinuePlaying();
4706 /* restore deactivated drawing when quick-loading level tape recording */
4707 if (tape.playing && tape.deactivate_display)
4708 TapeDeactivateDisplayOn();
4713 static boolean RequestEnvelope(char *text, unsigned int req_state)
4720 if (game_status == GAME_MODE_PLAYING)
4722 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4723 BlitScreenToBitmap_EM(backbuffer);
4724 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4725 BlitScreenToBitmap_SP(backbuffer);
4728 /* disable deactivated drawing when quick-loading level tape recording */
4729 if (tape.playing && tape.deactivate_display)
4730 TapeDeactivateDisplayOff(TRUE);
4732 SetMouseCursor(CURSOR_DEFAULT);
4734 #if defined(NETWORK_AVALIABLE)
4735 /* pause network game while waiting for request to answer */
4736 if (options.network &&
4737 game_status == GAME_MODE_PLAYING &&
4738 req_state & REQUEST_WAIT_FOR_INPUT)
4739 SendToServer_PausePlaying();
4742 /* simulate releasing mouse button over last gadget, if still pressed */
4744 HandleGadgets(-1, -1, 0);
4748 // (replace with setting corresponding request background)
4749 // SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4750 // SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4752 /* clear door drawing field */
4753 // DrawBackground(DX, DY, DXSIZE, DYSIZE);
4756 if (global.use_envelope_request)
4760 CreateToolButtons();
4766 if (req_state & REQ_ASK)
4768 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_YES], FALSE);
4769 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_NO], FALSE);
4771 else if (req_state & REQ_CONFIRM)
4773 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_CONFIRM], FALSE);
4775 else if (req_state & REQ_PLAYER)
4777 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_1], FALSE);
4778 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_2], FALSE);
4779 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_3], FALSE);
4780 MapGadgetExt(tool_gadget[TOOL_CTRL_ID_PLAYER_4], FALSE);
4783 if (req_state & REQ_ASK)
4785 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
4786 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
4788 else if (req_state & REQ_CONFIRM)
4790 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
4792 else if (req_state & REQ_PLAYER)
4794 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
4795 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
4796 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
4797 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
4802 ShowEnvelopeRequest(text, req_state, ACTION_OPENING);
4805 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
4807 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
4808 i == TOOL_CTRL_ID_NO)) ||
4809 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
4810 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
4811 i == TOOL_CTRL_ID_PLAYER_2 &&
4812 i == TOOL_CTRL_ID_PLAYER_3 &&
4813 i == TOOL_CTRL_ID_PLAYER_4)))
4815 int x = tool_gadget[i]->x + dDX;
4816 int y = tool_gadget[i]->y + dDY;
4818 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
4823 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
4825 if (game_status == GAME_MODE_PLAYING)
4827 SetPanelBackground();
4828 SetDrawBackgroundMask(REDRAW_DOOR_1);
4832 SetDrawBackgroundMask(REDRAW_FIELD);
4839 if (game_status != GAME_MODE_MAIN)
4843 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4845 // ---------- handle request buttons ----------
4846 result = RequestHandleEvents(req_state);
4848 if (game_status != GAME_MODE_MAIN)
4853 ShowEnvelopeRequest(text, req_state, ACTION_CLOSING);
4857 if (game_status == GAME_MODE_PLAYING)
4859 SetPanelBackground();
4860 SetDrawBackgroundMask(REDRAW_DOOR_1);
4864 SetDrawBackgroundMask(REDRAW_FIELD);
4867 #if defined(NETWORK_AVALIABLE)
4868 /* continue network game after request */
4869 if (options.network &&
4870 game_status == GAME_MODE_PLAYING &&
4871 req_state & REQUEST_WAIT_FOR_INPUT)
4872 SendToServer_ContinuePlaying();
4875 /* restore deactivated drawing when quick-loading level tape recording */
4876 if (tape.playing && tape.deactivate_display)
4877 TapeDeactivateDisplayOn();
4882 boolean Request(char *text, unsigned int req_state)
4884 if (global.use_envelope_request)
4885 return RequestEnvelope(text, req_state);
4887 return RequestDoor(text, req_state);
4890 #else // =====================================================================
4892 boolean Request(char *text, unsigned int req_state)
4894 int mx, my, ty, result = -1;
4895 unsigned int old_door_state;
4896 int last_game_status = game_status; /* save current game status */
4897 int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
4898 int font_nr = FONT_TEXT_2;
4900 int max_word_len = 0;
4906 global.use_envelope_request = 1;
4910 if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN)
4912 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4913 font_nr = FONT_TEXT_1;
4916 for (text_ptr = text; *text_ptr; text_ptr++)
4918 max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
4920 if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
4922 max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
4924 font_nr = FONT_TEXT_1;
4926 font_nr = FONT_LEVEL_NUMBER;
4934 if (game_status == GAME_MODE_PLAYING)
4936 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
4937 BlitScreenToBitmap_EM(backbuffer);
4938 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
4939 BlitScreenToBitmap_SP(backbuffer);
4942 /* disable deactivated drawing when quick-loading level tape recording */
4943 if (tape.playing && tape.deactivate_display)
4944 TapeDeactivateDisplayOff(TRUE);
4946 SetMouseCursor(CURSOR_DEFAULT);
4948 #if defined(NETWORK_AVALIABLE)
4949 /* pause network game while waiting for request to answer */
4950 if (options.network &&
4951 game_status == GAME_MODE_PLAYING &&
4952 req_state & REQUEST_WAIT_FOR_INPUT)
4953 SendToServer_PausePlaying();
4956 old_door_state = GetDoorState();
4958 /* simulate releasing mouse button over last gadget, if still pressed */
4960 HandleGadgets(-1, -1, 0);
4964 /* draw released gadget before proceeding */
4968 if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request)
4970 if (old_door_state & DOOR_OPEN_1)
4974 if (!global.use_envelope_request)
4975 CloseDoor(DOOR_CLOSE_1);
4977 CloseDoor(DOOR_CLOSE_1);
4980 /* save old door content */
4981 BlitBitmap(bitmap_db_door, bitmap_db_door,
4982 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
4983 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
4987 SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
4990 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
4992 /* clear door drawing field */
4993 DrawBackground(DX, DY, DXSIZE, DYSIZE);
4995 /* force DOOR font inside door area */
4996 game_status = GAME_MODE_PSEUDO_DOOR;
4998 /* write text for request */
4999 for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++)
5001 char text_line[max_request_line_len + 1];
5007 for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
5009 tc = *(text_ptr + tx);
5010 if (!tc || tc == ' ')
5021 strncpy(text_line, text_ptr, tl);
5024 DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
5025 DY + 8 + ty * (getFontHeight(font_nr) + 2),
5026 text_line, font_nr);
5028 text_ptr += tl + (tc == ' ' ? 1 : 0);
5031 game_status = last_game_status; /* restore current game status */
5034 if (global.use_envelope_request)
5038 CreateToolButtons();
5042 if (req_state & REQ_ASK)
5044 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
5045 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
5047 else if (req_state & REQ_CONFIRM)
5049 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
5051 else if (req_state & REQ_PLAYER)
5053 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
5054 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
5055 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
5056 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
5059 /* copy request gadgets to door backbuffer */
5060 BlitBitmap(drawto, bitmap_db_door,
5061 DX, DY, DXSIZE, DYSIZE,
5062 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5065 if (global.use_envelope_request)
5067 ShowEnvelopeRequest(text, ACTION_OPENING);
5069 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
5071 if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES ||
5072 i == TOOL_CTRL_ID_NO)) ||
5073 (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) ||
5074 (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 &&
5075 i == TOOL_CTRL_ID_PLAYER_2 &&
5076 i == TOOL_CTRL_ID_PLAYER_3 &&
5077 i == TOOL_CTRL_ID_PLAYER_4)))
5079 int x = tool_gadget[i]->x + dDX;
5080 int y = tool_gadget[i]->y + dDY;
5082 ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END);
5089 if (!global.use_envelope_request)
5090 OpenDoor(DOOR_OPEN_1);
5092 OpenDoor(DOOR_OPEN_1);
5095 if (!(req_state & REQUEST_WAIT_FOR_INPUT))
5097 if (game_status == GAME_MODE_PLAYING)
5099 SetPanelBackground();
5100 SetDrawBackgroundMask(REDRAW_DOOR_1);
5104 SetDrawBackgroundMask(REDRAW_FIELD);
5111 if (game_status != GAME_MODE_MAIN && !global.use_envelope_request)
5114 if (game_status != GAME_MODE_MAIN)
5118 button_status = MB_RELEASED;
5120 request_gadget_id = -1;
5122 SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
5134 case EVENT_BUTTONPRESS:
5135 case EVENT_BUTTONRELEASE:
5136 case EVENT_MOTIONNOTIFY:
5138 if (event.type == EVENT_MOTIONNOTIFY)
5140 if (!PointerInWindow(window))
5141 continue; /* window and pointer are on different screens */
5146 motion_status = TRUE;
5147 mx = ((MotionEvent *) &event)->x;
5148 my = ((MotionEvent *) &event)->y;
5152 motion_status = FALSE;
5153 mx = ((ButtonEvent *) &event)->x;
5154 my = ((ButtonEvent *) &event)->y;
5155 if (event.type == EVENT_BUTTONPRESS)
5156 button_status = ((ButtonEvent *) &event)->button;
5158 button_status = MB_RELEASED;
5161 /* this sets 'request_gadget_id' */
5162 HandleGadgets(mx, my, button_status);
5164 switch (request_gadget_id)
5166 case TOOL_CTRL_ID_YES:
5169 case TOOL_CTRL_ID_NO:
5172 case TOOL_CTRL_ID_CONFIRM:
5173 result = TRUE | FALSE;
5176 case TOOL_CTRL_ID_PLAYER_1:
5179 case TOOL_CTRL_ID_PLAYER_2:
5182 case TOOL_CTRL_ID_PLAYER_3:
5185 case TOOL_CTRL_ID_PLAYER_4:
5196 case EVENT_KEYPRESS:
5197 switch (GetEventKey((KeyEvent *)&event, TRUE))
5200 if (req_state & REQ_CONFIRM)
5209 #if defined(TARGET_SDL2)
5219 if (req_state & REQ_PLAYER)
5223 case EVENT_KEYRELEASE:
5224 ClearPlayerAction();
5228 HandleOtherEvents(&event);
5232 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
5234 int joy = AnyJoystick();
5236 if (joy & JOY_BUTTON_1)
5238 else if (joy & JOY_BUTTON_2)
5244 if (game_status == GAME_MODE_PLAYING && local_player->LevelSolved_GameEnd)
5246 HandleGameActions();
5252 if (!PendingEvent()) /* delay only if no pending events */
5257 game_status = GAME_MODE_PSEUDO_DOOR;
5263 game_status = last_game_status; /* restore current game status */
5271 if (!PendingEvent()) /* delay only if no pending events */
5274 /* don't eat all CPU time */
5281 if (game_status != GAME_MODE_MAIN)
5287 if (global.use_envelope_request)
5288 ShowEnvelopeRequest(text, ACTION_CLOSING);
5292 if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request)
5294 if (!(req_state & REQ_STAY_OPEN))
5297 CloseDoor(DOOR_CLOSE_1);
5299 if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
5300 (req_state & REQ_REOPEN))
5301 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
5306 if (game_status == GAME_MODE_PLAYING)
5308 SetPanelBackground();
5309 SetDrawBackgroundMask(REDRAW_DOOR_1);
5313 SetDrawBackgroundMask(REDRAW_FIELD);
5316 #if defined(NETWORK_AVALIABLE)
5317 /* continue network game after request */
5318 if (options.network &&
5319 game_status == GAME_MODE_PLAYING &&
5320 req_state & REQUEST_WAIT_FOR_INPUT)
5321 SendToServer_ContinuePlaying();
5324 /* restore deactivated drawing when quick-loading level tape recording */
5325 if (tape.playing && tape.deactivate_display)
5326 TapeDeactivateDisplayOn();
5333 static int compareDoorPartOrderInfo(const void *object1, const void *object2)
5335 const struct DoorPartOrderInfo *dpo1 = (struct DoorPartOrderInfo *)object1;
5336 const struct DoorPartOrderInfo *dpo2 = (struct DoorPartOrderInfo *)object2;
5339 if (dpo1->sort_priority != dpo2->sort_priority)
5340 compare_result = dpo1->sort_priority - dpo2->sort_priority;
5342 compare_result = dpo1->nr - dpo2->nr;
5344 return compare_result;
5347 void InitGraphicCompatibilityInfo_Doors()
5353 struct DoorInfo *door;
5357 { DOOR_1, IMG_DOOR_1_GFX_PART_1, IMG_DOOR_1_GFX_PART_8, &door_1 },
5358 { DOOR_2, IMG_DOOR_2_GFX_PART_1, IMG_DOOR_2_GFX_PART_8, &door_2 },
5360 { -1, -1, -1, NULL }
5362 struct Rect door_rect_list[] =
5364 { DX, DY, DXSIZE, DYSIZE },
5365 { VX, VY, VXSIZE, VYSIZE }
5369 for (i = 0; doors[i].door_token != -1; i++)
5371 int door_token = doors[i].door_token;
5372 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5373 int part_1 = doors[i].part_1;
5374 int part_8 = doors[i].part_8;
5375 int part_2 = part_1 + 1;
5376 int part_3 = part_1 + 2;
5377 struct DoorInfo *door = doors[i].door;
5378 struct Rect *door_rect = &door_rect_list[door_index];
5379 boolean door_gfx_redefined = FALSE;
5381 /* check if any door part graphic definitions have been redefined */
5383 for (j = 0; door_part_controls[j].door_token != -1; j++)
5385 struct DoorPartControlInfo *dpc = &door_part_controls[j];
5386 struct FileInfo *fi = getImageListEntryFromImageID(dpc->graphic);
5388 if (dpc->door_token == door_token && fi->redefined)
5389 door_gfx_redefined = TRUE;
5392 /* check for old-style door graphic/animation modifications */
5394 if (!door_gfx_redefined)
5396 if (door->anim_mode & ANIM_STATIC_PANEL)
5398 door->panel.step_xoffset = 0;
5399 door->panel.step_yoffset = 0;
5402 if (door->anim_mode & (ANIM_HORIZONTAL | ANIM_VERTICAL))
5404 struct GraphicInfo *g_part_1 = &graphic_info[part_1];
5405 struct GraphicInfo *g_part_2 = &graphic_info[part_2];
5406 int num_door_steps, num_panel_steps;
5408 /* remove door part graphics other than the two default wings */
5410 for (j = 0; door_part_controls[j].door_token != -1; j++)
5412 struct DoorPartControlInfo *dpc = &door_part_controls[j];
5413 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5415 if (dpc->graphic >= part_3 &&
5416 dpc->graphic <= part_8)
5420 /* set graphics and screen positions of the default wings */
5422 g_part_1->width = door_rect->width;
5423 g_part_1->height = door_rect->height;
5424 g_part_2->width = door_rect->width;
5425 g_part_2->height = door_rect->height;
5426 g_part_2->src_x = door_rect->width;
5427 g_part_2->src_y = g_part_1->src_y;
5429 door->part_2.x = door->part_1.x;
5430 door->part_2.y = door->part_1.y;
5432 if (door->width != -1)
5434 g_part_1->width = door->width;
5435 g_part_2->width = door->width;
5437 // special treatment for graphics and screen position of right wing
5438 g_part_2->src_x += door_rect->width - door->width;
5439 door->part_2.x += door_rect->width - door->width;
5442 if (door->height != -1)
5444 g_part_1->height = door->height;
5445 g_part_2->height = door->height;
5447 // special treatment for graphics and screen position of bottom wing
5448 g_part_2->src_y += door_rect->height - door->height;
5449 door->part_2.y += door_rect->height - door->height;
5452 /* set animation delays for the default wings and panels */
5454 door->part_1.step_delay = door->step_delay;
5455 door->part_2.step_delay = door->step_delay;
5456 door->panel.step_delay = door->step_delay;
5458 /* set animation draw order for the default wings */
5460 door->part_1.sort_priority = 2; /* draw left wing over ... */
5461 door->part_2.sort_priority = 1; /* ... right wing */
5463 /* set animation draw offset for the default wings */
5465 if (door->anim_mode & ANIM_HORIZONTAL)
5467 door->part_1.step_xoffset = door->step_offset;
5468 door->part_1.step_yoffset = 0;
5469 door->part_2.step_xoffset = door->step_offset * -1;
5470 door->part_2.step_yoffset = 0;
5472 num_door_steps = g_part_1->width / door->step_offset;
5474 else // ANIM_VERTICAL
5476 door->part_1.step_xoffset = 0;
5477 door->part_1.step_yoffset = door->step_offset;
5478 door->part_2.step_xoffset = 0;
5479 door->part_2.step_yoffset = door->step_offset * -1;
5481 num_door_steps = g_part_1->height / door->step_offset;
5484 /* set animation draw offset for the default panels */
5486 if (door->step_offset > 1)
5488 num_panel_steps = 2 * door_rect->height / door->step_offset;
5489 door->panel.start_step = num_panel_steps - num_door_steps;
5493 num_panel_steps = door_rect->height / door->step_offset;
5494 door->panel.start_step = num_panel_steps - num_door_steps / 2;
5495 door->panel.step_delay *= 2;
5506 for (i = 0; door_part_controls[i].door_token != -1; i++)
5508 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5509 struct DoorPartOrderInfo *dpo = &door_part_order[i];
5511 /* initialize "start_step_opening" and "start_step_closing", if needed */
5512 if (dpc->pos->start_step_opening == 0 &&
5513 dpc->pos->start_step_closing == 0)
5515 // dpc->pos->start_step_opening = dpc->pos->start_step;
5516 dpc->pos->start_step_closing = dpc->pos->start_step;
5519 /* fill structure for door part draw order (sorted below) */
5521 dpo->sort_priority = dpc->pos->sort_priority;
5524 struct DoorPartPosInfo *pos = dpc->pos;
5526 printf(":0: step_xoffset == %d, step_yoffset == %d\n",
5527 pos->step_xoffset, pos->step_yoffset);
5531 /* sort door part controls according to sort_priority and graphic number */
5532 qsort(door_part_order, MAX_DOOR_PARTS,
5533 sizeof(struct DoorPartOrderInfo), compareDoorPartOrderInfo);
5536 unsigned int OpenDoor(unsigned int door_state)
5538 if (door_state & DOOR_COPY_BACK)
5540 if (door_state & DOOR_OPEN_1)
5541 BlitBitmap(bitmap_db_door, bitmap_db_door,
5542 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
5543 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5545 if (door_state & DOOR_OPEN_2)
5546 BlitBitmap(bitmap_db_door, bitmap_db_door,
5547 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
5548 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5550 door_state &= ~DOOR_COPY_BACK;
5553 return MoveDoor(door_state);
5556 unsigned int CloseDoor(unsigned int door_state)
5558 unsigned int old_door_state = GetDoorState();
5560 if (!(door_state & DOOR_NO_COPY_BACK))
5562 if (old_door_state & DOOR_OPEN_1)
5563 BlitBitmap(backbuffer, bitmap_db_door,
5564 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
5566 if (old_door_state & DOOR_OPEN_2)
5567 BlitBitmap(backbuffer, bitmap_db_door,
5568 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
5570 door_state &= ~DOOR_NO_COPY_BACK;
5573 return MoveDoor(door_state);
5576 unsigned int GetDoorState()
5578 return MoveDoor(DOOR_GET_STATE);
5581 unsigned int SetDoorState(unsigned int door_state)
5583 return MoveDoor(door_state | DOOR_SET_STATE);
5588 // ========== TEST 1 ===========================================================
5590 int euclid(int a, int b)
5592 return (b ? euclid(b, a % b) : a);
5595 unsigned int MoveDoor(unsigned int door_state)
5597 struct XY panel_pos_list[] =
5599 { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 },
5600 { DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 },
5602 struct Rect door_rect_list[] =
5604 { DX, DY, DXSIZE, DYSIZE },
5605 { VX, VY, VXSIZE, VYSIZE }
5607 static int door1 = DOOR_OPEN_1;
5608 static int door2 = DOOR_CLOSE_2;
5609 unsigned int door_delay = 0;
5610 unsigned int door_delay_value;
5614 if (door_1.width < 0 || door_1.width > DXSIZE)
5615 door_1.width = DXSIZE;
5616 if (door_1.height < 0 || door_1.height > DYSIZE)
5617 door_1.height = DYSIZE;
5618 if (door_2.width < 0 || door_2.width > VXSIZE)
5619 door_2.width = VXSIZE;
5620 if (door_2.height < 0 || door_2.height > VYSIZE)
5621 door_2.height = VYSIZE;
5624 if (door_state == DOOR_GET_STATE)
5625 return (door1 | door2);
5627 if (door_state & DOOR_SET_STATE)
5629 if (door_state & DOOR_ACTION_1)
5630 door1 = door_state & DOOR_ACTION_1;
5631 if (door_state & DOOR_ACTION_2)
5632 door2 = door_state & DOOR_ACTION_2;
5634 return (door1 | door2);
5637 if (!(door_state & DOOR_FORCE_REDRAW))
5639 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
5640 door_state &= ~DOOR_OPEN_1;
5641 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
5642 door_state &= ~DOOR_CLOSE_1;
5643 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
5644 door_state &= ~DOOR_OPEN_2;
5645 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
5646 door_state &= ~DOOR_CLOSE_2;
5650 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
5653 if (setup.quick_doors)
5655 stepsize = 20; /* must be chosen to always draw last frame */
5656 door_delay_value = 0;
5660 if (global.autoplay_leveldir)
5662 door_state |= DOOR_NO_DELAY;
5663 door_state &= ~DOOR_CLOSE_ALL;
5667 if (game_status == GAME_MODE_EDITOR)
5668 door_state |= DOOR_NO_DELAY;
5671 if (door_state & DOOR_ACTION)
5673 boolean door_panel_drawn[NUM_DOORS];
5674 boolean door_part_skip[MAX_DOOR_PARTS];
5675 boolean door_part_done[MAX_DOOR_PARTS];
5676 boolean door_part_done_all;
5677 int num_steps[MAX_DOOR_PARTS];
5678 int max_move_delay = 0; // delay for complete animations of all doors
5679 int max_step_delay = 0; // delay (ms) between two animation frames
5680 int num_move_steps = 0; // number of animation steps for all doors
5681 int current_move_delay = 0;
5684 for (i = 0; i < MAX_DOOR_PARTS; i++)
5686 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5687 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5688 int door_token = dpc->door_token;
5690 door_part_done[i] = FALSE;
5691 door_part_skip[i] = (!(door_state & door_token) ||
5696 for (i = 0; i < MAX_DOOR_PARTS; i++)
5698 struct DoorPartControlInfo *dpc = &door_part_controls[i];
5699 struct DoorPartPosInfo *pos = dpc->pos;
5700 int start_step = pos->start_step;
5702 printf("::: ---> %d: start_step == %d [%d]\n",
5703 i, start_step, door_part_done[i]);
5707 for (i = 0; i < MAX_DOOR_PARTS; i++)
5709 int nr = door_part_order[i].nr;
5710 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5711 struct DoorPartPosInfo *pos = dpc->pos;
5712 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5713 int door_token = dpc->door_token;
5714 boolean is_panel = DOOR_PART_IS_PANEL(nr);
5715 int step_xoffset = ABS(pos->step_xoffset);
5716 int step_yoffset = ABS(pos->step_yoffset);
5717 int step_delay = pos->step_delay;
5718 int current_door_state = door_state & door_token;
5719 boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
5720 boolean door_closing = ((current_door_state & DOOR_CLOSE) != 0);
5721 boolean part_opening = (is_panel ? door_closing : door_opening);
5722 int start_step = (part_opening ? pos->start_step_opening :
5723 pos->start_step_closing);
5724 float move_xsize = (step_xoffset ? g->width : 0);
5725 float move_ysize = (step_yoffset ? g->height : 0);
5726 int move_xsteps = (step_xoffset ? ceil(move_xsize / step_xoffset) : 0);
5727 int move_ysteps = (step_yoffset ? ceil(move_ysize / step_yoffset) : 0);
5728 int move_steps = (move_xsteps && move_ysteps ?
5729 MIN(move_xsteps, move_ysteps) :
5730 move_xsteps ? move_xsteps : move_ysteps) - start_step;
5731 int move_delay = move_steps * step_delay;
5733 if (door_part_skip[nr])
5736 max_move_delay = MAX(max_move_delay, move_delay);
5737 max_step_delay = (max_step_delay == 0 ? step_delay :
5738 euclid(max_step_delay, step_delay));
5739 num_steps[nr] = move_steps;
5743 printf("::: %d: move_delay == %d, start_step == %d [%d]\n",
5744 i, move_delay, start_step, door_part_order[i].nr);
5746 if (DOOR_PART_IS_PANEL(i))
5747 printf("::: %d: move_delay == %d, start_step == %d\n",
5748 i, move_delay, start_step);
5753 num_move_steps = max_move_delay / max_step_delay;
5755 door_delay_value = max_step_delay;
5758 door_delay_value *= 10;
5762 printf("::: num_move_steps == %d, max_move_delay == %d, max_step_delay == %d\n", num_move_steps, max_move_delay, max_step_delay);
5765 for (k = 0; k < num_move_steps; k++)
5767 door_part_done_all = TRUE;
5769 for (i = 0; i < NUM_DOORS; i++)
5770 door_panel_drawn[i] = FALSE;
5772 for (i = 0; i < MAX_DOOR_PARTS; i++)
5774 int nr = door_part_order[i].nr;
5775 struct DoorPartControlInfo *dpc = &door_part_controls[nr];
5776 struct DoorPartPosInfo *pos = dpc->pos;
5777 struct GraphicInfo *g = &graphic_info[dpc->graphic];
5778 int door_token = dpc->door_token;
5779 int door_index = DOOR_INDEX_FROM_TOKEN(door_token);
5780 boolean is_panel = DOOR_PART_IS_PANEL(nr);
5781 struct XY *panel_pos = &panel_pos_list[door_index];
5782 struct Rect *door_rect = &door_rect_list[door_index];
5783 Bitmap *bitmap = (is_panel ? bitmap_db_door : g->bitmap);
5784 int current_door_state = door_state & door_token;
5785 boolean door_opening = ((current_door_state & DOOR_OPEN) != 0);
5786 boolean door_closing = !door_opening;
5787 boolean part_opening = (is_panel ? door_closing : door_opening);
5788 boolean part_closing = !part_opening;
5789 int start_step = (part_opening ? pos->start_step_opening :
5790 pos->start_step_closing);
5791 int step_delay = pos->step_delay;
5792 int step_factor = step_delay / max_step_delay;
5793 int k1 = (step_factor ? k / step_factor + 1 : k);
5794 int k2 = (part_opening ? k1 + start_step : num_steps[nr] - k1);
5795 int kk = (k2 < 0 ? 0 : k2);
5796 int src_x, src_y, src_xx, src_yy;
5797 int dst_x, dst_y, dst_xx, dst_yy;
5801 if (DOOR_PART_IS_PANEL(nr))
5803 int start_step = pos->start_step;
5805 k2 = (door_closing ? k1 : num_steps[nr] - k1);// - start_step;
5806 kk = (k2 < 0 ? 0 : k2);
5812 if (nr != 16 && nr != 0)
5823 if (door_part_skip[nr])
5827 if (!(door_state & door_token))
5834 if (current_move_delay % step_delay)
5840 if (!door_panel_drawn[door_index])
5843 ClearRectangle(drawto, door_rect->x, door_rect->y,
5844 door_rect->width, door_rect->height);
5846 BlitBitmap(bitmap_db_door, drawto, panel_pos->x, panel_pos->y,
5847 door_rect->width, door_rect->height,
5848 door_rect->x, door_rect->y);
5851 door_panel_drawn[door_index] = TRUE;
5854 // draw opening or closing door parts
5856 if (pos->step_xoffset < 0) // door part on right side
5859 dst_xx = pos->x + ABS(kk * pos->step_xoffset);
5862 if (dst_xx + width > door_rect->width)
5863 width = door_rect->width - dst_xx;
5865 else // door part on left side
5868 dst_xx = pos->x - kk * pos->step_xoffset;
5872 src_xx = ABS(dst_xx);
5876 width = g->width - src_xx;
5878 // printf("::: k == %d [%d] \n", k, start_step);
5881 if (pos->step_yoffset < 0) // door part on bottom side
5884 dst_yy = pos->y + ABS(kk * pos->step_yoffset);
5887 if (dst_yy + height > door_rect->height)
5888 height = door_rect->height - dst_yy;
5890 else // door part on top side
5893 dst_yy = pos->y - kk * pos->step_yoffset;
5897 src_yy = ABS(dst_yy);
5901 height = g->height - src_yy;
5906 src_x = panel_pos->x + src_xx;
5907 src_y = panel_pos->y + src_yy;
5911 src_x = g->src_x + src_xx;
5912 src_y = g->src_y + src_yy;
5915 dst_x = door_rect->x + dst_xx;
5916 dst_y = door_rect->y + dst_yy;
5919 if (DOOR_PART_IS_PANEL(nr))
5921 printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
5922 width, height, g->width, g->height, src_x, src_y);
5926 if (width >= 0 && width <= g->width &&
5927 height >= 0 && height <= g->height)
5929 if (is_panel || !pos->draw_masked)
5930 BlitBitmap(bitmap, drawto, src_x, src_y, width, height,
5933 BlitBitmapMasked(bitmap, drawto, src_x, src_y, width, height,
5938 if (DOOR_PART_IS_PANEL(nr))
5940 bitmap = bitmap_db_door;
5941 src_x = panel_pos->x + src_xx;
5942 src_y = panel_pos->y + src_yy;
5944 printf("::: width == %d, height == %d [%d, %d] [%d, %d]\n",
5945 width, height, g->width, g->height, src_x, src_y);
5947 if (width >= 0 && width <= g->width &&
5948 height >= 0 && height <= g->height)
5949 BlitBitmap(bitmap, drawto, src_x, src_y,
5955 redraw_mask |= REDRAW_DOOR_FROM_TOKEN(door_token);
5958 if ((part_opening && (width < 0 || height < 0)) ||
5959 (part_closing && (width >= g->width && height >= g->height)))
5960 door_part_done[nr] = TRUE;
5962 if ((door_opening && (width < 0 || height < 0)) ||
5963 (door_closing && (width >= g->width && height >= g->height)))
5964 door_part_done[nr] = TRUE;
5967 // continue door part animations, but not panel after door has closed
5968 if (!door_part_done[nr] && !(is_panel && door_closing))
5969 door_part_done_all = FALSE;
5972 if (!door_part_done[nr])
5973 printf("::: k == %d, nr == %d\n", k, nr);
5977 if (!(door_state & DOOR_NO_DELAY))
5981 if (game_status == GAME_MODE_MAIN)
5984 WaitUntilDelayReached(&door_delay, door_delay_value);
5986 current_move_delay += max_step_delay;
5990 door_part_done_all = TRUE;
5992 for (i = 0; i < MAX_DOOR_PARTS; i++)
5993 if (!door_part_done[i] &&
5994 !(DOOR_PART_IS_PANEL(i) && door_closing))
5995 door_part_done_all = FALSE;
5998 if (door_part_done_all)
6004 if (door_state & DOOR_ACTION_1)
6005 door1 = door_state & DOOR_ACTION_1;
6006 if (door_state & DOOR_ACTION_2)
6007 door2 = door_state & DOOR_ACTION_2;
6010 printf("::: DOORS DONE %08x\n", door_state);
6012 printf("::: GO!\n");
6015 return (door1 | door2);
6020 // ========== OLD ==============================================================
6022 unsigned int MoveDoor(unsigned int door_state)
6024 static int door1 = DOOR_OPEN_1;
6025 static int door2 = DOOR_CLOSE_2;
6026 unsigned int door_delay = 0;
6027 unsigned int door_delay_value;
6031 if (door_1.width < 0 || door_1.width > DXSIZE)
6032 door_1.width = DXSIZE;
6033 if (door_1.height < 0 || door_1.height > DYSIZE)
6034 door_1.height = DYSIZE;
6035 if (door_2.width < 0 || door_2.width > VXSIZE)
6036 door_2.width = VXSIZE;
6037 if (door_2.height < 0 || door_2.height > VYSIZE)
6038 door_2.height = VYSIZE;
6041 if (door_state == DOOR_GET_STATE)
6042 return (door1 | door2);
6044 if (door_state & DOOR_SET_STATE)
6046 if (door_state & DOOR_ACTION_1)
6047 door1 = door_state & DOOR_ACTION_1;
6048 if (door_state & DOOR_ACTION_2)
6049 door2 = door_state & DOOR_ACTION_2;
6051 return (door1 | door2);
6054 if (!(door_state & DOOR_FORCE_REDRAW))
6056 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
6057 door_state &= ~DOOR_OPEN_1;
6058 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
6059 door_state &= ~DOOR_CLOSE_1;
6060 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
6061 door_state &= ~DOOR_OPEN_2;
6062 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
6063 door_state &= ~DOOR_CLOSE_2;
6066 door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
6069 // door_delay_value *= 4; // !!! TEST ONLY !!!
6071 if (setup.quick_doors)
6073 stepsize = 20; /* must be chosen to always draw last frame */
6074 door_delay_value = 0;
6077 if (global.autoplay_leveldir)
6079 door_state |= DOOR_NO_DELAY;
6080 door_state &= ~DOOR_CLOSE_ALL;
6084 if (game_status == GAME_MODE_EDITOR)
6085 door_state |= DOOR_NO_DELAY;
6088 if (door_state & DOOR_ACTION)
6091 struct GraphicInfo *g1_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
6092 struct GraphicInfo *g1_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
6093 struct GraphicInfo *g2_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
6094 struct GraphicInfo *g2_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
6095 int door_1_left_width = g1_left->width;
6096 int door_1_left_height = g1_left->height;
6097 int door_1_right_width = g1_right->width;
6098 int door_1_right_height = g1_right->height;
6099 int door_2_left_width = g2_left->width;
6100 int door_2_left_height = g2_left->height;
6101 int door_2_right_width = g2_right->width;
6102 int door_2_right_height = g2_right->height;
6103 int door_1_width = MAX(door_1_left_width, door_1_right_width);
6104 int door_1_height = MAX(door_1_left_height, door_1_right_height);
6105 int door_2_width = MAX(door_2_left_width, door_2_right_width);
6106 int door_2_height = MAX(door_2_left_height, door_2_right_height);
6108 boolean handle_door_1 = (door_state & DOOR_ACTION_1);
6109 boolean handle_door_2 = (door_state & DOOR_ACTION_2);
6110 boolean door_1_done = (!handle_door_1);
6111 boolean door_2_done = (!handle_door_2);
6112 boolean door_1_vertical = (door_1.anim_mode & ANIM_VERTICAL);
6113 boolean door_2_vertical = (door_2.anim_mode & ANIM_VERTICAL);
6116 int door_size_1 = (door_1_vertical ? door_1_height : door_1_width);
6117 int door_size_2 = (door_2_vertical ? door_2_height : door_2_width);
6119 int door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
6120 int door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
6123 int door_size_1 = (door_1_vertical ? door_1.height : door_1.width);
6124 int door_size_2 = (door_2_vertical ? door_2.height : door_2.width);
6126 int max_door_size_1 = (door_1_vertical ? DYSIZE : DXSIZE);
6127 int max_door_size_2 = (door_2_vertical ? VYSIZE : VXSIZE);
6128 // int door_size = (handle_door_1 ? door_size_1 : door_size_2);
6129 int door_size = (handle_door_2 ? door_size_2 : door_size_1);
6130 int max_door_size = (handle_door_1 ? max_door_size_1 : max_door_size_2);
6131 int door_skip = max_door_size - door_size;
6132 int end = door_size;
6133 int start = ((door_state & DOOR_NO_DELAY) ? end : 0);
6136 if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
6138 /* opening door sound has priority over simultaneously closing door */
6139 if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
6140 PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
6141 else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
6142 PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
6145 for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize)
6149 Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6150 GC gc = bitmap->stored_clip_gc;
6153 if (door_state & DOOR_ACTION_1 &&
6154 x * door_1.step_offset <= door_size_1)
6156 int a = MIN(x * door_1.step_offset, end);
6157 int p = (door_state & DOOR_OPEN_1 ? end - a : a);
6161 int i = p + door_skip;
6165 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_1_WING_LEFT];
6166 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_1_WING_RIGHT];
6167 Bitmap *bm_left = g_left->bitmap;
6168 Bitmap *bm_right = g_right->bitmap;
6169 GC gc_left = bm_left->stored_clip_gc;
6170 GC gc_right = bm_right->stored_clip_gc;
6173 int classic_dxsize = 100;
6174 int classic_dysize = 280;
6175 boolean classic_door_1_size = (DXSIZE == classic_dxsize &&
6176 DYSIZE == classic_dysize);
6178 if (door_1.anim_mode & ANIM_STATIC_PANEL)
6180 BlitBitmap(bitmap_db_door, drawto,
6181 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1,
6182 DXSIZE, DYSIZE, DX, DY);
6186 BlitBitmap(bitmap_db_door, drawto,
6187 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + p / 2,
6188 DXSIZE, DYSIZE - p / 2, DX, DY);
6191 // printf("::: p == %d\n", p);
6192 ClearRectangle(drawto, DX, DY + DYSIZE - p / 2, DXSIZE, p / 2);
6196 if (door_1.anim_mode & ANIM_HORIZONTAL && x <= DXSIZE)
6199 int src1_x = g_right->src_x;
6200 int src1_y = g_right->src_y;
6201 int src2_x = g_left->src_x + g_left->width - i;
6202 int src2_y = g_left->src_y;
6203 int dst1_x = DX + DXSIZE - i;
6208 int height = DYSIZE;
6210 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6211 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6214 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6215 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6218 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6219 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
6220 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
6221 int dst2_x = DX, dst2_y = DY;
6222 int width = i, height = DYSIZE;
6224 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6225 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6228 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6229 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6233 else if (door_1.anim_mode & ANIM_VERTICAL && x <= DYSIZE)
6236 int src1_x = g_right->src_x;
6237 int src1_y = g_right->src_y;
6238 int src2_x = g_left->src_x;
6239 int src2_y = g_left->src_y + g_left->height - i;
6241 int dst1_y = DY + DYSIZE - i;
6247 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6248 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6251 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6252 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6255 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6256 int src2_x = 0, src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
6257 int dst1_x = DX, dst1_y = DY + DYSIZE - i;
6258 int dst2_x = DX, dst2_y = DY;
6259 int width = DXSIZE, height = i;
6261 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6262 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6265 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6266 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6270 else if (classic_door_1_size && x <= DXSIZE) /* ANIM_DEFAULT */
6272 int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
6275 int src1_x = g_right->src_x;
6276 int src1_y = g_right->src_y;
6277 int src2_x = g_left->src_x + g_left->width - i;
6278 int src2_y = g_left->src_y;
6279 int dst1_x = DX + DXSIZE - i;
6284 int height1 = 63, height2 = DYSIZE / 2 - height1;
6285 int ypos1 = 0, ypos2 = height2;
6286 int ypos3 = DYSIZE / 2, ypos4 = DYSIZE - height2;
6288 SetClipOrigin(bm_right, gc_right,
6289 dst1_x - src1_x, dst1_y - src1_y + j);
6290 BlitBitmapMasked(bm_right, drawto,
6291 src1_x, src1_y + ypos1, width, height2,
6292 dst1_x, dst1_y + ypos1 + j);
6293 BlitBitmapMasked(bm_right, drawto,
6294 src1_x, src1_y + ypos3, width, height1,
6295 dst1_x, dst1_y + ypos3 + j);
6296 SetClipOrigin(bm_left, gc_left,
6297 dst2_x - src2_x, dst2_y - src2_y - j);
6298 BlitBitmapMasked(bm_left, drawto,
6299 src2_x, src2_y + ypos1 + j, width, height2 - j,
6300 dst2_x, dst2_y + ypos1);
6301 BlitBitmapMasked(bm_left, drawto,
6302 src2_x, src2_y + ypos3, width, height1,
6303 dst2_x, dst2_y + ypos3 - j);
6305 SetClipOrigin(bm_left, gc_left,
6306 dst2_x - src2_x, dst2_y - src2_y - j);
6307 BlitBitmapMasked(bm_left, drawto,
6308 src2_x, src2_y + ypos2, width, height1,
6309 dst2_x, dst2_y + ypos2 - j);
6310 BlitBitmapMasked(bm_left, drawto,
6311 src2_x, src2_y + ypos4, width, height2,
6312 dst2_x, dst2_y + ypos4 - j);
6313 SetClipOrigin(bm_right, gc_right,
6314 dst1_x - src1_x, dst1_y - src1_y + j);
6315 BlitBitmapMasked(bm_right, drawto,
6316 src1_x, src1_y + ypos2, width, height1,
6317 dst1_x, dst1_y + ypos2 + j);
6318 BlitBitmapMasked(bm_right, drawto,
6319 src1_x, src1_y + ypos4, width, height2 - j,
6320 dst1_x, dst1_y + ypos4 + j);
6323 int src1_x = DXSIZE, src1_y = DOOR_GFX_PAGEY1;
6324 int src2_x = DXSIZE - i, src2_y = DOOR_GFX_PAGEY1;
6325 int dst1_x = DX + DXSIZE - i, dst1_y = DY;
6326 int dst2_x = DX, dst2_y = DY;
6327 int width = i, height = DYSIZE;
6328 int ypos1 = 63, ypos2 = 77, ypos3 = 140, ypos4 = 203;
6330 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6331 BlitBitmapMasked(bitmap, drawto,
6332 src1_x, src1_y, width, ypos2,
6333 dst1_x, dst1_y + j);
6334 BlitBitmapMasked(bitmap, drawto,
6335 src1_x, src1_y + ypos3, width, ypos1,
6336 dst1_x, dst1_y + ypos3 + j);
6337 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
6338 BlitBitmapMasked(bitmap, drawto,
6339 src2_x, src2_y + j, width, ypos2 - j,
6341 BlitBitmapMasked(bitmap, drawto,
6342 src2_x, src2_y + ypos3, width, ypos1,
6343 dst2_x, dst2_y + ypos3 - j);
6345 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y - j);
6346 BlitBitmapMasked(bitmap, drawto,
6347 src2_x, src2_y + ypos2, width, ypos1,
6348 dst2_x, dst2_y + ypos2 - j);
6349 BlitBitmapMasked(bitmap, drawto,
6350 src2_x, src2_y + ypos4, width, ypos2,
6351 dst2_x, dst2_y + ypos4 - j);
6352 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6353 BlitBitmapMasked(bitmap, drawto,
6354 src1_x, src1_y + ypos2, width, ypos1,
6355 dst1_x, dst1_y + ypos2 + j);
6356 BlitBitmapMasked(bitmap, drawto,
6357 src1_x, src1_y + ypos4, width, ypos2 - j,
6358 dst1_x, dst1_y + ypos4 + j);
6361 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
6362 BlitBitmapMasked(bitmap, drawto,
6363 DXSIZE, DOOR_GFX_PAGEY1, i, 77,
6364 DX + DXSIZE - i, DY + j);
6365 BlitBitmapMasked(bitmap, drawto,
6366 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
6367 DX + DXSIZE - i, DY + 140 + j);
6368 SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
6369 DY - (DOOR_GFX_PAGEY1 + j));
6370 BlitBitmapMasked(bitmap, drawto,
6371 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
6373 BlitBitmapMasked(bitmap, drawto,
6374 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
6377 BlitBitmapMasked(bitmap, drawto,
6378 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
6380 BlitBitmapMasked(bitmap, drawto,
6381 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
6383 SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
6384 BlitBitmapMasked(bitmap, drawto,
6385 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
6386 DX + DXSIZE - i, DY + 77 + j);
6387 BlitBitmapMasked(bitmap, drawto,
6388 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
6389 DX + DXSIZE - i, DY + 203 + j);
6394 redraw_mask |= REDRAW_DOOR_1;
6395 door_1_done = (a == end);
6398 if (door_state & DOOR_ACTION_2 &&
6399 x * door_2.step_offset <= door_size_2)
6401 int a = MIN(x * door_2.step_offset, door_size);
6402 int p = (door_state & DOOR_OPEN_2 ? door_size - a : a);
6403 int i = p + door_skip;
6406 struct GraphicInfo *g_left = &graphic_info[IMG_DOOR_2_WING_LEFT];
6407 struct GraphicInfo *g_right = &graphic_info[IMG_DOOR_2_WING_RIGHT];
6408 Bitmap *bm_left = g_left->bitmap;
6409 Bitmap *bm_right = g_right->bitmap;
6410 GC gc_left = bm_left->stored_clip_gc;
6411 GC gc_right = bm_right->stored_clip_gc;
6414 int classic_vxsize = 100;
6415 int classic_vysize = 100;
6416 boolean classic_door_2_size = (VXSIZE == classic_vxsize &&
6417 VYSIZE == classic_vysize);
6419 if (door_2.anim_mode & ANIM_STATIC_PANEL)
6421 BlitBitmap(bitmap_db_door, drawto,
6422 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2,
6423 VXSIZE, VYSIZE, VX, VY);
6425 else if (x <= VYSIZE)
6427 BlitBitmap(bitmap_db_door, drawto,
6428 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + p / 2,
6429 VXSIZE, VYSIZE - p / 2, VX, VY);
6431 ClearRectangle(drawto, VX, VY + VYSIZE - p / 2, VXSIZE, p / 2);
6434 if (door_2.anim_mode & ANIM_HORIZONTAL && x <= VXSIZE)
6437 int src1_x = g_right->src_x;
6438 int src1_y = g_right->src_y;
6439 int src2_x = g_left->src_x + g_left->width - i;
6440 int src2_y = g_left->src_y;
6441 int dst1_x = VX + VXSIZE - i;
6446 int height = VYSIZE;
6448 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6449 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6452 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6453 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6456 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6457 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6458 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6459 int dst2_x = VX, dst2_y = VY;
6460 int width = i, height = VYSIZE;
6462 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6463 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6466 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6467 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6471 else if (door_2.anim_mode & ANIM_VERTICAL && x <= VYSIZE)
6474 int src1_x = g_right->src_x;
6475 int src1_y = g_right->src_y;
6476 int src2_x = g_left->src_x;
6477 int src2_y = g_left->src_y + g_left->height - i;
6479 int dst1_y = VY + VYSIZE - i;
6485 SetClipOrigin(bm_right, gc_right, dst1_x - src1_x, dst1_y - src1_y);
6486 BlitBitmapMasked(bm_right, drawto, src1_x, src1_y, width, height,
6489 SetClipOrigin(bm_left, gc_left, dst2_x - src2_x, dst2_y - src2_y);
6490 BlitBitmapMasked(bm_left, drawto, src2_x, src2_y, width, height,
6493 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6494 int src2_x = 0, src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
6495 int dst1_x = VX, dst1_y = VY + VYSIZE - i;
6496 int dst2_x = VX, dst2_y = VY;
6497 int width = VXSIZE, height = i;
6499 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
6500 BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
6503 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
6504 BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
6508 else if (classic_door_2_size && x <= VXSIZE) /* ANIM_DEFAULT */
6510 int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
6513 int src1_x = g_right->src_x;
6514 int src1_y = g_right->src_y;
6515 int src2_x = g_left->src_x + g_left->width - i;
6516 int src2_y = g_left->src_y;
6517 int dst1_x = VX + VXSIZE - i;
6522 int height = VYSIZE / 2;
6523 int ypos1 = 0, ypos2 = VYSIZE / 2;
6525 SetClipOrigin(bm_right, gc_right,
6526 dst1_x - src1_x, dst1_y - src1_y + j);
6527 BlitBitmapMasked(bm_right, drawto,
6528 src1_x, src1_y + ypos1, width, height,
6529 dst1_x, dst1_y + ypos1 + j);
6530 SetClipOrigin(bm_left, gc_left,
6531 dst2_x - src2_x, dst2_y - src2_y - j);
6532 BlitBitmapMasked(bm_left, drawto,
6533 src2_x, src2_y + ypos1 + j, width, height - j,
6534 dst2_x, dst2_y + ypos1);
6536 SetClipOrigin(bm_left, gc_left,
6537 dst2_x - src2_x, dst2_y - src2_y - j);
6538 BlitBitmapMasked(bm_left, drawto,
6539 src2_x, src2_y + ypos2, width, height,
6540 dst2_x, dst2_y + ypos2 - j);
6541 SetClipOrigin(bm_right, gc_right,
6542 dst1_x - src1_x, dst1_y - src1_y + j);
6543 BlitBitmapMasked(bm_right, drawto,
6544 src1_x, src1_y + ypos2, width, height - j,
6545 dst1_x, dst1_y + ypos2 + j);
6547 int src1_x = VXSIZE, src1_y = DOOR_GFX_PAGEY2;
6548 int src2_x = VXSIZE - i, src2_y = DOOR_GFX_PAGEY2;
6549 int dst1_x = VX + VXSIZE - i, dst1_y = VY;
6550 int dst2_x = VX, dst2_y = VY;
6551 int width = i, height = VYSIZE;
6552 int ypos = VYSIZE / 2;
6554 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6555 BlitBitmapMasked(bitmap, drawto,
6556 src1_x, src1_y, width, ypos,
6557 dst1_x, dst1_y + j);
6558 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6559 BlitBitmapMasked(bitmap, drawto,
6560 src2_x, src2_y + j, width, ypos - j,
6563 SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src1_y - j);
6564 BlitBitmapMasked(bitmap, drawto,
6565 src2_x, src2_y + ypos, width, ypos,
6566 dst2_x, dst2_y + ypos - j);
6567 SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y + j);
6568 BlitBitmapMasked(bitmap, drawto,
6569 src1_x, src1_y + ypos, width, ypos - j,
6570 dst1_x, dst1_y + ypos + j);
6573 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6574 BlitBitmapMasked(bitmap, drawto,
6575 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
6576 VX + VXSIZE - i, VY + j);
6577 SetClipOrigin(bitmap, gc,
6578 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
6579 BlitBitmapMasked(bitmap, drawto,
6580 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
6583 BlitBitmapMasked(bitmap, drawto,
6584 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6585 i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
6586 SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
6587 BlitBitmapMasked(bitmap, drawto,
6588 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
6590 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
6595 redraw_mask |= REDRAW_DOOR_2;
6596 door_2_done = (a == VXSIZE);
6599 if (!(door_state & DOOR_NO_DELAY))
6603 if (game_status == GAME_MODE_MAIN)
6606 WaitUntilDelayReached(&door_delay, door_delay_value);
6611 if (door_state & DOOR_ACTION_1)
6612 door1 = door_state & DOOR_ACTION_1;
6613 if (door_state & DOOR_ACTION_2)
6614 door2 = door_state & DOOR_ACTION_2;
6616 return (door1 | door2);
6621 void DrawSpecialEditorDoor()
6624 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6625 int top_border_width = gfx1->width;
6626 int top_border_height = gfx1->height;
6627 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6628 int ex = EX - outer_border;
6629 int ey = EY - outer_border;
6630 int vy = VY - outer_border;
6631 int exsize = EXSIZE + 2 * outer_border;
6633 CloseDoor(DOOR_CLOSE_2);
6635 /* draw bigger level editor toolbox window */
6636 BlitBitmap(gfx1->bitmap, drawto, gfx1->src_x, gfx1->src_y,
6637 top_border_width, top_border_height, ex, ey - top_border_height);
6638 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto, ex, vy,
6639 exsize, EYSIZE - VYSIZE + outer_border, ex, ey);
6641 /* draw bigger level editor toolbox window */
6642 BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
6643 DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
6645 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6646 EX - 6, VY - 4, EXSIZE + 12, EYSIZE - VYSIZE + 4,
6650 redraw_mask |= REDRAW_ALL;
6653 void UndrawSpecialEditorDoor()
6656 struct GraphicInfo *gfx1 = &graphic_info[IMG_DOOR_2_TOP_BORDER_CORRECTION];
6657 int top_border_width = gfx1->width;
6658 int top_border_height = gfx1->height;
6659 int outer_border = viewport.door_2[GAME_MODE_EDITOR].border_size;
6660 int ex = EX - outer_border;
6661 int ey = EY - outer_border;
6662 int ey_top = ey - top_border_height;
6663 int exsize = EXSIZE + 2 * outer_border;
6664 int eysize = EYSIZE + 2 * outer_border;
6666 /* draw normal tape recorder window */
6667 if (graphic_info[IMG_GLOBAL_BORDER].bitmap)
6669 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6670 ex, ey_top, top_border_width, top_border_height,
6672 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6673 ex, ey, exsize, eysize, ex, ey);
6677 // if screen background is set to "[NONE]", clear editor toolbox window
6678 ClearRectangle(drawto, ex, ey_top, top_border_width, top_border_height);
6679 ClearRectangle(drawto, ex, ey, exsize, eysize);
6682 /* draw normal tape recorder window */
6683 BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
6684 EX - 6, EY - 12, EXSIZE + 12, EYSIZE - VYSIZE + 12,
6688 redraw_mask |= REDRAW_ALL;
6692 /* ---------- new tool button stuff ---------------------------------------- */
6699 struct TextPosInfo *pos;
6702 } toolbutton_info[NUM_TOOL_BUTTONS] =
6705 IMG_REQUEST_BUTTON_GFX_YES, &request.button.yes,
6706 TOOL_CTRL_ID_YES, "yes"
6709 IMG_REQUEST_BUTTON_GFX_NO, &request.button.no,
6710 TOOL_CTRL_ID_NO, "no"
6713 IMG_REQUEST_BUTTON_GFX_CONFIRM, &request.button.confirm,
6714 TOOL_CTRL_ID_CONFIRM, "confirm"
6717 IMG_REQUEST_BUTTON_GFX_PLAYER_1, &request.button.player_1,
6718 TOOL_CTRL_ID_PLAYER_1, "player 1"
6721 IMG_REQUEST_BUTTON_GFX_PLAYER_2, &request.button.player_2,
6722 TOOL_CTRL_ID_PLAYER_2, "player 2"
6725 IMG_REQUEST_BUTTON_GFX_PLAYER_3, &request.button.player_3,
6726 TOOL_CTRL_ID_PLAYER_3, "player 3"
6729 IMG_REQUEST_BUTTON_GFX_PLAYER_4, &request.button.player_4,
6730 TOOL_CTRL_ID_PLAYER_4, "player 4"
6734 void CreateToolButtons()
6738 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6740 struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic];
6741 struct TextPosInfo *pos = toolbutton_info[i].pos;
6742 struct GadgetInfo *gi;
6743 Bitmap *deco_bitmap = None;
6744 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6745 unsigned int event_mask = GD_EVENT_RELEASED;
6748 int gd_x = gfx->src_x;
6749 int gd_y = gfx->src_y;
6750 int gd_xp = gfx->src_x + gfx->pressed_xoffset;
6751 int gd_yp = gfx->src_y + gfx->pressed_yoffset;
6754 if (global.use_envelope_request)
6755 setRequestPosition(&dx, &dy, TRUE);
6757 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
6759 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
6761 getSizedGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0,
6762 pos->size, &deco_bitmap, &deco_x, &deco_y);
6763 deco_xpos = (gfx->width - pos->size) / 2;
6764 deco_ypos = (gfx->height - pos->size) / 2;
6767 gi = CreateGadget(GDI_CUSTOM_ID, id,
6768 GDI_INFO_TEXT, toolbutton_info[i].infotext,
6769 GDI_X, dx + GDI_ACTIVE_POS(pos->x),
6770 GDI_Y, dy + GDI_ACTIVE_POS(pos->y),
6771 GDI_WIDTH, gfx->width,
6772 GDI_HEIGHT, gfx->height,
6773 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
6774 GDI_STATE, GD_BUTTON_UNPRESSED,
6775 GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y,
6776 GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp,
6777 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
6778 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
6779 GDI_DECORATION_SIZE, pos->size, pos->size,
6780 GDI_DECORATION_SHIFTING, 1, 1,
6781 GDI_DIRECT_DRAW, FALSE,
6782 GDI_EVENT_MASK, event_mask,
6783 GDI_CALLBACK_ACTION, HandleToolButtons,
6787 Error(ERR_EXIT, "cannot create gadget");
6789 tool_gadget[id] = gi;
6795 /* graphic position values for tool buttons */
6796 #define TOOL_BUTTON_YES_XPOS 2
6797 #define TOOL_BUTTON_YES_YPOS 250
6798 #define TOOL_BUTTON_YES_GFX_YPOS 0
6799 #define TOOL_BUTTON_YES_XSIZE 46
6800 #define TOOL_BUTTON_YES_YSIZE 28
6801 #define TOOL_BUTTON_NO_XPOS 52
6802 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
6803 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
6804 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
6805 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
6806 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
6807 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
6808 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
6809 #define TOOL_BUTTON_CONFIRM_XSIZE 96
6810 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
6811 #define TOOL_BUTTON_PLAYER_XSIZE 30
6812 #define TOOL_BUTTON_PLAYER_YSIZE 30
6813 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
6814 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
6815 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
6816 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
6817 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6818 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6819 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6820 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6821 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6822 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
6823 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
6824 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
6825 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6826 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6827 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6828 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
6829 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6830 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6831 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
6832 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
6841 } toolbutton_info[NUM_TOOL_BUTTONS] =
6844 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
6845 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
6846 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
6851 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
6852 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
6853 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
6858 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
6859 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
6860 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
6861 TOOL_CTRL_ID_CONFIRM,
6865 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6866 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
6867 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6868 TOOL_CTRL_ID_PLAYER_1,
6872 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6873 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
6874 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6875 TOOL_CTRL_ID_PLAYER_2,
6879 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6880 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
6881 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6882 TOOL_CTRL_ID_PLAYER_3,
6886 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
6887 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
6888 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
6889 TOOL_CTRL_ID_PLAYER_4,
6894 void CreateToolButtons()
6898 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6900 Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
6901 Bitmap *deco_bitmap = None;
6902 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
6903 struct GadgetInfo *gi;
6904 unsigned int event_mask;
6905 int gd_xoffset, gd_yoffset;
6906 int gd_x1, gd_x2, gd_y;
6909 event_mask = GD_EVENT_RELEASED;
6911 gd_xoffset = toolbutton_info[i].xpos;
6912 gd_yoffset = toolbutton_info[i].ypos;
6913 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
6914 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
6915 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
6917 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
6919 int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
6921 getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
6922 &deco_bitmap, &deco_x, &deco_y);
6923 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
6924 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
6927 gi = CreateGadget(GDI_CUSTOM_ID, id,
6928 GDI_INFO_TEXT, toolbutton_info[i].infotext,
6929 GDI_X, DX + GDI_ACTIVE_POS(toolbutton_info[i].x),
6930 GDI_Y, DY + GDI_ACTIVE_POS(toolbutton_info[i].y),
6931 GDI_WIDTH, toolbutton_info[i].width,
6932 GDI_HEIGHT, toolbutton_info[i].height,
6933 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
6934 GDI_STATE, GD_BUTTON_UNPRESSED,
6935 GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
6936 GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
6937 GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
6938 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
6939 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
6940 GDI_DECORATION_SHIFTING, 1, 1,
6941 GDI_DIRECT_DRAW, FALSE,
6942 GDI_EVENT_MASK, event_mask,
6943 GDI_CALLBACK_ACTION, HandleToolButtons,
6947 Error(ERR_EXIT, "cannot create gadget");
6949 tool_gadget[id] = gi;
6955 void FreeToolButtons()
6959 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6960 FreeGadget(tool_gadget[i]);
6963 static void UnmapToolButtons()
6967 for (i = 0; i < NUM_TOOL_BUTTONS; i++)
6968 UnmapGadget(tool_gadget[i]);
6971 static void HandleToolButtons(struct GadgetInfo *gi)
6973 request_gadget_id = gi->custom_id;
6976 static struct Mapping_EM_to_RND_object
6979 boolean is_rnd_to_em_mapping; /* unique mapping EM <-> RND */
6980 boolean is_backside; /* backside of moving element */
6986 em_object_mapping_list[] =
6989 Xblank, TRUE, FALSE,
6993 Yacid_splash_eB, FALSE, FALSE,
6994 EL_ACID_SPLASH_RIGHT, -1, -1
6997 Yacid_splash_wB, FALSE, FALSE,
6998 EL_ACID_SPLASH_LEFT, -1, -1
7001 #ifdef EM_ENGINE_BAD_ROLL
7003 Xstone_force_e, FALSE, FALSE,
7004 EL_ROCK, -1, MV_BIT_RIGHT
7007 Xstone_force_w, FALSE, FALSE,
7008 EL_ROCK, -1, MV_BIT_LEFT
7011 Xnut_force_e, FALSE, FALSE,
7012 EL_NUT, -1, MV_BIT_RIGHT
7015 Xnut_force_w, FALSE, FALSE,
7016 EL_NUT, -1, MV_BIT_LEFT
7019 Xspring_force_e, FALSE, FALSE,
7020 EL_SPRING, -1, MV_BIT_RIGHT
7023 Xspring_force_w, FALSE, FALSE,
7024 EL_SPRING, -1, MV_BIT_LEFT
7027 Xemerald_force_e, FALSE, FALSE,
7028 EL_EMERALD, -1, MV_BIT_RIGHT
7031 Xemerald_force_w, FALSE, FALSE,
7032 EL_EMERALD, -1, MV_BIT_LEFT
7035 Xdiamond_force_e, FALSE, FALSE,
7036 EL_DIAMOND, -1, MV_BIT_RIGHT
7039 Xdiamond_force_w, FALSE, FALSE,
7040 EL_DIAMOND, -1, MV_BIT_LEFT
7043 Xbomb_force_e, FALSE, FALSE,
7044 EL_BOMB, -1, MV_BIT_RIGHT
7047 Xbomb_force_w, FALSE, FALSE,
7048 EL_BOMB, -1, MV_BIT_LEFT
7050 #endif /* EM_ENGINE_BAD_ROLL */
7053 Xstone, TRUE, FALSE,
7057 Xstone_pause, FALSE, FALSE,
7061 Xstone_fall, FALSE, FALSE,
7065 Ystone_s, FALSE, FALSE,
7066 EL_ROCK, ACTION_FALLING, -1
7069 Ystone_sB, FALSE, TRUE,
7070 EL_ROCK, ACTION_FALLING, -1
7073 Ystone_e, FALSE, FALSE,
7074 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
7077 Ystone_eB, FALSE, TRUE,
7078 EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT
7081 Ystone_w, FALSE, FALSE,
7082 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
7085 Ystone_wB, FALSE, TRUE,
7086 EL_ROCK, ACTION_MOVING, MV_BIT_LEFT
7093 Xnut_pause, FALSE, FALSE,
7097 Xnut_fall, FALSE, FALSE,
7101 Ynut_s, FALSE, FALSE,
7102 EL_NUT, ACTION_FALLING, -1
7105 Ynut_sB, FALSE, TRUE,
7106 EL_NUT, ACTION_FALLING, -1
7109 Ynut_e, FALSE, FALSE,
7110 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
7113 Ynut_eB, FALSE, TRUE,
7114 EL_NUT, ACTION_MOVING, MV_BIT_RIGHT
7117 Ynut_w, FALSE, FALSE,
7118 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
7121 Ynut_wB, FALSE, TRUE,
7122 EL_NUT, ACTION_MOVING, MV_BIT_LEFT
7125 Xbug_n, TRUE, FALSE,
7129 Xbug_e, TRUE, FALSE,
7130 EL_BUG_RIGHT, -1, -1
7133 Xbug_s, TRUE, FALSE,
7137 Xbug_w, TRUE, FALSE,
7141 Xbug_gon, FALSE, FALSE,
7145 Xbug_goe, FALSE, FALSE,
7146 EL_BUG_RIGHT, -1, -1
7149 Xbug_gos, FALSE, FALSE,
7153 Xbug_gow, FALSE, FALSE,
7157 Ybug_n, FALSE, FALSE,
7158 EL_BUG, ACTION_MOVING, MV_BIT_UP
7161 Ybug_nB, FALSE, TRUE,
7162 EL_BUG, ACTION_MOVING, MV_BIT_UP
7165 Ybug_e, FALSE, FALSE,
7166 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
7169 Ybug_eB, FALSE, TRUE,
7170 EL_BUG, ACTION_MOVING, MV_BIT_RIGHT
7173 Ybug_s, FALSE, FALSE,
7174 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
7177 Ybug_sB, FALSE, TRUE,
7178 EL_BUG, ACTION_MOVING, MV_BIT_DOWN
7181 Ybug_w, FALSE, FALSE,
7182 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
7185 Ybug_wB, FALSE, TRUE,
7186 EL_BUG, ACTION_MOVING, MV_BIT_LEFT
7189 Ybug_w_n, FALSE, FALSE,
7190 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
7193 Ybug_n_e, FALSE, FALSE,
7194 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
7197 Ybug_e_s, FALSE, FALSE,
7198 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
7201 Ybug_s_w, FALSE, FALSE,
7202 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
7205 Ybug_e_n, FALSE, FALSE,
7206 EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
7209 Ybug_s_e, FALSE, FALSE,
7210 EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
7213 Ybug_w_s, FALSE, FALSE,
7214 EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
7217 Ybug_n_w, FALSE, FALSE,
7218 EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
7221 Ybug_stone, FALSE, FALSE,
7222 EL_BUG, ACTION_SMASHED_BY_ROCK, -1
7225 Ybug_spring, FALSE, FALSE,
7226 EL_BUG, ACTION_SMASHED_BY_SPRING, -1
7229 Xtank_n, TRUE, FALSE,
7230 EL_SPACESHIP_UP, -1, -1
7233 Xtank_e, TRUE, FALSE,
7234 EL_SPACESHIP_RIGHT, -1, -1
7237 Xtank_s, TRUE, FALSE,
7238 EL_SPACESHIP_DOWN, -1, -1
7241 Xtank_w, TRUE, FALSE,
7242 EL_SPACESHIP_LEFT, -1, -1
7245 Xtank_gon, FALSE, FALSE,
7246 EL_SPACESHIP_UP, -1, -1
7249 Xtank_goe, FALSE, FALSE,
7250 EL_SPACESHIP_RIGHT, -1, -1
7253 Xtank_gos, FALSE, FALSE,
7254 EL_SPACESHIP_DOWN, -1, -1
7257 Xtank_gow, FALSE, FALSE,
7258 EL_SPACESHIP_LEFT, -1, -1
7261 Ytank_n, FALSE, FALSE,
7262 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
7265 Ytank_nB, FALSE, TRUE,
7266 EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP
7269 Ytank_e, FALSE, FALSE,
7270 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
7273 Ytank_eB, FALSE, TRUE,
7274 EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT
7277 Ytank_s, FALSE, FALSE,
7278 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
7281 Ytank_sB, FALSE, TRUE,
7282 EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN
7285 Ytank_w, FALSE, FALSE,
7286 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
7289 Ytank_wB, FALSE, TRUE,
7290 EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT
7293 Ytank_w_n, FALSE, FALSE,
7294 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP
7297 Ytank_n_e, FALSE, FALSE,
7298 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
7301 Ytank_e_s, FALSE, FALSE,
7302 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
7305 Ytank_s_w, FALSE, FALSE,
7306 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
7309 Ytank_e_n, FALSE, FALSE,
7310 EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
7313 Ytank_s_e, FALSE, FALSE,
7314 EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
7317 Ytank_w_s, FALSE, FALSE,
7318 EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
7321 Ytank_n_w, FALSE, FALSE,
7322 EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT
7325 Ytank_stone, FALSE, FALSE,
7326 EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1
7329 Ytank_spring, FALSE, FALSE,
7330 EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1
7333 Xandroid, TRUE, FALSE,
7334 EL_EMC_ANDROID, ACTION_ACTIVE, -1
7337 Xandroid_1_n, FALSE, FALSE,
7338 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
7341 Xandroid_2_n, FALSE, FALSE,
7342 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_UP
7345 Xandroid_1_e, FALSE, FALSE,
7346 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
7349 Xandroid_2_e, FALSE, FALSE,
7350 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_RIGHT
7353 Xandroid_1_w, FALSE, FALSE,
7354 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
7357 Xandroid_2_w, FALSE, FALSE,
7358 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_LEFT
7361 Xandroid_1_s, FALSE, FALSE,
7362 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
7365 Xandroid_2_s, FALSE, FALSE,
7366 EL_EMC_ANDROID, ACTION_ACTIVE, MV_BIT_DOWN
7369 Yandroid_n, FALSE, FALSE,
7370 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
7373 Yandroid_nB, FALSE, TRUE,
7374 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_UP
7377 Yandroid_ne, FALSE, FALSE,
7378 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPRIGHT
7381 Yandroid_neB, FALSE, TRUE,
7382 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPRIGHT
7385 Yandroid_e, FALSE, FALSE,
7386 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
7389 Yandroid_eB, FALSE, TRUE,
7390 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_RIGHT
7393 Yandroid_se, FALSE, FALSE,
7394 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNRIGHT
7397 Yandroid_seB, FALSE, TRUE,
7398 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNRIGHT
7401 Yandroid_s, FALSE, FALSE,
7402 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
7405 Yandroid_sB, FALSE, TRUE,
7406 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_DOWN
7409 Yandroid_sw, FALSE, FALSE,
7410 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_DOWNLEFT
7413 Yandroid_swB, FALSE, TRUE,
7414 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_DOWNLEFT
7417 Yandroid_w, FALSE, FALSE,
7418 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
7421 Yandroid_wB, FALSE, TRUE,
7422 EL_EMC_ANDROID, ACTION_MOVING, MV_BIT_LEFT
7425 Yandroid_nw, FALSE, FALSE,
7426 EL_EMC_ANDROID, ACTION_GROWING, MV_BIT_UPLEFT
7429 Yandroid_nwB, FALSE, TRUE,
7430 EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT
7433 Xspring, TRUE, FALSE,
7437 Xspring_pause, FALSE, FALSE,
7441 Xspring_e, FALSE, FALSE,
7445 Xspring_w, FALSE, FALSE,
7449 Xspring_fall, FALSE, FALSE,
7453 Yspring_s, FALSE, FALSE,
7454 EL_SPRING, ACTION_FALLING, -1
7457 Yspring_sB, FALSE, TRUE,
7458 EL_SPRING, ACTION_FALLING, -1
7461 Yspring_e, FALSE, FALSE,
7462 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
7465 Yspring_eB, FALSE, TRUE,
7466 EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT
7469 Yspring_w, FALSE, FALSE,
7470 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
7473 Yspring_wB, FALSE, TRUE,
7474 EL_SPRING, ACTION_MOVING, MV_BIT_LEFT
7477 Yspring_kill_e, FALSE, FALSE,
7478 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
7481 Yspring_kill_eB, FALSE, TRUE,
7482 EL_SPRING, ACTION_EATING, MV_BIT_RIGHT
7485 Yspring_kill_w, FALSE, FALSE,
7486 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7489 Yspring_kill_wB, FALSE, TRUE,
7490 EL_SPRING, ACTION_EATING, MV_BIT_LEFT
7493 Xeater_n, TRUE, FALSE,
7494 EL_YAMYAM_UP, -1, -1
7497 Xeater_e, TRUE, FALSE,
7498 EL_YAMYAM_RIGHT, -1, -1
7501 Xeater_w, TRUE, FALSE,
7502 EL_YAMYAM_LEFT, -1, -1
7505 Xeater_s, TRUE, FALSE,
7506 EL_YAMYAM_DOWN, -1, -1
7509 Yeater_n, FALSE, FALSE,
7510 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7513 Yeater_nB, FALSE, TRUE,
7514 EL_YAMYAM, ACTION_MOVING, MV_BIT_UP
7517 Yeater_e, FALSE, FALSE,
7518 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7521 Yeater_eB, FALSE, TRUE,
7522 EL_YAMYAM, ACTION_MOVING, MV_BIT_RIGHT
7525 Yeater_s, FALSE, FALSE,
7526 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7529 Yeater_sB, FALSE, TRUE,
7530 EL_YAMYAM, ACTION_MOVING, MV_BIT_DOWN
7533 Yeater_w, FALSE, FALSE,
7534 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7537 Yeater_wB, FALSE, TRUE,
7538 EL_YAMYAM, ACTION_MOVING, MV_BIT_LEFT
7541 Yeater_stone, FALSE, FALSE,
7542 EL_YAMYAM, ACTION_SMASHED_BY_ROCK, -1
7545 Yeater_spring, FALSE, FALSE,
7546 EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1
7549 Xalien, TRUE, FALSE,
7553 Xalien_pause, FALSE, FALSE,
7557 Yalien_n, FALSE, FALSE,
7558 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7561 Yalien_nB, FALSE, TRUE,
7562 EL_ROBOT, ACTION_MOVING, MV_BIT_UP
7565 Yalien_e, FALSE, FALSE,
7566 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7569 Yalien_eB, FALSE, TRUE,
7570 EL_ROBOT, ACTION_MOVING, MV_BIT_RIGHT
7573 Yalien_s, FALSE, FALSE,
7574 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7577 Yalien_sB, FALSE, TRUE,
7578 EL_ROBOT, ACTION_MOVING, MV_BIT_DOWN
7581 Yalien_w, FALSE, FALSE,
7582 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7585 Yalien_wB, FALSE, TRUE,
7586 EL_ROBOT, ACTION_MOVING, MV_BIT_LEFT
7589 Yalien_stone, FALSE, FALSE,
7590 EL_ROBOT, ACTION_SMASHED_BY_ROCK, -1
7593 Yalien_spring, FALSE, FALSE,
7594 EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1
7597 Xemerald, TRUE, FALSE,
7601 Xemerald_pause, FALSE, FALSE,
7605 Xemerald_fall, FALSE, FALSE,
7609 Xemerald_shine, FALSE, FALSE,
7610 EL_EMERALD, ACTION_TWINKLING, -1
7613 Yemerald_s, FALSE, FALSE,
7614 EL_EMERALD, ACTION_FALLING, -1
7617 Yemerald_sB, FALSE, TRUE,
7618 EL_EMERALD, ACTION_FALLING, -1
7621 Yemerald_e, FALSE, FALSE,
7622 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7625 Yemerald_eB, FALSE, TRUE,
7626 EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT
7629 Yemerald_w, FALSE, FALSE,
7630 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7633 Yemerald_wB, FALSE, TRUE,
7634 EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT
7637 Yemerald_eat, FALSE, FALSE,
7638 EL_EMERALD, ACTION_COLLECTING, -1
7641 Yemerald_stone, FALSE, FALSE,
7642 EL_NUT, ACTION_BREAKING, -1
7645 Xdiamond, TRUE, FALSE,
7649 Xdiamond_pause, FALSE, FALSE,
7653 Xdiamond_fall, FALSE, FALSE,
7657 Xdiamond_shine, FALSE, FALSE,
7658 EL_DIAMOND, ACTION_TWINKLING, -1
7661 Ydiamond_s, FALSE, FALSE,
7662 EL_DIAMOND, ACTION_FALLING, -1
7665 Ydiamond_sB, FALSE, TRUE,
7666 EL_DIAMOND, ACTION_FALLING, -1
7669 Ydiamond_e, FALSE, FALSE,
7670 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7673 Ydiamond_eB, FALSE, TRUE,
7674 EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT
7677 Ydiamond_w, FALSE, FALSE,
7678 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7681 Ydiamond_wB, FALSE, TRUE,
7682 EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT
7685 Ydiamond_eat, FALSE, FALSE,
7686 EL_DIAMOND, ACTION_COLLECTING, -1
7689 Ydiamond_stone, FALSE, FALSE,
7690 EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1
7693 Xdrip_fall, TRUE, FALSE,
7694 EL_AMOEBA_DROP, -1, -1
7697 Xdrip_stretch, FALSE, FALSE,
7698 EL_AMOEBA_DROP, ACTION_FALLING, -1
7701 Xdrip_stretchB, FALSE, TRUE,
7702 EL_AMOEBA_DROP, ACTION_FALLING, -1
7705 Xdrip_eat, FALSE, FALSE,
7706 EL_AMOEBA_DROP, ACTION_GROWING, -1
7709 Ydrip_s1, FALSE, FALSE,
7710 EL_AMOEBA_DROP, ACTION_FALLING, -1
7713 Ydrip_s1B, FALSE, TRUE,
7714 EL_AMOEBA_DROP, ACTION_FALLING, -1
7717 Ydrip_s2, FALSE, FALSE,
7718 EL_AMOEBA_DROP, ACTION_FALLING, -1
7721 Ydrip_s2B, FALSE, TRUE,
7722 EL_AMOEBA_DROP, ACTION_FALLING, -1
7729 Xbomb_pause, FALSE, FALSE,
7733 Xbomb_fall, FALSE, FALSE,
7737 Ybomb_s, FALSE, FALSE,
7738 EL_BOMB, ACTION_FALLING, -1
7741 Ybomb_sB, FALSE, TRUE,
7742 EL_BOMB, ACTION_FALLING, -1
7745 Ybomb_e, FALSE, FALSE,
7746 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7749 Ybomb_eB, FALSE, TRUE,
7750 EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT
7753 Ybomb_w, FALSE, FALSE,
7754 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7757 Ybomb_wB, FALSE, TRUE,
7758 EL_BOMB, ACTION_MOVING, MV_BIT_LEFT
7761 Ybomb_eat, FALSE, FALSE,
7762 EL_BOMB, ACTION_ACTIVATING, -1
7765 Xballoon, TRUE, FALSE,
7769 Yballoon_n, FALSE, FALSE,
7770 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7773 Yballoon_nB, FALSE, TRUE,
7774 EL_BALLOON, ACTION_MOVING, MV_BIT_UP
7777 Yballoon_e, FALSE, FALSE,
7778 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7781 Yballoon_eB, FALSE, TRUE,
7782 EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT
7785 Yballoon_s, FALSE, FALSE,
7786 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7789 Yballoon_sB, FALSE, TRUE,
7790 EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN
7793 Yballoon_w, FALSE, FALSE,
7794 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7797 Yballoon_wB, FALSE, TRUE,
7798 EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT
7801 Xgrass, TRUE, FALSE,
7802 EL_EMC_GRASS, -1, -1
7805 Ygrass_nB, FALSE, FALSE,
7806 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP
7809 Ygrass_eB, FALSE, FALSE,
7810 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT
7813 Ygrass_sB, FALSE, FALSE,
7814 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN
7817 Ygrass_wB, FALSE, FALSE,
7818 EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT
7825 Ydirt_nB, FALSE, FALSE,
7826 EL_SAND, ACTION_DIGGING, MV_BIT_UP
7829 Ydirt_eB, FALSE, FALSE,
7830 EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT
7833 Ydirt_sB, FALSE, FALSE,
7834 EL_SAND, ACTION_DIGGING, MV_BIT_DOWN
7837 Ydirt_wB, FALSE, FALSE,
7838 EL_SAND, ACTION_DIGGING, MV_BIT_LEFT
7841 Xacid_ne, TRUE, FALSE,
7842 EL_ACID_POOL_TOPRIGHT, -1, -1
7845 Xacid_se, TRUE, FALSE,
7846 EL_ACID_POOL_BOTTOMRIGHT, -1, -1
7849 Xacid_s, TRUE, FALSE,
7850 EL_ACID_POOL_BOTTOM, -1, -1
7853 Xacid_sw, TRUE, FALSE,
7854 EL_ACID_POOL_BOTTOMLEFT, -1, -1
7857 Xacid_nw, TRUE, FALSE,
7858 EL_ACID_POOL_TOPLEFT, -1, -1
7861 Xacid_1, TRUE, FALSE,
7865 Xacid_2, FALSE, FALSE,
7869 Xacid_3, FALSE, FALSE,
7873 Xacid_4, FALSE, FALSE,
7877 Xacid_5, FALSE, FALSE,
7881 Xacid_6, FALSE, FALSE,
7885 Xacid_7, FALSE, FALSE,
7889 Xacid_8, FALSE, FALSE,
7893 Xball_1, TRUE, FALSE,
7894 EL_EMC_MAGIC_BALL, -1, -1
7897 Xball_1B, FALSE, FALSE,
7898 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7901 Xball_2, FALSE, FALSE,
7902 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7905 Xball_2B, FALSE, FALSE,
7906 EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1
7909 Yball_eat, FALSE, FALSE,
7910 EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1
7913 Ykey_1_eat, FALSE, FALSE,
7914 EL_EM_KEY_1, ACTION_COLLECTING, -1
7917 Ykey_2_eat, FALSE, FALSE,
7918 EL_EM_KEY_2, ACTION_COLLECTING, -1
7921 Ykey_3_eat, FALSE, FALSE,
7922 EL_EM_KEY_3, ACTION_COLLECTING, -1
7925 Ykey_4_eat, FALSE, FALSE,
7926 EL_EM_KEY_4, ACTION_COLLECTING, -1
7929 Ykey_5_eat, FALSE, FALSE,
7930 EL_EMC_KEY_5, ACTION_COLLECTING, -1
7933 Ykey_6_eat, FALSE, FALSE,
7934 EL_EMC_KEY_6, ACTION_COLLECTING, -1
7937 Ykey_7_eat, FALSE, FALSE,
7938 EL_EMC_KEY_7, ACTION_COLLECTING, -1
7941 Ykey_8_eat, FALSE, FALSE,
7942 EL_EMC_KEY_8, ACTION_COLLECTING, -1
7945 Ylenses_eat, FALSE, FALSE,
7946 EL_EMC_LENSES, ACTION_COLLECTING, -1
7949 Ymagnify_eat, FALSE, FALSE,
7950 EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1
7953 Ygrass_eat, FALSE, FALSE,
7954 EL_EMC_GRASS, ACTION_SNAPPING, -1
7957 Ydirt_eat, FALSE, FALSE,
7958 EL_SAND, ACTION_SNAPPING, -1
7961 Xgrow_ns, TRUE, FALSE,
7962 EL_EXPANDABLE_WALL_VERTICAL, -1, -1
7965 Ygrow_ns_eat, FALSE, FALSE,
7966 EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
7969 Xgrow_ew, TRUE, FALSE,
7970 EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
7973 Ygrow_ew_eat, FALSE, FALSE,
7974 EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
7977 Xwonderwall, TRUE, FALSE,
7978 EL_MAGIC_WALL, -1, -1
7981 XwonderwallB, FALSE, FALSE,
7982 EL_MAGIC_WALL, ACTION_ACTIVE, -1
7985 Xamoeba_1, TRUE, FALSE,
7986 EL_AMOEBA_DRY, ACTION_OTHER, -1
7989 Xamoeba_2, FALSE, FALSE,
7990 EL_AMOEBA_DRY, ACTION_OTHER, -1
7993 Xamoeba_3, FALSE, FALSE,
7994 EL_AMOEBA_DRY, ACTION_OTHER, -1
7997 Xamoeba_4, FALSE, FALSE,
7998 EL_AMOEBA_DRY, ACTION_OTHER, -1
8001 Xamoeba_5, TRUE, FALSE,
8002 EL_AMOEBA_WET, ACTION_OTHER, -1
8005 Xamoeba_6, FALSE, FALSE,
8006 EL_AMOEBA_WET, ACTION_OTHER, -1
8009 Xamoeba_7, FALSE, FALSE,
8010 EL_AMOEBA_WET, ACTION_OTHER, -1
8013 Xamoeba_8, FALSE, FALSE,
8014 EL_AMOEBA_WET, ACTION_OTHER, -1
8017 Xdoor_1, TRUE, FALSE,
8018 EL_EM_GATE_1, -1, -1
8021 Xdoor_2, TRUE, FALSE,
8022 EL_EM_GATE_2, -1, -1
8025 Xdoor_3, TRUE, FALSE,
8026 EL_EM_GATE_3, -1, -1
8029 Xdoor_4, TRUE, FALSE,
8030 EL_EM_GATE_4, -1, -1
8033 Xdoor_5, TRUE, FALSE,
8034 EL_EMC_GATE_5, -1, -1
8037 Xdoor_6, TRUE, FALSE,
8038 EL_EMC_GATE_6, -1, -1
8041 Xdoor_7, TRUE, FALSE,
8042 EL_EMC_GATE_7, -1, -1
8045 Xdoor_8, TRUE, FALSE,
8046 EL_EMC_GATE_8, -1, -1
8049 Xkey_1, TRUE, FALSE,
8053 Xkey_2, TRUE, FALSE,
8057 Xkey_3, TRUE, FALSE,
8061 Xkey_4, TRUE, FALSE,
8065 Xkey_5, TRUE, FALSE,
8066 EL_EMC_KEY_5, -1, -1
8069 Xkey_6, TRUE, FALSE,
8070 EL_EMC_KEY_6, -1, -1
8073 Xkey_7, TRUE, FALSE,
8074 EL_EMC_KEY_7, -1, -1
8077 Xkey_8, TRUE, FALSE,
8078 EL_EMC_KEY_8, -1, -1
8081 Xwind_n, TRUE, FALSE,
8082 EL_BALLOON_SWITCH_UP, -1, -1
8085 Xwind_e, TRUE, FALSE,
8086 EL_BALLOON_SWITCH_RIGHT, -1, -1
8089 Xwind_s, TRUE, FALSE,
8090 EL_BALLOON_SWITCH_DOWN, -1, -1
8093 Xwind_w, TRUE, FALSE,
8094 EL_BALLOON_SWITCH_LEFT, -1, -1
8097 Xwind_nesw, TRUE, FALSE,
8098 EL_BALLOON_SWITCH_ANY, -1, -1
8101 Xwind_stop, TRUE, FALSE,
8102 EL_BALLOON_SWITCH_NONE, -1, -1
8106 EL_EM_EXIT_CLOSED, -1, -1
8109 Xexit_1, TRUE, FALSE,
8110 EL_EM_EXIT_OPEN, -1, -1
8113 Xexit_2, FALSE, FALSE,
8114 EL_EM_EXIT_OPEN, -1, -1
8117 Xexit_3, FALSE, FALSE,
8118 EL_EM_EXIT_OPEN, -1, -1
8121 Xdynamite, TRUE, FALSE,
8122 EL_EM_DYNAMITE, -1, -1
8125 Ydynamite_eat, FALSE, FALSE,
8126 EL_EM_DYNAMITE, ACTION_COLLECTING, -1
8129 Xdynamite_1, TRUE, FALSE,
8130 EL_EM_DYNAMITE_ACTIVE, -1, -1
8133 Xdynamite_2, FALSE, FALSE,
8134 EL_EM_DYNAMITE_ACTIVE, -1, -1
8137 Xdynamite_3, FALSE, FALSE,
8138 EL_EM_DYNAMITE_ACTIVE, -1, -1
8141 Xdynamite_4, FALSE, FALSE,
8142 EL_EM_DYNAMITE_ACTIVE, -1, -1
8145 Xbumper, TRUE, FALSE,
8146 EL_EMC_SPRING_BUMPER, -1, -1
8149 XbumperB, FALSE, FALSE,
8150 EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
8153 Xwheel, TRUE, FALSE,
8154 EL_ROBOT_WHEEL, -1, -1
8157 XwheelB, FALSE, FALSE,
8158 EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
8161 Xswitch, TRUE, FALSE,
8162 EL_EMC_MAGIC_BALL_SWITCH, -1, -1
8165 XswitchB, FALSE, FALSE,
8166 EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
8170 EL_QUICKSAND_EMPTY, -1, -1
8173 Xsand_stone, TRUE, FALSE,
8174 EL_QUICKSAND_FULL, -1, -1
8177 Xsand_stonein_1, FALSE, TRUE,
8178 EL_ROCK, ACTION_FILLING, -1
8181 Xsand_stonein_2, FALSE, TRUE,
8182 EL_ROCK, ACTION_FILLING, -1
8185 Xsand_stonein_3, FALSE, TRUE,
8186 EL_ROCK, ACTION_FILLING, -1
8189 Xsand_stonein_4, FALSE, TRUE,
8190 EL_ROCK, ACTION_FILLING, -1
8194 Xsand_stonesand_1, FALSE, FALSE,
8195 EL_QUICKSAND_EMPTYING, -1, -1
8198 Xsand_stonesand_2, FALSE, FALSE,
8199 EL_QUICKSAND_EMPTYING, -1, -1
8202 Xsand_stonesand_3, FALSE, FALSE,
8203 EL_QUICKSAND_EMPTYING, -1, -1
8206 Xsand_stonesand_4, FALSE, FALSE,
8207 EL_QUICKSAND_EMPTYING, -1, -1
8210 Xsand_stonesand_quickout_1, FALSE, FALSE,
8211 EL_QUICKSAND_EMPTYING, -1, -1
8214 Xsand_stonesand_quickout_2, FALSE, FALSE,
8215 EL_QUICKSAND_EMPTYING, -1, -1
8219 Xsand_stonesand_1, FALSE, FALSE,
8220 EL_QUICKSAND_FULL, -1, -1
8223 Xsand_stonesand_2, FALSE, FALSE,
8224 EL_QUICKSAND_FULL, -1, -1
8227 Xsand_stonesand_3, FALSE, FALSE,
8228 EL_QUICKSAND_FULL, -1, -1
8231 Xsand_stonesand_4, FALSE, FALSE,
8232 EL_QUICKSAND_FULL, -1, -1
8236 Xsand_stoneout_1, FALSE, FALSE,
8237 EL_ROCK, ACTION_EMPTYING, -1
8240 Xsand_stoneout_2, FALSE, FALSE,
8241 EL_ROCK, ACTION_EMPTYING, -1
8245 Xsand_sandstone_1, FALSE, FALSE,
8246 EL_QUICKSAND_FILLING, -1, -1
8249 Xsand_sandstone_2, FALSE, FALSE,
8250 EL_QUICKSAND_FILLING, -1, -1
8253 Xsand_sandstone_3, FALSE, FALSE,
8254 EL_QUICKSAND_FILLING, -1, -1
8257 Xsand_sandstone_4, FALSE, FALSE,
8258 EL_QUICKSAND_FILLING, -1, -1
8262 Xsand_sandstone_1, FALSE, FALSE,
8263 EL_QUICKSAND_FULL, -1, -1
8266 Xsand_sandstone_2, FALSE, FALSE,
8267 EL_QUICKSAND_FULL, -1, -1
8270 Xsand_sandstone_3, FALSE, FALSE,
8271 EL_QUICKSAND_FULL, -1, -1
8274 Xsand_sandstone_4, FALSE, FALSE,
8275 EL_QUICKSAND_FULL, -1, -1
8279 Xplant, TRUE, FALSE,
8280 EL_EMC_PLANT, -1, -1
8283 Yplant, FALSE, FALSE,
8284 EL_EMC_PLANT, -1, -1
8287 Xlenses, TRUE, FALSE,
8288 EL_EMC_LENSES, -1, -1
8291 Xmagnify, TRUE, FALSE,
8292 EL_EMC_MAGNIFIER, -1, -1
8295 Xdripper, TRUE, FALSE,
8296 EL_EMC_DRIPPER, -1, -1
8299 XdripperB, FALSE, FALSE,
8300 EL_EMC_DRIPPER, ACTION_ACTIVE, -1
8303 Xfake_blank, TRUE, FALSE,
8304 EL_INVISIBLE_WALL, -1, -1
8307 Xfake_blankB, FALSE, FALSE,
8308 EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
8311 Xfake_grass, TRUE, FALSE,
8312 EL_EMC_FAKE_GRASS, -1, -1
8315 Xfake_grassB, FALSE, FALSE,
8316 EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
8319 Xfake_door_1, TRUE, FALSE,
8320 EL_EM_GATE_1_GRAY, -1, -1
8323 Xfake_door_2, TRUE, FALSE,
8324 EL_EM_GATE_2_GRAY, -1, -1
8327 Xfake_door_3, TRUE, FALSE,
8328 EL_EM_GATE_3_GRAY, -1, -1
8331 Xfake_door_4, TRUE, FALSE,
8332 EL_EM_GATE_4_GRAY, -1, -1
8335 Xfake_door_5, TRUE, FALSE,
8336 EL_EMC_GATE_5_GRAY, -1, -1
8339 Xfake_door_6, TRUE, FALSE,
8340 EL_EMC_GATE_6_GRAY, -1, -1
8343 Xfake_door_7, TRUE, FALSE,
8344 EL_EMC_GATE_7_GRAY, -1, -1
8347 Xfake_door_8, TRUE, FALSE,
8348 EL_EMC_GATE_8_GRAY, -1, -1
8351 Xfake_acid_1, TRUE, FALSE,
8352 EL_EMC_FAKE_ACID, -1, -1
8355 Xfake_acid_2, FALSE, FALSE,
8356 EL_EMC_FAKE_ACID, -1, -1
8359 Xfake_acid_3, FALSE, FALSE,
8360 EL_EMC_FAKE_ACID, -1, -1
8363 Xfake_acid_4, FALSE, FALSE,
8364 EL_EMC_FAKE_ACID, -1, -1
8367 Xfake_acid_5, FALSE, FALSE,
8368 EL_EMC_FAKE_ACID, -1, -1
8371 Xfake_acid_6, FALSE, FALSE,
8372 EL_EMC_FAKE_ACID, -1, -1
8375 Xfake_acid_7, FALSE, FALSE,
8376 EL_EMC_FAKE_ACID, -1, -1
8379 Xfake_acid_8, FALSE, FALSE,
8380 EL_EMC_FAKE_ACID, -1, -1
8383 Xsteel_1, TRUE, FALSE,
8384 EL_STEELWALL, -1, -1
8387 Xsteel_2, TRUE, FALSE,
8388 EL_EMC_STEELWALL_2, -1, -1
8391 Xsteel_3, TRUE, FALSE,
8392 EL_EMC_STEELWALL_3, -1, -1
8395 Xsteel_4, TRUE, FALSE,
8396 EL_EMC_STEELWALL_4, -1, -1
8399 Xwall_1, TRUE, FALSE,
8403 Xwall_2, TRUE, FALSE,
8404 EL_EMC_WALL_14, -1, -1
8407 Xwall_3, TRUE, FALSE,
8408 EL_EMC_WALL_15, -1, -1
8411 Xwall_4, TRUE, FALSE,
8412 EL_EMC_WALL_16, -1, -1
8415 Xround_wall_1, TRUE, FALSE,
8416 EL_WALL_SLIPPERY, -1, -1
8419 Xround_wall_2, TRUE, FALSE,
8420 EL_EMC_WALL_SLIPPERY_2, -1, -1
8423 Xround_wall_3, TRUE, FALSE,
8424 EL_EMC_WALL_SLIPPERY_3, -1, -1
8427 Xround_wall_4, TRUE, FALSE,
8428 EL_EMC_WALL_SLIPPERY_4, -1, -1
8431 Xdecor_1, TRUE, FALSE,
8432 EL_EMC_WALL_8, -1, -1
8435 Xdecor_2, TRUE, FALSE,
8436 EL_EMC_WALL_6, -1, -1
8439 Xdecor_3, TRUE, FALSE,
8440 EL_EMC_WALL_4, -1, -1
8443 Xdecor_4, TRUE, FALSE,
8444 EL_EMC_WALL_7, -1, -1
8447 Xdecor_5, TRUE, FALSE,
8448 EL_EMC_WALL_5, -1, -1
8451 Xdecor_6, TRUE, FALSE,
8452 EL_EMC_WALL_9, -1, -1
8455 Xdecor_7, TRUE, FALSE,
8456 EL_EMC_WALL_10, -1, -1
8459 Xdecor_8, TRUE, FALSE,
8460 EL_EMC_WALL_1, -1, -1
8463 Xdecor_9, TRUE, FALSE,
8464 EL_EMC_WALL_2, -1, -1
8467 Xdecor_10, TRUE, FALSE,
8468 EL_EMC_WALL_3, -1, -1
8471 Xdecor_11, TRUE, FALSE,
8472 EL_EMC_WALL_11, -1, -1
8475 Xdecor_12, TRUE, FALSE,
8476 EL_EMC_WALL_12, -1, -1
8479 Xalpha_0, TRUE, FALSE,
8480 EL_CHAR('0'), -1, -1
8483 Xalpha_1, TRUE, FALSE,
8484 EL_CHAR('1'), -1, -1
8487 Xalpha_2, TRUE, FALSE,
8488 EL_CHAR('2'), -1, -1
8491 Xalpha_3, TRUE, FALSE,
8492 EL_CHAR('3'), -1, -1
8495 Xalpha_4, TRUE, FALSE,
8496 EL_CHAR('4'), -1, -1
8499 Xalpha_5, TRUE, FALSE,
8500 EL_CHAR('5'), -1, -1
8503 Xalpha_6, TRUE, FALSE,
8504 EL_CHAR('6'), -1, -1
8507 Xalpha_7, TRUE, FALSE,
8508 EL_CHAR('7'), -1, -1
8511 Xalpha_8, TRUE, FALSE,
8512 EL_CHAR('8'), -1, -1
8515 Xalpha_9, TRUE, FALSE,
8516 EL_CHAR('9'), -1, -1
8519 Xalpha_excla, TRUE, FALSE,
8520 EL_CHAR('!'), -1, -1
8523 Xalpha_quote, TRUE, FALSE,
8524 EL_CHAR('"'), -1, -1
8527 Xalpha_comma, TRUE, FALSE,
8528 EL_CHAR(','), -1, -1
8531 Xalpha_minus, TRUE, FALSE,
8532 EL_CHAR('-'), -1, -1
8535 Xalpha_perio, TRUE, FALSE,
8536 EL_CHAR('.'), -1, -1
8539 Xalpha_colon, TRUE, FALSE,
8540 EL_CHAR(':'), -1, -1
8543 Xalpha_quest, TRUE, FALSE,
8544 EL_CHAR('?'), -1, -1
8547 Xalpha_a, TRUE, FALSE,
8548 EL_CHAR('A'), -1, -1
8551 Xalpha_b, TRUE, FALSE,
8552 EL_CHAR('B'), -1, -1
8555 Xalpha_c, TRUE, FALSE,
8556 EL_CHAR('C'), -1, -1
8559 Xalpha_d, TRUE, FALSE,
8560 EL_CHAR('D'), -1, -1
8563 Xalpha_e, TRUE, FALSE,
8564 EL_CHAR('E'), -1, -1
8567 Xalpha_f, TRUE, FALSE,
8568 EL_CHAR('F'), -1, -1
8571 Xalpha_g, TRUE, FALSE,
8572 EL_CHAR('G'), -1, -1
8575 Xalpha_h, TRUE, FALSE,
8576 EL_CHAR('H'), -1, -1
8579 Xalpha_i, TRUE, FALSE,
8580 EL_CHAR('I'), -1, -1
8583 Xalpha_j, TRUE, FALSE,
8584 EL_CHAR('J'), -1, -1
8587 Xalpha_k, TRUE, FALSE,
8588 EL_CHAR('K'), -1, -1
8591 Xalpha_l, TRUE, FALSE,
8592 EL_CHAR('L'), -1, -1
8595 Xalpha_m, TRUE, FALSE,
8596 EL_CHAR('M'), -1, -1
8599 Xalpha_n, TRUE, FALSE,
8600 EL_CHAR('N'), -1, -1
8603 Xalpha_o, TRUE, FALSE,
8604 EL_CHAR('O'), -1, -1
8607 Xalpha_p, TRUE, FALSE,
8608 EL_CHAR('P'), -1, -1
8611 Xalpha_q, TRUE, FALSE,
8612 EL_CHAR('Q'), -1, -1
8615 Xalpha_r, TRUE, FALSE,
8616 EL_CHAR('R'), -1, -1
8619 Xalpha_s, TRUE, FALSE,
8620 EL_CHAR('S'), -1, -1
8623 Xalpha_t, TRUE, FALSE,
8624 EL_CHAR('T'), -1, -1
8627 Xalpha_u, TRUE, FALSE,
8628 EL_CHAR('U'), -1, -1
8631 Xalpha_v, TRUE, FALSE,
8632 EL_CHAR('V'), -1, -1
8635 Xalpha_w, TRUE, FALSE,
8636 EL_CHAR('W'), -1, -1
8639 Xalpha_x, TRUE, FALSE,
8640 EL_CHAR('X'), -1, -1
8643 Xalpha_y, TRUE, FALSE,
8644 EL_CHAR('Y'), -1, -1
8647 Xalpha_z, TRUE, FALSE,
8648 EL_CHAR('Z'), -1, -1
8651 Xalpha_arrow_e, TRUE, FALSE,
8652 EL_CHAR('>'), -1, -1
8655 Xalpha_arrow_w, TRUE, FALSE,
8656 EL_CHAR('<'), -1, -1
8659 Xalpha_copyr, TRUE, FALSE,
8660 EL_CHAR('©'), -1, -1
8664 Xboom_bug, FALSE, FALSE,
8665 EL_BUG, ACTION_EXPLODING, -1
8668 Xboom_bomb, FALSE, FALSE,
8669 EL_BOMB, ACTION_EXPLODING, -1
8672 Xboom_android, FALSE, FALSE,
8673 EL_EMC_ANDROID, ACTION_OTHER, -1
8676 Xboom_1, FALSE, FALSE,
8677 EL_DEFAULT, ACTION_EXPLODING, -1
8680 Xboom_2, FALSE, FALSE,
8681 EL_DEFAULT, ACTION_EXPLODING, -1
8684 Znormal, FALSE, FALSE,
8688 Zdynamite, FALSE, FALSE,
8692 Zplayer, FALSE, FALSE,
8696 ZBORDER, FALSE, FALSE,
8706 static struct Mapping_EM_to_RND_player
8715 em_player_mapping_list[] =
8719 EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP,
8723 EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT,
8727 EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN,
8731 EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT,
8735 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP,
8739 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT,
8743 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN,
8747 EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT,
8751 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP,
8755 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT,
8759 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN,
8763 EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT,
8767 EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP,
8771 EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT,
8775 EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN,
8779 EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT,
8783 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP,
8787 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT,
8791 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN,
8795 EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT,
8799 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP,
8803 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT,
8807 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN,
8811 EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT,
8815 EL_PLAYER_1, ACTION_DEFAULT, -1,
8819 EL_PLAYER_2, ACTION_DEFAULT, -1,
8823 EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP,
8827 EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT,
8831 EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN,
8835 EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT,
8839 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP,
8843 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT,
8847 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN,
8851 EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT,
8855 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP,
8859 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT,
8863 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN,
8867 EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT,
8871 EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP,
8875 EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT,
8879 EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN,
8883 EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT,
8887 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP,
8891 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT,
8895 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN,
8899 EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT,
8903 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP,
8907 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT,
8911 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN,
8915 EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT,
8919 EL_PLAYER_3, ACTION_DEFAULT, -1,
8923 EL_PLAYER_4, ACTION_DEFAULT, -1,
8932 int map_element_RND_to_EM(int element_rnd)
8934 static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
8935 static boolean mapping_initialized = FALSE;
8937 if (!mapping_initialized)
8941 /* return "Xalpha_quest" for all undefined elements in mapping array */
8942 for (i = 0; i < NUM_FILE_ELEMENTS; i++)
8943 mapping_RND_to_EM[i] = Xalpha_quest;
8945 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
8946 if (em_object_mapping_list[i].is_rnd_to_em_mapping)
8947 mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
8948 em_object_mapping_list[i].element_em;
8950 mapping_initialized = TRUE;
8953 if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
8954 return mapping_RND_to_EM[element_rnd];
8956 Error(ERR_WARN, "invalid RND level element %d", element_rnd);
8961 int map_element_EM_to_RND(int element_em)
8963 static unsigned short mapping_EM_to_RND[TILE_MAX];
8964 static boolean mapping_initialized = FALSE;
8966 if (!mapping_initialized)
8970 /* return "EL_UNKNOWN" for all undefined elements in mapping array */
8971 for (i = 0; i < TILE_MAX; i++)
8972 mapping_EM_to_RND[i] = EL_UNKNOWN;
8974 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
8975 mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
8976 em_object_mapping_list[i].element_rnd;
8978 mapping_initialized = TRUE;
8981 if (element_em >= 0 && element_em < TILE_MAX)
8982 return mapping_EM_to_RND[element_em];
8984 Error(ERR_WARN, "invalid EM level element %d", element_em);
8989 void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
8991 struct LevelInfo_EM *level_em = level->native_em_level;
8992 struct LEVEL *lev = level_em->lev;
8995 for (i = 0; i < TILE_MAX; i++)
8996 lev->android_array[i] = Xblank;
8998 for (i = 0; i < level->num_android_clone_elements; i++)
9000 int element_rnd = level->android_clone_element[i];
9001 int element_em = map_element_RND_to_EM(element_rnd);
9003 for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
9004 if (em_object_mapping_list[j].element_rnd == element_rnd)
9005 lev->android_array[em_object_mapping_list[j].element_em] = element_em;
9009 void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
9011 struct LevelInfo_EM *level_em = level->native_em_level;
9012 struct LEVEL *lev = level_em->lev;
9015 level->num_android_clone_elements = 0;
9017 for (i = 0; i < TILE_MAX; i++)
9019 int element_em = lev->android_array[i];
9021 boolean element_found = FALSE;
9023 if (element_em == Xblank)
9026 element_rnd = map_element_EM_to_RND(element_em);
9028 for (j = 0; j < level->num_android_clone_elements; j++)
9029 if (level->android_clone_element[j] == element_rnd)
9030 element_found = TRUE;
9034 level->android_clone_element[level->num_android_clone_elements++] =
9037 if (level->num_android_clone_elements == MAX_ANDROID_ELEMENTS)
9042 if (level->num_android_clone_elements == 0)
9044 level->num_android_clone_elements = 1;
9045 level->android_clone_element[0] = EL_EMPTY;
9049 int map_direction_RND_to_EM(int direction)
9051 return (direction == MV_UP ? 0 :
9052 direction == MV_RIGHT ? 1 :
9053 direction == MV_DOWN ? 2 :
9054 direction == MV_LEFT ? 3 :
9058 int map_direction_EM_to_RND(int direction)
9060 return (direction == 0 ? MV_UP :
9061 direction == 1 ? MV_RIGHT :
9062 direction == 2 ? MV_DOWN :
9063 direction == 3 ? MV_LEFT :
9067 int map_element_RND_to_SP(int element_rnd)
9069 int element_sp = 0x20; /* map unknown elements to yellow "hardware" */
9071 if (element_rnd >= EL_SP_START &&
9072 element_rnd <= EL_SP_END)
9073 element_sp = element_rnd - EL_SP_START;
9074 else if (element_rnd == EL_EMPTY_SPACE)
9076 else if (element_rnd == EL_INVISIBLE_WALL)
9082 int map_element_SP_to_RND(int element_sp)
9084 int element_rnd = EL_UNKNOWN;
9086 if (element_sp >= 0x00 &&
9088 element_rnd = EL_SP_START + element_sp;
9089 else if (element_sp == 0x28)
9090 element_rnd = EL_INVISIBLE_WALL;
9095 int map_action_SP_to_RND(int action_sp)
9099 case actActive: return ACTION_ACTIVE;
9100 case actImpact: return ACTION_IMPACT;
9101 case actExploding: return ACTION_EXPLODING;
9102 case actDigging: return ACTION_DIGGING;
9103 case actSnapping: return ACTION_SNAPPING;
9104 case actCollecting: return ACTION_COLLECTING;
9105 case actPassing: return ACTION_PASSING;
9106 case actPushing: return ACTION_PUSHING;
9107 case actDropping: return ACTION_DROPPING;
9109 default: return ACTION_DEFAULT;
9113 int get_next_element(int element)
9117 case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL;
9118 case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY;
9119 case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL;
9120 case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY;
9121 case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL;
9122 case EL_MAGIC_WALL_EMPTYING: return EL_MAGIC_WALL_ACTIVE;
9123 case EL_BD_MAGIC_WALL_FILLING: return EL_BD_MAGIC_WALL_FULL;
9124 case EL_BD_MAGIC_WALL_EMPTYING: return EL_BD_MAGIC_WALL_ACTIVE;
9125 case EL_DC_MAGIC_WALL_FILLING: return EL_DC_MAGIC_WALL_FULL;
9126 case EL_DC_MAGIC_WALL_EMPTYING: return EL_DC_MAGIC_WALL_ACTIVE;
9127 case EL_AMOEBA_DROPPING: return EL_AMOEBA_WET;
9129 default: return element;
9134 int el_act_dir2img(int element, int action, int direction)
9136 element = GFX_ELEMENT(element);
9138 if (direction == MV_NONE)
9139 return element_info[element].graphic[action];
9141 direction = MV_DIR_TO_BIT(direction);
9143 return element_info[element].direction_graphic[action][direction];
9146 int el_act_dir2img(int element, int action, int direction)
9148 element = GFX_ELEMENT(element);
9149 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
9151 /* direction_graphic[][] == graphic[] for undefined direction graphics */
9152 return element_info[element].direction_graphic[action][direction];
9157 static int el_act_dir2crm(int element, int action, int direction)
9159 element = GFX_ELEMENT(element);
9161 if (direction == MV_NONE)
9162 return element_info[element].crumbled[action];
9164 direction = MV_DIR_TO_BIT(direction);
9166 return element_info[element].direction_crumbled[action][direction];
9169 static int el_act_dir2crm(int element, int action, int direction)
9171 element = GFX_ELEMENT(element);
9172 direction = MV_DIR_TO_BIT(direction); /* default: MV_NONE => MV_DOWN */
9174 /* direction_graphic[][] == graphic[] for undefined direction graphics */
9175 return element_info[element].direction_crumbled[action][direction];
9179 int el_act2img(int element, int action)
9181 element = GFX_ELEMENT(element);
9183 return element_info[element].graphic[action];
9186 int el_act2crm(int element, int action)
9188 element = GFX_ELEMENT(element);
9190 return element_info[element].crumbled[action];
9193 int el_dir2img(int element, int direction)
9195 element = GFX_ELEMENT(element);
9197 return el_act_dir2img(element, ACTION_DEFAULT, direction);
9200 int el2baseimg(int element)
9202 return element_info[element].graphic[ACTION_DEFAULT];
9205 int el2img(int element)
9207 element = GFX_ELEMENT(element);
9209 return element_info[element].graphic[ACTION_DEFAULT];
9212 int el2edimg(int element)
9214 element = GFX_ELEMENT(element);
9216 return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
9219 int el2preimg(int element)
9221 element = GFX_ELEMENT(element);
9223 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
9226 int el2panelimg(int element)
9228 element = GFX_ELEMENT(element);
9230 return element_info[element].special_graphic[GFX_SPECIAL_ARG_PANEL];
9233 int font2baseimg(int font_nr)
9235 return font_info[font_nr].special_graphic[GFX_SPECIAL_ARG_DEFAULT];
9238 int getBeltNrFromBeltElement(int element)
9240 return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 :
9241 element < EL_CONVEYOR_BELT_3_LEFT ? 1 :
9242 element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3);
9245 int getBeltNrFromBeltActiveElement(int element)
9247 return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 :
9248 element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 :
9249 element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3);
9252 int getBeltNrFromBeltSwitchElement(int element)
9254 return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 :
9255 element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 :
9256 element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3);
9259 int getBeltDirNrFromBeltElement(int element)
9261 static int belt_base_element[4] =
9263 EL_CONVEYOR_BELT_1_LEFT,
9264 EL_CONVEYOR_BELT_2_LEFT,
9265 EL_CONVEYOR_BELT_3_LEFT,
9266 EL_CONVEYOR_BELT_4_LEFT
9269 int belt_nr = getBeltNrFromBeltElement(element);
9270 int belt_dir_nr = element - belt_base_element[belt_nr];
9272 return (belt_dir_nr % 3);
9275 int getBeltDirNrFromBeltSwitchElement(int element)
9277 static int belt_base_element[4] =
9279 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
9280 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
9281 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
9282 EL_CONVEYOR_BELT_4_SWITCH_LEFT
9285 int belt_nr = getBeltNrFromBeltSwitchElement(element);
9286 int belt_dir_nr = element - belt_base_element[belt_nr];
9288 return (belt_dir_nr % 3);
9291 int getBeltDirFromBeltElement(int element)
9293 static int belt_move_dir[3] =
9300 int belt_dir_nr = getBeltDirNrFromBeltElement(element);
9302 return belt_move_dir[belt_dir_nr];
9305 int getBeltDirFromBeltSwitchElement(int element)
9307 static int belt_move_dir[3] =
9314 int belt_dir_nr = getBeltDirNrFromBeltSwitchElement(element);
9316 return belt_move_dir[belt_dir_nr];
9319 int getBeltElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
9321 static int belt_base_element[4] =
9323 EL_CONVEYOR_BELT_1_LEFT,
9324 EL_CONVEYOR_BELT_2_LEFT,
9325 EL_CONVEYOR_BELT_3_LEFT,
9326 EL_CONVEYOR_BELT_4_LEFT
9329 return belt_base_element[belt_nr] + belt_dir_nr;
9332 int getBeltElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
9334 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
9336 return getBeltElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
9339 int getBeltSwitchElementFromBeltNrAndBeltDirNr(int belt_nr, int belt_dir_nr)
9341 static int belt_base_element[4] =
9343 EL_CONVEYOR_BELT_1_SWITCH_LEFT,
9344 EL_CONVEYOR_BELT_2_SWITCH_LEFT,
9345 EL_CONVEYOR_BELT_3_SWITCH_LEFT,
9346 EL_CONVEYOR_BELT_4_SWITCH_LEFT
9349 return belt_base_element[belt_nr] + belt_dir_nr;
9352 int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir)
9354 int belt_dir_nr = (belt_dir == MV_LEFT ? 0 : belt_dir == MV_RIGHT ? 2 : 1);
9356 return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
9360 boolean getTeamMode_EM()
9362 return game.team_mode;
9365 int getNumActivePlayers_EM()
9368 int num_players = 0;
9372 return (setup.team_mode ? MAX_PLAYERS : 1);
9374 for (i = 0; i < MAX_PLAYERS; i++)
9375 if (tape.player_participates[i])
9378 return (num_players > 1 ? MAX_PLAYERS : 1);
9382 int num_players = 0;
9385 /* when recording game, activate all connected players */
9389 for (i = 0; i < MAX_PLAYERS; i++)
9390 if (tape.player_participates[i])
9398 int getGameFrameDelay_EM(int native_em_game_frame_delay)
9400 int game_frame_delay_value;
9402 game_frame_delay_value =
9403 (tape.playing && tape.fast_forward ? FfwdFrameDelay :
9404 GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
9407 if (tape.playing && tape.warp_forward && !tape.pausing)
9408 game_frame_delay_value = 0;
9410 return game_frame_delay_value;
9413 unsigned int InitRND(int seed)
9415 if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
9416 return InitEngineRandom_EM(seed);
9417 else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
9418 return InitEngineRandom_SP(seed);
9420 return InitEngineRandom_RND(seed);
9424 static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
9425 static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
9428 inline static int get_effective_element_EM(int tile, int frame_em)
9430 int element = object_mapping[tile].element_rnd;
9431 int action = object_mapping[tile].action;
9432 boolean is_backside = object_mapping[tile].is_backside;
9433 boolean action_removing = (action == ACTION_DIGGING ||
9434 action == ACTION_SNAPPING ||
9435 action == ACTION_COLLECTING);
9441 case Yacid_splash_eB:
9442 case Yacid_splash_wB:
9443 return (frame_em > 5 ? EL_EMPTY : element);
9447 case Ydiamond_stone:
9448 // if (!game.use_native_emc_graphics_engine)
9456 else /* frame_em == 7 */
9460 case Yacid_splash_eB:
9461 case Yacid_splash_wB:
9464 case Yemerald_stone:
9467 case Ydiamond_stone:
9471 case Xdrip_stretchB:
9490 case Xsand_stonein_1:
9491 case Xsand_stonein_2:
9492 case Xsand_stonein_3:
9493 case Xsand_stonein_4:
9497 return (is_backside || action_removing ? EL_EMPTY : element);
9502 inline static boolean check_linear_animation_EM(int tile)
9506 case Xsand_stonesand_1:
9507 case Xsand_stonesand_quickout_1:
9508 case Xsand_sandstone_1:
9509 case Xsand_stonein_1:
9510 case Xsand_stoneout_1:
9530 case Yacid_splash_eB:
9531 case Yacid_splash_wB:
9532 case Yemerald_stone:
9540 inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em,
9541 boolean has_crumbled_graphics,
9542 int crumbled, int sync_frame)
9544 /* if element can be crumbled, but certain action graphics are just empty
9545 space (like instantly snapping sand to empty space in 1 frame), do not
9546 treat these empty space graphics as crumbled graphics in EMC engine */
9547 if (crumbled == IMG_EMPTY_SPACE)
9548 has_crumbled_graphics = FALSE;
9550 if (has_crumbled_graphics)
9552 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9553 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
9554 g_crumbled->anim_delay,
9555 g_crumbled->anim_mode,
9556 g_crumbled->anim_start_frame,
9559 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
9560 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
9562 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
9564 g_em->has_crumbled_graphics = TRUE;
9568 g_em->crumbled_bitmap = NULL;
9569 g_em->crumbled_src_x = 0;
9570 g_em->crumbled_src_y = 0;
9571 g_em->crumbled_border_size = 0;
9573 g_em->has_crumbled_graphics = FALSE;
9577 void ResetGfxAnimation_EM(int x, int y, int tile)
9582 void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em,
9583 int tile, int frame_em, int x, int y)
9585 int action = object_mapping[tile].action;
9587 int direction = object_mapping[tile].direction;
9588 int effective_element = get_effective_element_EM(tile, frame_em);
9589 int graphic = (direction == MV_NONE ?
9590 el_act2img(effective_element, action) :
9591 el_act_dir2img(effective_element, action, direction));
9592 struct GraphicInfo *g = &graphic_info[graphic];
9595 boolean action_removing = (action == ACTION_DIGGING ||
9596 action == ACTION_SNAPPING ||
9597 action == ACTION_COLLECTING);
9598 boolean action_moving = (action == ACTION_FALLING ||
9599 action == ACTION_MOVING ||
9600 action == ACTION_PUSHING ||
9601 action == ACTION_EATING ||
9602 action == ACTION_FILLING ||
9603 action == ACTION_EMPTYING);
9604 boolean action_falling = (action == ACTION_FALLING ||
9605 action == ACTION_FILLING ||
9606 action == ACTION_EMPTYING);
9608 /* special case: graphic uses "2nd movement tile" and has defined
9609 7 frames for movement animation (or less) => use default graphic
9610 for last (8th) frame which ends the movement animation */
9611 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9613 action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */
9614 graphic = (direction == MV_NONE ?
9615 el_act2img(effective_element, action) :
9616 el_act_dir2img(effective_element, action, direction));
9618 g = &graphic_info[graphic];
9622 if (tile == Xsand_stonesand_1 ||
9623 tile == Xsand_stonesand_2 ||
9624 tile == Xsand_stonesand_3 ||
9625 tile == Xsand_stonesand_4)
9626 printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9630 if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0)
9634 // printf("::: resetting... [%d]\n", tile);
9637 if (action_removing || check_linear_animation_EM(tile))
9639 GfxFrame[x][y] = frame_em;
9641 // printf("::: resetting... [%d]\n", tile);
9644 else if (action_moving)
9646 boolean is_backside = object_mapping[tile].is_backside;
9650 int direction = object_mapping[tile].direction;
9651 int move_dir = (action_falling ? MV_DOWN : direction);
9656 /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */
9657 if (g->double_movement && frame_em == 0)
9661 // printf("::: resetting... [%d]\n", tile);
9665 if (move_dir == MV_LEFT)
9666 GfxFrame[x - 1][y] = GfxFrame[x][y];
9667 else if (move_dir == MV_RIGHT)
9668 GfxFrame[x + 1][y] = GfxFrame[x][y];
9669 else if (move_dir == MV_UP)
9670 GfxFrame[x][y - 1] = GfxFrame[x][y];
9671 else if (move_dir == MV_DOWN)
9672 GfxFrame[x][y + 1] = GfxFrame[x][y];
9679 /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */
9680 if (tile == Xsand_stonesand_quickout_1 ||
9681 tile == Xsand_stonesand_quickout_2)
9686 if (tile == Xsand_stonesand_1 ||
9687 tile == Xsand_stonesand_2 ||
9688 tile == Xsand_stonesand_3 ||
9689 tile == Xsand_stonesand_4)
9690 printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile);
9694 if (graphic_info[graphic].anim_global_sync)
9695 sync_frame = FrameCounter;
9696 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9697 sync_frame = GfxFrame[x][y];
9699 sync_frame = 0; /* playfield border (pseudo steel) */
9701 SetRandomAnimationValue(x, y);
9703 int frame = getAnimationFrame(g->anim_frames,
9706 g->anim_start_frame,
9709 g_em->unique_identifier =
9710 (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height;
9714 void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em,
9715 int tile, int frame_em, int x, int y)
9717 int action = object_mapping[tile].action;
9718 int direction = object_mapping[tile].direction;
9719 boolean is_backside = object_mapping[tile].is_backside;
9720 int effective_element = get_effective_element_EM(tile, frame_em);
9722 int effective_action = action;
9724 int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT);
9726 int graphic = (direction == MV_NONE ?
9727 el_act2img(effective_element, effective_action) :
9728 el_act_dir2img(effective_element, effective_action,
9730 int crumbled = (direction == MV_NONE ?
9731 el_act2crm(effective_element, effective_action) :
9732 el_act_dir2crm(effective_element, effective_action,
9734 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
9735 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
9736 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
9737 struct GraphicInfo *g = &graphic_info[graphic];
9739 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9743 /* special case: graphic uses "2nd movement tile" and has defined
9744 7 frames for movement animation (or less) => use default graphic
9745 for last (8th) frame which ends the movement animation */
9746 if (g->double_movement && g->anim_frames < 8 && frame_em == 7)
9748 effective_action = ACTION_DEFAULT;
9749 graphic = (direction == MV_NONE ?
9750 el_act2img(effective_element, effective_action) :
9751 el_act_dir2img(effective_element, effective_action,
9753 crumbled = (direction == MV_NONE ?
9754 el_act2crm(effective_element, effective_action) :
9755 el_act_dir2crm(effective_element, effective_action,
9758 g = &graphic_info[graphic];
9768 if (frame_em == 0) /* reset animation frame for certain elements */
9770 if (check_linear_animation_EM(tile))
9775 if (graphic_info[graphic].anim_global_sync)
9776 sync_frame = FrameCounter;
9777 else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY))
9778 sync_frame = GfxFrame[x][y];
9780 sync_frame = 0; /* playfield border (pseudo steel) */
9782 SetRandomAnimationValue(x, y);
9787 int xxx_sync_frame = (i == Xdrip_stretch ? 7 :
9788 i == Xdrip_stretchB ? 7 :
9789 i == Ydrip_s2 ? j + 8 :
9790 i == Ydrip_s2B ? j + 8 :
9799 i == Xfake_acid_1 ? 0 :
9800 i == Xfake_acid_2 ? 10 :
9801 i == Xfake_acid_3 ? 20 :
9802 i == Xfake_acid_4 ? 30 :
9803 i == Xfake_acid_5 ? 40 :
9804 i == Xfake_acid_6 ? 50 :
9805 i == Xfake_acid_7 ? 60 :
9806 i == Xfake_acid_8 ? 70 :
9808 i == Xball_2B ? j + 8 :
9809 i == Yball_eat ? j + 1 :
9810 i == Ykey_1_eat ? j + 1 :
9811 i == Ykey_2_eat ? j + 1 :
9812 i == Ykey_3_eat ? j + 1 :
9813 i == Ykey_4_eat ? j + 1 :
9814 i == Ykey_5_eat ? j + 1 :
9815 i == Ykey_6_eat ? j + 1 :
9816 i == Ykey_7_eat ? j + 1 :
9817 i == Ykey_8_eat ? j + 1 :
9818 i == Ylenses_eat ? j + 1 :
9819 i == Ymagnify_eat ? j + 1 :
9820 i == Ygrass_eat ? j + 1 :
9821 i == Ydirt_eat ? j + 1 :
9822 i == Xamoeba_1 ? 0 :
9823 i == Xamoeba_2 ? 1 :
9824 i == Xamoeba_3 ? 2 :
9825 i == Xamoeba_4 ? 3 :
9826 i == Xamoeba_5 ? 0 :
9827 i == Xamoeba_6 ? 1 :
9828 i == Xamoeba_7 ? 2 :
9829 i == Xamoeba_8 ? 3 :
9830 i == Xexit_2 ? j + 8 :
9831 i == Xexit_3 ? j + 16 :
9832 i == Xdynamite_1 ? 0 :
9833 i == Xdynamite_2 ? 8 :
9834 i == Xdynamite_3 ? 16 :
9835 i == Xdynamite_4 ? 24 :
9836 i == Xsand_stonein_1 ? j + 1 :
9837 i == Xsand_stonein_2 ? j + 9 :
9838 i == Xsand_stonein_3 ? j + 17 :
9839 i == Xsand_stonein_4 ? j + 25 :
9840 i == Xsand_stoneout_1 && j == 0 ? 0 :
9841 i == Xsand_stoneout_1 && j == 1 ? 0 :
9842 i == Xsand_stoneout_1 && j == 2 ? 1 :
9843 i == Xsand_stoneout_1 && j == 3 ? 2 :
9844 i == Xsand_stoneout_1 && j == 4 ? 2 :
9845 i == Xsand_stoneout_1 && j == 5 ? 3 :
9846 i == Xsand_stoneout_1 && j == 6 ? 4 :
9847 i == Xsand_stoneout_1 && j == 7 ? 4 :
9848 i == Xsand_stoneout_2 && j == 0 ? 5 :
9849 i == Xsand_stoneout_2 && j == 1 ? 6 :
9850 i == Xsand_stoneout_2 && j == 2 ? 7 :
9851 i == Xsand_stoneout_2 && j == 3 ? 8 :
9852 i == Xsand_stoneout_2 && j == 4 ? 9 :
9853 i == Xsand_stoneout_2 && j == 5 ? 11 :
9854 i == Xsand_stoneout_2 && j == 6 ? 13 :
9855 i == Xsand_stoneout_2 && j == 7 ? 15 :
9856 i == Xboom_bug && j == 1 ? 2 :
9857 i == Xboom_bug && j == 2 ? 2 :
9858 i == Xboom_bug && j == 3 ? 4 :
9859 i == Xboom_bug && j == 4 ? 4 :
9860 i == Xboom_bug && j == 5 ? 2 :
9861 i == Xboom_bug && j == 6 ? 2 :
9862 i == Xboom_bug && j == 7 ? 0 :
9863 i == Xboom_bomb && j == 1 ? 2 :
9864 i == Xboom_bomb && j == 2 ? 2 :
9865 i == Xboom_bomb && j == 3 ? 4 :
9866 i == Xboom_bomb && j == 4 ? 4 :
9867 i == Xboom_bomb && j == 5 ? 2 :
9868 i == Xboom_bomb && j == 6 ? 2 :
9869 i == Xboom_bomb && j == 7 ? 0 :
9870 i == Xboom_android && j == 7 ? 6 :
9871 i == Xboom_1 && j == 1 ? 2 :
9872 i == Xboom_1 && j == 2 ? 2 :
9873 i == Xboom_1 && j == 3 ? 4 :
9874 i == Xboom_1 && j == 4 ? 4 :
9875 i == Xboom_1 && j == 5 ? 6 :
9876 i == Xboom_1 && j == 6 ? 6 :
9877 i == Xboom_1 && j == 7 ? 8 :
9878 i == Xboom_2 && j == 0 ? 8 :
9879 i == Xboom_2 && j == 1 ? 8 :
9880 i == Xboom_2 && j == 2 ? 10 :
9881 i == Xboom_2 && j == 3 ? 10 :
9882 i == Xboom_2 && j == 4 ? 10 :
9883 i == Xboom_2 && j == 5 ? 12 :
9884 i == Xboom_2 && j == 6 ? 12 :
9885 i == Xboom_2 && j == 7 ? 12 :
9887 special_animation && j == 4 ? 3 :
9888 effective_action != action ? 0 :
9894 int xxx_effective_action;
9895 int xxx_has_action_graphics;
9898 int element = object_mapping[i].element_rnd;
9899 int action = object_mapping[i].action;
9900 int direction = object_mapping[i].direction;
9901 boolean is_backside = object_mapping[i].is_backside;
9903 boolean action_removing = (action == ACTION_DIGGING ||
9904 action == ACTION_SNAPPING ||
9905 action == ACTION_COLLECTING);
9907 boolean action_exploding = ((action == ACTION_EXPLODING ||
9908 action == ACTION_SMASHED_BY_ROCK ||
9909 action == ACTION_SMASHED_BY_SPRING) &&
9910 element != EL_DIAMOND);
9911 boolean action_active = (action == ACTION_ACTIVE);
9912 boolean action_other = (action == ACTION_OTHER);
9916 int effective_element = get_effective_element_EM(i, j);
9918 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
9919 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
9921 i == Xdrip_stretch ? element :
9922 i == Xdrip_stretchB ? element :
9923 i == Ydrip_s1 ? element :
9924 i == Ydrip_s1B ? element :
9925 i == Xball_1B ? element :
9926 i == Xball_2 ? element :
9927 i == Xball_2B ? element :
9928 i == Yball_eat ? element :
9929 i == Ykey_1_eat ? element :
9930 i == Ykey_2_eat ? element :
9931 i == Ykey_3_eat ? element :
9932 i == Ykey_4_eat ? element :
9933 i == Ykey_5_eat ? element :
9934 i == Ykey_6_eat ? element :
9935 i == Ykey_7_eat ? element :
9936 i == Ykey_8_eat ? element :
9937 i == Ylenses_eat ? element :
9938 i == Ymagnify_eat ? element :
9939 i == Ygrass_eat ? element :
9940 i == Ydirt_eat ? element :
9941 i == Yemerald_stone ? EL_EMERALD :
9942 i == Ydiamond_stone ? EL_ROCK :
9943 i == Xsand_stonein_1 ? element :
9944 i == Xsand_stonein_2 ? element :
9945 i == Xsand_stonein_3 ? element :
9946 i == Xsand_stonein_4 ? element :
9947 is_backside ? EL_EMPTY :
9948 action_removing ? EL_EMPTY :
9951 int effective_action = (j < 7 ? action :
9952 i == Xdrip_stretch ? action :
9953 i == Xdrip_stretchB ? action :
9954 i == Ydrip_s1 ? action :
9955 i == Ydrip_s1B ? action :
9956 i == Xball_1B ? action :
9957 i == Xball_2 ? action :
9958 i == Xball_2B ? action :
9959 i == Yball_eat ? action :
9960 i == Ykey_1_eat ? action :
9961 i == Ykey_2_eat ? action :
9962 i == Ykey_3_eat ? action :
9963 i == Ykey_4_eat ? action :
9964 i == Ykey_5_eat ? action :
9965 i == Ykey_6_eat ? action :
9966 i == Ykey_7_eat ? action :
9967 i == Ykey_8_eat ? action :
9968 i == Ylenses_eat ? action :
9969 i == Ymagnify_eat ? action :
9970 i == Ygrass_eat ? action :
9971 i == Ydirt_eat ? action :
9972 i == Xsand_stonein_1 ? action :
9973 i == Xsand_stonein_2 ? action :
9974 i == Xsand_stonein_3 ? action :
9975 i == Xsand_stonein_4 ? action :
9976 i == Xsand_stoneout_1 ? action :
9977 i == Xsand_stoneout_2 ? action :
9978 i == Xboom_android ? ACTION_EXPLODING :
9979 action_exploding ? ACTION_EXPLODING :
9980 action_active ? action :
9981 action_other ? action :
9983 int graphic = (el_act_dir2img(effective_element, effective_action,
9985 int crumbled = (el_act_dir2crm(effective_element, effective_action,
9987 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
9988 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
9989 boolean has_action_graphics = (graphic != base_graphic);
9990 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
9991 struct GraphicInfo *g = &graphic_info[graphic];
9993 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
9995 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
9998 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
9999 boolean special_animation = (action != ACTION_DEFAULT &&
10000 g->anim_frames == 3 &&
10001 g->anim_delay == 2 &&
10002 g->anim_mode & ANIM_LINEAR);
10003 xxx_sync_frame = (i == Xdrip_stretch ? 7 :
10004 i == Xdrip_stretchB ? 7 :
10005 i == Ydrip_s2 ? j + 8 :
10006 i == Ydrip_s2B ? j + 8 :
10008 i == Xacid_2 ? 10 :
10009 i == Xacid_3 ? 20 :
10010 i == Xacid_4 ? 30 :
10011 i == Xacid_5 ? 40 :
10012 i == Xacid_6 ? 50 :
10013 i == Xacid_7 ? 60 :
10014 i == Xacid_8 ? 70 :
10015 i == Xfake_acid_1 ? 0 :
10016 i == Xfake_acid_2 ? 10 :
10017 i == Xfake_acid_3 ? 20 :
10018 i == Xfake_acid_4 ? 30 :
10019 i == Xfake_acid_5 ? 40 :
10020 i == Xfake_acid_6 ? 50 :
10021 i == Xfake_acid_7 ? 60 :
10022 i == Xfake_acid_8 ? 70 :
10024 i == Xball_2B ? j + 8 :
10025 i == Yball_eat ? j + 1 :
10026 i == Ykey_1_eat ? j + 1 :
10027 i == Ykey_2_eat ? j + 1 :
10028 i == Ykey_3_eat ? j + 1 :
10029 i == Ykey_4_eat ? j + 1 :
10030 i == Ykey_5_eat ? j + 1 :
10031 i == Ykey_6_eat ? j + 1 :
10032 i == Ykey_7_eat ? j + 1 :
10033 i == Ykey_8_eat ? j + 1 :
10034 i == Ylenses_eat ? j + 1 :
10035 i == Ymagnify_eat ? j + 1 :
10036 i == Ygrass_eat ? j + 1 :
10037 i == Ydirt_eat ? j + 1 :
10038 i == Xamoeba_1 ? 0 :
10039 i == Xamoeba_2 ? 1 :
10040 i == Xamoeba_3 ? 2 :
10041 i == Xamoeba_4 ? 3 :
10042 i == Xamoeba_5 ? 0 :
10043 i == Xamoeba_6 ? 1 :
10044 i == Xamoeba_7 ? 2 :
10045 i == Xamoeba_8 ? 3 :
10046 i == Xexit_2 ? j + 8 :
10047 i == Xexit_3 ? j + 16 :
10048 i == Xdynamite_1 ? 0 :
10049 i == Xdynamite_2 ? 8 :
10050 i == Xdynamite_3 ? 16 :
10051 i == Xdynamite_4 ? 24 :
10052 i == Xsand_stonein_1 ? j + 1 :
10053 i == Xsand_stonein_2 ? j + 9 :
10054 i == Xsand_stonein_3 ? j + 17 :
10055 i == Xsand_stonein_4 ? j + 25 :
10056 i == Xsand_stoneout_1 && j == 0 ? 0 :
10057 i == Xsand_stoneout_1 && j == 1 ? 0 :
10058 i == Xsand_stoneout_1 && j == 2 ? 1 :
10059 i == Xsand_stoneout_1 && j == 3 ? 2 :
10060 i == Xsand_stoneout_1 && j == 4 ? 2 :
10061 i == Xsand_stoneout_1 && j == 5 ? 3 :
10062 i == Xsand_stoneout_1 && j == 6 ? 4 :
10063 i == Xsand_stoneout_1 && j == 7 ? 4 :
10064 i == Xsand_stoneout_2 && j == 0 ? 5 :
10065 i == Xsand_stoneout_2 && j == 1 ? 6 :
10066 i == Xsand_stoneout_2 && j == 2 ? 7 :
10067 i == Xsand_stoneout_2 && j == 3 ? 8 :
10068 i == Xsand_stoneout_2 && j == 4 ? 9 :
10069 i == Xsand_stoneout_2 && j == 5 ? 11 :
10070 i == Xsand_stoneout_2 && j == 6 ? 13 :
10071 i == Xsand_stoneout_2 && j == 7 ? 15 :
10072 i == Xboom_bug && j == 1 ? 2 :
10073 i == Xboom_bug && j == 2 ? 2 :
10074 i == Xboom_bug && j == 3 ? 4 :
10075 i == Xboom_bug && j == 4 ? 4 :
10076 i == Xboom_bug && j == 5 ? 2 :
10077 i == Xboom_bug && j == 6 ? 2 :
10078 i == Xboom_bug && j == 7 ? 0 :
10079 i == Xboom_bomb && j == 1 ? 2 :
10080 i == Xboom_bomb && j == 2 ? 2 :
10081 i == Xboom_bomb && j == 3 ? 4 :
10082 i == Xboom_bomb && j == 4 ? 4 :
10083 i == Xboom_bomb && j == 5 ? 2 :
10084 i == Xboom_bomb && j == 6 ? 2 :
10085 i == Xboom_bomb && j == 7 ? 0 :
10086 i == Xboom_android && j == 7 ? 6 :
10087 i == Xboom_1 && j == 1 ? 2 :
10088 i == Xboom_1 && j == 2 ? 2 :
10089 i == Xboom_1 && j == 3 ? 4 :
10090 i == Xboom_1 && j == 4 ? 4 :
10091 i == Xboom_1 && j == 5 ? 6 :
10092 i == Xboom_1 && j == 6 ? 6 :
10093 i == Xboom_1 && j == 7 ? 8 :
10094 i == Xboom_2 && j == 0 ? 8 :
10095 i == Xboom_2 && j == 1 ? 8 :
10096 i == Xboom_2 && j == 2 ? 10 :
10097 i == Xboom_2 && j == 3 ? 10 :
10098 i == Xboom_2 && j == 4 ? 10 :
10099 i == Xboom_2 && j == 5 ? 12 :
10100 i == Xboom_2 && j == 6 ? 12 :
10101 i == Xboom_2 && j == 7 ? 12 :
10102 special_animation && j == 4 ? 3 :
10103 effective_action != action ? 0 :
10106 xxx_effective_action = effective_action;
10107 xxx_has_action_graphics = has_action_graphics;
10112 int frame = getAnimationFrame(g->anim_frames,
10115 g->anim_start_frame,
10129 int old_src_x = g_em->src_x;
10130 int old_src_y = g_em->src_y;
10134 getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y,
10135 g->double_movement && is_backside);
10137 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
10138 &g_em->src_x, &g_em->src_y, FALSE);
10143 if (tile == Ydiamond_stone)
10144 printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n",
10149 g->anim_start_frame,
10152 g_em->src_x, g_em->src_y,
10153 g_em->src_offset_x, g_em->src_offset_y,
10154 g_em->dst_offset_x, g_em->dst_offset_y,
10166 if (graphic == IMG_BUG_MOVING_RIGHT)
10167 printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y,
10168 g->double_movement, is_backside,
10169 old_src_x, old_src_y, g_em->src_x, g_em->src_y);
10177 g_em->src_offset_x = 0;
10178 g_em->src_offset_y = 0;
10179 g_em->dst_offset_x = 0;
10180 g_em->dst_offset_y = 0;
10181 g_em->width = TILEX;
10182 g_em->height = TILEY;
10184 g_em->preserve_background = FALSE;
10187 /* (updating the "crumbled" graphic definitions is probably not really needed,
10188 as animations for crumbled graphics can't be longer than one EMC cycle) */
10190 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10195 g_em->crumbled_bitmap = NULL;
10196 g_em->crumbled_src_x = 0;
10197 g_em->crumbled_src_y = 0;
10199 g_em->has_crumbled_graphics = FALSE;
10201 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10203 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10204 g_crumbled->anim_delay,
10205 g_crumbled->anim_mode,
10206 g_crumbled->anim_start_frame,
10209 getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap,
10210 &g_em->crumbled_src_x, &g_em->crumbled_src_y);
10212 g_em->has_crumbled_graphics = TRUE;
10218 int effective_action = xxx_effective_action;
10219 int has_action_graphics = xxx_has_action_graphics;
10221 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10222 effective_action == ACTION_MOVING ||
10223 effective_action == ACTION_PUSHING ||
10224 effective_action == ACTION_EATING)) ||
10225 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10226 effective_action == ACTION_EMPTYING)))
10229 (effective_action == ACTION_FALLING ||
10230 effective_action == ACTION_FILLING ||
10231 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10232 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10233 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10234 int num_steps = (i == Ydrip_s1 ? 16 :
10235 i == Ydrip_s1B ? 16 :
10236 i == Ydrip_s2 ? 16 :
10237 i == Ydrip_s2B ? 16 :
10238 i == Xsand_stonein_1 ? 32 :
10239 i == Xsand_stonein_2 ? 32 :
10240 i == Xsand_stonein_3 ? 32 :
10241 i == Xsand_stonein_4 ? 32 :
10242 i == Xsand_stoneout_1 ? 16 :
10243 i == Xsand_stoneout_2 ? 16 : 8);
10244 int cx = ABS(dx) * (TILEX / num_steps);
10245 int cy = ABS(dy) * (TILEY / num_steps);
10246 int step_frame = (i == Ydrip_s2 ? j + 8 :
10247 i == Ydrip_s2B ? j + 8 :
10248 i == Xsand_stonein_2 ? j + 8 :
10249 i == Xsand_stonein_3 ? j + 16 :
10250 i == Xsand_stonein_4 ? j + 24 :
10251 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10252 int step = (is_backside ? step_frame : num_steps - step_frame);
10254 if (is_backside) /* tile where movement starts */
10256 if (dx < 0 || dy < 0)
10258 g_em->src_offset_x = cx * step;
10259 g_em->src_offset_y = cy * step;
10263 g_em->dst_offset_x = cx * step;
10264 g_em->dst_offset_y = cy * step;
10267 else /* tile where movement ends */
10269 if (dx < 0 || dy < 0)
10271 g_em->dst_offset_x = cx * step;
10272 g_em->dst_offset_y = cy * step;
10276 g_em->src_offset_x = cx * step;
10277 g_em->src_offset_y = cy * step;
10281 g_em->width = TILEX - cx * step;
10282 g_em->height = TILEY - cy * step;
10285 /* create unique graphic identifier to decide if tile must be redrawn */
10286 /* bit 31 - 16 (16 bit): EM style graphic
10287 bit 15 - 12 ( 4 bit): EM style frame
10288 bit 11 - 6 ( 6 bit): graphic width
10289 bit 5 - 0 ( 6 bit): graphic height */
10290 g_em->unique_identifier =
10291 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10297 void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em,
10298 int player_nr, int anim, int frame_em)
10300 int element = player_mapping[player_nr][anim].element_rnd;
10301 int action = player_mapping[player_nr][anim].action;
10302 int direction = player_mapping[player_nr][anim].direction;
10303 int graphic = (direction == MV_NONE ?
10304 el_act2img(element, action) :
10305 el_act_dir2img(element, action, direction));
10306 struct GraphicInfo *g = &graphic_info[graphic];
10309 InitPlayerGfxAnimation(&stored_player[player_nr], action, direction);
10311 stored_player[player_nr].StepFrame = frame_em;
10313 sync_frame = stored_player[player_nr].Frame;
10315 int frame = getAnimationFrame(g->anim_frames,
10318 g->anim_start_frame,
10321 getGraphicSourceExt(graphic, frame, &g_em->bitmap,
10322 &g_em->src_x, &g_em->src_y, FALSE);
10325 printf("::: %d: %d, %d [%d]\n",
10327 stored_player[player_nr].Frame,
10328 stored_player[player_nr].StepFrame,
10333 void InitGraphicInfo_EM(void)
10336 struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
10337 struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX];
10342 int num_em_gfx_errors = 0;
10344 if (graphic_info_em_object[0][0].bitmap == NULL)
10346 /* EM graphics not yet initialized in em_open_all() */
10351 printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
10354 /* always start with reliable default values */
10355 for (i = 0; i < TILE_MAX; i++)
10357 object_mapping[i].element_rnd = EL_UNKNOWN;
10358 object_mapping[i].is_backside = FALSE;
10359 object_mapping[i].action = ACTION_DEFAULT;
10360 object_mapping[i].direction = MV_NONE;
10363 /* always start with reliable default values */
10364 for (p = 0; p < MAX_PLAYERS; p++)
10366 for (i = 0; i < SPR_MAX; i++)
10368 player_mapping[p][i].element_rnd = EL_UNKNOWN;
10369 player_mapping[p][i].action = ACTION_DEFAULT;
10370 player_mapping[p][i].direction = MV_NONE;
10374 for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
10376 int e = em_object_mapping_list[i].element_em;
10378 object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
10379 object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
10381 if (em_object_mapping_list[i].action != -1)
10382 object_mapping[e].action = em_object_mapping_list[i].action;
10384 if (em_object_mapping_list[i].direction != -1)
10385 object_mapping[e].direction =
10386 MV_DIR_FROM_BIT(em_object_mapping_list[i].direction);
10389 for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
10391 int a = em_player_mapping_list[i].action_em;
10392 int p = em_player_mapping_list[i].player_nr;
10394 player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
10396 if (em_player_mapping_list[i].action != -1)
10397 player_mapping[p][a].action = em_player_mapping_list[i].action;
10399 if (em_player_mapping_list[i].direction != -1)
10400 player_mapping[p][a].direction =
10401 MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
10404 for (i = 0; i < TILE_MAX; i++)
10406 int element = object_mapping[i].element_rnd;
10407 int action = object_mapping[i].action;
10408 int direction = object_mapping[i].direction;
10409 boolean is_backside = object_mapping[i].is_backside;
10411 boolean action_removing = (action == ACTION_DIGGING ||
10412 action == ACTION_SNAPPING ||
10413 action == ACTION_COLLECTING);
10415 boolean action_exploding = ((action == ACTION_EXPLODING ||
10416 action == ACTION_SMASHED_BY_ROCK ||
10417 action == ACTION_SMASHED_BY_SPRING) &&
10418 element != EL_DIAMOND);
10419 boolean action_active = (action == ACTION_ACTIVE);
10420 boolean action_other = (action == ACTION_OTHER);
10422 for (j = 0; j < 8; j++)
10425 int effective_element = get_effective_element_EM(i, j);
10427 int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
10428 j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
10430 i == Xdrip_stretch ? element :
10431 i == Xdrip_stretchB ? element :
10432 i == Ydrip_s1 ? element :
10433 i == Ydrip_s1B ? element :
10434 i == Xball_1B ? element :
10435 i == Xball_2 ? element :
10436 i == Xball_2B ? element :
10437 i == Yball_eat ? element :
10438 i == Ykey_1_eat ? element :
10439 i == Ykey_2_eat ? element :
10440 i == Ykey_3_eat ? element :
10441 i == Ykey_4_eat ? element :
10442 i == Ykey_5_eat ? element :
10443 i == Ykey_6_eat ? element :
10444 i == Ykey_7_eat ? element :
10445 i == Ykey_8_eat ? element :
10446 i == Ylenses_eat ? element :
10447 i == Ymagnify_eat ? element :
10448 i == Ygrass_eat ? element :
10449 i == Ydirt_eat ? element :
10450 i == Yemerald_stone ? EL_EMERALD :
10451 i == Ydiamond_stone ? EL_ROCK :
10452 i == Xsand_stonein_1 ? element :
10453 i == Xsand_stonein_2 ? element :
10454 i == Xsand_stonein_3 ? element :
10455 i == Xsand_stonein_4 ? element :
10456 is_backside ? EL_EMPTY :
10457 action_removing ? EL_EMPTY :
10460 int effective_action = (j < 7 ? action :
10461 i == Xdrip_stretch ? action :
10462 i == Xdrip_stretchB ? action :
10463 i == Ydrip_s1 ? action :
10464 i == Ydrip_s1B ? action :
10465 i == Xball_1B ? action :
10466 i == Xball_2 ? action :
10467 i == Xball_2B ? action :
10468 i == Yball_eat ? action :
10469 i == Ykey_1_eat ? action :
10470 i == Ykey_2_eat ? action :
10471 i == Ykey_3_eat ? action :
10472 i == Ykey_4_eat ? action :
10473 i == Ykey_5_eat ? action :
10474 i == Ykey_6_eat ? action :
10475 i == Ykey_7_eat ? action :
10476 i == Ykey_8_eat ? action :
10477 i == Ylenses_eat ? action :
10478 i == Ymagnify_eat ? action :
10479 i == Ygrass_eat ? action :
10480 i == Ydirt_eat ? action :
10481 i == Xsand_stonein_1 ? action :
10482 i == Xsand_stonein_2 ? action :
10483 i == Xsand_stonein_3 ? action :
10484 i == Xsand_stonein_4 ? action :
10485 i == Xsand_stoneout_1 ? action :
10486 i == Xsand_stoneout_2 ? action :
10487 i == Xboom_android ? ACTION_EXPLODING :
10488 action_exploding ? ACTION_EXPLODING :
10489 action_active ? action :
10490 action_other ? action :
10492 int graphic = (el_act_dir2img(effective_element, effective_action,
10494 int crumbled = (el_act_dir2crm(effective_element, effective_action,
10496 int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
10497 int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
10498 boolean has_action_graphics = (graphic != base_graphic);
10499 boolean has_crumbled_graphics = (base_crumbled != base_graphic);
10500 struct GraphicInfo *g = &graphic_info[graphic];
10502 struct GraphicInfo *g_crumbled = &graphic_info[crumbled];
10504 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10505 Bitmap *src_bitmap;
10507 /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
10508 boolean special_animation = (action != ACTION_DEFAULT &&
10509 g->anim_frames == 3 &&
10510 g->anim_delay == 2 &&
10511 g->anim_mode & ANIM_LINEAR);
10512 int sync_frame = (i == Xdrip_stretch ? 7 :
10513 i == Xdrip_stretchB ? 7 :
10514 i == Ydrip_s2 ? j + 8 :
10515 i == Ydrip_s2B ? j + 8 :
10517 i == Xacid_2 ? 10 :
10518 i == Xacid_3 ? 20 :
10519 i == Xacid_4 ? 30 :
10520 i == Xacid_5 ? 40 :
10521 i == Xacid_6 ? 50 :
10522 i == Xacid_7 ? 60 :
10523 i == Xacid_8 ? 70 :
10524 i == Xfake_acid_1 ? 0 :
10525 i == Xfake_acid_2 ? 10 :
10526 i == Xfake_acid_3 ? 20 :
10527 i == Xfake_acid_4 ? 30 :
10528 i == Xfake_acid_5 ? 40 :
10529 i == Xfake_acid_6 ? 50 :
10530 i == Xfake_acid_7 ? 60 :
10531 i == Xfake_acid_8 ? 70 :
10533 i == Xball_2B ? j + 8 :
10534 i == Yball_eat ? j + 1 :
10535 i == Ykey_1_eat ? j + 1 :
10536 i == Ykey_2_eat ? j + 1 :
10537 i == Ykey_3_eat ? j + 1 :
10538 i == Ykey_4_eat ? j + 1 :
10539 i == Ykey_5_eat ? j + 1 :
10540 i == Ykey_6_eat ? j + 1 :
10541 i == Ykey_7_eat ? j + 1 :
10542 i == Ykey_8_eat ? j + 1 :
10543 i == Ylenses_eat ? j + 1 :
10544 i == Ymagnify_eat ? j + 1 :
10545 i == Ygrass_eat ? j + 1 :
10546 i == Ydirt_eat ? j + 1 :
10547 i == Xamoeba_1 ? 0 :
10548 i == Xamoeba_2 ? 1 :
10549 i == Xamoeba_3 ? 2 :
10550 i == Xamoeba_4 ? 3 :
10551 i == Xamoeba_5 ? 0 :
10552 i == Xamoeba_6 ? 1 :
10553 i == Xamoeba_7 ? 2 :
10554 i == Xamoeba_8 ? 3 :
10555 i == Xexit_2 ? j + 8 :
10556 i == Xexit_3 ? j + 16 :
10557 i == Xdynamite_1 ? 0 :
10558 i == Xdynamite_2 ? 8 :
10559 i == Xdynamite_3 ? 16 :
10560 i == Xdynamite_4 ? 24 :
10561 i == Xsand_stonein_1 ? j + 1 :
10562 i == Xsand_stonein_2 ? j + 9 :
10563 i == Xsand_stonein_3 ? j + 17 :
10564 i == Xsand_stonein_4 ? j + 25 :
10565 i == Xsand_stoneout_1 && j == 0 ? 0 :
10566 i == Xsand_stoneout_1 && j == 1 ? 0 :
10567 i == Xsand_stoneout_1 && j == 2 ? 1 :
10568 i == Xsand_stoneout_1 && j == 3 ? 2 :
10569 i == Xsand_stoneout_1 && j == 4 ? 2 :
10570 i == Xsand_stoneout_1 && j == 5 ? 3 :
10571 i == Xsand_stoneout_1 && j == 6 ? 4 :
10572 i == Xsand_stoneout_1 && j == 7 ? 4 :
10573 i == Xsand_stoneout_2 && j == 0 ? 5 :
10574 i == Xsand_stoneout_2 && j == 1 ? 6 :
10575 i == Xsand_stoneout_2 && j == 2 ? 7 :
10576 i == Xsand_stoneout_2 && j == 3 ? 8 :
10577 i == Xsand_stoneout_2 && j == 4 ? 9 :
10578 i == Xsand_stoneout_2 && j == 5 ? 11 :
10579 i == Xsand_stoneout_2 && j == 6 ? 13 :
10580 i == Xsand_stoneout_2 && j == 7 ? 15 :
10581 i == Xboom_bug && j == 1 ? 2 :
10582 i == Xboom_bug && j == 2 ? 2 :
10583 i == Xboom_bug && j == 3 ? 4 :
10584 i == Xboom_bug && j == 4 ? 4 :
10585 i == Xboom_bug && j == 5 ? 2 :
10586 i == Xboom_bug && j == 6 ? 2 :
10587 i == Xboom_bug && j == 7 ? 0 :
10588 i == Xboom_bomb && j == 1 ? 2 :
10589 i == Xboom_bomb && j == 2 ? 2 :
10590 i == Xboom_bomb && j == 3 ? 4 :
10591 i == Xboom_bomb && j == 4 ? 4 :
10592 i == Xboom_bomb && j == 5 ? 2 :
10593 i == Xboom_bomb && j == 6 ? 2 :
10594 i == Xboom_bomb && j == 7 ? 0 :
10595 i == Xboom_android && j == 7 ? 6 :
10596 i == Xboom_1 && j == 1 ? 2 :
10597 i == Xboom_1 && j == 2 ? 2 :
10598 i == Xboom_1 && j == 3 ? 4 :
10599 i == Xboom_1 && j == 4 ? 4 :
10600 i == Xboom_1 && j == 5 ? 6 :
10601 i == Xboom_1 && j == 6 ? 6 :
10602 i == Xboom_1 && j == 7 ? 8 :
10603 i == Xboom_2 && j == 0 ? 8 :
10604 i == Xboom_2 && j == 1 ? 8 :
10605 i == Xboom_2 && j == 2 ? 10 :
10606 i == Xboom_2 && j == 3 ? 10 :
10607 i == Xboom_2 && j == 4 ? 10 :
10608 i == Xboom_2 && j == 5 ? 12 :
10609 i == Xboom_2 && j == 6 ? 12 :
10610 i == Xboom_2 && j == 7 ? 12 :
10611 special_animation && j == 4 ? 3 :
10612 effective_action != action ? 0 :
10616 Bitmap *debug_bitmap = g_em->bitmap;
10617 int debug_src_x = g_em->src_x;
10618 int debug_src_y = g_em->src_y;
10621 int frame = getAnimationFrame(g->anim_frames,
10624 g->anim_start_frame,
10627 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
10628 g->double_movement && is_backside);
10630 g_em->bitmap = src_bitmap;
10631 g_em->src_x = src_x;
10632 g_em->src_y = src_y;
10633 g_em->src_offset_x = 0;
10634 g_em->src_offset_y = 0;
10635 g_em->dst_offset_x = 0;
10636 g_em->dst_offset_y = 0;
10637 g_em->width = TILEX;
10638 g_em->height = TILEY;
10640 g_em->preserve_background = FALSE;
10643 set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled,
10648 g_em->crumbled_bitmap = NULL;
10649 g_em->crumbled_src_x = 0;
10650 g_em->crumbled_src_y = 0;
10651 g_em->crumbled_border_size = 0;
10653 g_em->has_crumbled_graphics = FALSE;
10656 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
10657 printf("::: empty crumbled: %d [%s], %d, %d\n",
10658 effective_element, element_info[effective_element].token_name,
10659 effective_action, direction);
10662 /* if element can be crumbled, but certain action graphics are just empty
10663 space (like instantly snapping sand to empty space in 1 frame), do not
10664 treat these empty space graphics as crumbled graphics in EMC engine */
10665 if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
10667 int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames,
10668 g_crumbled->anim_delay,
10669 g_crumbled->anim_mode,
10670 g_crumbled->anim_start_frame,
10673 getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y);
10675 g_em->has_crumbled_graphics = TRUE;
10676 g_em->crumbled_bitmap = src_bitmap;
10677 g_em->crumbled_src_x = src_x;
10678 g_em->crumbled_src_y = src_y;
10679 g_em->crumbled_border_size = graphic_info[crumbled].border_size;
10683 if (g_em == &graphic_info_em_object[207][0])
10684 printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n",
10685 graphic_info_em_object[207][0].crumbled_src_x,
10686 graphic_info_em_object[207][0].crumbled_src_y,
10688 crumbled, frame, src_x, src_y,
10693 g->anim_start_frame,
10695 gfx.anim_random_frame,
10700 printf("::: EMC tile %d is crumbled\n", i);
10706 if (element == EL_ROCK &&
10707 effective_action == ACTION_FILLING)
10708 printf("::: has_action_graphics == %d\n", has_action_graphics);
10711 if ((!g->double_movement && (effective_action == ACTION_FALLING ||
10712 effective_action == ACTION_MOVING ||
10713 effective_action == ACTION_PUSHING ||
10714 effective_action == ACTION_EATING)) ||
10715 (!has_action_graphics && (effective_action == ACTION_FILLING ||
10716 effective_action == ACTION_EMPTYING)))
10719 (effective_action == ACTION_FALLING ||
10720 effective_action == ACTION_FILLING ||
10721 effective_action == ACTION_EMPTYING ? MV_DOWN : direction);
10722 int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
10723 int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0);
10724 int num_steps = (i == Ydrip_s1 ? 16 :
10725 i == Ydrip_s1B ? 16 :
10726 i == Ydrip_s2 ? 16 :
10727 i == Ydrip_s2B ? 16 :
10728 i == Xsand_stonein_1 ? 32 :
10729 i == Xsand_stonein_2 ? 32 :
10730 i == Xsand_stonein_3 ? 32 :
10731 i == Xsand_stonein_4 ? 32 :
10732 i == Xsand_stoneout_1 ? 16 :
10733 i == Xsand_stoneout_2 ? 16 : 8);
10734 int cx = ABS(dx) * (TILEX / num_steps);
10735 int cy = ABS(dy) * (TILEY / num_steps);
10736 int step_frame = (i == Ydrip_s2 ? j + 8 :
10737 i == Ydrip_s2B ? j + 8 :
10738 i == Xsand_stonein_2 ? j + 8 :
10739 i == Xsand_stonein_3 ? j + 16 :
10740 i == Xsand_stonein_4 ? j + 24 :
10741 i == Xsand_stoneout_2 ? j + 8 : j) + 1;
10742 int step = (is_backside ? step_frame : num_steps - step_frame);
10744 if (is_backside) /* tile where movement starts */
10746 if (dx < 0 || dy < 0)
10748 g_em->src_offset_x = cx * step;
10749 g_em->src_offset_y = cy * step;
10753 g_em->dst_offset_x = cx * step;
10754 g_em->dst_offset_y = cy * step;
10757 else /* tile where movement ends */
10759 if (dx < 0 || dy < 0)
10761 g_em->dst_offset_x = cx * step;
10762 g_em->dst_offset_y = cy * step;
10766 g_em->src_offset_x = cx * step;
10767 g_em->src_offset_y = cy * step;
10771 g_em->width = TILEX - cx * step;
10772 g_em->height = TILEY - cy * step;
10775 /* create unique graphic identifier to decide if tile must be redrawn */
10776 /* bit 31 - 16 (16 bit): EM style graphic
10777 bit 15 - 12 ( 4 bit): EM style frame
10778 bit 11 - 6 ( 6 bit): graphic width
10779 bit 5 - 0 ( 6 bit): graphic height */
10780 g_em->unique_identifier =
10781 (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
10785 /* skip check for EMC elements not contained in original EMC artwork */
10786 if (element == EL_EMC_FAKE_ACID)
10789 if (g_em->bitmap != debug_bitmap ||
10790 g_em->src_x != debug_src_x ||
10791 g_em->src_y != debug_src_y ||
10792 g_em->src_offset_x != 0 ||
10793 g_em->src_offset_y != 0 ||
10794 g_em->dst_offset_x != 0 ||
10795 g_em->dst_offset_y != 0 ||
10796 g_em->width != TILEX ||
10797 g_em->height != TILEY)
10799 static int last_i = -1;
10807 printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
10808 i, element, element_info[element].token_name,
10809 element_action_info[effective_action].suffix, direction);
10811 if (element != effective_element)
10812 printf(" [%d ('%s')]",
10814 element_info[effective_element].token_name);
10818 if (g_em->bitmap != debug_bitmap)
10819 printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
10820 j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
10822 if (g_em->src_x != debug_src_x ||
10823 g_em->src_y != debug_src_y)
10824 printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
10825 j, (is_backside ? 'B' : 'F'),
10826 g_em->src_x, g_em->src_y,
10827 g_em->src_x / 32, g_em->src_y / 32,
10828 debug_src_x, debug_src_y,
10829 debug_src_x / 32, debug_src_y / 32);
10831 if (g_em->src_offset_x != 0 ||
10832 g_em->src_offset_y != 0 ||
10833 g_em->dst_offset_x != 0 ||
10834 g_em->dst_offset_y != 0)
10835 printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
10837 g_em->src_offset_x, g_em->src_offset_y,
10838 g_em->dst_offset_x, g_em->dst_offset_y);
10840 if (g_em->width != TILEX ||
10841 g_em->height != TILEY)
10842 printf(" %d (%d): size %d,%d should be %d,%d\n",
10844 g_em->width, g_em->height, TILEX, TILEY);
10846 num_em_gfx_errors++;
10853 for (i = 0; i < TILE_MAX; i++)
10855 for (j = 0; j < 8; j++)
10857 int element = object_mapping[i].element_rnd;
10858 int action = object_mapping[i].action;
10859 int direction = object_mapping[i].direction;
10860 boolean is_backside = object_mapping[i].is_backside;
10861 int graphic_action = el_act_dir2img(element, action, direction);
10862 int graphic_default = el_act_dir2img(element, ACTION_DEFAULT, direction);
10864 if ((action == ACTION_SMASHED_BY_ROCK ||
10865 action == ACTION_SMASHED_BY_SPRING ||
10866 action == ACTION_EATING) &&
10867 graphic_action == graphic_default)
10869 int e = (action == ACTION_SMASHED_BY_ROCK ? Ystone_s :
10870 action == ACTION_SMASHED_BY_SPRING ? Yspring_s :
10871 direction == MV_LEFT ? (is_backside? Yspring_wB: Yspring_w) :
10872 direction == MV_RIGHT ? (is_backside? Yspring_eB: Yspring_e) :
10875 /* no separate animation for "smashed by rock" -- use rock instead */
10876 struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
10877 struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
10879 g_em->bitmap = g_xx->bitmap;
10880 g_em->src_x = g_xx->src_x;
10881 g_em->src_y = g_xx->src_y;
10882 g_em->src_offset_x = g_xx->src_offset_x;
10883 g_em->src_offset_y = g_xx->src_offset_y;
10884 g_em->dst_offset_x = g_xx->dst_offset_x;
10885 g_em->dst_offset_y = g_xx->dst_offset_y;
10886 g_em->width = g_xx->width;
10887 g_em->height = g_xx->height;
10888 g_em->unique_identifier = g_xx->unique_identifier;
10891 g_em->preserve_background = TRUE;
10896 for (p = 0; p < MAX_PLAYERS; p++)
10898 for (i = 0; i < SPR_MAX; i++)
10900 int element = player_mapping[p][i].element_rnd;
10901 int action = player_mapping[p][i].action;
10902 int direction = player_mapping[p][i].direction;
10904 for (j = 0; j < 8; j++)
10906 int effective_element = element;
10907 int effective_action = action;
10908 int graphic = (direction == MV_NONE ?
10909 el_act2img(effective_element, effective_action) :
10910 el_act_dir2img(effective_element, effective_action,
10912 struct GraphicInfo *g = &graphic_info[graphic];
10913 struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
10914 Bitmap *src_bitmap;
10916 int sync_frame = j;
10919 Bitmap *debug_bitmap = g_em->bitmap;
10920 int debug_src_x = g_em->src_x;
10921 int debug_src_y = g_em->src_y;
10924 int frame = getAnimationFrame(g->anim_frames,
10927 g->anim_start_frame,
10930 getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
10932 g_em->bitmap = src_bitmap;
10933 g_em->src_x = src_x;
10934 g_em->src_y = src_y;
10935 g_em->src_offset_x = 0;
10936 g_em->src_offset_y = 0;
10937 g_em->dst_offset_x = 0;
10938 g_em->dst_offset_y = 0;
10939 g_em->width = TILEX;
10940 g_em->height = TILEY;
10944 /* skip check for EMC elements not contained in original EMC artwork */
10945 if (element == EL_PLAYER_3 ||
10946 element == EL_PLAYER_4)
10949 if (g_em->bitmap != debug_bitmap ||
10950 g_em->src_x != debug_src_x ||
10951 g_em->src_y != debug_src_y)
10953 static int last_i = -1;
10961 printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
10962 p, i, element, element_info[element].token_name,
10963 element_action_info[effective_action].suffix, direction);
10965 if (element != effective_element)
10966 printf(" [%d ('%s')]",
10968 element_info[effective_element].token_name);
10972 if (g_em->bitmap != debug_bitmap)
10973 printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
10974 j, (int)(g_em->bitmap), (int)(debug_bitmap));
10976 if (g_em->src_x != debug_src_x ||
10977 g_em->src_y != debug_src_y)
10978 printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
10980 g_em->src_x, g_em->src_y,
10981 g_em->src_x / 32, g_em->src_y / 32,
10982 debug_src_x, debug_src_y,
10983 debug_src_x / 32, debug_src_y / 32);
10985 num_em_gfx_errors++;
10995 printf("::: [%d errors found]\n", num_em_gfx_errors);
11001 void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
11002 boolean any_player_moving,
11003 boolean player_is_dropping)
11005 if (tape.single_step && tape.recording && !tape.pausing)
11008 boolean active_players = FALSE;
11011 for (i = 0; i < MAX_PLAYERS; i++)
11012 if (action[i] != JOY_NO_ACTION)
11013 active_players = TRUE;
11017 if (frame == 0 && !player_is_dropping)
11018 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
11022 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
11023 boolean murphy_is_dropping)
11026 printf("::: waiting: %d, dropping: %d\n",
11027 murphy_is_waiting, murphy_is_dropping);
11030 if (tape.single_step && tape.recording && !tape.pausing)
11032 // if (murphy_is_waiting || murphy_is_dropping)
11033 if (murphy_is_waiting)
11036 printf("::: murphy is waiting -> pause mode\n");
11039 TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
11044 void getGraphicSource_SP(struct GraphicInfo_SP *g_sp,
11045 int graphic, int sync_frame, int x, int y)
11047 int frame = getGraphicAnimationFrame(graphic, sync_frame);
11049 getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y);
11052 boolean isNextAnimationFrame_SP(int graphic, int sync_frame)
11054 return (IS_NEXT_FRAME(sync_frame, graphic));
11057 int getGraphicInfo_Delay(int graphic)
11059 return graphic_info[graphic].anim_delay;
11062 void PlayMenuSoundExt(int sound)
11064 if (sound == SND_UNDEFINED)
11067 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11068 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11071 if (IS_LOOP_SOUND(sound))
11072 PlaySoundLoop(sound);
11077 void PlayMenuSound()
11079 PlayMenuSoundExt(menu.sound[game_status]);
11082 void PlayMenuSoundStereo(int sound, int stereo_position)
11084 if (sound == SND_UNDEFINED)
11087 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11088 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11091 if (IS_LOOP_SOUND(sound))
11092 PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP);
11094 PlaySoundStereo(sound, stereo_position);
11097 void PlayMenuSoundIfLoopExt(int sound)
11099 if (sound == SND_UNDEFINED)
11102 if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) ||
11103 (!setup.sound_loops && IS_LOOP_SOUND(sound)))
11106 if (IS_LOOP_SOUND(sound))
11107 PlaySoundLoop(sound);
11110 void PlayMenuSoundIfLoop()
11112 PlayMenuSoundIfLoopExt(menu.sound[game_status]);
11115 void PlayMenuMusicExt(int music)
11117 if (music == MUS_UNDEFINED)
11120 if (!setup.sound_music)
11126 void PlayMenuMusic()
11128 PlayMenuMusicExt(menu.music[game_status]);
11131 void PlaySoundActivating()
11134 PlaySound(SND_MENU_ITEM_ACTIVATING);
11138 void PlaySoundSelecting()
11141 PlaySound(SND_MENU_ITEM_SELECTING);
11145 void ToggleFullscreenOrChangeWindowScalingIfNeeded()
11147 boolean change_fullscreen = (setup.fullscreen !=
11148 video.fullscreen_enabled);
11149 boolean change_fullscreen_mode = (video.fullscreen_enabled &&
11150 !strEqual(setup.fullscreen_mode,
11151 video.fullscreen_mode_current));
11152 boolean change_window_scaling_percent = (!video.fullscreen_enabled &&
11153 setup.window_scaling_percent !=
11154 video.window_scaling_percent);
11156 if (change_window_scaling_percent && video.fullscreen_enabled)
11159 if (!change_window_scaling_percent && !video.fullscreen_available)
11162 #if defined(TARGET_SDL2)
11163 if (change_window_scaling_percent)
11165 SDLSetWindowScaling(setup.window_scaling_percent);
11169 else if (change_fullscreen)
11171 SDLSetWindowFullscreen(setup.fullscreen);
11173 /* set setup value according to successfully changed fullscreen mode */
11174 setup.fullscreen = video.fullscreen_enabled;
11180 if (change_fullscreen ||
11181 change_fullscreen_mode ||
11182 change_window_scaling_percent)
11184 Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
11186 /* save backbuffer content which gets lost when toggling fullscreen mode */
11187 BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11189 if (change_fullscreen_mode)
11191 /* keep fullscreen, but change fullscreen mode (screen resolution) */
11192 video.fullscreen_enabled = FALSE; /* force new fullscreen mode */
11195 if (change_window_scaling_percent)
11197 /* keep window mode, but change window scaling */
11198 video.fullscreen_enabled = TRUE; /* force new window scaling */
11201 /* toggle fullscreen */
11202 ChangeVideoModeIfNeeded(setup.fullscreen);
11204 /* set setup value according to successfully changed fullscreen mode */
11205 setup.fullscreen = video.fullscreen_enabled;
11207 /* restore backbuffer content from temporary backbuffer backup bitmap */
11208 BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11210 FreeBitmap(tmp_backbuffer);
11213 /* update visible window/screen */
11214 BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
11216 redraw_mask = REDRAW_ALL;
11221 void ChangeViewportPropertiesIfNeeded()
11224 int *door_1_x = &DX;
11225 int *door_1_y = &DY;
11226 int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX);
11227 int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY);
11229 int gfx_game_mode = (game_status == GAME_MODE_PLAYING ||
11230 game_status == GAME_MODE_EDITOR ? game_status :
11232 int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
11234 struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
11235 struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
11236 struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode2];
11237 struct RectWithBorder *vp_door_3 = &viewport.door_2[GAME_MODE_EDITOR];
11238 int border_size = vp_playfield->border_size;
11239 int new_sx = vp_playfield->x + border_size;
11240 int new_sy = vp_playfield->y + border_size;
11241 int new_sxsize = vp_playfield->width - 2 * border_size;
11242 int new_sysize = vp_playfield->height - 2 * border_size;
11243 int new_real_sx = vp_playfield->x;
11244 int new_real_sy = vp_playfield->y;
11245 int new_full_sxsize = vp_playfield->width;
11246 int new_full_sysize = vp_playfield->height;
11247 int new_dx = vp_door_1->x;
11248 int new_dy = vp_door_1->y;
11249 int new_dxsize = vp_door_1->width;
11250 int new_dysize = vp_door_1->height;
11251 int new_vx = vp_door_2->x;
11252 int new_vy = vp_door_2->y;
11253 int new_vxsize = vp_door_2->width;
11254 int new_vysize = vp_door_2->height;
11255 int new_ex = vp_door_3->x;
11256 int new_ey = vp_door_3->y;
11257 int new_exsize = vp_door_3->width;
11258 int new_eysize = vp_door_3->height;
11260 int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1);
11261 int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var :
11262 gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE);
11263 int new_scr_fieldx = new_sxsize / tilesize;
11264 int new_scr_fieldy = new_sysize / tilesize;
11265 int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var;
11266 int new_scr_fieldy_buffers = new_sysize / new_tilesize_var;
11268 int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE;
11269 int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE;
11271 boolean init_gfx_buffers = FALSE;
11272 boolean init_video_buffer = FALSE;
11273 boolean init_gadgets_and_toons = FALSE;
11276 /* !!! TEST ONLY !!! */
11277 // InitGfxBuffers();
11281 if (viewport.window.width != WIN_XSIZE ||
11282 viewport.window.height != WIN_YSIZE)
11284 WIN_XSIZE = viewport.window.width;
11285 WIN_YSIZE = viewport.window.height;
11288 init_video_buffer = TRUE;
11289 init_gfx_buffers = TRUE;
11291 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
11295 SetDrawDeactivationMask(REDRAW_NONE);
11296 SetDrawBackgroundMask(REDRAW_FIELD);
11298 // RedrawBackground();
11302 // printf("::: video: init_video_buffer, init_gfx_buffers\n");
11305 if (new_scr_fieldx != SCR_FIELDX ||
11306 new_scr_fieldy != SCR_FIELDY)
11308 /* this always toggles between MAIN and GAME when using small tile size */
11310 SCR_FIELDX = new_scr_fieldx;
11311 SCR_FIELDY = new_scr_fieldy;
11313 // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
11317 if (new_tilesize_var != TILESIZE_VAR &&
11318 gfx_game_mode == GAME_MODE_PLAYING)
11320 /* doing this outside GAME_MODE_PLAYING would give wrong playfield size */
11322 TILESIZE_VAR = new_tilesize_var;
11324 init_gfx_buffers = TRUE;
11326 // printf("::: tilesize: init_gfx_buffers\n");
11330 if (new_sx != SX ||
11338 new_sxsize != SXSIZE ||
11339 new_sysize != SYSIZE ||
11340 new_dxsize != DXSIZE ||
11341 new_dysize != DYSIZE ||
11342 new_vxsize != VXSIZE ||
11343 new_vysize != VYSIZE ||
11344 new_exsize != EXSIZE ||
11345 new_eysize != EYSIZE ||
11346 new_real_sx != REAL_SX ||
11347 new_real_sy != REAL_SY ||
11348 new_full_sxsize != FULL_SXSIZE ||
11349 new_full_sysize != FULL_SYSIZE ||
11350 new_tilesize_var != TILESIZE_VAR
11353 vp_door_1->x != *door_1_x ||
11354 vp_door_1->y != *door_1_y ||
11355 vp_door_2->x != *door_2_x ||
11356 vp_door_2->y != *door_2_y
11368 SXSIZE = new_sxsize;
11369 SYSIZE = new_sysize;
11370 DXSIZE = new_dxsize;
11371 DYSIZE = new_dysize;
11372 VXSIZE = new_vxsize;
11373 VYSIZE = new_vysize;
11374 EXSIZE = new_exsize;
11375 EYSIZE = new_eysize;
11376 REAL_SX = new_real_sx;
11377 REAL_SY = new_real_sy;
11378 FULL_SXSIZE = new_full_sxsize;
11379 FULL_SYSIZE = new_full_sysize;
11380 TILESIZE_VAR = new_tilesize_var;
11383 printf("::: %d, %d, %d [%d]\n",
11384 SCR_FIELDX, SCR_FIELDY, TILESIZE_VAR,
11385 setup.small_game_graphics);
11389 *door_1_x = vp_door_1->x;
11390 *door_1_y = vp_door_1->y;
11391 *door_2_x = vp_door_2->x;
11392 *door_2_y = vp_door_2->y;
11396 init_gfx_buffers = TRUE;
11398 // printf("::: viewports: init_gfx_buffers\n");
11404 if (gfx_game_mode == GAME_MODE_MAIN)
11408 init_gadgets_and_toons = TRUE;
11410 // printf("::: viewports: init_gadgets_and_toons\n");
11418 if (init_gfx_buffers)
11420 // printf("::: init_gfx_buffers\n");
11422 SCR_FIELDX = new_scr_fieldx_buffers;
11423 SCR_FIELDY = new_scr_fieldy_buffers;
11427 SCR_FIELDX = new_scr_fieldx;
11428 SCR_FIELDY = new_scr_fieldy;
11431 if (init_video_buffer)
11433 // printf("::: init_video_buffer\n");
11435 InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
11437 SetDrawDeactivationMask(REDRAW_NONE);
11438 SetDrawBackgroundMask(REDRAW_FIELD);
11441 if (init_gadgets_and_toons)
11443 // printf("::: init_gadgets_and_toons\n");
11450 printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status);