1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
17 #include <machine/joystick.h>
31 extern boolean wait_for_vsync;
34 /* tool button identifiers */
35 #define TOOL_CTRL_ID_YES 0
36 #define TOOL_CTRL_ID_NO 1
37 #define TOOL_CTRL_ID_CONFIRM 2
38 #define TOOL_CTRL_ID_PLAYER_1 3
39 #define TOOL_CTRL_ID_PLAYER_2 4
40 #define TOOL_CTRL_ID_PLAYER_3 5
41 #define TOOL_CTRL_ID_PLAYER_4 6
43 #define NUM_TOOL_BUTTONS 7
45 /* forward declaration for internal use */
46 static int getGraphicAnimationPhase(int, int, int);
47 static void DrawGraphicAnimationShiftedThruMask(int, int, int, int, int,
49 static void UnmapToolButtons();
50 static void HandleToolButtons(struct GadgetInfo *);
52 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
53 static int request_gadget_id = -1;
55 void SetDrawtoField(int mode)
57 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
68 drawto_field = fieldbuffer;
70 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
81 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
88 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
90 if (setup.direct_draw && game_status == PLAYING)
91 redraw_mask &= ~REDRAW_MAIN;
93 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
94 redraw_mask |= REDRAW_FIELD;
96 if (redraw_mask & REDRAW_FIELD)
97 redraw_mask &= ~REDRAW_TILES;
102 /* synchronize X11 graphics at this point; if we would synchronize the
103 display immediately after the buffer switching (after the XFlush),
104 this could mean that we have to wait for the graphics to complete,
105 although we could go on doing calculations for the next frame */
107 XSync(display, FALSE);
109 if (redraw_mask & REDRAW_ALL)
111 XCopyArea(display, backbuffer, window, gc,
112 0, 0, WIN_XSIZE, WIN_YSIZE,
117 if (redraw_mask & REDRAW_FIELD)
119 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
121 XCopyArea(display, backbuffer, window, gc,
122 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
127 int fx = FX, fy = FY;
129 if (setup.soft_scrolling)
131 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
132 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
135 if (setup.soft_scrolling ||
136 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
137 ABS(ScreenMovPos) == ScrollStepSize ||
138 redraw_tiles > REDRAWTILES_THRESHOLD)
140 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
144 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
146 (setup.soft_scrolling ?
147 "setup.soft_scrolling" :
148 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
149 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
150 ABS(ScreenGfxPos) == ScrollStepSize ?
151 "ABS(ScreenGfxPos) == ScrollStepSize" :
152 "redraw_tiles > REDRAWTILES_THRESHOLD"));
157 redraw_mask &= ~REDRAW_MAIN;
160 if (redraw_mask & REDRAW_DOORS)
162 if (redraw_mask & REDRAW_DOOR_1)
163 XCopyArea(display, backbuffer, window, gc,
164 DX, DY, DXSIZE, DYSIZE,
166 if (redraw_mask & REDRAW_DOOR_2)
168 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
169 XCopyArea(display,backbuffer,window,gc,
170 VX,VY, VXSIZE,VYSIZE,
174 if (redraw_mask & REDRAW_VIDEO_1)
175 XCopyArea(display,backbuffer,window,gc,
176 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
177 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
178 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
179 if (redraw_mask & REDRAW_VIDEO_2)
180 XCopyArea(display,backbuffer,window,gc,
181 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
182 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
183 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
184 if (redraw_mask & REDRAW_VIDEO_3)
185 XCopyArea(display,backbuffer,window,gc,
186 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
187 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
188 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
191 if (redraw_mask & REDRAW_DOOR_3)
192 XCopyArea(display, backbuffer, window, gc,
193 EX, EY, EXSIZE, EYSIZE,
195 redraw_mask &= ~REDRAW_DOORS;
198 if (redraw_mask & REDRAW_MICROLEVEL)
200 XCopyArea(display,backbuffer,window,gc,
201 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
202 MICROLEV_XPOS, MICROLEV_YPOS);
203 XCopyArea(display,backbuffer,window,gc,
204 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
205 SX, MICROLABEL_YPOS);
206 redraw_mask &= ~REDRAW_MICROLEVEL;
209 if (redraw_mask & REDRAW_TILES)
211 for(x=0; x<SCR_FIELDX; x++)
212 for(y=0; y<SCR_FIELDY; y++)
213 if (redraw[redraw_x1 + x][redraw_y1 + y])
214 XCopyArea(display, buffer, window, gc,
215 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
216 SX + x * TILEX, SY + y * TILEY);
221 for(x=0; x<MAX_BUF_XSIZE; x++)
222 for(y=0; y<MAX_BUF_YSIZE; y++)
231 long fading_delay = 300;
233 if (setup.fading && (redraw_mask & REDRAW_FIELD))
240 XFillRectangle(display,window,gc,
241 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
244 for(i=0;i<2*FULL_SYSIZE;i++)
246 for(y=0;y<FULL_SYSIZE;y++)
248 XCopyArea(display,backbuffer,window,gc,
249 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
257 for(i=1;i<FULL_SYSIZE;i+=2)
258 XCopyArea(display,backbuffer,window,gc,
259 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
265 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
266 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
267 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
271 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
272 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
273 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
277 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
278 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
279 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
283 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
284 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
285 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
289 redraw_mask &= ~REDRAW_MAIN;
298 XFillRectangle(display, backbuffer, gc,
299 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
301 if (setup.soft_scrolling && game_status == PLAYING)
303 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
304 SetDrawtoField(DRAW_BUFFERED);
307 SetDrawtoField(DRAW_BACKBUFFER);
309 if (setup.direct_draw && game_status == PLAYING)
311 XFillRectangle(display, window, gc,
312 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
313 SetDrawtoField(DRAW_DIRECT);
316 redraw_mask |= REDRAW_FIELD;
319 int getFontWidth(int font_size, int font_type)
321 return (font_size == FS_BIG ? FONT1_XSIZE :
322 font_size == FS_MEDIUM ? FONT6_XSIZE :
323 font_type == FC_SPECIAL1 ? FONT3_XSIZE :
324 font_type == FC_SPECIAL2 ? FONT4_XSIZE :
325 font_type == FC_SPECIAL3 ? FONT5_XSIZE :
329 int getFontHeight(int font_size, int font_type)
331 return (font_size == FS_BIG ? FONT1_YSIZE :
332 font_size == FS_MEDIUM ? FONT6_YSIZE :
333 font_type == FC_SPECIAL1 ? FONT3_YSIZE :
334 font_type == FC_SPECIAL2 ? FONT4_YSIZE :
335 font_type == FC_SPECIAL3 ? FONT5_YSIZE :
339 void DrawInitText(char *text, int ypos, int color)
341 if (display && window && pix[PIX_SMALLFONT])
343 XFillRectangle(display, window, gc, 0, ypos, WIN_XSIZE, FONT2_YSIZE);
344 DrawTextExt(window, gc, (WIN_XSIZE - strlen(text) * FONT2_XSIZE)/2,
345 ypos,text,FS_SMALL,color);
350 void DrawTextFCentered(int y, int font_type, char *format, ...)
352 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
353 int font_width = getFontWidth(FS_SMALL, font_type);
356 va_start(ap, format);
357 vsprintf(buffer, format, ap);
360 DrawText(SX + (SXSIZE - strlen(buffer) * font_width) / 2, SY + y,
361 buffer, FS_SMALL, font_type);
364 void DrawTextF(int x, int y, int font_type, char *format, ...)
366 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
369 va_start(ap, format);
370 vsprintf(buffer, format, ap);
373 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
376 void DrawText(int x, int y, char *text, int font_size, int font_type)
378 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
381 redraw_mask |= REDRAW_FIELD;
383 redraw_mask |= REDRAW_DOOR_1;
386 void DrawTextExt(Drawable d, GC gc, int x, int y,
387 char *text, int font_size, int font_type)
389 int font_width, font_height, font_start;
391 boolean print_inverse = FALSE;
393 if (font_size != FS_SMALL && font_size != FS_BIG && font_size != FS_MEDIUM)
394 font_size = FS_SMALL;
395 if (font_type < FC_RED || font_type > FC_SPECIAL3)
398 font_width = getFontWidth(font_size, font_type);
399 font_height = getFontHeight(font_size, font_type);
401 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT :
402 font_size == FS_MEDIUM ? PIX_MEDIUMFONT :
404 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE :
405 font_size == FS_MEDIUM ? FONT6_YSIZE :
407 FONT_LINES_PER_FONT);
409 if (font_type == FC_SPECIAL3)
410 font_start += (FONT4_YSIZE - FONT2_YSIZE) * FONT_LINES_PER_FONT;
416 if (c == '~' && font_size == FS_SMALL)
418 print_inverse = TRUE;
422 if (c >= 'a' && c <= 'z')
424 else if (c == 'ä' || c == 'Ä')
426 else if (c == 'ö' || c == 'Ö')
428 else if (c == 'ü' || c == 'Ü')
431 if (c >= 32 && c <= 95)
433 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
434 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
435 int dest_x = x, dest_y = y;
439 XCopyArea(display, pix[font_pixmap], d, gc,
440 FONT_CHARS_PER_LINE * font_width,
441 3 * font_height + font_start,
442 font_width, font_height, x, y);
444 XSetClipOrigin(display, clip_gc[font_pixmap],
445 dest_x - src_x, dest_y - src_y);
446 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
447 0, 0, font_width, font_height, dest_x, dest_y);
450 XCopyArea(display, pix[font_pixmap], d, gc,
451 src_x, src_y, font_width, font_height, dest_x, dest_y);
458 void DrawAllPlayers()
462 for(i=0; i<MAX_PLAYERS; i++)
463 if (stored_player[i].active)
464 DrawPlayer(&stored_player[i]);
467 void DrawPlayerField(int x, int y)
469 if (!IS_PLAYER(x, y))
472 DrawPlayer(PLAYERINFO(x, y));
475 void DrawPlayer(struct PlayerInfo *player)
477 int jx = player->jx, jy = player->jy;
478 int last_jx = player->last_jx, last_jy = player->last_jy;
479 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
480 int sx = SCREENX(jx), sy = SCREENY(jy);
481 int sxx = 0, syy = 0;
482 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
484 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
486 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
490 if (!IN_LEV_FIELD(jx,jy))
492 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
493 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
494 printf("DrawPlayerField(): This should never happen!\n");
499 if (element == EL_EXPLODING)
502 /* draw things in the field the player is leaving, if needed */
504 if (player_is_moving)
506 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
508 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
509 DrawLevelFieldThruMask(last_jx, last_jy);
511 else if (last_element == EL_DYNAMITE_ACTIVE)
512 DrawDynamite(last_jx, last_jy);
514 DrawLevelField(last_jx, last_jy);
516 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
520 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
521 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
523 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
526 DrawLevelField(next_jx, next_jy);
530 if (!IN_SCR_FIELD(sx, sy))
533 if (setup.direct_draw)
534 SetDrawtoField(DRAW_BUFFERED);
536 /* draw things behind the player, if needed */
539 DrawLevelElement(jx, jy, Store[jx][jy]);
540 else if (!IS_ACTIVE_BOMB(element))
541 DrawLevelField(jx, jy);
543 /* draw player himself */
545 if (game.emulation == EMU_SUPAPLEX)
547 static int last_dir = MV_LEFT;
548 int action = (player->programmed_action ? player->programmed_action :
550 boolean action_moving =
552 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
553 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
555 graphic = GFX_SP_MURPHY;
559 if (player->MovDir == MV_LEFT)
560 graphic = GFX_MURPHY_PUSH_LEFT;
561 else if (player->MovDir == MV_RIGHT)
562 graphic = GFX_MURPHY_PUSH_RIGHT;
563 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
564 graphic = GFX_MURPHY_PUSH_LEFT;
565 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
566 graphic = GFX_MURPHY_PUSH_RIGHT;
568 else if (player->snapped)
570 if (player->MovDir == MV_LEFT)
571 graphic = GFX_MURPHY_SNAP_LEFT;
572 else if (player->MovDir == MV_RIGHT)
573 graphic = GFX_MURPHY_SNAP_RIGHT;
574 else if (player->MovDir == MV_UP)
575 graphic = GFX_MURPHY_SNAP_UP;
576 else if (player->MovDir == MV_DOWN)
577 graphic = GFX_MURPHY_SNAP_DOWN;
579 else if (action_moving)
581 if (player->MovDir == MV_LEFT)
582 graphic = GFX_MURPHY_GO_LEFT;
583 else if (player->MovDir == MV_RIGHT)
584 graphic = GFX_MURPHY_GO_RIGHT;
585 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
586 graphic = GFX_MURPHY_GO_LEFT;
587 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
588 graphic = GFX_MURPHY_GO_RIGHT;
590 graphic = GFX_MURPHY_GO_LEFT;
592 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
595 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
596 last_dir = player->MovDir;
600 if (player->MovDir == MV_LEFT)
602 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
603 else if (player->MovDir == MV_RIGHT)
605 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
606 else if (player->MovDir == MV_UP)
607 graphic = GFX_SPIELER1_UP;
608 else /* MV_DOWN || MV_NO_MOVING */
609 graphic = GFX_SPIELER1_DOWN;
611 graphic += player->index_nr * 3 * HEROES_PER_LINE;
612 graphic += player->Frame;
617 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
618 sxx = player->GfxPos;
620 syy = player->GfxPos;
623 if (!setup.soft_scrolling && ScreenMovPos)
626 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
628 if (SHIELD_ON(player))
630 int graphic = (player->shield_active_time_left ? GFX2_SHIELD_ACTIVE :
631 GFX2_SHIELD_PASSIVE);
633 DrawGraphicAnimationShiftedThruMask(sx, sy, sxx, syy, graphic,
634 3, 8, ANIM_OSCILLATE);
637 if (player->Pushing && player->GfxPos)
639 int px = SCREENX(next_jx), py = SCREENY(next_jy);
641 if (element == EL_SOKOBAN_FELD_LEER ||
642 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
643 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
647 int element = Feld[next_jx][next_jy];
648 int graphic = el2gfx(element);
650 if ((element == EL_FELSBROCKEN ||
651 element == EL_SP_ZONK ||
652 element == EL_BD_ROCK) && sxx)
654 int phase = (player->GfxPos / (TILEX / 4));
656 if (player->MovDir == MV_LEFT)
659 graphic += (phase + 4) % 4;
662 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
666 /* draw things in front of player (active dynamite or dynabombs) */
668 if (IS_ACTIVE_BOMB(element))
670 graphic = el2gfx(element);
672 if (element == EL_DYNAMITE_ACTIVE)
674 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
679 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
683 if (game.emulation == EMU_SUPAPLEX)
684 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
686 DrawGraphicThruMask(sx, sy, graphic + phase);
689 if (player_is_moving && last_element == EL_EXPLODING)
691 int phase = Frame[last_jx][last_jy];
695 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
696 GFX_EXPLOSION + ((phase - 1) / delay - 1));
699 /* draw elements that stay over the player */
700 /* handle the field the player is leaving ... */
701 if (player_is_moving && IS_OVER_PLAYER(last_element))
702 DrawLevelField(last_jx, last_jy);
703 /* ... and the field the player is entering */
704 if (IS_OVER_PLAYER(element))
705 DrawLevelField(jx, jy);
707 if (setup.direct_draw)
709 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
710 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
711 int x_size = TILEX * (1 + ABS(jx - last_jx));
712 int y_size = TILEY * (1 + ABS(jy - last_jy));
714 XCopyArea(display, drawto_field, window, gc,
715 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
716 SetDrawtoField(DRAW_DIRECT);
719 MarkTileDirty(sx,sy);
722 static int getGraphicAnimationPhase(int frames, int delay, int mode)
726 if (mode == ANIM_OSCILLATE)
728 int max_anim_frames = 2 * frames - 2;
729 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
730 phase = (phase < frames ? phase : max_anim_frames - phase);
733 phase = (FrameCounter % (delay * frames)) / delay;
735 if (mode == ANIM_REVERSE)
741 void DrawGraphicAnimationExt(int x, int y, int graphic,
742 int frames, int delay, int mode, int mask_mode)
744 int phase = getGraphicAnimationPhase(frames, delay, mode);
746 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
748 if (mask_mode == USE_MASKING)
749 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
751 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
755 void DrawGraphicAnimation(int x, int y, int graphic,
756 int frames, int delay, int mode)
758 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
761 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
762 int frames, int delay, int mode)
764 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
767 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
770 int frames, int delay,
773 int phase = getGraphicAnimationPhase(frames, delay, mode);
775 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
778 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
780 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
782 graphic -= GFX_START_ROCKSSCREEN;
783 *pixmap_nr = PIX_BACK;
784 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
785 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
787 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
789 graphic -= GFX_START_ROCKSHEROES;
790 *pixmap_nr = PIX_HEROES;
791 *x = (graphic % HEROES_PER_LINE) * TILEX;
792 *y = (graphic / HEROES_PER_LINE) * TILEY;
794 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
796 graphic -= GFX_START_ROCKSSP;
798 *x = (graphic % SP_PER_LINE) * TILEX;
799 *y = (graphic / SP_PER_LINE) * TILEY;
801 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
803 graphic -= GFX_START_ROCKSDC;
805 *x = (graphic % DC_PER_LINE) * TILEX;
806 *y = (graphic / DC_PER_LINE) * TILEY;
808 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
810 graphic -= GFX_START_ROCKSMORE;
811 *pixmap_nr = PIX_MORE;
812 *x = (graphic % MORE_PER_LINE) * TILEX;
813 *y = (graphic / MORE_PER_LINE) * TILEY;
815 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
817 graphic -= GFX_START_ROCKSFONT;
818 *pixmap_nr = PIX_BIGFONT;
819 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
820 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
821 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
831 void DrawGraphic(int x, int y, int graphic)
834 if (!IN_SCR_FIELD(x,y))
836 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
837 printf("DrawGraphic(): This should never happen!\n");
842 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
846 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
851 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
852 XCopyArea(display, pix[pixmap_nr], d, gc,
853 src_x, src_y, TILEX, TILEY, x, y);
856 void DrawGraphicThruMask(int x, int y, int graphic)
859 if (!IN_SCR_FIELD(x,y))
861 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
862 printf("DrawGraphicThruMask(): This should never happen!\n");
867 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
871 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
879 if (graphic == GFX_LEERRAUM)
882 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
883 src_pixmap = pix[pixmap_nr];
884 drawing_gc = clip_gc[pixmap_nr];
886 if (tile_clipmask[tile] != None)
888 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
889 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
890 XCopyArea(display, src_pixmap, d, tile_clip_gc,
891 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
896 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
899 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
900 XCopyArea(display, src_pixmap, d, drawing_gc,
901 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
905 void DrawMiniGraphic(int x, int y, int graphic)
907 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
908 MarkTileDirty(x/2, y/2);
911 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
913 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
915 graphic -= GFX_START_ROCKSSCREEN;
916 *pixmap = pix[PIX_BACK];
917 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
918 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
920 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
922 graphic -= GFX_START_ROCKSSP;
923 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
924 *pixmap = pix[PIX_SP];
925 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
926 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
928 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
930 graphic -= GFX_START_ROCKSDC;
931 *pixmap = pix[PIX_DC];
932 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
933 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
935 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
937 graphic -= GFX_START_ROCKSMORE;
938 *pixmap = pix[PIX_MORE];
939 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
940 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
942 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
944 graphic -= GFX_START_ROCKSFONT;
945 *pixmap = pix[PIX_SMALLFONT];
946 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
947 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
948 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
952 *pixmap = pix[PIX_SP];
958 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
963 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
964 XCopyArea(display, pixmap, d, gc,
965 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
968 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
969 int cut_mode, int mask_mode)
971 int width = TILEX, height = TILEY;
973 int src_x, src_y, dest_x, dest_y;
981 DrawGraphic(x, y, graphic);
985 if (dx || dy) /* Verschiebung der Grafik? */
987 if (x < BX1) /* Element kommt von links ins Bild */
994 else if (x > BX2) /* Element kommt von rechts ins Bild */
1000 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1006 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1008 else if (dx) /* allg. Bewegung in x-Richtung */
1009 MarkTileDirty(x + SIGN(dx), y);
1011 if (y < BY1) /* Element kommt von oben ins Bild */
1013 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1021 else if (y > BY2) /* Element kommt von unten ins Bild */
1027 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1033 else if (dy > 0 && cut_mode == CUT_ABOVE)
1035 if (y == BY2) /* Element unterhalb des Bildes */
1041 MarkTileDirty(x, y + 1);
1042 } /* Element verläßt unten das Bild */
1043 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1045 else if (dy) /* allg. Bewegung in y-Richtung */
1046 MarkTileDirty(x, y + SIGN(dy));
1049 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
1050 src_pixmap = pix[pixmap_nr];
1051 drawing_gc = clip_gc[pixmap_nr];
1056 dest_x = FX + x * TILEX + dx;
1057 dest_y = FY + y * TILEY + dy;
1060 if (!IN_SCR_FIELD(x,y))
1062 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1063 printf("DrawGraphicShifted(): This should never happen!\n");
1068 if (mask_mode == USE_MASKING)
1070 if (tile_clipmask[tile] != None)
1072 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
1073 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1074 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1075 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1080 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1083 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1084 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1085 src_x, src_y, width, height, dest_x, dest_y);
1089 XCopyArea(display, src_pixmap, drawto_field, gc,
1090 src_x, src_y, width, height, dest_x, dest_y);
1095 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1098 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1101 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1102 int cut_mode, int mask_mode)
1104 int ux = LEVELX(x), uy = LEVELY(y);
1105 int graphic = el2gfx(element);
1106 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1107 int phase4 = phase8 / 2;
1108 int phase2 = phase8 / 4;
1109 int dir = MovDir[ux][uy];
1111 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1113 graphic += 4 * !phase2;
1117 else if (dir == MV_LEFT)
1119 else if (dir == MV_DOWN)
1122 else if (element == EL_SP_SNIKSNAK)
1125 graphic = GFX_SP_SNIKSNAK_LEFT;
1126 else if (dir == MV_RIGHT)
1127 graphic = GFX_SP_SNIKSNAK_RIGHT;
1128 else if (dir == MV_UP)
1129 graphic = GFX_SP_SNIKSNAK_UP;
1131 graphic = GFX_SP_SNIKSNAK_DOWN;
1133 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1135 else if (element == EL_SP_ELECTRON)
1137 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1139 else if (element == EL_MOLE || element == EL_PINGUIN ||
1140 element == EL_SCHWEIN || element == EL_DRACHE)
1143 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1144 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1145 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1146 else if (dir == MV_RIGHT)
1147 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1148 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1149 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1150 else if (dir == MV_UP)
1151 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1152 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1153 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1155 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1156 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1157 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1161 else if (element == EL_SONDE)
1163 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1165 else if (element == EL_SALZSAEURE)
1167 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1169 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1173 else if (element == EL_BALLOON)
1177 else if ((element == EL_FELSBROCKEN ||
1178 element == EL_SP_ZONK ||
1179 element == EL_BD_ROCK ||
1180 IS_GEM(element)) && !cut_mode)
1182 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1184 if (element == EL_FELSBROCKEN ||
1185 element == EL_SP_ZONK ||
1186 element == EL_BD_ROCK)
1189 graphic += (4 - phase4) % 4;
1190 else if (dir == MV_RIGHT)
1193 graphic += phase2 * 2;
1195 else if (element != EL_SP_INFOTRON)
1199 else if (element == EL_MAGIC_WALL_EMPTY ||
1200 element == EL_MAGIC_WALL_BD_EMPTY ||
1201 element == EL_MAGIC_WALL_FULL ||
1202 element == EL_MAGIC_WALL_BD_FULL)
1204 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1206 else if (IS_AMOEBOID(element))
1208 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1209 graphic += (x + 2 * y + 4) % 4;
1211 else if (element == EL_MAUER_LEBT)
1213 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1215 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1216 links_massiv = TRUE;
1217 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1218 rechts_massiv = TRUE;
1220 if (links_massiv && rechts_massiv)
1221 graphic = GFX_MAUERWERK;
1222 else if (links_massiv)
1223 graphic = GFX_MAUER_R;
1224 else if (rechts_massiv)
1225 graphic = GFX_MAUER_L;
1227 else if ((element == EL_INVISIBLE_STEEL ||
1228 element == EL_UNSICHTBAR ||
1229 element == EL_SAND_INVISIBLE) && game.light_time_left)
1231 graphic = (element == EL_INVISIBLE_STEEL ? GFX_INVISIBLE_STEEL_ON :
1232 element == EL_UNSICHTBAR ? GFX_UNSICHTBAR_ON :
1233 GFX_SAND_INVISIBLE_ON);
1237 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1238 else if (mask_mode == USE_MASKING)
1239 DrawGraphicThruMask(x, y, graphic);
1241 DrawGraphic(x, y, graphic);
1244 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1245 int cut_mode, int mask_mode)
1247 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1248 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1249 cut_mode, mask_mode);
1252 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1255 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1258 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1261 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1264 void DrawScreenElementThruMask(int x, int y, int element)
1266 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1269 void DrawLevelElementThruMask(int x, int y, int element)
1271 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1274 void DrawLevelFieldThruMask(int x, int y)
1276 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1279 void ErdreichAnbroeckeln(int x, int y)
1281 int i, width, height, cx,cy;
1282 int ux = LEVELX(x), uy = LEVELY(y);
1283 int element, graphic;
1285 static int xy[4][2] =
1293 if (!IN_LEV_FIELD(ux, uy))
1296 element = Feld[ux][uy];
1298 if (element == EL_ERDREICH ||
1299 element == EL_LANDMINE ||
1300 element == EL_TRAP_INACTIVE ||
1301 element == EL_TRAP_ACTIVE)
1303 if (!IN_SCR_FIELD(x, y))
1306 graphic = GFX_ERDENRAND;
1312 uxx = ux + xy[i][0];
1313 uyy = uy + xy[i][1];
1314 if (!IN_LEV_FIELD(uxx, uyy))
1317 element = Feld[uxx][uyy];
1319 if (element == EL_ERDREICH ||
1320 element == EL_LANDMINE ||
1321 element == EL_TRAP_INACTIVE ||
1322 element == EL_TRAP_ACTIVE)
1325 if (i == 1 || i == 2)
1329 cx = (i == 2 ? TILEX - snip : 0);
1337 cy = (i == 3 ? TILEY - snip : 0);
1340 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1341 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1342 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1343 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1346 MarkTileDirty(x, y);
1350 graphic = GFX_ERDENRAND;
1354 int xx, yy, uxx, uyy;
1358 uxx = ux + xy[i][0];
1359 uyy = uy + xy[i][1];
1361 if (!IN_LEV_FIELD(uxx, uyy) ||
1362 (Feld[uxx][uyy] != EL_ERDREICH &&
1363 Feld[uxx][uyy] != EL_LANDMINE &&
1364 Feld[uxx][uyy] != EL_TRAP_INACTIVE &&
1365 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1366 !IN_SCR_FIELD(xx, yy))
1369 if (i == 1 || i == 2)
1373 cx = (i == 1 ? TILEX - snip : 0);
1381 cy = (i==0 ? TILEY-snip : 0);
1384 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1385 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1386 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1387 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1389 MarkTileDirty(xx, yy);
1394 void DrawScreenElement(int x, int y, int element)
1396 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1397 ErdreichAnbroeckeln(x, y);
1400 void DrawLevelElement(int x, int y, int element)
1402 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1403 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1406 void DrawScreenField(int x, int y)
1408 int ux = LEVELX(x), uy = LEVELY(y);
1411 if (!IN_LEV_FIELD(ux, uy))
1413 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1414 element = EL_LEERRAUM;
1416 element = BorderElement;
1418 DrawScreenElement(x, y, element);
1422 element = Feld[ux][uy];
1424 if (IS_MOVING(ux, uy))
1426 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1427 boolean cut_mode = NO_CUTTING;
1429 if (Store[ux][uy] == EL_MORAST_LEER ||
1430 Store[ux][uy] == EL_MAGIC_WALL_EMPTY ||
1431 Store[ux][uy] == EL_MAGIC_WALL_BD_EMPTY ||
1432 Store[ux][uy] == EL_AMOEBE_NASS)
1433 cut_mode = CUT_ABOVE;
1434 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1435 Store[ux][uy] == EL_MAGIC_WALL_FULL ||
1436 Store[ux][uy] == EL_MAGIC_WALL_BD_FULL)
1437 cut_mode = CUT_BELOW;
1439 if (cut_mode == CUT_ABOVE)
1440 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1442 DrawScreenElement(x, y, EL_LEERRAUM);
1445 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1447 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1449 if (Store[ux][uy] == EL_SALZSAEURE)
1450 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1452 else if (IS_BLOCKED(ux, uy))
1457 boolean cut_mode = NO_CUTTING;
1459 Blocked2Moving(ux, uy, &oldx, &oldy);
1462 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1463 MovDir[oldx][oldy] == MV_RIGHT);
1465 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1466 Store[oldx][oldy] == EL_MAGIC_WALL_EMPTY ||
1467 Store[oldx][oldy] == EL_MAGIC_WALL_BD_EMPTY ||
1468 Store[oldx][oldy] == EL_AMOEBE_NASS)
1469 cut_mode = CUT_ABOVE;
1471 DrawScreenElement(x, y, EL_LEERRAUM);
1472 element = Feld[oldx][oldy];
1475 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1477 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1479 else if (IS_DRAWABLE(element))
1480 DrawScreenElement(x, y, element);
1482 DrawScreenElement(x, y, EL_LEERRAUM);
1485 void DrawLevelField(int x, int y)
1487 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1488 DrawScreenField(SCREENX(x), SCREENY(y));
1489 else if (IS_MOVING(x, y))
1493 Moving2Blocked(x, y, &newx, &newy);
1494 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1495 DrawScreenField(SCREENX(newx), SCREENY(newy));
1497 else if (IS_BLOCKED(x, y))
1501 Blocked2Moving(x, y, &oldx, &oldy);
1502 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1503 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1507 void DrawMiniElement(int x, int y, int element)
1513 DrawMiniGraphic(x, y, -1);
1517 graphic = el2gfx(element);
1518 DrawMiniGraphic(x, y, graphic);
1521 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1523 int x = sx + scroll_x, y = sy + scroll_y;
1525 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1526 DrawMiniElement(sx, sy, EL_LEERRAUM);
1527 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1528 DrawMiniElement(sx, sy, Feld[x][y]);
1531 int steel_type, steel_position;
1534 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1535 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1536 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1537 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1538 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1539 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1542 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1543 steel_position = (x == -1 && y == -1 ? 0 :
1544 x == lev_fieldx && y == -1 ? 1 :
1545 x == -1 && y == lev_fieldy ? 2 :
1546 x == lev_fieldx && y == lev_fieldy ? 3 :
1547 x == -1 || x == lev_fieldx ? 4 :
1548 y == -1 || y == lev_fieldy ? 5 : -1);
1550 if (steel_position != -1)
1551 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1555 void DrawMicroElement(int xpos, int ypos, int element)
1559 if (element == EL_LEERRAUM)
1562 graphic = el2gfx(element);
1564 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1566 graphic -= GFX_START_ROCKSSP;
1567 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
1568 XCopyArea(display, pix[PIX_SP], drawto, gc,
1569 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
1570 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
1571 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1573 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1575 graphic -= GFX_START_ROCKSDC;
1576 XCopyArea(display, pix[PIX_DC], drawto, gc,
1577 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
1578 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
1579 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1581 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1583 graphic -= GFX_START_ROCKSMORE;
1584 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1585 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1586 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1587 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1590 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1591 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1592 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1593 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1602 for(x=BX1; x<=BX2; x++)
1603 for(y=BY1; y<=BY2; y++)
1604 DrawScreenField(x, y);
1606 redraw_mask |= REDRAW_FIELD;
1609 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1613 for(x=0; x<size_x; x++)
1614 for(y=0; y<size_y; y++)
1615 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1617 redraw_mask |= REDRAW_FIELD;
1620 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1624 XFillRectangle(display, drawto, gc,
1625 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1627 if (lev_fieldx < STD_LEV_FIELDX)
1628 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1629 if (lev_fieldy < STD_LEV_FIELDY)
1630 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1632 xpos += MICRO_TILEX;
1633 ypos += MICRO_TILEY;
1635 for(x=-1; x<=STD_LEV_FIELDX; x++)
1637 for(y=-1; y<=STD_LEV_FIELDY; y++)
1639 int lx = from_x + x, ly = from_y + y;
1641 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1642 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1644 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1645 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1650 redraw_mask |= REDRAW_MICROLEVEL;
1653 #define MICROLABEL_EMPTY 0
1654 #define MICROLABEL_LEVEL_NAME 1
1655 #define MICROLABEL_CREATED_BY 2
1656 #define MICROLABEL_LEVEL_AUTHOR 3
1657 #define MICROLABEL_IMPORTED_FROM 4
1658 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1660 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1662 static void DrawMicroLevelLabelExt(int mode)
1664 char label_text[MAX_MICROLABEL_SIZE + 1];
1666 XFillRectangle(display, drawto,gc,
1667 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1669 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1670 mode == MICROLABEL_CREATED_BY ? "created by" :
1671 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1672 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1673 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1674 leveldir_current->imported_from : ""),
1675 MAX_MICROLABEL_SIZE);
1676 label_text[MAX_MICROLABEL_SIZE] = '\0';
1678 if (strlen(label_text) > 0)
1680 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1681 int lypos = MICROLABEL_YPOS;
1683 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1686 redraw_mask |= REDRAW_MICROLEVEL;
1689 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1691 static unsigned long scroll_delay = 0;
1692 static unsigned long label_delay = 0;
1693 static int from_x, from_y, scroll_direction;
1694 static int label_state, label_counter;
1698 from_x = from_y = 0;
1699 scroll_direction = MV_RIGHT;
1703 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1704 DrawMicroLevelLabelExt(label_state);
1706 /* initialize delay counters */
1707 DelayReached(&scroll_delay, 0);
1708 DelayReached(&label_delay, 0);
1713 /* scroll micro level, if needed */
1714 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1715 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1717 switch (scroll_direction)
1723 scroll_direction = MV_UP;
1727 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1730 scroll_direction = MV_DOWN;
1737 scroll_direction = MV_RIGHT;
1741 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1744 scroll_direction = MV_LEFT;
1751 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1754 /* redraw micro level label, if needed */
1755 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1756 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1757 strcmp(level.author, leveldir_current->name) != 0 &&
1758 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1760 int max_label_counter = 23;
1762 if (leveldir_current->imported_from != NULL)
1763 max_label_counter += 14;
1765 label_counter = (label_counter + 1) % max_label_counter;
1766 label_state = (label_counter >= 0 && label_counter <= 7 ?
1767 MICROLABEL_LEVEL_NAME :
1768 label_counter >= 9 && label_counter <= 12 ?
1769 MICROLABEL_CREATED_BY :
1770 label_counter >= 14 && label_counter <= 21 ?
1771 MICROLABEL_LEVEL_AUTHOR :
1772 label_counter >= 23 && label_counter <= 26 ?
1773 MICROLABEL_IMPORTED_FROM :
1774 label_counter >= 28 && label_counter <= 35 ?
1775 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1776 DrawMicroLevelLabelExt(label_state);
1780 int REQ_in_range(int x, int y)
1782 if (y > DY+249 && y < DY+278)
1784 if (x > DX+1 && x < DX+48)
1786 else if (x > DX+51 && x < DX+98)
1792 boolean Request(char *text, unsigned int req_state)
1794 int mx, my, ty, result = -1;
1795 unsigned int old_door_state;
1798 /* pause network game while waiting for request to answer */
1799 if (options.network &&
1800 game_status == PLAYING &&
1801 req_state & REQUEST_WAIT_FOR)
1802 SendToServer_PausePlaying();
1805 old_door_state = GetDoorState();
1809 CloseDoor(DOOR_CLOSE_1);
1811 /* save old door content */
1812 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1813 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1814 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1816 /* clear door drawing field */
1817 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1819 /* write text for request */
1820 for(ty=0; ty<13; ty++)
1828 for(tl=0,tx=0; tx<7; tl++,tx++)
1831 if (!tc || tc == 32)
1842 DrawTextExt(drawto, gc,
1843 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1844 txt, FS_SMALL, FC_YELLOW);
1845 text += tl + (tc == 32 ? 1 : 0);
1848 if (req_state & REQ_ASK)
1850 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1851 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1853 else if (req_state & REQ_CONFIRM)
1855 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1857 else if (req_state & REQ_PLAYER)
1859 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1860 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1861 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1862 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1865 /* copy request gadgets to door backbuffer */
1866 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1867 DX, DY, DXSIZE, DYSIZE,
1868 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1870 OpenDoor(DOOR_OPEN_1);
1876 if (!(req_state & REQUEST_WAIT_FOR))
1879 if (game_status != MAINMENU)
1882 button_status = MB_RELEASED;
1884 request_gadget_id = -1;
1888 if (XPending(display))
1892 XNextEvent(display, &event);
1900 if (event.type == MotionNotify)
1907 if (!XQueryPointer(display, window, &root, &child,
1908 &root_x, &root_y, &win_x, &win_y, &mask))
1914 motion_status = TRUE;
1915 mx = ((XMotionEvent *) &event)->x;
1916 my = ((XMotionEvent *) &event)->y;
1920 motion_status = FALSE;
1921 mx = ((XButtonEvent *) &event)->x;
1922 my = ((XButtonEvent *) &event)->y;
1923 if (event.type==ButtonPress)
1924 button_status = ((XButtonEvent *) &event)->button;
1926 button_status = MB_RELEASED;
1929 /* this sets 'request_gadget_id' */
1930 HandleGadgets(mx, my, button_status);
1932 switch(request_gadget_id)
1934 case TOOL_CTRL_ID_YES:
1937 case TOOL_CTRL_ID_NO:
1940 case TOOL_CTRL_ID_CONFIRM:
1941 result = TRUE | FALSE;
1944 case TOOL_CTRL_ID_PLAYER_1:
1947 case TOOL_CTRL_ID_PLAYER_2:
1950 case TOOL_CTRL_ID_PLAYER_3:
1953 case TOOL_CTRL_ID_PLAYER_4:
1965 switch(XLookupKeysym((XKeyEvent *)&event,
1966 ((XKeyEvent *)&event)->state))
1979 if (req_state & REQ_PLAYER)
1984 key_joystick_mapping = 0;
1988 HandleOtherEvents(&event);
1992 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1994 int joy = AnyJoystick();
1996 if (joy & JOY_BUTTON_1)
1998 else if (joy & JOY_BUTTON_2)
2004 /* don't eat all CPU time */
2008 if (game_status != MAINMENU)
2013 if (!(req_state & REQ_STAY_OPEN))
2015 CloseDoor(DOOR_CLOSE_1);
2017 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2019 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
2020 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2021 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2022 OpenDoor(DOOR_OPEN_1);
2029 /* continue network game after request */
2030 if (options.network &&
2031 game_status == PLAYING &&
2032 req_state & REQUEST_WAIT_FOR)
2033 SendToServer_ContinuePlaying();
2039 unsigned int OpenDoor(unsigned int door_state)
2041 unsigned int new_door_state;
2043 if (door_state & DOOR_COPY_BACK)
2045 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
2046 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2047 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2048 door_state &= ~DOOR_COPY_BACK;
2051 new_door_state = MoveDoor(door_state);
2053 return(new_door_state);
2056 unsigned int CloseDoor(unsigned int door_state)
2058 unsigned int new_door_state;
2060 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2061 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2062 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2063 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2065 new_door_state = MoveDoor(door_state);
2067 return(new_door_state);
2070 unsigned int GetDoorState()
2072 return(MoveDoor(DOOR_GET_STATE));
2075 unsigned int MoveDoor(unsigned int door_state)
2077 static int door1 = DOOR_OPEN_1;
2078 static int door2 = DOOR_CLOSE_2;
2079 static unsigned long door_delay = 0;
2080 int x, start, stepsize = 2;
2081 unsigned long door_delay_value = stepsize * 5;
2083 if (door_state == DOOR_GET_STATE)
2084 return(door1 | door2);
2086 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2087 door_state &= ~DOOR_OPEN_1;
2088 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2089 door_state &= ~DOOR_CLOSE_1;
2090 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2091 door_state &= ~DOOR_OPEN_2;
2092 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2093 door_state &= ~DOOR_CLOSE_2;
2095 if (setup.quick_doors)
2098 door_delay_value = 0;
2099 StopSound(SND_OEFFNEN);
2102 if (door_state & DOOR_ACTION)
2104 if (!(door_state & DOOR_NO_DELAY))
2105 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2107 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2109 for(x=start; x<=DXSIZE; x+=stepsize)
2111 WaitUntilDelayReached(&door_delay, door_delay_value);
2113 if (door_state & DOOR_ACTION_1)
2115 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2116 int j = (DXSIZE - i) / 3;
2118 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2119 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2120 DXSIZE,DYSIZE - i/2, DX, DY);
2122 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2124 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2125 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2126 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2127 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2128 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2129 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2131 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2132 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2133 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2134 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2135 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2136 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2138 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2139 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2141 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2142 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2144 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2145 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2146 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2147 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2148 DX + DXSIZE - i, DY + 77 + j);
2149 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2150 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2151 DX + DXSIZE - i, DY + 203 + j);
2153 redraw_mask |= REDRAW_DOOR_1;
2156 if (door_state & DOOR_ACTION_2)
2158 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2159 int j = (VXSIZE - i) / 3;
2161 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2162 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2163 VXSIZE, VYSIZE - i/2, VX, VY);
2165 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2167 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2168 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2169 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2170 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2171 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2172 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2173 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2174 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2176 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2177 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2178 VX, VY + VYSIZE / 2 - j);
2179 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2180 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2181 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2182 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2183 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2185 redraw_mask |= REDRAW_DOOR_2;
2190 if (game_status == MAINMENU)
2195 if (setup.quick_doors)
2196 StopSound(SND_OEFFNEN);
2198 if (door_state & DOOR_ACTION_1)
2199 door1 = door_state & DOOR_ACTION_1;
2200 if (door_state & DOOR_ACTION_2)
2201 door2 = door_state & DOOR_ACTION_2;
2203 return (door1 | door2);
2206 void DrawSpecialEditorDoor()
2208 /* draw bigger toolbox window */
2209 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2210 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2212 redraw_mask |= REDRAW_ALL;
2215 void UndrawSpecialEditorDoor()
2217 /* draw normal tape recorder window */
2218 XCopyArea(display, pix[PIX_BACK], drawto, gc,
2219 562, 344, 108, 56, EX - 4, EY - 12);
2221 redraw_mask |= REDRAW_ALL;
2224 int ReadPixel(Drawable d, int x, int y)
2226 XImage *pixel_image;
2227 unsigned long pixel_value;
2229 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2230 pixel_value = XGetPixel(pixel_image, 0, 0);
2232 XDestroyImage(pixel_image);
2237 /* ---------- new tool button stuff ---------------------------------------- */
2239 /* graphic position values for tool buttons */
2240 #define TOOL_BUTTON_YES_XPOS 2
2241 #define TOOL_BUTTON_YES_YPOS 250
2242 #define TOOL_BUTTON_YES_GFX_YPOS 0
2243 #define TOOL_BUTTON_YES_XSIZE 46
2244 #define TOOL_BUTTON_YES_YSIZE 28
2245 #define TOOL_BUTTON_NO_XPOS 52
2246 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2247 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2248 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2249 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2250 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2251 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2252 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2253 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2254 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2255 #define TOOL_BUTTON_PLAYER_XSIZE 30
2256 #define TOOL_BUTTON_PLAYER_YSIZE 30
2257 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2258 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2259 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2260 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2261 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2262 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2263 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2264 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2265 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2266 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2267 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2268 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2269 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2270 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2271 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2272 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2273 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2274 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2275 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2276 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2285 } toolbutton_info[NUM_TOOL_BUTTONS] =
2288 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2289 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2290 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2295 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2296 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2297 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2302 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2303 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2304 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2305 TOOL_CTRL_ID_CONFIRM,
2309 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2310 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2311 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2312 TOOL_CTRL_ID_PLAYER_1,
2316 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2317 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2318 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2319 TOOL_CTRL_ID_PLAYER_2,
2323 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2324 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2325 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2326 TOOL_CTRL_ID_PLAYER_3,
2330 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2331 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2332 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2333 TOOL_CTRL_ID_PLAYER_4,
2338 static void DoNotDisplayInfoText(void *ptr)
2343 void CreateToolButtons()
2347 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2349 Pixmap gd_pixmap = pix[PIX_DOOR];
2350 Pixmap deco_pixmap = None;
2351 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2352 struct GadgetInfo *gi;
2353 unsigned long event_mask;
2354 int gd_xoffset, gd_yoffset;
2355 int gd_x1, gd_x2, gd_y;
2358 event_mask = GD_EVENT_RELEASED;
2360 gd_xoffset = toolbutton_info[i].xpos;
2361 gd_yoffset = toolbutton_info[i].ypos;
2362 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2363 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2364 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2366 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2368 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2369 &deco_pixmap, &deco_x, &deco_y);
2370 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2371 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2374 gi = CreateGadget(GDI_CUSTOM_ID, id,
2375 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2376 GDI_X, DX + toolbutton_info[i].x,
2377 GDI_Y, DY + toolbutton_info[i].y,
2378 GDI_WIDTH, toolbutton_info[i].width,
2379 GDI_HEIGHT, toolbutton_info[i].height,
2380 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2381 GDI_STATE, GD_BUTTON_UNPRESSED,
2382 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2383 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2384 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2385 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2386 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2387 GDI_DECORATION_SHIFTING, 1, 1,
2388 GDI_EVENT_MASK, event_mask,
2389 GDI_CALLBACK_ACTION, HandleToolButtons,
2390 GDI_CALLBACK_INFO, DoNotDisplayInfoText,
2394 Error(ERR_EXIT, "cannot create gadget");
2396 tool_gadget[id] = gi;
2400 static void UnmapToolButtons()
2404 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2405 UnmapGadget(tool_gadget[i]);
2408 static void HandleToolButtons(struct GadgetInfo *gi)
2410 request_gadget_id = gi->custom_id;
2413 int el2gfx(int element)
2417 case EL_LEERRAUM: return -1;
2418 case EL_ERDREICH: return GFX_ERDREICH;
2419 case EL_MAUERWERK: return GFX_MAUERWERK;
2420 case EL_FELSBODEN: return GFX_FELSBODEN;
2421 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2422 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2423 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2424 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2425 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2426 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2427 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2428 case EL_SPIELER1: return GFX_SPIELER1;
2429 case EL_SPIELER2: return GFX_SPIELER2;
2430 case EL_SPIELER3: return GFX_SPIELER3;
2431 case EL_SPIELER4: return GFX_SPIELER4;
2432 case EL_KAEFER: return GFX_KAEFER;
2433 case EL_KAEFER_RIGHT: return GFX_KAEFER_RIGHT;
2434 case EL_KAEFER_UP: return GFX_KAEFER_UP;
2435 case EL_KAEFER_LEFT: return GFX_KAEFER_LEFT;
2436 case EL_KAEFER_DOWN: return GFX_KAEFER_DOWN;
2437 case EL_FLIEGER: return GFX_FLIEGER;
2438 case EL_FLIEGER_RIGHT: return GFX_FLIEGER_RIGHT;
2439 case EL_FLIEGER_UP: return GFX_FLIEGER_UP;
2440 case EL_FLIEGER_LEFT: return GFX_FLIEGER_LEFT;
2441 case EL_FLIEGER_DOWN: return GFX_FLIEGER_DOWN;
2442 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2443 case EL_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2444 case EL_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2445 case EL_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2446 case EL_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2447 case EL_FIREFLY: return GFX_FIREFLY;
2448 case EL_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2449 case EL_FIREFLY_UP: return GFX_FIREFLY_UP;
2450 case EL_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2451 case EL_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2452 case EL_MAMPFER: return GFX_MAMPFER;
2453 case EL_ROBOT: return GFX_ROBOT;
2454 case EL_BETON: return GFX_BETON;
2455 case EL_DIAMANT: return GFX_DIAMANT;
2456 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2457 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2458 case EL_TROPFEN: return GFX_TROPFEN;
2459 case EL_BOMBE: return GFX_BOMBE;
2460 case EL_MAGIC_WALL_OFF: return GFX_MAGIC_WALL_OFF;
2461 case EL_MAGIC_WALL_EMPTY: return GFX_MAGIC_WALL_EMPTY;
2462 case EL_MAGIC_WALL_FULL: return GFX_MAGIC_WALL_FULL;
2463 case EL_MAGIC_WALL_DEAD: return GFX_MAGIC_WALL_DEAD;
2464 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2465 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2466 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2467 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2468 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2469 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2470 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2471 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2472 case EL_LIFE: return GFX_LIFE;
2473 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2474 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2475 case EL_BADEWANNE: return GFX_BADEWANNE;
2476 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2477 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2478 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2479 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2480 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2481 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2482 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2483 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2484 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2485 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2486 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2487 case EL_PFORTE1: return GFX_PFORTE1;
2488 case EL_PFORTE2: return GFX_PFORTE2;
2489 case EL_PFORTE3: return GFX_PFORTE3;
2490 case EL_PFORTE4: return GFX_PFORTE4;
2491 case EL_PFORTE1X: return GFX_PFORTE1X;
2492 case EL_PFORTE2X: return GFX_PFORTE2X;
2493 case EL_PFORTE3X: return GFX_PFORTE3X;
2494 case EL_PFORTE4X: return GFX_PFORTE4X;
2495 case EL_DYNAMITE_INACTIVE: return GFX_DYNAMIT_AUS;
2496 case EL_PACMAN: return GFX_PACMAN;
2497 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2498 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2499 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2500 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2501 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2502 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2503 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2504 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2505 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2506 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2507 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2508 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2509 case EL_MAUER_X: return GFX_MAUER_X;
2510 case EL_MAUER_Y: return GFX_MAUER_Y;
2511 case EL_MAUER_XY: return GFX_MAUER_XY;
2512 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2513 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2514 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2515 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2516 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2517 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2518 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2519 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2520 case EL_MAMPFER2: return GFX_MAMPFER2;
2521 case EL_MAGIC_WALL_BD_OFF: return GFX_MAGIC_WALL_BD_OFF;
2522 case EL_MAGIC_WALL_BD_EMPTY:return GFX_MAGIC_WALL_BD_EMPTY;
2523 case EL_MAGIC_WALL_BD_FULL: return GFX_MAGIC_WALL_BD_FULL;
2524 case EL_MAGIC_WALL_BD_DEAD: return GFX_MAGIC_WALL_BD_DEAD;
2525 case EL_DYNABOMB_ACTIVE_1: return GFX_DYNABOMB;
2526 case EL_DYNABOMB_ACTIVE_2: return GFX_DYNABOMB;
2527 case EL_DYNABOMB_ACTIVE_3: return GFX_DYNABOMB;
2528 case EL_DYNABOMB_ACTIVE_4: return GFX_DYNABOMB;
2529 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2530 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2531 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2532 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2533 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2534 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2535 case EL_MOLE: return GFX_MOLE;
2536 case EL_PINGUIN: return GFX_PINGUIN;
2537 case EL_SCHWEIN: return GFX_SCHWEIN;
2538 case EL_DRACHE: return GFX_DRACHE;
2539 case EL_SONDE: return GFX_SONDE;
2540 case EL_PFEIL_LEFT: return GFX_PFEIL_LEFT;
2541 case EL_PFEIL_RIGHT: return GFX_PFEIL_RIGHT;
2542 case EL_PFEIL_UP: return GFX_PFEIL_UP;
2543 case EL_PFEIL_DOWN: return GFX_PFEIL_DOWN;
2544 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2545 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2546 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2547 case EL_SP_ZONK: return GFX_SP_ZONK;
2548 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2549 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2550 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2551 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2552 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2553 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2554 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2555 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2556 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2557 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2558 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2559 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2560 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2561 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2562 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2563 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2564 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2565 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2566 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2567 case EL_PEARL: return GFX_PEARL;
2568 case EL_CRYSTAL: return GFX_CRYSTAL;
2569 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2570 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2571 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2572 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2573 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2574 case EL_SHIELD_PASSIVE: return GFX_SHIELD_PASSIVE;
2575 case EL_SHIELD_ACTIVE: return GFX_SHIELD_ACTIVE;
2576 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2577 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2578 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2579 case EL_SWITCHGATE_SWITCH_1:return GFX_SWITCHGATE_SWITCH_1;
2580 case EL_SWITCHGATE_SWITCH_2:return GFX_SWITCHGATE_SWITCH_2;
2581 case EL_BELT1_LEFT: return GFX_BELT1_LEFT;
2582 case EL_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2583 case EL_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2584 case EL_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2585 case EL_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2586 case EL_BELT1_SWITCH_RIGHT: return GFX_BELT1_SWITCH_RIGHT;
2587 case EL_BELT2_LEFT: return GFX_BELT2_LEFT;
2588 case EL_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2589 case EL_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2590 case EL_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2591 case EL_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2592 case EL_BELT2_SWITCH_RIGHT: return GFX_BELT2_SWITCH_RIGHT;
2593 case EL_BELT3_LEFT: return GFX_BELT3_LEFT;
2594 case EL_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2595 case EL_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2596 case EL_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2597 case EL_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2598 case EL_BELT3_SWITCH_RIGHT: return GFX_BELT3_SWITCH_RIGHT;
2599 case EL_BELT4_LEFT: return GFX_BELT4_LEFT;
2600 case EL_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2601 case EL_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2602 case EL_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2603 case EL_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2604 case EL_BELT4_SWITCH_RIGHT: return GFX_BELT4_SWITCH_RIGHT;
2605 case EL_LANDMINE: return GFX_LANDMINE;
2606 case EL_ENVELOPE: return GFX_ENVELOPE;
2607 case EL_LIGHT_SWITCH_OFF: return GFX_LIGHT_SWITCH_OFF;
2608 case EL_LIGHT_SWITCH_ON: return GFX_LIGHT_SWITCH_ON;
2609 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2610 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2611 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2612 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2613 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2614 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2615 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2616 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2617 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2618 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2619 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2620 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2621 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2622 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2623 case EL_MOLE_UP: return GFX_MOLE_UP;
2624 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2625 case EL_STEEL_SLANTED: return GFX_STEEL_SLANTED;
2626 case EL_SAND_INVISIBLE: return GFX_SAND_INVISIBLE;
2627 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2628 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2629 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2630 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2631 case EL_TIMEGATE_SWITCH_ON: return GFX_TIMEGATE_SWITCH;
2632 case EL_TIMEGATE_SWITCH_OFF:return GFX_TIMEGATE_SWITCH;
2633 case EL_BALLOON: return GFX_BALLOON;
2634 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2635 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2636 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2637 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2638 case EL_BALLOON_SEND_ANY: return GFX_BALLOON_SEND_ANY;
2639 case EL_EMC_STEEL_WALL_1: return GFX_EMC_STEEL_WALL_1;
2640 case EL_EMC_STEEL_WALL_2: return GFX_EMC_STEEL_WALL_2;
2641 case EL_EMC_STEEL_WALL_3: return GFX_EMC_STEEL_WALL_3;
2642 case EL_EMC_STEEL_WALL_4: return GFX_EMC_STEEL_WALL_4;
2643 case EL_EMC_WALL_1: return GFX_EMC_WALL_1;
2644 case EL_EMC_WALL_2: return GFX_EMC_WALL_2;
2645 case EL_EMC_WALL_3: return GFX_EMC_WALL_3;
2646 case EL_EMC_WALL_4: return GFX_EMC_WALL_4;
2647 case EL_EMC_WALL_5: return GFX_EMC_WALL_5;
2648 case EL_EMC_WALL_6: return GFX_EMC_WALL_6;
2649 case EL_EMC_WALL_7: return GFX_EMC_WALL_7;
2650 case EL_EMC_WALL_8: return GFX_EMC_WALL_8;
2651 case EL_TUBE_CROSS: return GFX_TUBE_CROSS;
2652 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2653 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2654 case EL_TUBE_VERT_LEFT: return GFX_TUBE_VERT_LEFT;
2655 case EL_TUBE_VERT_RIGHT: return GFX_TUBE_VERT_RIGHT;
2656 case EL_TUBE_HORIZ_UP: return GFX_TUBE_HORIZ_UP;
2657 case EL_TUBE_HORIZ_DOWN: return GFX_TUBE_HORIZ_DOWN;
2658 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2659 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2660 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2661 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2662 case EL_SPRING: return GFX_SPRING;
2663 case EL_SPRING_MOVING: return GFX_SPRING;
2664 case EL_TRAP_INACTIVE: return GFX_TRAP_INACTIVE;
2665 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2666 case EL_BD_WALL: return GFX_BD_WALL;
2667 case EL_BD_ROCK: return GFX_BD_ROCK;
2668 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2669 case EL_SP_MURPHY_CLONE: return GFX_SP_MURPHY_CLONE;
2673 if (IS_CHAR(element))
2674 return GFX_CHAR_START + (element - EL_CHAR_START);
2675 else if (element >= EL_SP_START && element <= EL_SP_END)
2677 int nr_element = element - EL_SP_START;
2678 int gfx_per_line = 8;
2680 (nr_element / gfx_per_line) * SP_PER_LINE +
2681 (nr_element % gfx_per_line);
2683 return GFX_START_ROCKSSP + nr_graphic;