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 += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
593 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
594 last_dir = player->MovDir;
598 if (player->MovDir == MV_LEFT)
600 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
601 else if (player->MovDir == MV_RIGHT)
603 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
604 else if (player->MovDir == MV_UP)
605 graphic = GFX_SPIELER1_UP;
606 else /* MV_DOWN || MV_NO_MOVING */
607 graphic = GFX_SPIELER1_DOWN;
609 graphic += player->index_nr * 3 * HEROES_PER_LINE;
610 graphic += player->Frame;
615 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
616 sxx = player->GfxPos;
618 syy = player->GfxPos;
621 if (!setup.soft_scrolling && ScreenMovPos)
624 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
626 if (SHIELD_ON(player))
628 int graphic = (player->shield_active_time_left ? GFX2_SHIELD_ACTIVE :
629 GFX2_SHIELD_PASSIVE);
631 DrawGraphicAnimationShiftedThruMask(sx, sy, sxx, syy, graphic,
632 3, 8, ANIM_OSCILLATE);
635 if (player->Pushing && player->GfxPos)
637 int px = SCREENX(next_jx), py = SCREENY(next_jy);
639 if (element == EL_SOKOBAN_FELD_LEER ||
640 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
641 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
645 int element = Feld[next_jx][next_jy];
646 int graphic = el2gfx(element);
648 if ((element == EL_FELSBROCKEN ||
649 element == EL_SP_ZONK ||
650 element == EL_BD_ROCK) && sxx)
652 int phase = (player->GfxPos / (TILEX / 4));
654 if (player->MovDir == MV_LEFT)
657 graphic += (phase + 4) % 4;
660 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
664 /* draw things in front of player (active dynamite or dynabombs) */
666 if (IS_ACTIVE_BOMB(element))
668 graphic = el2gfx(element);
670 if (element == EL_DYNAMITE_ACTIVE)
672 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
677 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
681 if (game.emulation == EMU_SUPAPLEX)
682 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
684 DrawGraphicThruMask(sx, sy, graphic + phase);
687 if (player_is_moving && last_element == EL_EXPLODING)
689 int phase = Frame[last_jx][last_jy];
693 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
694 GFX_EXPLOSION + ((phase - 1) / delay - 1));
697 /* draw elements that stay over the player */
698 /* handle the field the player is leaving ... */
699 if (player_is_moving && IS_OVER_PLAYER(last_element))
700 DrawLevelField(last_jx, last_jy);
701 /* ... and the field the player is entering */
702 if (IS_OVER_PLAYER(element))
703 DrawLevelField(jx, jy);
705 if (setup.direct_draw)
707 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
708 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
709 int x_size = TILEX * (1 + ABS(jx - last_jx));
710 int y_size = TILEY * (1 + ABS(jy - last_jy));
712 XCopyArea(display, drawto_field, window, gc,
713 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
714 SetDrawtoField(DRAW_DIRECT);
717 MarkTileDirty(sx,sy);
720 static int getGraphicAnimationPhase(int frames, int delay, int mode)
724 if (mode == ANIM_OSCILLATE)
726 int max_anim_frames = 2 * frames - 2;
727 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
728 phase = (phase < frames ? phase : max_anim_frames - phase);
731 phase = (FrameCounter % (delay * frames)) / delay;
733 if (mode == ANIM_REVERSE)
739 void DrawGraphicAnimationExt(int x, int y, int graphic,
740 int frames, int delay, int mode, int mask_mode)
742 int phase = getGraphicAnimationPhase(frames, delay, mode);
744 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
746 if (mask_mode == USE_MASKING)
747 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
749 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
753 void DrawGraphicAnimation(int x, int y, int graphic,
754 int frames, int delay, int mode)
756 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
759 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
760 int frames, int delay, int mode)
762 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
765 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
768 int frames, int delay,
771 int phase = getGraphicAnimationPhase(frames, delay, mode);
773 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
776 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
778 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
780 graphic -= GFX_START_ROCKSSCREEN;
781 *pixmap_nr = PIX_BACK;
782 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
783 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
785 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
787 graphic -= GFX_START_ROCKSHEROES;
788 *pixmap_nr = PIX_HEROES;
789 *x = (graphic % HEROES_PER_LINE) * TILEX;
790 *y = (graphic / HEROES_PER_LINE) * TILEY;
792 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
794 graphic -= GFX_START_ROCKSSP;
796 *x = (graphic % SP_PER_LINE) * TILEX;
797 *y = (graphic / SP_PER_LINE) * TILEY;
799 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
801 graphic -= GFX_START_ROCKSDC;
803 *x = (graphic % DC_PER_LINE) * TILEX;
804 *y = (graphic / DC_PER_LINE) * TILEY;
806 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
808 graphic -= GFX_START_ROCKSMORE;
809 *pixmap_nr = PIX_MORE;
810 *x = (graphic % MORE_PER_LINE) * TILEX;
811 *y = (graphic / MORE_PER_LINE) * TILEY;
813 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
815 graphic -= GFX_START_ROCKSFONT;
816 *pixmap_nr = PIX_BIGFONT;
817 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
818 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
819 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
829 void DrawGraphic(int x, int y, int graphic)
832 if (!IN_SCR_FIELD(x,y))
834 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
835 printf("DrawGraphic(): This should never happen!\n");
840 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
844 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
849 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
850 XCopyArea(display, pix[pixmap_nr], d, gc,
851 src_x, src_y, TILEX, TILEY, x, y);
854 void DrawGraphicThruMask(int x, int y, int graphic)
857 if (!IN_SCR_FIELD(x,y))
859 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
860 printf("DrawGraphicThruMask(): This should never happen!\n");
865 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
869 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
877 if (graphic == GFX_LEERRAUM)
880 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
881 src_pixmap = pix[pixmap_nr];
882 drawing_gc = clip_gc[pixmap_nr];
884 if (tile_clipmask[tile] != None)
886 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
887 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
888 XCopyArea(display, src_pixmap, d, tile_clip_gc,
889 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
894 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
897 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
898 XCopyArea(display, src_pixmap, d, drawing_gc,
899 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
903 void DrawMiniGraphic(int x, int y, int graphic)
905 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
906 MarkTileDirty(x/2, y/2);
909 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
911 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
913 graphic -= GFX_START_ROCKSSCREEN;
914 *pixmap = pix[PIX_BACK];
915 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
916 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
918 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
920 graphic -= GFX_START_ROCKSSP;
921 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
922 *pixmap = pix[PIX_SP];
923 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
924 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
926 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
928 graphic -= GFX_START_ROCKSDC;
929 *pixmap = pix[PIX_DC];
930 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
931 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
933 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
935 graphic -= GFX_START_ROCKSMORE;
936 *pixmap = pix[PIX_MORE];
937 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
938 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
940 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
942 graphic -= GFX_START_ROCKSFONT;
943 *pixmap = pix[PIX_SMALLFONT];
944 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
945 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
946 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
950 *pixmap = pix[PIX_SP];
956 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
961 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
962 XCopyArea(display, pixmap, d, gc,
963 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
966 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
967 int cut_mode, int mask_mode)
969 int width = TILEX, height = TILEY;
971 int src_x, src_y, dest_x, dest_y;
979 DrawGraphic(x, y, graphic);
983 if (dx || dy) /* Verschiebung der Grafik? */
985 if (x < BX1) /* Element kommt von links ins Bild */
992 else if (x > BX2) /* Element kommt von rechts ins Bild */
998 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1004 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1006 else if (dx) /* allg. Bewegung in x-Richtung */
1007 MarkTileDirty(x + SIGN(dx), y);
1009 if (y < BY1) /* Element kommt von oben ins Bild */
1011 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1019 else if (y > BY2) /* Element kommt von unten ins Bild */
1025 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1031 else if (dy > 0 && cut_mode == CUT_ABOVE)
1033 if (y == BY2) /* Element unterhalb des Bildes */
1039 MarkTileDirty(x, y + 1);
1040 } /* Element verläßt unten das Bild */
1041 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1043 else if (dy) /* allg. Bewegung in y-Richtung */
1044 MarkTileDirty(x, y + SIGN(dy));
1047 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
1048 src_pixmap = pix[pixmap_nr];
1049 drawing_gc = clip_gc[pixmap_nr];
1054 dest_x = FX + x * TILEX + dx;
1055 dest_y = FY + y * TILEY + dy;
1058 if (!IN_SCR_FIELD(x,y))
1060 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1061 printf("DrawGraphicShifted(): This should never happen!\n");
1066 if (mask_mode == USE_MASKING)
1068 if (tile_clipmask[tile] != None)
1070 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
1071 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1072 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1073 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1078 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1081 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1082 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1083 src_x, src_y, width, height, dest_x, dest_y);
1087 XCopyArea(display, src_pixmap, drawto_field, gc,
1088 src_x, src_y, width, height, dest_x, dest_y);
1093 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1096 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1099 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1100 int cut_mode, int mask_mode)
1102 int ux = LEVELX(x), uy = LEVELY(y);
1103 int graphic = el2gfx(element);
1104 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1105 int phase4 = phase8 / 2;
1106 int phase2 = phase8 / 4;
1107 int dir = MovDir[ux][uy];
1109 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1111 graphic += 4 * !phase2;
1115 else if (dir == MV_LEFT)
1117 else if (dir == MV_DOWN)
1120 else if (element == EL_SP_SNIKSNAK)
1123 graphic = GFX_SP_SNIKSNAK_LEFT;
1124 else if (dir == MV_RIGHT)
1125 graphic = GFX_SP_SNIKSNAK_RIGHT;
1126 else if (dir == MV_UP)
1127 graphic = GFX_SP_SNIKSNAK_UP;
1129 graphic = GFX_SP_SNIKSNAK_DOWN;
1131 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1133 else if (element == EL_SP_ELECTRON)
1135 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1137 else if (element == EL_MOLE || element == EL_PINGUIN ||
1138 element == EL_SCHWEIN || element == EL_DRACHE)
1141 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1142 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1143 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1144 else if (dir == MV_RIGHT)
1145 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1146 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1147 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1148 else if (dir == MV_UP)
1149 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1150 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1151 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1153 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1154 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1155 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1159 else if (element == EL_SONDE)
1161 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1163 else if (element == EL_SALZSAEURE)
1165 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1167 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1171 else if (element == EL_BALLOON)
1175 else if ((element == EL_FELSBROCKEN ||
1176 element == EL_SP_ZONK ||
1177 element == EL_BD_ROCK ||
1178 IS_GEM(element)) && !cut_mode)
1180 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1182 if (element == EL_FELSBROCKEN ||
1183 element == EL_SP_ZONK ||
1184 element == EL_BD_ROCK)
1187 graphic += (4 - phase4) % 4;
1188 else if (dir == MV_RIGHT)
1191 graphic += phase2 * 2;
1193 else if (element != EL_SP_INFOTRON)
1197 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1198 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1200 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1202 else if (IS_AMOEBOID(element))
1204 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1205 graphic += (x + 2 * y + 4) % 4;
1207 else if (element == EL_MAUER_LEBT)
1209 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1211 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1212 links_massiv = TRUE;
1213 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1214 rechts_massiv = TRUE;
1216 if (links_massiv && rechts_massiv)
1217 graphic = GFX_MAUERWERK;
1218 else if (links_massiv)
1219 graphic = GFX_MAUER_R;
1220 else if (rechts_massiv)
1221 graphic = GFX_MAUER_L;
1223 else if ((element == EL_INVISIBLE_STEEL ||
1224 element == EL_UNSICHTBAR ||
1225 element == EL_SAND_INVISIBLE) && game.light_time_left)
1227 graphic = (element == EL_INVISIBLE_STEEL ? GFX_INVISIBLE_STEEL_ON :
1228 element == EL_UNSICHTBAR ? GFX_UNSICHTBAR_ON :
1229 GFX_SAND_INVISIBLE_ON);
1233 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1234 else if (mask_mode == USE_MASKING)
1235 DrawGraphicThruMask(x, y, graphic);
1237 DrawGraphic(x, y, graphic);
1240 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1241 int cut_mode, int mask_mode)
1243 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1244 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1245 cut_mode, mask_mode);
1248 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1251 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1254 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1257 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1260 void DrawScreenElementThruMask(int x, int y, int element)
1262 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1265 void DrawLevelElementThruMask(int x, int y, int element)
1267 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1270 void DrawLevelFieldThruMask(int x, int y)
1272 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1275 void ErdreichAnbroeckeln(int x, int y)
1277 int i, width, height, cx,cy;
1278 int ux = LEVELX(x), uy = LEVELY(y);
1279 int element, graphic;
1281 static int xy[4][2] =
1289 if (!IN_LEV_FIELD(ux, uy))
1292 element = Feld[ux][uy];
1294 if (element == EL_ERDREICH ||
1295 element == EL_LANDMINE ||
1296 element == EL_TRAP_INACTIVE ||
1297 element == EL_TRAP_ACTIVE)
1299 if (!IN_SCR_FIELD(x, y))
1302 graphic = GFX_ERDENRAND;
1308 uxx = ux + xy[i][0];
1309 uyy = uy + xy[i][1];
1310 if (!IN_LEV_FIELD(uxx, uyy))
1313 element = Feld[uxx][uyy];
1315 if (element == EL_ERDREICH ||
1316 element == EL_LANDMINE ||
1317 element == EL_TRAP_INACTIVE ||
1318 element == EL_TRAP_ACTIVE)
1321 if (i == 1 || i == 2)
1325 cx = (i == 2 ? TILEX - snip : 0);
1333 cy = (i == 3 ? TILEY - snip : 0);
1336 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1337 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1338 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1339 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1342 MarkTileDirty(x, y);
1346 graphic = GFX_ERDENRAND;
1350 int xx, yy, uxx, uyy;
1354 uxx = ux + xy[i][0];
1355 uyy = uy + xy[i][1];
1357 if (!IN_LEV_FIELD(uxx, uyy) ||
1358 (Feld[uxx][uyy] != EL_ERDREICH &&
1359 Feld[uxx][uyy] != EL_LANDMINE &&
1360 Feld[uxx][uyy] != EL_TRAP_INACTIVE &&
1361 Feld[uxx][uyy] != EL_TRAP_ACTIVE) ||
1362 !IN_SCR_FIELD(xx, yy))
1365 if (i == 1 || i == 2)
1369 cx = (i == 1 ? TILEX - snip : 0);
1377 cy = (i==0 ? TILEY-snip : 0);
1380 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1381 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1382 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1383 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1385 MarkTileDirty(xx, yy);
1390 void DrawScreenElement(int x, int y, int element)
1392 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1393 ErdreichAnbroeckeln(x, y);
1396 void DrawLevelElement(int x, int y, int element)
1398 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1399 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1402 void DrawScreenField(int x, int y)
1404 int ux = LEVELX(x), uy = LEVELY(y);
1407 if (!IN_LEV_FIELD(ux, uy))
1409 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1410 element = EL_LEERRAUM;
1412 element = BorderElement;
1414 DrawScreenElement(x, y, element);
1418 element = Feld[ux][uy];
1420 if (IS_MOVING(ux, uy))
1422 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1423 boolean cut_mode = NO_CUTTING;
1425 if (Store[ux][uy] == EL_MORAST_LEER ||
1426 Store[ux][uy] == EL_SIEB_LEER ||
1427 Store[ux][uy] == EL_SIEB2_LEER ||
1428 Store[ux][uy] == EL_AMOEBE_NASS)
1429 cut_mode = CUT_ABOVE;
1430 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1431 Store[ux][uy] == EL_SIEB_VOLL ||
1432 Store[ux][uy] == EL_SIEB2_VOLL)
1433 cut_mode = CUT_BELOW;
1435 if (cut_mode == CUT_ABOVE)
1436 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1438 DrawScreenElement(x, y, EL_LEERRAUM);
1441 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1443 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1445 if (Store[ux][uy] == EL_SALZSAEURE)
1446 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1448 else if (IS_BLOCKED(ux, uy))
1453 boolean cut_mode = NO_CUTTING;
1455 Blocked2Moving(ux, uy, &oldx, &oldy);
1458 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1459 MovDir[oldx][oldy] == MV_RIGHT);
1461 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1462 Store[oldx][oldy] == EL_SIEB_LEER ||
1463 Store[oldx][oldy] == EL_SIEB2_LEER ||
1464 Store[oldx][oldy] == EL_AMOEBE_NASS)
1465 cut_mode = CUT_ABOVE;
1467 DrawScreenElement(x, y, EL_LEERRAUM);
1468 element = Feld[oldx][oldy];
1471 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1473 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1475 else if (IS_DRAWABLE(element))
1476 DrawScreenElement(x, y, element);
1478 DrawScreenElement(x, y, EL_LEERRAUM);
1481 void DrawLevelField(int x, int y)
1483 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1484 DrawScreenField(SCREENX(x), SCREENY(y));
1485 else if (IS_MOVING(x, y))
1489 Moving2Blocked(x, y, &newx, &newy);
1490 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1491 DrawScreenField(SCREENX(newx), SCREENY(newy));
1493 else if (IS_BLOCKED(x, y))
1497 Blocked2Moving(x, y, &oldx, &oldy);
1498 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1499 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1503 void DrawMiniElement(int x, int y, int element)
1509 DrawMiniGraphic(x, y, -1);
1513 graphic = el2gfx(element);
1514 DrawMiniGraphic(x, y, graphic);
1517 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1519 int x = sx + scroll_x, y = sy + scroll_y;
1521 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1522 DrawMiniElement(sx, sy, EL_LEERRAUM);
1523 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1524 DrawMiniElement(sx, sy, Feld[x][y]);
1527 int steel_type, steel_position;
1530 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1531 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1532 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1533 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1534 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1535 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1538 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1539 steel_position = (x == -1 && y == -1 ? 0 :
1540 x == lev_fieldx && y == -1 ? 1 :
1541 x == -1 && y == lev_fieldy ? 2 :
1542 x == lev_fieldx && y == lev_fieldy ? 3 :
1543 x == -1 || x == lev_fieldx ? 4 :
1544 y == -1 || y == lev_fieldy ? 5 : -1);
1546 if (steel_position != -1)
1547 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1551 void DrawMicroElement(int xpos, int ypos, int element)
1555 if (element == EL_LEERRAUM)
1558 graphic = el2gfx(element);
1560 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1562 graphic -= GFX_START_ROCKSSP;
1563 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
1564 XCopyArea(display, pix[PIX_SP], drawto, gc,
1565 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
1566 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
1567 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1569 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1571 graphic -= GFX_START_ROCKSDC;
1572 XCopyArea(display, pix[PIX_DC], drawto, gc,
1573 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
1574 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
1575 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1577 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1579 graphic -= GFX_START_ROCKSMORE;
1580 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1581 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1582 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1583 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1586 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1587 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1588 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1589 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1598 for(x=BX1; x<=BX2; x++)
1599 for(y=BY1; y<=BY2; y++)
1600 DrawScreenField(x, y);
1602 redraw_mask |= REDRAW_FIELD;
1605 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1609 for(x=0; x<size_x; x++)
1610 for(y=0; y<size_y; y++)
1611 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1613 redraw_mask |= REDRAW_FIELD;
1616 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1620 XFillRectangle(display, drawto, gc,
1621 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1623 if (lev_fieldx < STD_LEV_FIELDX)
1624 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1625 if (lev_fieldy < STD_LEV_FIELDY)
1626 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1628 xpos += MICRO_TILEX;
1629 ypos += MICRO_TILEY;
1631 for(x=-1; x<=STD_LEV_FIELDX; x++)
1633 for(y=-1; y<=STD_LEV_FIELDY; y++)
1635 int lx = from_x + x, ly = from_y + y;
1637 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1638 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1640 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1641 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1646 redraw_mask |= REDRAW_MICROLEVEL;
1649 #define MICROLABEL_EMPTY 0
1650 #define MICROLABEL_LEVEL_NAME 1
1651 #define MICROLABEL_CREATED_BY 2
1652 #define MICROLABEL_LEVEL_AUTHOR 3
1653 #define MICROLABEL_IMPORTED_FROM 4
1654 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1656 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1658 static void DrawMicroLevelLabelExt(int mode)
1660 char label_text[MAX_MICROLABEL_SIZE + 1];
1662 XFillRectangle(display, drawto,gc,
1663 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1665 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1666 mode == MICROLABEL_CREATED_BY ? "created by" :
1667 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1668 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1669 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1670 leveldir_current->imported_from : ""),
1671 MAX_MICROLABEL_SIZE);
1672 label_text[MAX_MICROLABEL_SIZE] = '\0';
1674 if (strlen(label_text) > 0)
1676 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1677 int lypos = MICROLABEL_YPOS;
1679 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1682 redraw_mask |= REDRAW_MICROLEVEL;
1685 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1687 static unsigned long scroll_delay = 0;
1688 static unsigned long label_delay = 0;
1689 static int from_x, from_y, scroll_direction;
1690 static int label_state, label_counter;
1694 from_x = from_y = 0;
1695 scroll_direction = MV_RIGHT;
1699 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1700 DrawMicroLevelLabelExt(label_state);
1702 /* initialize delay counters */
1703 DelayReached(&scroll_delay, 0);
1704 DelayReached(&label_delay, 0);
1709 /* scroll micro level, if needed */
1710 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1711 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1713 switch (scroll_direction)
1719 scroll_direction = MV_UP;
1723 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1726 scroll_direction = MV_DOWN;
1733 scroll_direction = MV_RIGHT;
1737 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1740 scroll_direction = MV_LEFT;
1747 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1750 /* redraw micro level label, if needed */
1751 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1752 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1753 strcmp(level.author, leveldir_current->name) != 0 &&
1754 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1756 int max_label_counter = 23;
1758 if (leveldir_current->imported_from != NULL)
1759 max_label_counter += 14;
1761 label_counter = (label_counter + 1) % max_label_counter;
1762 label_state = (label_counter >= 0 && label_counter <= 7 ?
1763 MICROLABEL_LEVEL_NAME :
1764 label_counter >= 9 && label_counter <= 12 ?
1765 MICROLABEL_CREATED_BY :
1766 label_counter >= 14 && label_counter <= 21 ?
1767 MICROLABEL_LEVEL_AUTHOR :
1768 label_counter >= 23 && label_counter <= 26 ?
1769 MICROLABEL_IMPORTED_FROM :
1770 label_counter >= 28 && label_counter <= 35 ?
1771 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1772 DrawMicroLevelLabelExt(label_state);
1776 int REQ_in_range(int x, int y)
1778 if (y > DY+249 && y < DY+278)
1780 if (x > DX+1 && x < DX+48)
1782 else if (x > DX+51 && x < DX+98)
1788 boolean Request(char *text, unsigned int req_state)
1790 int mx, my, ty, result = -1;
1791 unsigned int old_door_state;
1794 /* pause network game while waiting for request to answer */
1795 if (options.network &&
1796 game_status == PLAYING &&
1797 req_state & REQUEST_WAIT_FOR)
1798 SendToServer_PausePlaying();
1801 old_door_state = GetDoorState();
1805 CloseDoor(DOOR_CLOSE_1);
1807 /* save old door content */
1808 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1809 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1810 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1812 /* clear door drawing field */
1813 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1815 /* write text for request */
1816 for(ty=0; ty<13; ty++)
1824 for(tl=0,tx=0; tx<7; tl++,tx++)
1827 if (!tc || tc == 32)
1838 DrawTextExt(drawto, gc,
1839 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1840 txt, FS_SMALL, FC_YELLOW);
1841 text += tl + (tc == 32 ? 1 : 0);
1844 if (req_state & REQ_ASK)
1846 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1847 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1849 else if (req_state & REQ_CONFIRM)
1851 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1853 else if (req_state & REQ_PLAYER)
1855 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1856 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1857 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1858 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1861 /* copy request gadgets to door backbuffer */
1862 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1863 DX, DY, DXSIZE, DYSIZE,
1864 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1866 OpenDoor(DOOR_OPEN_1);
1872 if (!(req_state & REQUEST_WAIT_FOR))
1875 if (game_status != MAINMENU)
1878 button_status = MB_RELEASED;
1880 request_gadget_id = -1;
1884 if (XPending(display))
1888 XNextEvent(display, &event);
1896 if (event.type == MotionNotify)
1903 if (!XQueryPointer(display, window, &root, &child,
1904 &root_x, &root_y, &win_x, &win_y, &mask))
1910 motion_status = TRUE;
1911 mx = ((XMotionEvent *) &event)->x;
1912 my = ((XMotionEvent *) &event)->y;
1916 motion_status = FALSE;
1917 mx = ((XButtonEvent *) &event)->x;
1918 my = ((XButtonEvent *) &event)->y;
1919 if (event.type==ButtonPress)
1920 button_status = ((XButtonEvent *) &event)->button;
1922 button_status = MB_RELEASED;
1925 /* this sets 'request_gadget_id' */
1926 HandleGadgets(mx, my, button_status);
1928 switch(request_gadget_id)
1930 case TOOL_CTRL_ID_YES:
1933 case TOOL_CTRL_ID_NO:
1936 case TOOL_CTRL_ID_CONFIRM:
1937 result = TRUE | FALSE;
1940 case TOOL_CTRL_ID_PLAYER_1:
1943 case TOOL_CTRL_ID_PLAYER_2:
1946 case TOOL_CTRL_ID_PLAYER_3:
1949 case TOOL_CTRL_ID_PLAYER_4:
1961 switch(XLookupKeysym((XKeyEvent *)&event,
1962 ((XKeyEvent *)&event)->state))
1975 if (req_state & REQ_PLAYER)
1980 key_joystick_mapping = 0;
1984 HandleOtherEvents(&event);
1988 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1990 int joy = AnyJoystick();
1992 if (joy & JOY_BUTTON_1)
1994 else if (joy & JOY_BUTTON_2)
2000 /* don't eat all CPU time */
2004 if (game_status != MAINMENU)
2009 if (!(req_state & REQ_STAY_OPEN))
2011 CloseDoor(DOOR_CLOSE_1);
2013 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2015 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
2016 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2017 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2018 OpenDoor(DOOR_OPEN_1);
2025 /* continue network game after request */
2026 if (options.network &&
2027 game_status == PLAYING &&
2028 req_state & REQUEST_WAIT_FOR)
2029 SendToServer_ContinuePlaying();
2035 unsigned int OpenDoor(unsigned int door_state)
2037 unsigned int new_door_state;
2039 if (door_state & DOOR_COPY_BACK)
2041 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
2042 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2043 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2044 door_state &= ~DOOR_COPY_BACK;
2047 new_door_state = MoveDoor(door_state);
2049 return(new_door_state);
2052 unsigned int CloseDoor(unsigned int door_state)
2054 unsigned int new_door_state;
2056 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2057 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2058 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2059 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2061 new_door_state = MoveDoor(door_state);
2063 return(new_door_state);
2066 unsigned int GetDoorState()
2068 return(MoveDoor(DOOR_GET_STATE));
2071 unsigned int MoveDoor(unsigned int door_state)
2073 static int door1 = DOOR_OPEN_1;
2074 static int door2 = DOOR_CLOSE_2;
2075 static unsigned long door_delay = 0;
2076 int x, start, stepsize = 2;
2077 unsigned long door_delay_value = stepsize * 5;
2079 if (door_state == DOOR_GET_STATE)
2080 return(door1 | door2);
2082 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2083 door_state &= ~DOOR_OPEN_1;
2084 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2085 door_state &= ~DOOR_CLOSE_1;
2086 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2087 door_state &= ~DOOR_OPEN_2;
2088 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2089 door_state &= ~DOOR_CLOSE_2;
2091 if (setup.quick_doors)
2094 door_delay_value = 0;
2095 StopSound(SND_OEFFNEN);
2098 if (door_state & DOOR_ACTION)
2100 if (!(door_state & DOOR_NO_DELAY))
2101 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2103 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2105 for(x=start; x<=DXSIZE; x+=stepsize)
2107 WaitUntilDelayReached(&door_delay, door_delay_value);
2109 if (door_state & DOOR_ACTION_1)
2111 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2112 int j = (DXSIZE - i) / 3;
2114 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2115 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2116 DXSIZE,DYSIZE - i/2, DX, DY);
2118 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2120 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2121 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2122 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2123 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2124 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2125 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2127 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2128 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2129 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2130 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2131 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2132 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2134 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2135 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2137 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2138 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2140 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2141 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2142 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2143 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2144 DX + DXSIZE - i, DY + 77 + j);
2145 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2146 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2147 DX + DXSIZE - i, DY + 203 + j);
2149 redraw_mask |= REDRAW_DOOR_1;
2152 if (door_state & DOOR_ACTION_2)
2154 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2155 int j = (VXSIZE - i) / 3;
2157 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2158 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2159 VXSIZE, VYSIZE - i/2, VX, VY);
2161 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2163 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2164 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2165 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2166 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2167 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2168 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2169 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2170 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2172 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2173 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2174 VX, VY + VYSIZE / 2 - j);
2175 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2176 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2177 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2178 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2179 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2181 redraw_mask |= REDRAW_DOOR_2;
2186 if (game_status == MAINMENU)
2191 if (setup.quick_doors)
2192 StopSound(SND_OEFFNEN);
2194 if (door_state & DOOR_ACTION_1)
2195 door1 = door_state & DOOR_ACTION_1;
2196 if (door_state & DOOR_ACTION_2)
2197 door2 = door_state & DOOR_ACTION_2;
2199 return (door1 | door2);
2202 void DrawSpecialEditorDoor()
2204 /* draw bigger toolbox window */
2205 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2206 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2208 redraw_mask |= REDRAW_ALL;
2211 void UndrawSpecialEditorDoor()
2213 /* draw normal tape recorder window */
2214 XCopyArea(display, pix[PIX_BACK], drawto, gc,
2215 562, 344, 108, 56, EX - 4, EY - 12);
2217 redraw_mask |= REDRAW_ALL;
2220 int ReadPixel(Drawable d, int x, int y)
2222 XImage *pixel_image;
2223 unsigned long pixel_value;
2225 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2226 pixel_value = XGetPixel(pixel_image, 0, 0);
2228 XDestroyImage(pixel_image);
2233 /* ---------- new tool button stuff ---------------------------------------- */
2235 /* graphic position values for tool buttons */
2236 #define TOOL_BUTTON_YES_XPOS 2
2237 #define TOOL_BUTTON_YES_YPOS 250
2238 #define TOOL_BUTTON_YES_GFX_YPOS 0
2239 #define TOOL_BUTTON_YES_XSIZE 46
2240 #define TOOL_BUTTON_YES_YSIZE 28
2241 #define TOOL_BUTTON_NO_XPOS 52
2242 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2243 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2244 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2245 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2246 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2247 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2248 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2249 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2250 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2251 #define TOOL_BUTTON_PLAYER_XSIZE 30
2252 #define TOOL_BUTTON_PLAYER_YSIZE 30
2253 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2254 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2255 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2256 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2257 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2258 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2259 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2260 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2261 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2262 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2263 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2264 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2265 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2266 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2267 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2268 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2269 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2270 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2271 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2272 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2281 } toolbutton_info[NUM_TOOL_BUTTONS] =
2284 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2285 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2286 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2291 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2292 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2293 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2298 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2299 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2300 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2301 TOOL_CTRL_ID_CONFIRM,
2305 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2306 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2307 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2308 TOOL_CTRL_ID_PLAYER_1,
2312 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2313 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2314 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2315 TOOL_CTRL_ID_PLAYER_2,
2319 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2320 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2321 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2322 TOOL_CTRL_ID_PLAYER_3,
2326 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2327 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2328 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2329 TOOL_CTRL_ID_PLAYER_4,
2334 static void DoNotDisplayInfoText(void *ptr)
2339 void CreateToolButtons()
2343 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2345 Pixmap gd_pixmap = pix[PIX_DOOR];
2346 Pixmap deco_pixmap = None;
2347 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2348 struct GadgetInfo *gi;
2349 unsigned long event_mask;
2350 int gd_xoffset, gd_yoffset;
2351 int gd_x1, gd_x2, gd_y;
2354 event_mask = GD_EVENT_RELEASED;
2356 gd_xoffset = toolbutton_info[i].xpos;
2357 gd_yoffset = toolbutton_info[i].ypos;
2358 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2359 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2360 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2362 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2364 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2365 &deco_pixmap, &deco_x, &deco_y);
2366 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2367 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2370 gi = CreateGadget(GDI_CUSTOM_ID, id,
2371 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2372 GDI_X, DX + toolbutton_info[i].x,
2373 GDI_Y, DY + toolbutton_info[i].y,
2374 GDI_WIDTH, toolbutton_info[i].width,
2375 GDI_HEIGHT, toolbutton_info[i].height,
2376 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2377 GDI_STATE, GD_BUTTON_UNPRESSED,
2378 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2379 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2380 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2381 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2382 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2383 GDI_DECORATION_SHIFTING, 1, 1,
2384 GDI_EVENT_MASK, event_mask,
2385 GDI_CALLBACK_ACTION, HandleToolButtons,
2386 GDI_CALLBACK_INFO, DoNotDisplayInfoText,
2390 Error(ERR_EXIT, "cannot create gadget");
2392 tool_gadget[id] = gi;
2396 static void UnmapToolButtons()
2400 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2401 UnmapGadget(tool_gadget[i]);
2404 static void HandleToolButtons(struct GadgetInfo *gi)
2406 request_gadget_id = gi->custom_id;
2409 int el2gfx(int element)
2413 case EL_LEERRAUM: return -1;
2414 case EL_ERDREICH: return GFX_ERDREICH;
2415 case EL_MAUERWERK: return GFX_MAUERWERK;
2416 case EL_FELSBODEN: return GFX_FELSBODEN;
2417 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2418 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2419 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2420 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2421 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2422 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2423 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2424 case EL_SPIELER1: return GFX_SPIELER1;
2425 case EL_SPIELER2: return GFX_SPIELER2;
2426 case EL_SPIELER3: return GFX_SPIELER3;
2427 case EL_SPIELER4: return GFX_SPIELER4;
2428 case EL_KAEFER: return GFX_KAEFER;
2429 case EL_KAEFER_RIGHT: return GFX_KAEFER_RIGHT;
2430 case EL_KAEFER_UP: return GFX_KAEFER_UP;
2431 case EL_KAEFER_LEFT: return GFX_KAEFER_LEFT;
2432 case EL_KAEFER_DOWN: return GFX_KAEFER_DOWN;
2433 case EL_FLIEGER: return GFX_FLIEGER;
2434 case EL_FLIEGER_RIGHT: return GFX_FLIEGER_RIGHT;
2435 case EL_FLIEGER_UP: return GFX_FLIEGER_UP;
2436 case EL_FLIEGER_LEFT: return GFX_FLIEGER_LEFT;
2437 case EL_FLIEGER_DOWN: return GFX_FLIEGER_DOWN;
2438 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2439 case EL_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2440 case EL_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2441 case EL_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2442 case EL_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2443 case EL_FIREFLY: return GFX_FIREFLY;
2444 case EL_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2445 case EL_FIREFLY_UP: return GFX_FIREFLY_UP;
2446 case EL_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2447 case EL_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2448 case EL_MAMPFER: return GFX_MAMPFER;
2449 case EL_ROBOT: return GFX_ROBOT;
2450 case EL_BETON: return GFX_BETON;
2451 case EL_DIAMANT: return GFX_DIAMANT;
2452 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2453 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2454 case EL_TROPFEN: return GFX_TROPFEN;
2455 case EL_BOMBE: return GFX_BOMBE;
2456 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2457 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2458 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2459 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2460 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2461 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2462 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2463 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2464 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2465 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2466 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2467 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2468 case EL_LIFE: return GFX_LIFE;
2469 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2470 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2471 case EL_BADEWANNE: return GFX_BADEWANNE;
2472 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2473 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2474 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2475 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2476 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2477 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2478 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2479 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2480 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2481 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2482 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2483 case EL_PFORTE1: return GFX_PFORTE1;
2484 case EL_PFORTE2: return GFX_PFORTE2;
2485 case EL_PFORTE3: return GFX_PFORTE3;
2486 case EL_PFORTE4: return GFX_PFORTE4;
2487 case EL_PFORTE1X: return GFX_PFORTE1X;
2488 case EL_PFORTE2X: return GFX_PFORTE2X;
2489 case EL_PFORTE3X: return GFX_PFORTE3X;
2490 case EL_PFORTE4X: return GFX_PFORTE4X;
2491 case EL_DYNAMITE_INACTIVE: return GFX_DYNAMIT_AUS;
2492 case EL_PACMAN: return GFX_PACMAN;
2493 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2494 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2495 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2496 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2497 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2498 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2499 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2500 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2501 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2502 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2503 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2504 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2505 case EL_MAUER_X: return GFX_MAUER_X;
2506 case EL_MAUER_Y: return GFX_MAUER_Y;
2507 case EL_MAUER_XY: return GFX_MAUER_XY;
2508 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2509 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2510 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2511 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2512 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2513 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2514 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2515 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2516 case EL_MAMPFER2: return GFX_MAMPFER2;
2517 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2518 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2519 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2520 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2521 case EL_DYNABOMB_ACTIVE_1: return GFX_DYNABOMB;
2522 case EL_DYNABOMB_ACTIVE_2: return GFX_DYNABOMB;
2523 case EL_DYNABOMB_ACTIVE_3: return GFX_DYNABOMB;
2524 case EL_DYNABOMB_ACTIVE_4: return GFX_DYNABOMB;
2525 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2526 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2527 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2528 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2529 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2530 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2531 case EL_MOLE: return GFX_MOLE;
2532 case EL_PINGUIN: return GFX_PINGUIN;
2533 case EL_SCHWEIN: return GFX_SCHWEIN;
2534 case EL_DRACHE: return GFX_DRACHE;
2535 case EL_SONDE: return GFX_SONDE;
2536 case EL_PFEIL_LEFT: return GFX_PFEIL_LEFT;
2537 case EL_PFEIL_RIGHT: return GFX_PFEIL_RIGHT;
2538 case EL_PFEIL_UP: return GFX_PFEIL_UP;
2539 case EL_PFEIL_DOWN: return GFX_PFEIL_DOWN;
2540 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2541 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2542 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2543 case EL_SP_ZONK: return GFX_SP_ZONK;
2544 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2545 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2546 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2547 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2548 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2549 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2550 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2551 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2552 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2553 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2554 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2555 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2556 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2557 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2558 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2559 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2560 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2561 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2562 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2563 case EL_PEARL: return GFX_PEARL;
2564 case EL_CRYSTAL: return GFX_CRYSTAL;
2565 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2566 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2567 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2568 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2569 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2570 case EL_SHIELD_PASSIVE: return GFX_SHIELD_PASSIVE;
2571 case EL_SHIELD_ACTIVE: return GFX_SHIELD_ACTIVE;
2572 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2573 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2574 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2575 case EL_SWITCHGATE_SWITCH_1:return GFX_SWITCHGATE_SWITCH_1;
2576 case EL_SWITCHGATE_SWITCH_2:return GFX_SWITCHGATE_SWITCH_2;
2577 case EL_BELT1_LEFT: return GFX_BELT1_LEFT;
2578 case EL_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2579 case EL_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2580 case EL_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2581 case EL_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2582 case EL_BELT1_SWITCH_RIGHT: return GFX_BELT1_SWITCH_RIGHT;
2583 case EL_BELT2_LEFT: return GFX_BELT2_LEFT;
2584 case EL_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2585 case EL_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2586 case EL_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2587 case EL_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2588 case EL_BELT2_SWITCH_RIGHT: return GFX_BELT2_SWITCH_RIGHT;
2589 case EL_BELT3_LEFT: return GFX_BELT3_LEFT;
2590 case EL_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2591 case EL_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2592 case EL_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2593 case EL_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2594 case EL_BELT3_SWITCH_RIGHT: return GFX_BELT3_SWITCH_RIGHT;
2595 case EL_BELT4_LEFT: return GFX_BELT4_LEFT;
2596 case EL_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2597 case EL_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2598 case EL_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2599 case EL_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2600 case EL_BELT4_SWITCH_RIGHT: return GFX_BELT4_SWITCH_RIGHT;
2601 case EL_LANDMINE: return GFX_LANDMINE;
2602 case EL_ENVELOPE: return GFX_ENVELOPE;
2603 case EL_LIGHT_SWITCH_OFF: return GFX_LIGHT_SWITCH_OFF;
2604 case EL_LIGHT_SWITCH_ON: return GFX_LIGHT_SWITCH_ON;
2605 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2606 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2607 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2608 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2609 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2610 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2611 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2612 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2613 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2614 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2615 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2616 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2617 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2618 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2619 case EL_MOLE_UP: return GFX_MOLE_UP;
2620 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2621 case EL_STEEL_SLANTED: return GFX_STEEL_SLANTED;
2622 case EL_SAND_INVISIBLE: return GFX_SAND_INVISIBLE;
2623 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2624 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2625 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2626 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2627 case EL_TIMEGATE_SWITCH_ON: return GFX_TIMEGATE_SWITCH;
2628 case EL_TIMEGATE_SWITCH_OFF:return GFX_TIMEGATE_SWITCH;
2629 case EL_BALLOON: return GFX_BALLOON;
2630 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2631 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2632 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2633 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2634 case EL_BALLOON_SEND_ANY: return GFX_BALLOON_SEND_ANY;
2635 case EL_EMC_STEEL_WALL_1: return GFX_EMC_STEEL_WALL_1;
2636 case EL_EMC_STEEL_WALL_2: return GFX_EMC_STEEL_WALL_2;
2637 case EL_EMC_STEEL_WALL_3: return GFX_EMC_STEEL_WALL_3;
2638 case EL_EMC_STEEL_WALL_4: return GFX_EMC_STEEL_WALL_4;
2639 case EL_EMC_WALL_1: return GFX_EMC_WALL_1;
2640 case EL_EMC_WALL_2: return GFX_EMC_WALL_2;
2641 case EL_EMC_WALL_3: return GFX_EMC_WALL_3;
2642 case EL_EMC_WALL_4: return GFX_EMC_WALL_4;
2643 case EL_EMC_WALL_5: return GFX_EMC_WALL_5;
2644 case EL_EMC_WALL_6: return GFX_EMC_WALL_6;
2645 case EL_EMC_WALL_7: return GFX_EMC_WALL_7;
2646 case EL_EMC_WALL_8: return GFX_EMC_WALL_8;
2647 case EL_TUBE_CROSS: return GFX_TUBE_CROSS;
2648 case EL_TUBE_VERTICAL: return GFX_TUBE_VERTICAL;
2649 case EL_TUBE_HORIZONTAL: return GFX_TUBE_HORIZONTAL;
2650 case EL_TUBE_VERT_LEFT: return GFX_TUBE_VERT_LEFT;
2651 case EL_TUBE_VERT_RIGHT: return GFX_TUBE_VERT_RIGHT;
2652 case EL_TUBE_HORIZ_UP: return GFX_TUBE_HORIZ_UP;
2653 case EL_TUBE_HORIZ_DOWN: return GFX_TUBE_HORIZ_DOWN;
2654 case EL_TUBE_LEFT_UP: return GFX_TUBE_LEFT_UP;
2655 case EL_TUBE_LEFT_DOWN: return GFX_TUBE_LEFT_DOWN;
2656 case EL_TUBE_RIGHT_UP: return GFX_TUBE_RIGHT_UP;
2657 case EL_TUBE_RIGHT_DOWN: return GFX_TUBE_RIGHT_DOWN;
2658 case EL_SPRING: return GFX_SPRING;
2659 case EL_SPRING_MOVING: return GFX_SPRING;
2660 case EL_TRAP_INACTIVE: return GFX_TRAP_INACTIVE;
2661 case EL_TRAP_ACTIVE: return GFX_TRAP_ACTIVE;
2662 case EL_BD_WALL: return GFX_BD_WALL;
2663 case EL_BD_ROCK: return GFX_BD_ROCK;
2664 case EL_DX_SUPABOMB: return GFX_DX_SUPABOMB;
2668 if (IS_CHAR(element))
2669 return GFX_CHAR_START + (element - EL_CHAR_START);
2670 else if (element >= EL_SP_START && element <= EL_SP_END)
2672 int nr_element = element - EL_SP_START;
2673 int gfx_per_line = 8;
2675 (nr_element / gfx_per_line) * SP_PER_LINE +
2676 (nr_element % gfx_per_line);
2678 return GFX_START_ROCKSSP + nr_graphic;