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_type == FC_SPECIAL1 ? FONT3_XSIZE :
323 font_type == FC_SPECIAL2 ? FONT4_XSIZE :
324 font_type == FC_SPECIAL3 ? FONT5_XSIZE :
328 int getFontHeight(int font_size, int font_type)
330 return (font_size == FS_BIG ? FONT1_YSIZE :
331 font_type == FC_SPECIAL1 ? FONT3_YSIZE :
332 font_type == FC_SPECIAL2 ? FONT4_YSIZE :
333 font_type == FC_SPECIAL3 ? FONT5_YSIZE :
337 void DrawInitText(char *text, int ypos, int color)
339 if (display && window && pix[PIX_SMALLFONT])
341 XFillRectangle(display, window, gc, 0, ypos, WIN_XSIZE, FONT2_YSIZE);
342 DrawTextExt(window, gc, (WIN_XSIZE - strlen(text) * FONT2_XSIZE)/2,
343 ypos,text,FS_SMALL,color);
348 void DrawTextFCentered(int y, int font_type, char *format, ...)
350 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
351 int font_width = getFontWidth(FS_SMALL, font_type);
354 va_start(ap, format);
355 vsprintf(buffer, format, ap);
358 DrawText(SX + (SXSIZE - strlen(buffer) * font_width) / 2, SY + y,
359 buffer, FS_SMALL, font_type);
362 void DrawTextF(int x, int y, int font_type, char *format, ...)
364 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
367 va_start(ap, format);
368 vsprintf(buffer, format, ap);
371 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
374 void DrawText(int x, int y, char *text, int font_size, int font_type)
376 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
379 redraw_mask |= REDRAW_FIELD;
381 redraw_mask |= REDRAW_DOOR_1;
384 void DrawTextExt(Drawable d, GC gc, int x, int y,
385 char *text, int font_size, int font_type)
387 int font_width, font_height, font_start;
389 boolean print_inverse = FALSE;
391 if (font_size != FS_SMALL && font_size != FS_BIG)
392 font_size = FS_SMALL;
393 if (font_type < FC_RED || font_type > FC_SPECIAL3)
396 font_width = getFontWidth(font_size, font_type);
397 font_height = getFontHeight(font_size, font_type);
399 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
400 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
401 FONT_LINES_PER_FONT);
403 if (font_type == FC_SPECIAL3)
404 font_start += (FONT4_YSIZE - FONT2_YSIZE) * FONT_LINES_PER_FONT;
410 if (c == '~' && font_size == FS_SMALL)
412 print_inverse = TRUE;
416 if (c >= 'a' && c <= 'z')
418 else if (c == 'ä' || c == 'Ä')
420 else if (c == 'ö' || c == 'Ö')
422 else if (c == 'ü' || c == 'Ü')
425 if (c >= 32 && c <= 95)
427 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
428 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
429 int dest_x = x, dest_y = y;
433 XCopyArea(display, pix[font_pixmap], d, gc,
434 FONT_CHARS_PER_LINE * font_width,
435 3 * font_height + font_start,
436 font_width, font_height, x, y);
438 XSetClipOrigin(display, clip_gc[font_pixmap],
439 dest_x - src_x, dest_y - src_y);
440 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
441 0, 0, font_width, font_height, dest_x, dest_y);
444 XCopyArea(display, pix[font_pixmap], d, gc,
445 src_x, src_y, font_width, font_height, dest_x, dest_y);
452 void DrawAllPlayers()
456 for(i=0; i<MAX_PLAYERS; i++)
457 if (stored_player[i].active)
458 DrawPlayer(&stored_player[i]);
461 void DrawPlayerField(int x, int y)
463 if (!IS_PLAYER(x, y))
466 DrawPlayer(PLAYERINFO(x, y));
469 void DrawPlayer(struct PlayerInfo *player)
471 int jx = player->jx, jy = player->jy;
472 int last_jx = player->last_jx, last_jy = player->last_jy;
473 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
474 int sx = SCREENX(jx), sy = SCREENY(jy);
475 int sxx = 0, syy = 0;
476 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
478 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
480 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
484 if (!IN_LEV_FIELD(jx,jy))
486 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
487 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
488 printf("DrawPlayerField(): This should never happen!\n");
493 if (element == EL_EXPLODING)
496 /* draw things in the field the player is leaving, if needed */
498 if (player_is_moving)
500 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
502 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
503 DrawLevelFieldThruMask(last_jx, last_jy);
505 else if (last_element == EL_DYNAMITE_ACTIVE)
506 DrawDynamite(last_jx, last_jy);
508 DrawLevelField(last_jx, last_jy);
510 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
514 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
515 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
517 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
520 DrawLevelField(next_jx, next_jy);
524 if (!IN_SCR_FIELD(sx, sy))
527 if (setup.direct_draw)
528 SetDrawtoField(DRAW_BUFFERED);
530 /* draw things behind the player, if needed */
533 DrawLevelElement(jx, jy, Store[jx][jy]);
534 else if (!IS_ACTIVE_BOMB(element))
535 DrawLevelField(jx, jy);
537 /* draw player himself */
539 if (game.emulation == EMU_SUPAPLEX)
541 static int last_dir = MV_LEFT;
542 int action = (player->programmed_action ? player->programmed_action :
544 boolean action_moving =
546 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
547 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
549 graphic = GFX_SP_MURPHY;
553 if (player->MovDir == MV_LEFT)
554 graphic = GFX_MURPHY_PUSH_LEFT;
555 else if (player->MovDir == MV_RIGHT)
556 graphic = GFX_MURPHY_PUSH_RIGHT;
557 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
558 graphic = GFX_MURPHY_PUSH_LEFT;
559 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
560 graphic = GFX_MURPHY_PUSH_RIGHT;
562 else if (player->snapped)
564 if (player->MovDir == MV_LEFT)
565 graphic = GFX_MURPHY_SNAP_LEFT;
566 else if (player->MovDir == MV_RIGHT)
567 graphic = GFX_MURPHY_SNAP_RIGHT;
568 else if (player->MovDir == MV_UP)
569 graphic = GFX_MURPHY_SNAP_UP;
570 else if (player->MovDir == MV_DOWN)
571 graphic = GFX_MURPHY_SNAP_DOWN;
573 else if (action_moving)
575 if (player->MovDir == MV_LEFT)
576 graphic = GFX_MURPHY_GO_LEFT;
577 else if (player->MovDir == MV_RIGHT)
578 graphic = GFX_MURPHY_GO_RIGHT;
579 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
580 graphic = GFX_MURPHY_GO_LEFT;
581 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
582 graphic = GFX_MURPHY_GO_RIGHT;
584 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
587 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
588 last_dir = player->MovDir;
592 if (player->MovDir == MV_LEFT)
594 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
595 else if (player->MovDir == MV_RIGHT)
597 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
598 else if (player->MovDir == MV_UP)
599 graphic = GFX_SPIELER1_UP;
600 else /* MV_DOWN || MV_NO_MOVING */
601 graphic = GFX_SPIELER1_DOWN;
603 graphic += player->index_nr * 3 * HEROES_PER_LINE;
604 graphic += player->Frame;
609 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
610 sxx = player->GfxPos;
612 syy = player->GfxPos;
615 if (!setup.soft_scrolling && ScreenMovPos)
618 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
620 if (SHIELD_ON(player))
622 int graphic = (player->shield_active_time_left ? GFX2_SHIELD_ACTIVE :
623 GFX2_SHIELD_PASSIVE);
625 DrawGraphicAnimationShiftedThruMask(sx, sy, sxx, syy, graphic,
626 3, 8, ANIM_OSCILLATE);
629 if (player->Pushing && player->GfxPos)
631 int px = SCREENX(next_jx), py = SCREENY(next_jy);
633 if (element == EL_SOKOBAN_FELD_LEER ||
634 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
635 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
639 int element = Feld[next_jx][next_jy];
640 int graphic = el2gfx(element);
642 if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK) && sxx)
644 int phase = (player->GfxPos / (TILEX / 4));
646 if (player->MovDir == MV_LEFT)
649 graphic += (phase + 4) % 4;
652 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
656 /* draw things in front of player (active dynamite or dynabombs) */
658 if (IS_ACTIVE_BOMB(element))
660 graphic = el2gfx(element);
662 if (element == EL_DYNAMITE_ACTIVE)
664 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
669 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
673 if (game.emulation == EMU_SUPAPLEX)
674 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
676 DrawGraphicThruMask(sx, sy, graphic + phase);
679 if (player_is_moving && last_element == EL_EXPLODING)
681 int phase = Frame[last_jx][last_jy];
685 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
686 GFX_EXPLOSION + ((phase - 1) / delay - 1));
689 /* draw elements that stay over the player */
690 /* handle the field the player is leaving ... */
691 if (player_is_moving && IS_OVER_PLAYER(last_element))
692 DrawLevelField(last_jx, last_jy);
693 /* ... and the field the player is entering */
694 if (IS_OVER_PLAYER(element))
695 DrawLevelField(jx, jy);
697 if (setup.direct_draw)
699 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
700 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
701 int x_size = TILEX * (1 + ABS(jx - last_jx));
702 int y_size = TILEY * (1 + ABS(jy - last_jy));
704 XCopyArea(display, drawto_field, window, gc,
705 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
706 SetDrawtoField(DRAW_DIRECT);
709 MarkTileDirty(sx,sy);
712 static int getGraphicAnimationPhase(int frames, int delay, int mode)
716 if (mode == ANIM_OSCILLATE)
718 int max_anim_frames = 2 * frames - 2;
719 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
720 phase = (phase < frames ? phase : max_anim_frames - phase);
723 phase = (FrameCounter % (delay * frames)) / delay;
725 if (mode == ANIM_REVERSE)
731 void DrawGraphicAnimationExt(int x, int y, int graphic,
732 int frames, int delay, int mode, int mask_mode)
734 int phase = getGraphicAnimationPhase(frames, delay, mode);
736 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
738 if (mask_mode == USE_MASKING)
739 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
741 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
745 void DrawGraphicAnimation(int x, int y, int graphic,
746 int frames, int delay, int mode)
748 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
751 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
752 int frames, int delay, int mode)
754 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
757 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
760 int frames, int delay,
763 int phase = getGraphicAnimationPhase(frames, delay, mode);
765 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
768 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
770 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
772 graphic -= GFX_START_ROCKSSCREEN;
773 *pixmap_nr = PIX_BACK;
774 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
775 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
777 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
779 graphic -= GFX_START_ROCKSHEROES;
780 *pixmap_nr = PIX_HEROES;
781 *x = (graphic % HEROES_PER_LINE) * TILEX;
782 *y = (graphic / HEROES_PER_LINE) * TILEY;
784 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
786 graphic -= GFX_START_ROCKSSP;
788 *x = (graphic % SP_PER_LINE) * TILEX;
789 *y = (graphic / SP_PER_LINE) * TILEY;
791 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
793 graphic -= GFX_START_ROCKSDC;
795 *x = (graphic % DC_PER_LINE) * TILEX;
796 *y = (graphic / DC_PER_LINE) * TILEY;
798 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
800 graphic -= GFX_START_ROCKSFONT;
801 *pixmap_nr = PIX_BIGFONT;
802 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
803 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
804 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
814 void DrawGraphic(int x, int y, int graphic)
817 if (!IN_SCR_FIELD(x,y))
819 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
820 printf("DrawGraphic(): This should never happen!\n");
825 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
829 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
834 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
835 XCopyArea(display, pix[pixmap_nr], d, gc,
836 src_x, src_y, TILEX, TILEY, x, y);
839 void DrawGraphicThruMask(int x, int y, int graphic)
842 if (!IN_SCR_FIELD(x,y))
844 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
845 printf("DrawGraphicThruMask(): This should never happen!\n");
850 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
854 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
862 if (graphic == GFX_LEERRAUM)
865 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
866 src_pixmap = pix[pixmap_nr];
867 drawing_gc = clip_gc[pixmap_nr];
869 if (tile_clipmask[tile] != None)
871 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
872 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
873 XCopyArea(display, src_pixmap, d, tile_clip_gc,
874 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
879 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
882 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
883 XCopyArea(display, src_pixmap, d, drawing_gc,
884 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
888 void DrawMiniGraphic(int x, int y, int graphic)
890 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
891 MarkTileDirty(x/2, y/2);
894 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
896 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
898 graphic -= GFX_START_ROCKSSCREEN;
899 *pixmap = pix[PIX_BACK];
900 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
901 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
903 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
905 graphic -= GFX_START_ROCKSSP;
906 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
907 *pixmap = pix[PIX_SP];
908 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
909 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
911 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
913 graphic -= GFX_START_ROCKSDC;
914 *pixmap = pix[PIX_DC];
915 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
916 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
918 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
920 graphic -= GFX_START_ROCKSFONT;
921 *pixmap = pix[PIX_SMALLFONT];
922 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
923 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
924 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
928 *pixmap = pix[PIX_SP];
934 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
939 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
940 XCopyArea(display, pixmap, d, gc,
941 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
944 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
945 int cut_mode, int mask_mode)
947 int width = TILEX, height = TILEY;
949 int src_x, src_y, dest_x, dest_y;
957 DrawGraphic(x, y, graphic);
961 if (dx || dy) /* Verschiebung der Grafik? */
963 if (x < BX1) /* Element kommt von links ins Bild */
970 else if (x > BX2) /* Element kommt von rechts ins Bild */
976 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
982 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
984 else if (dx) /* allg. Bewegung in x-Richtung */
985 MarkTileDirty(x + SIGN(dx), y);
987 if (y < BY1) /* Element kommt von oben ins Bild */
989 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
997 else if (y > BY2) /* Element kommt von unten ins Bild */
1003 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1009 else if (dy > 0 && cut_mode == CUT_ABOVE)
1011 if (y == BY2) /* Element unterhalb des Bildes */
1017 MarkTileDirty(x, y + 1);
1018 } /* Element verläßt unten das Bild */
1019 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1021 else if (dy) /* allg. Bewegung in y-Richtung */
1022 MarkTileDirty(x, y + SIGN(dy));
1025 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
1026 src_pixmap = pix[pixmap_nr];
1027 drawing_gc = clip_gc[pixmap_nr];
1032 dest_x = FX + x * TILEX + dx;
1033 dest_y = FY + y * TILEY + dy;
1036 if (!IN_SCR_FIELD(x,y))
1038 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1039 printf("DrawGraphicShifted(): This should never happen!\n");
1044 if (mask_mode == USE_MASKING)
1046 if (tile_clipmask[tile] != None)
1048 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
1049 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1050 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1051 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1056 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1059 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1060 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1061 src_x, src_y, width, height, dest_x, dest_y);
1065 XCopyArea(display, src_pixmap, drawto_field, gc,
1066 src_x, src_y, width, height, dest_x, dest_y);
1071 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1074 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1077 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1078 int cut_mode, int mask_mode)
1080 int ux = LEVELX(x), uy = LEVELY(y);
1081 int graphic = el2gfx(element);
1082 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1083 int phase4 = phase8 / 2;
1084 int phase2 = phase8 / 4;
1085 int dir = MovDir[ux][uy];
1087 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1089 graphic += 4 * !phase2;
1093 else if (dir == MV_LEFT)
1095 else if (dir == MV_DOWN)
1098 else if (element == EL_SP_SNIKSNAK)
1101 graphic = GFX_SP_SNIKSNAK_LEFT;
1102 else if (dir == MV_RIGHT)
1103 graphic = GFX_SP_SNIKSNAK_RIGHT;
1104 else if (dir == MV_UP)
1105 graphic = GFX_SP_SNIKSNAK_UP;
1107 graphic = GFX_SP_SNIKSNAK_DOWN;
1109 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1111 else if (element == EL_SP_ELECTRON)
1113 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1115 else if (element == EL_MOLE || element == EL_PINGUIN ||
1116 element == EL_SCHWEIN || element == EL_DRACHE)
1119 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1120 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1121 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1122 else if (dir == MV_RIGHT)
1123 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1124 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1125 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1126 else if (dir == MV_UP)
1127 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1128 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1129 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1131 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1132 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1133 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1137 else if (element == EL_SONDE)
1139 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1141 else if (element == EL_SALZSAEURE)
1143 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1145 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1149 else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
1150 IS_GEM(element)) && !cut_mode)
1152 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1154 if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
1157 graphic += (4 - phase4) % 4;
1158 else if (dir == MV_RIGHT)
1161 graphic += phase2 * 2;
1163 else if (element != EL_SP_INFOTRON)
1167 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1168 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1170 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1172 else if (IS_AMOEBOID(element))
1174 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1175 graphic += (x + 2 * y + 4) % 4;
1177 else if (element == EL_MAUER_LEBT)
1179 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1181 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1182 links_massiv = TRUE;
1183 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1184 rechts_massiv = TRUE;
1186 if (links_massiv && rechts_massiv)
1187 graphic = GFX_MAUERWERK;
1188 else if (links_massiv)
1189 graphic = GFX_MAUER_R;
1190 else if (rechts_massiv)
1191 graphic = GFX_MAUER_L;
1193 else if ((element == EL_INVISIBLE_STEEL ||
1194 element == EL_UNSICHTBAR ||
1195 element == EL_SAND_INVISIBLE) && game.light_time_left)
1197 graphic = (element == EL_INVISIBLE_STEEL ? GFX_INVISIBLE_STEEL_ON :
1198 element == EL_UNSICHTBAR ? GFX_UNSICHTBAR_ON :
1199 GFX_SAND_INVISIBLE_ON);
1203 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1204 else if (mask_mode == USE_MASKING)
1205 DrawGraphicThruMask(x, y, graphic);
1207 DrawGraphic(x, y, graphic);
1210 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1211 int cut_mode, int mask_mode)
1213 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1214 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1215 cut_mode, mask_mode);
1218 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1221 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1224 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1227 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1230 void DrawScreenElementThruMask(int x, int y, int element)
1232 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1235 void DrawLevelElementThruMask(int x, int y, int element)
1237 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1240 void DrawLevelFieldThruMask(int x, int y)
1242 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1245 void ErdreichAnbroeckeln(int x, int y)
1247 int i, width, height, cx,cy;
1248 int ux = LEVELX(x), uy = LEVELY(y);
1249 int element, graphic;
1251 static int xy[4][2] =
1259 if (!IN_LEV_FIELD(ux, uy))
1262 element = Feld[ux][uy];
1264 if (element == EL_ERDREICH || element == EL_LANDMINE)
1266 if (!IN_SCR_FIELD(x, y))
1269 graphic = GFX_ERDENRAND;
1275 uxx = ux + xy[i][0];
1276 uyy = uy + xy[i][1];
1277 if (!IN_LEV_FIELD(uxx, uyy))
1280 element = Feld[uxx][uyy];
1282 if (element == EL_ERDREICH || element == EL_LANDMINE)
1285 if (i == 1 || i == 2)
1289 cx = (i == 2 ? TILEX - snip : 0);
1297 cy = (i == 3 ? TILEY - snip : 0);
1300 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1301 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1302 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1303 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1306 MarkTileDirty(x, y);
1310 graphic = GFX_ERDENRAND;
1314 int xx, yy, uxx, uyy;
1318 uxx = ux + xy[i][0];
1319 uyy = uy + xy[i][1];
1321 if (!IN_LEV_FIELD(uxx, uyy) ||
1322 (Feld[uxx][uyy] != EL_ERDREICH && Feld[uxx][uyy] != EL_LANDMINE) ||
1323 !IN_SCR_FIELD(xx, yy))
1326 if (i == 1 || i == 2)
1330 cx = (i == 1 ? TILEX - snip : 0);
1338 cy = (i==0 ? TILEY-snip : 0);
1341 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1342 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1343 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1344 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1346 MarkTileDirty(xx, yy);
1351 void DrawScreenElement(int x, int y, int element)
1353 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1354 ErdreichAnbroeckeln(x, y);
1357 void DrawLevelElement(int x, int y, int element)
1359 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1360 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1363 void DrawScreenField(int x, int y)
1365 int ux = LEVELX(x), uy = LEVELY(y);
1368 if (!IN_LEV_FIELD(ux, uy))
1370 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1371 element = EL_LEERRAUM;
1373 element = BorderElement;
1375 DrawScreenElement(x, y, element);
1379 element = Feld[ux][uy];
1381 if (IS_MOVING(ux, uy))
1383 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1384 boolean cut_mode = NO_CUTTING;
1386 if (Store[ux][uy] == EL_MORAST_LEER ||
1387 Store[ux][uy] == EL_SIEB_LEER ||
1388 Store[ux][uy] == EL_SIEB2_LEER ||
1389 Store[ux][uy] == EL_AMOEBE_NASS)
1390 cut_mode = CUT_ABOVE;
1391 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1392 Store[ux][uy] == EL_SIEB_VOLL ||
1393 Store[ux][uy] == EL_SIEB2_VOLL)
1394 cut_mode = CUT_BELOW;
1396 if (cut_mode == CUT_ABOVE)
1397 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1399 DrawScreenElement(x, y, EL_LEERRAUM);
1402 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1404 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1406 if (Store[ux][uy] == EL_SALZSAEURE)
1407 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1409 else if (IS_BLOCKED(ux, uy))
1414 boolean cut_mode = NO_CUTTING;
1416 Blocked2Moving(ux, uy, &oldx, &oldy);
1419 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1420 MovDir[oldx][oldy] == MV_RIGHT);
1422 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1423 Store[oldx][oldy] == EL_SIEB_LEER ||
1424 Store[oldx][oldy] == EL_SIEB2_LEER ||
1425 Store[oldx][oldy] == EL_AMOEBE_NASS)
1426 cut_mode = CUT_ABOVE;
1428 DrawScreenElement(x, y, EL_LEERRAUM);
1429 element = Feld[oldx][oldy];
1432 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1434 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1436 else if (IS_DRAWABLE(element))
1437 DrawScreenElement(x, y, element);
1439 DrawScreenElement(x, y, EL_LEERRAUM);
1442 void DrawLevelField(int x, int y)
1444 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1445 DrawScreenField(SCREENX(x), SCREENY(y));
1446 else if (IS_MOVING(x, y))
1450 Moving2Blocked(x, y, &newx, &newy);
1451 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1452 DrawScreenField(SCREENX(newx), SCREENY(newy));
1454 else if (IS_BLOCKED(x, y))
1458 Blocked2Moving(x, y, &oldx, &oldy);
1459 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1460 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1464 void DrawMiniElement(int x, int y, int element)
1470 DrawMiniGraphic(x, y, -1);
1474 graphic = el2gfx(element);
1475 DrawMiniGraphic(x, y, graphic);
1478 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1480 int x = sx + scroll_x, y = sy + scroll_y;
1482 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1483 DrawMiniElement(sx, sy, EL_LEERRAUM);
1484 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1485 DrawMiniElement(sx, sy, Feld[x][y]);
1488 int steel_type, steel_position;
1491 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1492 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1493 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1494 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1495 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1496 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1499 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1500 steel_position = (x == -1 && y == -1 ? 0 :
1501 x == lev_fieldx && y == -1 ? 1 :
1502 x == -1 && y == lev_fieldy ? 2 :
1503 x == lev_fieldx && y == lev_fieldy ? 3 :
1504 x == -1 || x == lev_fieldx ? 4 :
1505 y == -1 || y == lev_fieldy ? 5 : -1);
1507 if (steel_position != -1)
1508 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1512 void DrawMicroElement(int xpos, int ypos, int element)
1516 if (element == EL_LEERRAUM)
1519 graphic = el2gfx(element);
1521 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1523 graphic -= GFX_START_ROCKSSP;
1524 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
1525 XCopyArea(display, pix[PIX_SP], drawto, gc,
1526 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
1527 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
1528 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1530 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1532 graphic -= GFX_START_ROCKSDC;
1533 XCopyArea(display, pix[PIX_DC], drawto, gc,
1534 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
1535 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
1536 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1539 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1540 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1541 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1542 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1551 for(x=BX1; x<=BX2; x++)
1552 for(y=BY1; y<=BY2; y++)
1553 DrawScreenField(x, y);
1555 redraw_mask |= REDRAW_FIELD;
1558 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1562 for(x=0; x<size_x; x++)
1563 for(y=0; y<size_y; y++)
1564 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1566 redraw_mask |= REDRAW_FIELD;
1569 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1573 XFillRectangle(display, drawto, gc,
1574 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1576 if (lev_fieldx < STD_LEV_FIELDX)
1577 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1578 if (lev_fieldy < STD_LEV_FIELDY)
1579 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1581 xpos += MICRO_TILEX;
1582 ypos += MICRO_TILEY;
1584 for(x=-1; x<=STD_LEV_FIELDX; x++)
1586 for(y=-1; y<=STD_LEV_FIELDY; y++)
1588 int lx = from_x + x, ly = from_y + y;
1590 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1591 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1593 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1594 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1599 redraw_mask |= REDRAW_MICROLEVEL;
1602 #define MICROLABEL_EMPTY 0
1603 #define MICROLABEL_LEVEL_NAME 1
1604 #define MICROLABEL_CREATED_BY 2
1605 #define MICROLABEL_LEVEL_AUTHOR 3
1606 #define MICROLABEL_IMPORTED_FROM 4
1607 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1609 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1611 static void DrawMicroLevelLabelExt(int mode)
1613 char label_text[MAX_MICROLABEL_SIZE + 1];
1615 XFillRectangle(display, drawto,gc,
1616 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1618 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1619 mode == MICROLABEL_CREATED_BY ? "created by" :
1620 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1621 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1622 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1623 leveldir[leveldir_nr].imported_from : ""),
1624 MAX_MICROLABEL_SIZE);
1625 label_text[MAX_MICROLABEL_SIZE] = '\0';
1627 if (strlen(label_text) > 0)
1629 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1630 int lypos = MICROLABEL_YPOS;
1632 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1635 redraw_mask |= REDRAW_MICROLEVEL;
1638 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1640 static unsigned long scroll_delay = 0;
1641 static unsigned long label_delay = 0;
1642 static int from_x, from_y, scroll_direction;
1643 static int label_state, label_counter;
1647 from_x = from_y = 0;
1648 scroll_direction = MV_RIGHT;
1652 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1653 DrawMicroLevelLabelExt(label_state);
1655 /* initialize delay counters */
1656 DelayReached(&scroll_delay, 0);
1657 DelayReached(&label_delay, 0);
1662 /* scroll micro level, if needed */
1663 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1664 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1666 switch (scroll_direction)
1672 scroll_direction = MV_UP;
1676 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1679 scroll_direction = MV_DOWN;
1686 scroll_direction = MV_RIGHT;
1690 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1693 scroll_direction = MV_LEFT;
1700 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1703 /* redraw micro level label, if needed */
1704 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1705 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1706 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1707 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1709 int max_label_counter = 23;
1711 if (leveldir[leveldir_nr].imported_from != NULL)
1712 max_label_counter += 14;
1714 label_counter = (label_counter + 1) % max_label_counter;
1715 label_state = (label_counter >= 0 && label_counter <= 7 ?
1716 MICROLABEL_LEVEL_NAME :
1717 label_counter >= 9 && label_counter <= 12 ?
1718 MICROLABEL_CREATED_BY :
1719 label_counter >= 14 && label_counter <= 21 ?
1720 MICROLABEL_LEVEL_AUTHOR :
1721 label_counter >= 23 && label_counter <= 26 ?
1722 MICROLABEL_IMPORTED_FROM :
1723 label_counter >= 28 && label_counter <= 35 ?
1724 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1725 DrawMicroLevelLabelExt(label_state);
1729 int REQ_in_range(int x, int y)
1731 if (y > DY+249 && y < DY+278)
1733 if (x > DX+1 && x < DX+48)
1735 else if (x > DX+51 && x < DX+98)
1741 boolean Request(char *text, unsigned int req_state)
1743 int mx, my, ty, result = -1;
1744 unsigned int old_door_state;
1747 /* pause network game while waiting for request to answer */
1748 if (options.network &&
1749 game_status == PLAYING &&
1750 req_state & REQUEST_WAIT_FOR)
1751 SendToServer_PausePlaying();
1754 old_door_state = GetDoorState();
1758 CloseDoor(DOOR_CLOSE_1);
1760 /* save old door content */
1761 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1762 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1763 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1765 /* clear door drawing field */
1766 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1768 /* write text for request */
1769 for(ty=0; ty<13; ty++)
1777 for(tl=0,tx=0; tx<7; tl++,tx++)
1780 if (!tc || tc == 32)
1791 DrawTextExt(drawto, gc,
1792 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1793 txt, FS_SMALL, FC_YELLOW);
1794 text += tl + (tc == 32 ? 1 : 0);
1797 if (req_state & REQ_ASK)
1799 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1800 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1802 else if (req_state & REQ_CONFIRM)
1804 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1806 else if (req_state & REQ_PLAYER)
1808 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1809 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1810 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1811 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1814 /* copy request gadgets to door backbuffer */
1815 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1816 DX, DY, DXSIZE, DYSIZE,
1817 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1819 OpenDoor(DOOR_OPEN_1);
1825 if (!(req_state & REQUEST_WAIT_FOR))
1828 if (game_status != MAINMENU)
1831 button_status = MB_RELEASED;
1833 request_gadget_id = -1;
1837 if (XPending(display))
1841 XNextEvent(display, &event);
1849 if (event.type == MotionNotify)
1856 if (!XQueryPointer(display, window, &root, &child,
1857 &root_x, &root_y, &win_x, &win_y, &mask))
1863 motion_status = TRUE;
1864 mx = ((XMotionEvent *) &event)->x;
1865 my = ((XMotionEvent *) &event)->y;
1869 motion_status = FALSE;
1870 mx = ((XButtonEvent *) &event)->x;
1871 my = ((XButtonEvent *) &event)->y;
1872 if (event.type==ButtonPress)
1873 button_status = ((XButtonEvent *) &event)->button;
1875 button_status = MB_RELEASED;
1878 /* this sets 'request_gadget_id' */
1879 HandleGadgets(mx, my, button_status);
1881 switch(request_gadget_id)
1883 case TOOL_CTRL_ID_YES:
1886 case TOOL_CTRL_ID_NO:
1889 case TOOL_CTRL_ID_CONFIRM:
1890 result = TRUE | FALSE;
1893 case TOOL_CTRL_ID_PLAYER_1:
1896 case TOOL_CTRL_ID_PLAYER_2:
1899 case TOOL_CTRL_ID_PLAYER_3:
1902 case TOOL_CTRL_ID_PLAYER_4:
1914 switch(XLookupKeysym((XKeyEvent *)&event,
1915 ((XKeyEvent *)&event)->state))
1928 if (req_state & REQ_PLAYER)
1933 key_joystick_mapping = 0;
1937 HandleOtherEvents(&event);
1941 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1943 int joy = AnyJoystick();
1945 if (joy & JOY_BUTTON_1)
1947 else if (joy & JOY_BUTTON_2)
1953 /* don't eat all CPU time */
1957 if (game_status != MAINMENU)
1962 if (!(req_state & REQ_STAY_OPEN))
1964 CloseDoor(DOOR_CLOSE_1);
1966 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1968 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1969 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1970 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1971 OpenDoor(DOOR_OPEN_1);
1978 /* continue network game after request */
1979 if (options.network &&
1980 game_status == PLAYING &&
1981 req_state & REQUEST_WAIT_FOR)
1982 SendToServer_ContinuePlaying();
1988 unsigned int OpenDoor(unsigned int door_state)
1990 unsigned int new_door_state;
1992 if (door_state & DOOR_COPY_BACK)
1994 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1995 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1996 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1997 door_state &= ~DOOR_COPY_BACK;
2000 new_door_state = MoveDoor(door_state);
2002 return(new_door_state);
2005 unsigned int CloseDoor(unsigned int door_state)
2007 unsigned int new_door_state;
2009 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2010 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2011 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2012 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2014 new_door_state = MoveDoor(door_state);
2016 return(new_door_state);
2019 unsigned int GetDoorState()
2021 return(MoveDoor(DOOR_GET_STATE));
2024 unsigned int MoveDoor(unsigned int door_state)
2026 static int door1 = DOOR_OPEN_1;
2027 static int door2 = DOOR_CLOSE_2;
2028 static unsigned long door_delay = 0;
2029 int x, start, stepsize = 2;
2030 unsigned long door_delay_value = stepsize * 5;
2032 if (door_state == DOOR_GET_STATE)
2033 return(door1 | door2);
2035 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2036 door_state &= ~DOOR_OPEN_1;
2037 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2038 door_state &= ~DOOR_CLOSE_1;
2039 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2040 door_state &= ~DOOR_OPEN_2;
2041 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2042 door_state &= ~DOOR_CLOSE_2;
2044 if (setup.quick_doors)
2047 door_delay_value = 0;
2048 StopSound(SND_OEFFNEN);
2051 if (door_state & DOOR_ACTION)
2053 if (!(door_state & DOOR_NO_DELAY))
2054 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2056 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2058 for(x=start; x<=DXSIZE; x+=stepsize)
2060 WaitUntilDelayReached(&door_delay, door_delay_value);
2062 if (door_state & DOOR_ACTION_1)
2064 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2065 int j = (DXSIZE - i) / 3;
2067 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2068 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2069 DXSIZE,DYSIZE - i/2, DX, DY);
2071 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2073 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2074 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2075 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2076 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2077 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2078 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2080 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2081 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2082 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2083 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2084 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2085 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2087 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2088 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2090 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2091 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2093 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2094 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2095 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2096 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2097 DX + DXSIZE - i, DY + 77 + j);
2098 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2099 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2100 DX + DXSIZE - i, DY + 203 + j);
2102 redraw_mask |= REDRAW_DOOR_1;
2105 if (door_state & DOOR_ACTION_2)
2107 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2108 int j = (VXSIZE - i) / 3;
2110 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2111 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2112 VXSIZE, VYSIZE - i/2, VX, VY);
2114 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2116 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2117 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2118 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2119 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2120 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2121 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2122 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2123 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2125 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2126 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2127 VX, VY + VYSIZE / 2 - j);
2128 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2129 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2130 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2131 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2132 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2134 redraw_mask |= REDRAW_DOOR_2;
2139 if (game_status == MAINMENU)
2144 if (setup.quick_doors)
2145 StopSound(SND_OEFFNEN);
2147 if (door_state & DOOR_ACTION_1)
2148 door1 = door_state & DOOR_ACTION_1;
2149 if (door_state & DOOR_ACTION_2)
2150 door2 = door_state & DOOR_ACTION_2;
2152 return (door1 | door2);
2155 void DrawSpecialEditorDoor()
2157 /* draw bigger toolbox window */
2158 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2159 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2161 redraw_mask |= REDRAW_ALL;
2164 void UndrawSpecialEditorDoor()
2166 /* draw normal tape recorder window */
2167 XCopyArea(display, pix[PIX_BACK], drawto, gc,
2168 562, 344, 108, 56, EX - 4, EY - 12);
2170 redraw_mask |= REDRAW_ALL;
2173 int ReadPixel(Drawable d, int x, int y)
2175 XImage *pixel_image;
2176 unsigned long pixel_value;
2178 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2179 pixel_value = XGetPixel(pixel_image, 0, 0);
2181 XDestroyImage(pixel_image);
2186 /* ---------- new tool button stuff ---------------------------------------- */
2188 /* graphic position values for tool buttons */
2189 #define TOOL_BUTTON_YES_XPOS 2
2190 #define TOOL_BUTTON_YES_YPOS 250
2191 #define TOOL_BUTTON_YES_GFX_YPOS 0
2192 #define TOOL_BUTTON_YES_XSIZE 46
2193 #define TOOL_BUTTON_YES_YSIZE 28
2194 #define TOOL_BUTTON_NO_XPOS 52
2195 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2196 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2197 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2198 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2199 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2200 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2201 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2202 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2203 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2204 #define TOOL_BUTTON_PLAYER_XSIZE 30
2205 #define TOOL_BUTTON_PLAYER_YSIZE 30
2206 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2207 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2208 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2209 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2210 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2211 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2212 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2213 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2214 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2215 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2216 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2217 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2218 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2219 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2220 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2221 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2222 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2223 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2224 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2225 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2234 } toolbutton_info[NUM_TOOL_BUTTONS] =
2237 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2238 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2239 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2244 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2245 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2246 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2251 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2252 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2253 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2254 TOOL_CTRL_ID_CONFIRM,
2258 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2259 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2260 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2261 TOOL_CTRL_ID_PLAYER_1,
2265 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2266 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2267 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2268 TOOL_CTRL_ID_PLAYER_2,
2272 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2273 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2274 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2275 TOOL_CTRL_ID_PLAYER_3,
2279 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2280 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2281 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2282 TOOL_CTRL_ID_PLAYER_4,
2287 static void DoNotDisplayInfoText(void *ptr)
2292 void CreateToolButtons()
2296 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2298 Pixmap gd_pixmap = pix[PIX_DOOR];
2299 Pixmap deco_pixmap = None;
2300 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2301 struct GadgetInfo *gi;
2302 unsigned long event_mask;
2303 int gd_xoffset, gd_yoffset;
2304 int gd_x1, gd_x2, gd_y;
2307 event_mask = GD_EVENT_RELEASED;
2309 gd_xoffset = toolbutton_info[i].xpos;
2310 gd_yoffset = toolbutton_info[i].ypos;
2311 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2312 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2313 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2315 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2317 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2318 &deco_pixmap, &deco_x, &deco_y);
2319 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2320 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2323 gi = CreateGadget(GDI_CUSTOM_ID, id,
2324 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2325 GDI_X, DX + toolbutton_info[i].x,
2326 GDI_Y, DY + toolbutton_info[i].y,
2327 GDI_WIDTH, toolbutton_info[i].width,
2328 GDI_HEIGHT, toolbutton_info[i].height,
2329 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2330 GDI_STATE, GD_BUTTON_UNPRESSED,
2331 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2332 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2333 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2334 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2335 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2336 GDI_DECORATION_SHIFTING, 1, 1,
2337 GDI_EVENT_MASK, event_mask,
2338 GDI_CALLBACK_ACTION, HandleToolButtons,
2339 GDI_CALLBACK_INFO, DoNotDisplayInfoText,
2343 Error(ERR_EXIT, "cannot create gadget");
2345 tool_gadget[id] = gi;
2349 static void UnmapToolButtons()
2353 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2354 UnmapGadget(tool_gadget[i]);
2357 static void HandleToolButtons(struct GadgetInfo *gi)
2359 request_gadget_id = gi->custom_id;
2362 int el2gfx(int element)
2366 case EL_LEERRAUM: return -1;
2367 case EL_ERDREICH: return GFX_ERDREICH;
2368 case EL_MAUERWERK: return GFX_MAUERWERK;
2369 case EL_FELSBODEN: return GFX_FELSBODEN;
2370 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2371 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2372 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2373 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2374 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2375 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2376 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2377 case EL_SPIELER1: return GFX_SPIELER1;
2378 case EL_SPIELER2: return GFX_SPIELER2;
2379 case EL_SPIELER3: return GFX_SPIELER3;
2380 case EL_SPIELER4: return GFX_SPIELER4;
2381 case EL_KAEFER: return GFX_KAEFER;
2382 case EL_KAEFER_RIGHT: return GFX_KAEFER_RIGHT;
2383 case EL_KAEFER_UP: return GFX_KAEFER_UP;
2384 case EL_KAEFER_LEFT: return GFX_KAEFER_LEFT;
2385 case EL_KAEFER_DOWN: return GFX_KAEFER_DOWN;
2386 case EL_FLIEGER: return GFX_FLIEGER;
2387 case EL_FLIEGER_RIGHT: return GFX_FLIEGER_RIGHT;
2388 case EL_FLIEGER_UP: return GFX_FLIEGER_UP;
2389 case EL_FLIEGER_LEFT: return GFX_FLIEGER_LEFT;
2390 case EL_FLIEGER_DOWN: return GFX_FLIEGER_DOWN;
2391 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2392 case EL_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2393 case EL_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2394 case EL_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2395 case EL_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2396 case EL_FIREFLY: return GFX_FIREFLY;
2397 case EL_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2398 case EL_FIREFLY_UP: return GFX_FIREFLY_UP;
2399 case EL_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2400 case EL_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2401 case EL_MAMPFER: return GFX_MAMPFER;
2402 case EL_ROBOT: return GFX_ROBOT;
2403 case EL_BETON: return GFX_BETON;
2404 case EL_DIAMANT: return GFX_DIAMANT;
2405 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2406 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2407 case EL_TROPFEN: return GFX_TROPFEN;
2408 case EL_BOMBE: return GFX_BOMBE;
2409 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2410 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2411 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2412 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2413 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2414 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2415 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2416 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2417 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2418 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2419 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2420 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2421 case EL_LIFE: return GFX_LIFE;
2422 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2423 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2424 case EL_BADEWANNE: return GFX_BADEWANNE;
2425 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2426 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2427 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2428 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2429 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2430 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2431 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2432 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2433 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2434 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2435 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2436 case EL_PFORTE1: return GFX_PFORTE1;
2437 case EL_PFORTE2: return GFX_PFORTE2;
2438 case EL_PFORTE3: return GFX_PFORTE3;
2439 case EL_PFORTE4: return GFX_PFORTE4;
2440 case EL_PFORTE1X: return GFX_PFORTE1X;
2441 case EL_PFORTE2X: return GFX_PFORTE2X;
2442 case EL_PFORTE3X: return GFX_PFORTE3X;
2443 case EL_PFORTE4X: return GFX_PFORTE4X;
2444 case EL_DYNAMITE_INACTIVE: return GFX_DYNAMIT_AUS;
2445 case EL_PACMAN: return GFX_PACMAN;
2446 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2447 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2448 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2449 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2450 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2451 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2452 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2453 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2454 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2455 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2456 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2457 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2458 case EL_MAUER_X: return GFX_MAUER_X;
2459 case EL_MAUER_Y: return GFX_MAUER_Y;
2460 case EL_MAUER_XY: return GFX_MAUER_XY;
2461 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2462 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2463 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2464 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2465 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2466 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2467 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2468 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2469 case EL_MAMPFER2: return GFX_MAMPFER2;
2470 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2471 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2472 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2473 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2474 case EL_DYNABOMB_ACTIVE_1: return GFX_DYNABOMB;
2475 case EL_DYNABOMB_ACTIVE_2: return GFX_DYNABOMB;
2476 case EL_DYNABOMB_ACTIVE_3: return GFX_DYNABOMB;
2477 case EL_DYNABOMB_ACTIVE_4: return GFX_DYNABOMB;
2478 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2479 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2480 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2481 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2482 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2483 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2484 case EL_MOLE: return GFX_MOLE;
2485 case EL_PINGUIN: return GFX_PINGUIN;
2486 case EL_SCHWEIN: return GFX_SCHWEIN;
2487 case EL_DRACHE: return GFX_DRACHE;
2488 case EL_SONDE: return GFX_SONDE;
2489 case EL_PFEIL_LEFT: return GFX_PFEIL_LEFT;
2490 case EL_PFEIL_RIGHT: return GFX_PFEIL_RIGHT;
2491 case EL_PFEIL_UP: return GFX_PFEIL_UP;
2492 case EL_PFEIL_DOWN: return GFX_PFEIL_DOWN;
2493 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2494 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2495 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2496 case EL_SP_ZONK: return GFX_SP_ZONK;
2497 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2498 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2499 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2500 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2501 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2502 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2503 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2504 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2505 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2506 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2507 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2508 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2509 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2510 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2511 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2512 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2513 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2514 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2515 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2516 case EL_PEARL: return GFX_PEARL;
2517 case EL_CRYSTAL: return GFX_CRYSTAL;
2518 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2519 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2520 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2521 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2522 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2523 case EL_SHIELD_PASSIVE: return GFX_SHIELD_PASSIVE;
2524 case EL_SHIELD_ACTIVE: return GFX_SHIELD_ACTIVE;
2525 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2526 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2527 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2528 case EL_SWITCHGATE_SWITCH_1:return GFX_SWITCHGATE_SWITCH_1;
2529 case EL_SWITCHGATE_SWITCH_2:return GFX_SWITCHGATE_SWITCH_2;
2530 case EL_BELT1_LEFT: return GFX_BELT1_LEFT;
2531 case EL_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2532 case EL_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2533 case EL_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2534 case EL_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2535 case EL_BELT1_SWITCH_RIGHT: return GFX_BELT1_SWITCH_RIGHT;
2536 case EL_BELT2_LEFT: return GFX_BELT2_LEFT;
2537 case EL_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2538 case EL_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2539 case EL_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2540 case EL_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2541 case EL_BELT2_SWITCH_RIGHT: return GFX_BELT2_SWITCH_RIGHT;
2542 case EL_BELT3_LEFT: return GFX_BELT3_LEFT;
2543 case EL_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2544 case EL_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2545 case EL_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2546 case EL_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2547 case EL_BELT3_SWITCH_RIGHT: return GFX_BELT3_SWITCH_RIGHT;
2548 case EL_BELT4_LEFT: return GFX_BELT4_LEFT;
2549 case EL_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2550 case EL_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2551 case EL_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2552 case EL_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2553 case EL_BELT4_SWITCH_RIGHT: return GFX_BELT4_SWITCH_RIGHT;
2554 case EL_LANDMINE: return GFX_LANDMINE;
2555 case EL_ENVELOPE: return GFX_ENVELOPE;
2556 case EL_LIGHT_SWITCH_OFF: return GFX_LIGHT_SWITCH_OFF;
2557 case EL_LIGHT_SWITCH_ON: return GFX_LIGHT_SWITCH_ON;
2558 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2559 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2560 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2561 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2562 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2563 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2564 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2565 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2566 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2567 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2568 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2569 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2570 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2571 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2572 case EL_MOLE_UP: return GFX_MOLE_UP;
2573 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2574 case EL_STEEL_SLANTED: return GFX_STEEL_SLANTED;
2575 case EL_SAND_INVISIBLE: return GFX_SAND_INVISIBLE;
2576 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2577 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2578 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2579 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2580 case EL_TIMEGATE_SWITCH_ON: return GFX_TIMEGATE_SWITCH;
2581 case EL_TIMEGATE_SWITCH_OFF:return GFX_TIMEGATE_SWITCH;
2582 case EL_BALLOON: return GFX_BALLOON;
2583 case EL_BALLOON_SEND_LEFT: return GFX_BALLOON_SEND_LEFT;
2584 case EL_BALLOON_SEND_RIGHT: return GFX_BALLOON_SEND_RIGHT;
2585 case EL_BALLOON_SEND_UP: return GFX_BALLOON_SEND_UP;
2586 case EL_BALLOON_SEND_DOWN: return GFX_BALLOON_SEND_DOWN;
2587 case EL_BALLOON_SEND_ANY: return GFX_BALLOON_SEND_ANY;
2588 case EL_EMC_STEEL_WALL_1: return GFX_EMC_STEEL_WALL_1;
2589 case EL_EMC_STEEL_WALL_2: return GFX_EMC_STEEL_WALL_2;
2590 case EL_EMC_STEEL_WALL_3: return GFX_EMC_STEEL_WALL_3;
2591 case EL_EMC_STEEL_WALL_4: return GFX_EMC_STEEL_WALL_4;
2592 case EL_EMC_WALL_1: return GFX_EMC_WALL_1;
2593 case EL_EMC_WALL_2: return GFX_EMC_WALL_2;
2594 case EL_EMC_WALL_3: return GFX_EMC_WALL_3;
2595 case EL_EMC_WALL_4: return GFX_EMC_WALL_4;
2596 case EL_EMC_WALL_5: return GFX_EMC_WALL_5;
2597 case EL_EMC_WALL_6: return GFX_EMC_WALL_6;
2598 case EL_EMC_WALL_7: return GFX_EMC_WALL_7;
2599 case EL_EMC_WALL_8: return GFX_EMC_WALL_8;
2603 if (IS_CHAR(element))
2604 return GFX_CHAR_START + (element - EL_CHAR_START);
2605 else if (element >= EL_SP_START && element <= EL_SP_END)
2607 int nr_element = element - EL_SP_START;
2608 int gfx_per_line = 8;
2610 (nr_element / gfx_per_line) * SP_PER_LINE +
2611 (nr_element % gfx_per_line);
2613 return GFX_START_ROCKSSP + nr_graphic;