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 DrawTextFCentered(int y, int font_type, char *format, ...)
339 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
340 int font_width = getFontWidth(FS_SMALL, font_type);
343 va_start(ap, format);
344 vsprintf(buffer, format, ap);
347 DrawText(SX + (SXSIZE - strlen(buffer) * font_width) / 2, SY + y,
348 buffer, FS_SMALL, font_type);
351 void DrawTextF(int x, int y, int font_type, char *format, ...)
353 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
356 va_start(ap, format);
357 vsprintf(buffer, format, ap);
360 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
363 void DrawText(int x, int y, char *text, int font_size, int font_type)
365 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
368 redraw_mask |= REDRAW_FIELD;
370 redraw_mask |= REDRAW_DOOR_1;
373 void DrawTextExt(Drawable d, GC gc, int x, int y,
374 char *text, int font_size, int font_type)
376 int font_width, font_height, font_start;
378 boolean print_inverse = FALSE;
380 if (font_size != FS_SMALL && font_size != FS_BIG)
381 font_size = FS_SMALL;
382 if (font_type < FC_RED || font_type > FC_SPECIAL3)
385 font_width = getFontWidth(font_size, font_type);
386 font_height = getFontHeight(font_size, font_type);
388 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
389 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
390 FONT_LINES_PER_FONT);
392 if (font_type == FC_SPECIAL3)
393 font_start += (FONT4_YSIZE - FONT2_YSIZE) * FONT_LINES_PER_FONT;
399 if (c == '~' && font_size == FS_SMALL)
401 print_inverse = TRUE;
405 if (c >= 'a' && c <= 'z')
407 else if (c == 'ä' || c == 'Ä')
409 else if (c == 'ö' || c == 'Ö')
411 else if (c == 'ü' || c == 'Ü')
414 if (c >= 32 && c <= 95)
416 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
417 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
418 int dest_x = x, dest_y = y;
422 XCopyArea(display, pix[font_pixmap], d, gc,
423 FONT_CHARS_PER_LINE * font_width,
424 3 * font_height + font_start,
425 font_width, font_height, x, y);
427 XSetClipOrigin(display, clip_gc[font_pixmap],
428 dest_x - src_x, dest_y - src_y);
429 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
430 0, 0, font_width, font_height, dest_x, dest_y);
433 XCopyArea(display, pix[font_pixmap], d, gc,
434 src_x, src_y, font_width, font_height, dest_x, dest_y);
441 void DrawAllPlayers()
445 for(i=0; i<MAX_PLAYERS; i++)
446 if (stored_player[i].active)
447 DrawPlayer(&stored_player[i]);
450 void DrawPlayerField(int x, int y)
452 if (!IS_PLAYER(x, y))
455 DrawPlayer(PLAYERINFO(x, y));
458 void DrawPlayer(struct PlayerInfo *player)
460 int jx = player->jx, jy = player->jy;
461 int last_jx = player->last_jx, last_jy = player->last_jy;
462 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
463 int sx = SCREENX(jx), sy = SCREENY(jy);
464 int sxx = 0, syy = 0;
465 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
467 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
469 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
473 if (!IN_LEV_FIELD(jx,jy))
475 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
476 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
477 printf("DrawPlayerField(): This should never happen!\n");
482 if (element == EL_EXPLODING)
485 /* draw things in the field the player is leaving, if needed */
487 if (player_is_moving)
489 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
491 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
492 DrawLevelFieldThruMask(last_jx, last_jy);
494 else if (last_element == EL_DYNAMITE_ACTIVE)
495 DrawDynamite(last_jx, last_jy);
497 DrawLevelField(last_jx, last_jy);
499 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
503 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
504 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
506 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
509 DrawLevelField(next_jx, next_jy);
513 if (!IN_SCR_FIELD(sx, sy))
516 if (setup.direct_draw)
517 SetDrawtoField(DRAW_BUFFERED);
519 /* draw things behind the player, if needed */
522 DrawLevelElement(jx, jy, Store[jx][jy]);
523 else if (!IS_ACTIVE_BOMB(element))
524 DrawLevelField(jx, jy);
526 /* draw player himself */
528 if (game.emulation == EMU_SUPAPLEX)
530 static int last_dir = MV_LEFT;
531 int action = (player->programmed_action ? player->programmed_action :
533 boolean action_moving =
535 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
536 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
538 graphic = GFX_SP_MURPHY;
542 if (player->MovDir == MV_LEFT)
543 graphic = GFX_MURPHY_PUSH_LEFT;
544 else if (player->MovDir == MV_RIGHT)
545 graphic = GFX_MURPHY_PUSH_RIGHT;
546 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
547 graphic = GFX_MURPHY_PUSH_LEFT;
548 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
549 graphic = GFX_MURPHY_PUSH_RIGHT;
551 else if (player->snapped)
553 if (player->MovDir == MV_LEFT)
554 graphic = GFX_MURPHY_SNAP_LEFT;
555 else if (player->MovDir == MV_RIGHT)
556 graphic = GFX_MURPHY_SNAP_RIGHT;
557 else if (player->MovDir == MV_UP)
558 graphic = GFX_MURPHY_SNAP_UP;
559 else if (player->MovDir == MV_DOWN)
560 graphic = GFX_MURPHY_SNAP_DOWN;
562 else if (action_moving)
564 if (player->MovDir == MV_LEFT)
565 graphic = GFX_MURPHY_GO_LEFT;
566 else if (player->MovDir == MV_RIGHT)
567 graphic = GFX_MURPHY_GO_RIGHT;
568 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
569 graphic = GFX_MURPHY_GO_LEFT;
570 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
571 graphic = GFX_MURPHY_GO_RIGHT;
573 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
576 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
577 last_dir = player->MovDir;
581 if (player->MovDir == MV_LEFT)
583 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
584 else if (player->MovDir == MV_RIGHT)
586 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
587 else if (player->MovDir == MV_UP)
588 graphic = GFX_SPIELER1_UP;
589 else /* MV_DOWN || MV_NO_MOVING */
590 graphic = GFX_SPIELER1_DOWN;
592 graphic += player->index_nr * 3 * HEROES_PER_LINE;
593 graphic += player->Frame;
598 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
599 sxx = player->GfxPos;
601 syy = player->GfxPos;
604 if (!setup.soft_scrolling && ScreenMovPos)
607 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
609 if (SHIELD_ON(player))
611 int graphic = (player->shield_active_time_left ? GFX2_SHIELD_ACTIVE :
612 GFX2_SHIELD_PASSIVE);
614 DrawGraphicAnimationShiftedThruMask(sx, sy, sxx, syy, graphic,
615 3, 8, ANIM_OSCILLATE);
618 if (player->Pushing && player->GfxPos)
620 int px = SCREENX(next_jx), py = SCREENY(next_jy);
622 if (element == EL_SOKOBAN_FELD_LEER ||
623 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
624 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
628 int element = Feld[next_jx][next_jy];
629 int graphic = el2gfx(element);
631 if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK) && sxx)
633 int phase = (player->GfxPos / (TILEX / 4));
635 if (player->MovDir == MV_LEFT)
638 graphic += (phase + 4) % 4;
641 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
645 /* draw things in front of player (active dynamite or dynabombs) */
647 if (IS_ACTIVE_BOMB(element))
649 graphic = el2gfx(element);
651 if (element == EL_DYNAMITE_ACTIVE)
653 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
658 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
662 if (game.emulation == EMU_SUPAPLEX)
663 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
665 DrawGraphicThruMask(sx, sy, graphic + phase);
668 if (player_is_moving && last_element == EL_EXPLODING)
670 int phase = Frame[last_jx][last_jy];
674 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
675 GFX_EXPLOSION + ((phase - 1) / delay - 1));
678 /* draw elements that stay over the player */
679 /* handle the field the player is leaving ... */
680 if (player_is_moving && IS_OVER_PLAYER(last_element))
681 DrawLevelField(last_jx, last_jy);
682 /* ... and the field the player is entering */
683 if (IS_OVER_PLAYER(element))
684 DrawLevelField(jx, jy);
686 if (setup.direct_draw)
688 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
689 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
690 int x_size = TILEX * (1 + ABS(jx - last_jx));
691 int y_size = TILEY * (1 + ABS(jy - last_jy));
693 XCopyArea(display, drawto_field, window, gc,
694 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
695 SetDrawtoField(DRAW_DIRECT);
698 MarkTileDirty(sx,sy);
701 static int getGraphicAnimationPhase(int frames, int delay, int mode)
705 if (mode == ANIM_OSCILLATE)
707 int max_anim_frames = 2 * frames - 2;
708 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
709 phase = (phase < frames ? phase : max_anim_frames - phase);
712 phase = (FrameCounter % (delay * frames)) / delay;
714 if (mode == ANIM_REVERSE)
720 void DrawGraphicAnimationExt(int x, int y, int graphic,
721 int frames, int delay, int mode, int mask_mode)
723 int phase = getGraphicAnimationPhase(frames, delay, mode);
725 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
727 if (mask_mode == USE_MASKING)
728 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
730 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
734 void DrawGraphicAnimation(int x, int y, int graphic,
735 int frames, int delay, int mode)
737 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
740 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
741 int frames, int delay, int mode)
743 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
746 static void DrawGraphicAnimationShiftedThruMask(int sx, int sy,
749 int frames, int delay,
752 int phase = getGraphicAnimationPhase(frames, delay, mode);
754 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic + phase, NO_CUTTING);
757 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
759 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
761 graphic -= GFX_START_ROCKSSCREEN;
762 *pixmap_nr = PIX_BACK;
763 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
764 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
766 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
768 graphic -= GFX_START_ROCKSHEROES;
769 *pixmap_nr = PIX_HEROES;
770 *x = (graphic % HEROES_PER_LINE) * TILEX;
771 *y = (graphic / HEROES_PER_LINE) * TILEY;
773 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
775 graphic -= GFX_START_ROCKSSP;
777 *x = (graphic % SP_PER_LINE) * TILEX;
778 *y = (graphic / SP_PER_LINE) * TILEY;
780 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
782 graphic -= GFX_START_ROCKSDC;
784 *x = (graphic % DC_PER_LINE) * TILEX;
785 *y = (graphic / DC_PER_LINE) * TILEY;
787 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
789 graphic -= GFX_START_ROCKSFONT;
790 *pixmap_nr = PIX_BIGFONT;
791 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
792 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
793 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
803 void DrawGraphic(int x, int y, int graphic)
806 if (!IN_SCR_FIELD(x,y))
808 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
809 printf("DrawGraphic(): This should never happen!\n");
814 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
818 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
823 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
824 XCopyArea(display, pix[pixmap_nr], d, gc,
825 src_x, src_y, TILEX, TILEY, x, y);
828 void DrawGraphicThruMask(int x, int y, int graphic)
831 if (!IN_SCR_FIELD(x,y))
833 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
834 printf("DrawGraphicThruMask(): This should never happen!\n");
839 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
843 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
851 if (graphic == GFX_LEERRAUM)
854 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
855 src_pixmap = pix[pixmap_nr];
856 drawing_gc = clip_gc[pixmap_nr];
858 if (tile_clipmask[tile] != None)
860 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
861 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
862 XCopyArea(display, src_pixmap, d, tile_clip_gc,
863 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
868 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
871 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
872 XCopyArea(display, src_pixmap, d, drawing_gc,
873 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
877 void DrawMiniGraphic(int x, int y, int graphic)
879 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
880 MarkTileDirty(x/2, y/2);
883 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
885 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
887 graphic -= GFX_START_ROCKSSCREEN;
888 *pixmap = pix[PIX_BACK];
889 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
890 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
892 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
894 graphic -= GFX_START_ROCKSSP;
895 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
896 *pixmap = pix[PIX_SP];
897 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
898 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
900 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
902 graphic -= GFX_START_ROCKSDC;
903 *pixmap = pix[PIX_DC];
904 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
905 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
907 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
909 graphic -= GFX_START_ROCKSFONT;
910 *pixmap = pix[PIX_SMALLFONT];
911 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
912 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
913 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
917 *pixmap = pix[PIX_SP];
923 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
928 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
929 XCopyArea(display, pixmap, d, gc,
930 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
933 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
934 int cut_mode, int mask_mode)
936 int width = TILEX, height = TILEY;
938 int src_x, src_y, dest_x, dest_y;
946 DrawGraphic(x, y, graphic);
950 if (dx || dy) /* Verschiebung der Grafik? */
952 if (x < BX1) /* Element kommt von links ins Bild */
959 else if (x > BX2) /* Element kommt von rechts ins Bild */
965 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
971 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
973 else if (dx) /* allg. Bewegung in x-Richtung */
974 MarkTileDirty(x + SIGN(dx), y);
976 if (y < BY1) /* Element kommt von oben ins Bild */
978 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
986 else if (y > BY2) /* Element kommt von unten ins Bild */
992 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
998 else if (dy > 0 && cut_mode == CUT_ABOVE)
1000 if (y == BY2) /* Element unterhalb des Bildes */
1006 MarkTileDirty(x, y + 1);
1007 } /* Element verläßt unten das Bild */
1008 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1010 else if (dy) /* allg. Bewegung in y-Richtung */
1011 MarkTileDirty(x, y + SIGN(dy));
1014 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
1015 src_pixmap = pix[pixmap_nr];
1016 drawing_gc = clip_gc[pixmap_nr];
1021 dest_x = FX + x * TILEX + dx;
1022 dest_y = FY + y * TILEY + dy;
1025 if (!IN_SCR_FIELD(x,y))
1027 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1028 printf("DrawGraphicShifted(): This should never happen!\n");
1033 if (mask_mode == USE_MASKING)
1035 if (tile_clipmask[tile] != None)
1037 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
1038 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1039 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1040 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1045 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1048 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1049 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1050 src_x, src_y, width, height, dest_x, dest_y);
1054 XCopyArea(display, src_pixmap, drawto_field, gc,
1055 src_x, src_y, width, height, dest_x, dest_y);
1060 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1063 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1066 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1067 int cut_mode, int mask_mode)
1069 int ux = LEVELX(x), uy = LEVELY(y);
1070 int graphic = el2gfx(element);
1071 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1072 int phase4 = phase8 / 2;
1073 int phase2 = phase8 / 4;
1074 int dir = MovDir[ux][uy];
1076 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1078 graphic += 4 * !phase2;
1082 else if (dir == MV_LEFT)
1084 else if (dir == MV_DOWN)
1087 else if (element == EL_SP_SNIKSNAK)
1090 graphic = GFX_SP_SNIKSNAK_LEFT;
1091 else if (dir == MV_RIGHT)
1092 graphic = GFX_SP_SNIKSNAK_RIGHT;
1093 else if (dir == MV_UP)
1094 graphic = GFX_SP_SNIKSNAK_UP;
1096 graphic = GFX_SP_SNIKSNAK_DOWN;
1098 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1100 else if (element == EL_SP_ELECTRON)
1102 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1104 else if (element == EL_MOLE || element == EL_PINGUIN ||
1105 element == EL_SCHWEIN || element == EL_DRACHE)
1108 graphic = (element == EL_MOLE ? GFX_MOLE_LEFT :
1109 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1110 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1111 else if (dir == MV_RIGHT)
1112 graphic = (element == EL_MOLE ? GFX_MOLE_RIGHT :
1113 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1114 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1115 else if (dir == MV_UP)
1116 graphic = (element == EL_MOLE ? GFX_MOLE_UP :
1117 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1118 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1120 graphic = (element == EL_MOLE ? GFX_MOLE_DOWN :
1121 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1122 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1126 else if (element == EL_SONDE)
1128 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1130 else if (element == EL_SALZSAEURE)
1132 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1134 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1138 else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
1139 IS_GEM(element)) && !cut_mode)
1141 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1143 if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
1146 graphic += (4 - phase4) % 4;
1147 else if (dir == MV_RIGHT)
1150 graphic += phase2 * 2;
1152 else if (element != EL_SP_INFOTRON)
1156 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1157 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1159 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1161 else if (IS_AMOEBOID(element))
1163 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1164 graphic += (x + 2 * y + 4) % 4;
1166 else if (element == EL_MAUER_LEBT)
1168 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1170 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1171 links_massiv = TRUE;
1172 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1173 rechts_massiv = TRUE;
1175 if (links_massiv && rechts_massiv)
1176 graphic = GFX_MAUERWERK;
1177 else if (links_massiv)
1178 graphic = GFX_MAUER_R;
1179 else if (rechts_massiv)
1180 graphic = GFX_MAUER_L;
1182 else if ((element == EL_INVISIBLE_STEEL ||
1183 element == EL_UNSICHTBAR ||
1184 element == EL_SAND_INVISIBLE) && game.light_time_left)
1186 graphic = (element == EL_INVISIBLE_STEEL ? GFX_INVISIBLE_STEEL_ON :
1187 element == EL_UNSICHTBAR ? GFX_UNSICHTBAR_ON :
1188 GFX_SAND_INVISIBLE_ON);
1192 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1193 else if (mask_mode == USE_MASKING)
1194 DrawGraphicThruMask(x, y, graphic);
1196 DrawGraphic(x, y, graphic);
1199 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1200 int cut_mode, int mask_mode)
1202 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1203 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1204 cut_mode, mask_mode);
1207 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1210 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1213 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1216 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1219 void DrawScreenElementThruMask(int x, int y, int element)
1221 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1224 void DrawLevelElementThruMask(int x, int y, int element)
1226 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1229 void DrawLevelFieldThruMask(int x, int y)
1231 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1234 void ErdreichAnbroeckeln(int x, int y)
1236 int i, width, height, cx,cy;
1237 int ux = LEVELX(x), uy = LEVELY(y);
1238 int element, graphic;
1240 static int xy[4][2] =
1248 if (!IN_LEV_FIELD(ux, uy))
1251 element = Feld[ux][uy];
1253 if (element == EL_ERDREICH || element == EL_LANDMINE)
1255 if (!IN_SCR_FIELD(x, y))
1258 graphic = GFX_ERDENRAND;
1264 uxx = ux + xy[i][0];
1265 uyy = uy + xy[i][1];
1266 if (!IN_LEV_FIELD(uxx, uyy))
1269 element = Feld[uxx][uyy];
1271 if (element == EL_ERDREICH || element == EL_LANDMINE)
1274 if (i == 1 || i == 2)
1278 cx = (i == 2 ? TILEX - snip : 0);
1286 cy = (i == 3 ? TILEY - snip : 0);
1289 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1290 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1291 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1292 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1295 MarkTileDirty(x, y);
1299 graphic = GFX_ERDENRAND;
1303 int xx, yy, uxx, uyy;
1307 uxx = ux + xy[i][0];
1308 uyy = uy + xy[i][1];
1310 if (!IN_LEV_FIELD(uxx, uyy) ||
1311 (Feld[uxx][uyy] != EL_ERDREICH && Feld[uxx][uyy] != EL_LANDMINE) ||
1312 !IN_SCR_FIELD(xx, yy))
1315 if (i == 1 || i == 2)
1319 cx = (i == 1 ? TILEX - snip : 0);
1327 cy = (i==0 ? TILEY-snip : 0);
1330 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1331 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1332 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1333 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1335 MarkTileDirty(xx, yy);
1340 void DrawScreenElement(int x, int y, int element)
1342 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1343 ErdreichAnbroeckeln(x, y);
1346 void DrawLevelElement(int x, int y, int element)
1348 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1349 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1352 void DrawScreenField(int x, int y)
1354 int ux = LEVELX(x), uy = LEVELY(y);
1357 if (!IN_LEV_FIELD(ux, uy))
1359 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1360 element = EL_LEERRAUM;
1362 element = BorderElement;
1364 DrawScreenElement(x, y, element);
1368 element = Feld[ux][uy];
1370 if (IS_MOVING(ux, uy))
1372 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1373 boolean cut_mode = NO_CUTTING;
1375 if (Store[ux][uy] == EL_MORAST_LEER ||
1376 Store[ux][uy] == EL_SIEB_LEER ||
1377 Store[ux][uy] == EL_SIEB2_LEER ||
1378 Store[ux][uy] == EL_AMOEBE_NASS)
1379 cut_mode = CUT_ABOVE;
1380 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1381 Store[ux][uy] == EL_SIEB_VOLL ||
1382 Store[ux][uy] == EL_SIEB2_VOLL)
1383 cut_mode = CUT_BELOW;
1385 if (cut_mode == CUT_ABOVE)
1386 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1388 DrawScreenElement(x, y, EL_LEERRAUM);
1391 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1393 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1395 if (Store[ux][uy] == EL_SALZSAEURE)
1396 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1398 else if (IS_BLOCKED(ux, uy))
1403 boolean cut_mode = NO_CUTTING;
1405 Blocked2Moving(ux, uy, &oldx, &oldy);
1408 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1409 MovDir[oldx][oldy] == MV_RIGHT);
1411 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1412 Store[oldx][oldy] == EL_SIEB_LEER ||
1413 Store[oldx][oldy] == EL_SIEB2_LEER ||
1414 Store[oldx][oldy] == EL_AMOEBE_NASS)
1415 cut_mode = CUT_ABOVE;
1417 DrawScreenElement(x, y, EL_LEERRAUM);
1418 element = Feld[oldx][oldy];
1421 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1423 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1425 else if (IS_DRAWABLE(element))
1426 DrawScreenElement(x, y, element);
1428 DrawScreenElement(x, y, EL_LEERRAUM);
1431 void DrawLevelField(int x, int y)
1433 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1434 DrawScreenField(SCREENX(x), SCREENY(y));
1435 else if (IS_MOVING(x, y))
1439 Moving2Blocked(x, y, &newx, &newy);
1440 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1441 DrawScreenField(SCREENX(newx), SCREENY(newy));
1443 else if (IS_BLOCKED(x, y))
1447 Blocked2Moving(x, y, &oldx, &oldy);
1448 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1449 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1453 void DrawMiniElement(int x, int y, int element)
1459 DrawMiniGraphic(x, y, -1);
1463 graphic = el2gfx(element);
1464 DrawMiniGraphic(x, y, graphic);
1467 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1469 int x = sx + scroll_x, y = sy + scroll_y;
1471 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1472 DrawMiniElement(sx, sy, EL_LEERRAUM);
1473 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1474 DrawMiniElement(sx, sy, Feld[x][y]);
1477 int steel_type, steel_position;
1480 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1481 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1482 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1483 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1484 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1485 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1488 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1489 steel_position = (x == -1 && y == -1 ? 0 :
1490 x == lev_fieldx && y == -1 ? 1 :
1491 x == -1 && y == lev_fieldy ? 2 :
1492 x == lev_fieldx && y == lev_fieldy ? 3 :
1493 x == -1 || x == lev_fieldx ? 4 :
1494 y == -1 || y == lev_fieldy ? 5 : -1);
1496 if (steel_position != -1)
1497 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1501 void DrawMicroElement(int xpos, int ypos, int element)
1505 if (element == EL_LEERRAUM)
1508 graphic = el2gfx(element);
1510 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1512 graphic -= GFX_START_ROCKSSP;
1513 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
1514 XCopyArea(display, pix[PIX_SP], drawto, gc,
1515 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
1516 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
1517 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1519 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1521 graphic -= GFX_START_ROCKSDC;
1522 XCopyArea(display, pix[PIX_DC], drawto, gc,
1523 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
1524 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
1525 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1528 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1529 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1530 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1531 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1540 for(x=BX1; x<=BX2; x++)
1541 for(y=BY1; y<=BY2; y++)
1542 DrawScreenField(x, y);
1544 redraw_mask |= REDRAW_FIELD;
1547 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1551 for(x=0; x<size_x; x++)
1552 for(y=0; y<size_y; y++)
1553 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1555 redraw_mask |= REDRAW_FIELD;
1558 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1562 XFillRectangle(display, drawto, gc,
1563 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1565 if (lev_fieldx < STD_LEV_FIELDX)
1566 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1567 if (lev_fieldy < STD_LEV_FIELDY)
1568 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1570 xpos += MICRO_TILEX;
1571 ypos += MICRO_TILEY;
1573 for(x=-1; x<=STD_LEV_FIELDX; x++)
1575 for(y=-1; y<=STD_LEV_FIELDY; y++)
1577 int lx = from_x + x, ly = from_y + y;
1579 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1580 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1582 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1583 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1588 redraw_mask |= REDRAW_MICROLEVEL;
1591 #define MICROLABEL_EMPTY 0
1592 #define MICROLABEL_LEVEL_NAME 1
1593 #define MICROLABEL_CREATED_BY 2
1594 #define MICROLABEL_LEVEL_AUTHOR 3
1595 #define MICROLABEL_IMPORTED_FROM 4
1596 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1598 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1600 static void DrawMicroLevelLabelExt(int mode)
1602 char label_text[MAX_MICROLABEL_SIZE + 1];
1604 XFillRectangle(display, drawto,gc,
1605 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1607 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1608 mode == MICROLABEL_CREATED_BY ? "created by" :
1609 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1610 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1611 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1612 leveldir[leveldir_nr].imported_from : ""),
1613 MAX_MICROLABEL_SIZE);
1614 label_text[MAX_MICROLABEL_SIZE] = '\0';
1616 if (strlen(label_text) > 0)
1618 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1619 int lypos = MICROLABEL_YPOS;
1621 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1624 redraw_mask |= REDRAW_MICROLEVEL;
1627 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1629 static unsigned long scroll_delay = 0;
1630 static unsigned long label_delay = 0;
1631 static int from_x, from_y, scroll_direction;
1632 static int label_state, label_counter;
1636 from_x = from_y = 0;
1637 scroll_direction = MV_RIGHT;
1641 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1642 DrawMicroLevelLabelExt(label_state);
1644 /* initialize delay counters */
1645 DelayReached(&scroll_delay, 0);
1646 DelayReached(&label_delay, 0);
1651 /* scroll micro level, if needed */
1652 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1653 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1655 switch (scroll_direction)
1661 scroll_direction = MV_UP;
1665 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1668 scroll_direction = MV_DOWN;
1675 scroll_direction = MV_RIGHT;
1679 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1682 scroll_direction = MV_LEFT;
1689 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1692 /* redraw micro level label, if needed */
1693 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1694 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1695 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1696 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1698 int max_label_counter = 23;
1700 if (leveldir[leveldir_nr].imported_from != NULL)
1701 max_label_counter += 14;
1703 label_counter = (label_counter + 1) % max_label_counter;
1704 label_state = (label_counter >= 0 && label_counter <= 7 ?
1705 MICROLABEL_LEVEL_NAME :
1706 label_counter >= 9 && label_counter <= 12 ?
1707 MICROLABEL_CREATED_BY :
1708 label_counter >= 14 && label_counter <= 21 ?
1709 MICROLABEL_LEVEL_AUTHOR :
1710 label_counter >= 23 && label_counter <= 26 ?
1711 MICROLABEL_IMPORTED_FROM :
1712 label_counter >= 28 && label_counter <= 35 ?
1713 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1714 DrawMicroLevelLabelExt(label_state);
1718 int REQ_in_range(int x, int y)
1720 if (y > DY+249 && y < DY+278)
1722 if (x > DX+1 && x < DX+48)
1724 else if (x > DX+51 && x < DX+98)
1730 boolean Request(char *text, unsigned int req_state)
1732 int mx, my, ty, result = -1;
1733 unsigned int old_door_state;
1736 /* pause network game while waiting for request to answer */
1737 if (options.network &&
1738 game_status == PLAYING &&
1739 req_state & REQUEST_WAIT_FOR)
1740 SendToServer_PausePlaying();
1743 old_door_state = GetDoorState();
1747 CloseDoor(DOOR_CLOSE_1);
1749 /* save old door content */
1750 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1751 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1752 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1754 /* clear door drawing field */
1755 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1757 /* write text for request */
1758 for(ty=0; ty<13; ty++)
1766 for(tl=0,tx=0; tx<7; tl++,tx++)
1769 if (!tc || tc == 32)
1780 DrawTextExt(drawto, gc,
1781 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1782 txt, FS_SMALL, FC_YELLOW);
1783 text += tl + (tc == 32 ? 1 : 0);
1786 if (req_state & REQ_ASK)
1788 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1789 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1791 else if (req_state & REQ_CONFIRM)
1793 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1795 else if (req_state & REQ_PLAYER)
1797 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1798 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1799 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1800 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1803 /* copy request gadgets to door backbuffer */
1804 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1805 DX, DY, DXSIZE, DYSIZE,
1806 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1808 OpenDoor(DOOR_OPEN_1);
1814 if (!(req_state & REQUEST_WAIT_FOR))
1817 if (game_status != MAINMENU)
1820 button_status = MB_RELEASED;
1822 request_gadget_id = -1;
1826 if (XPending(display))
1830 XNextEvent(display, &event);
1838 if (event.type == MotionNotify)
1845 if (!XQueryPointer(display, window, &root, &child,
1846 &root_x, &root_y, &win_x, &win_y, &mask))
1852 motion_status = TRUE;
1853 mx = ((XMotionEvent *) &event)->x;
1854 my = ((XMotionEvent *) &event)->y;
1858 motion_status = FALSE;
1859 mx = ((XButtonEvent *) &event)->x;
1860 my = ((XButtonEvent *) &event)->y;
1861 if (event.type==ButtonPress)
1862 button_status = ((XButtonEvent *) &event)->button;
1864 button_status = MB_RELEASED;
1867 /* this sets 'request_gadget_id' */
1868 HandleGadgets(mx, my, button_status);
1870 switch(request_gadget_id)
1872 case TOOL_CTRL_ID_YES:
1875 case TOOL_CTRL_ID_NO:
1878 case TOOL_CTRL_ID_CONFIRM:
1879 result = TRUE | FALSE;
1882 case TOOL_CTRL_ID_PLAYER_1:
1885 case TOOL_CTRL_ID_PLAYER_2:
1888 case TOOL_CTRL_ID_PLAYER_3:
1891 case TOOL_CTRL_ID_PLAYER_4:
1903 switch(XLookupKeysym((XKeyEvent *)&event,
1904 ((XKeyEvent *)&event)->state))
1917 if (req_state & REQ_PLAYER)
1922 key_joystick_mapping = 0;
1926 HandleOtherEvents(&event);
1930 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1932 int joy = AnyJoystick();
1934 if (joy & JOY_BUTTON_1)
1936 else if (joy & JOY_BUTTON_2)
1942 /* don't eat all CPU time */
1946 if (game_status != MAINMENU)
1951 if (!(req_state & REQ_STAY_OPEN))
1953 CloseDoor(DOOR_CLOSE_1);
1955 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1957 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1958 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1959 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1960 OpenDoor(DOOR_OPEN_1);
1967 /* continue network game after request */
1968 if (options.network &&
1969 game_status == PLAYING &&
1970 req_state & REQUEST_WAIT_FOR)
1971 SendToServer_ContinuePlaying();
1977 unsigned int OpenDoor(unsigned int door_state)
1979 unsigned int new_door_state;
1981 if (door_state & DOOR_COPY_BACK)
1983 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1984 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1985 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1986 door_state &= ~DOOR_COPY_BACK;
1989 new_door_state = MoveDoor(door_state);
1991 return(new_door_state);
1994 unsigned int CloseDoor(unsigned int door_state)
1996 unsigned int new_door_state;
1998 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1999 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2000 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2001 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2003 new_door_state = MoveDoor(door_state);
2005 return(new_door_state);
2008 unsigned int GetDoorState()
2010 return(MoveDoor(DOOR_GET_STATE));
2013 unsigned int MoveDoor(unsigned int door_state)
2015 static int door1 = DOOR_OPEN_1;
2016 static int door2 = DOOR_CLOSE_2;
2017 static unsigned long door_delay = 0;
2018 int x, start, stepsize = 2;
2019 unsigned long door_delay_value = stepsize * 5;
2021 if (door_state == DOOR_GET_STATE)
2022 return(door1 | door2);
2024 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2025 door_state &= ~DOOR_OPEN_1;
2026 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2027 door_state &= ~DOOR_CLOSE_1;
2028 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2029 door_state &= ~DOOR_OPEN_2;
2030 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2031 door_state &= ~DOOR_CLOSE_2;
2033 if (setup.quick_doors)
2036 door_delay_value = 0;
2037 StopSound(SND_OEFFNEN);
2040 if (door_state & DOOR_ACTION)
2042 if (!(door_state & DOOR_NO_DELAY))
2043 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2045 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2047 for(x=start; x<=DXSIZE; x+=stepsize)
2049 WaitUntilDelayReached(&door_delay, door_delay_value);
2051 if (door_state & DOOR_ACTION_1)
2053 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2054 int j = (DXSIZE - i) / 3;
2056 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2057 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2058 DXSIZE,DYSIZE - i/2, DX, DY);
2060 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2062 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2063 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2064 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2065 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2066 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2067 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2069 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2070 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2071 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2072 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2073 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2074 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2076 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2077 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2079 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2080 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2082 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2083 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2084 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2085 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2086 DX + DXSIZE - i, DY + 77 + j);
2087 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2088 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2089 DX + DXSIZE - i, DY + 203 + j);
2091 redraw_mask |= REDRAW_DOOR_1;
2094 if (door_state & DOOR_ACTION_2)
2096 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2097 int j = (VXSIZE - i) / 3;
2099 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2100 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2101 VXSIZE, VYSIZE - i/2, VX, VY);
2103 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2105 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2106 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2107 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2108 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2109 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2110 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2111 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2112 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2114 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2115 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2116 VX, VY + VYSIZE / 2 - j);
2117 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2118 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2119 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2120 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2121 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2123 redraw_mask |= REDRAW_DOOR_2;
2128 if (game_status == MAINMENU)
2133 if (setup.quick_doors)
2134 StopSound(SND_OEFFNEN);
2136 if (door_state & DOOR_ACTION_1)
2137 door1 = door_state & DOOR_ACTION_1;
2138 if (door_state & DOOR_ACTION_2)
2139 door2 = door_state & DOOR_ACTION_2;
2141 return (door1 | door2);
2144 void DrawSpecialEditorDoor()
2146 /* draw bigger toolbox window */
2147 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2148 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2150 redraw_mask |= REDRAW_ALL;
2153 void UndrawSpecialEditorDoor()
2155 /* draw normal tape recorder window */
2156 XCopyArea(display, pix[PIX_BACK], drawto, gc,
2157 562, 344, 108, 56, EX - 4, EY - 12);
2159 redraw_mask |= REDRAW_ALL;
2162 int ReadPixel(Drawable d, int x, int y)
2164 XImage *pixel_image;
2165 unsigned long pixel_value;
2167 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2168 pixel_value = XGetPixel(pixel_image, 0, 0);
2170 XDestroyImage(pixel_image);
2175 /* ---------- new tool button stuff ---------------------------------------- */
2177 /* graphic position values for tool buttons */
2178 #define TOOL_BUTTON_YES_XPOS 2
2179 #define TOOL_BUTTON_YES_YPOS 250
2180 #define TOOL_BUTTON_YES_GFX_YPOS 0
2181 #define TOOL_BUTTON_YES_XSIZE 46
2182 #define TOOL_BUTTON_YES_YSIZE 28
2183 #define TOOL_BUTTON_NO_XPOS 52
2184 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2185 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2186 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2187 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2188 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2189 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2190 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2191 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2192 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2193 #define TOOL_BUTTON_PLAYER_XSIZE 30
2194 #define TOOL_BUTTON_PLAYER_YSIZE 30
2195 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2196 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2197 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2198 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2199 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2200 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2201 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2202 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2203 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2204 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2205 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2206 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2207 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2208 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2209 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2210 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2211 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2212 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2213 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2214 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2223 } toolbutton_info[NUM_TOOL_BUTTONS] =
2226 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2227 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2228 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2233 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2234 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2235 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2240 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2241 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2242 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2243 TOOL_CTRL_ID_CONFIRM,
2247 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2248 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2249 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2250 TOOL_CTRL_ID_PLAYER_1,
2254 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2255 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2256 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2257 TOOL_CTRL_ID_PLAYER_2,
2261 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2262 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2263 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2264 TOOL_CTRL_ID_PLAYER_3,
2268 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2269 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2270 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2271 TOOL_CTRL_ID_PLAYER_4,
2276 static void DoNotDisplayInfoText(void *ptr)
2281 void CreateToolButtons()
2285 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2287 Pixmap gd_pixmap = pix[PIX_DOOR];
2288 Pixmap deco_pixmap = None;
2289 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2290 struct GadgetInfo *gi;
2291 unsigned long event_mask;
2292 int gd_xoffset, gd_yoffset;
2293 int gd_x1, gd_x2, gd_y;
2296 event_mask = GD_EVENT_RELEASED;
2298 gd_xoffset = toolbutton_info[i].xpos;
2299 gd_yoffset = toolbutton_info[i].ypos;
2300 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2301 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2302 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2304 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2306 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2307 &deco_pixmap, &deco_x, &deco_y);
2308 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2309 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2312 gi = CreateGadget(GDI_CUSTOM_ID, id,
2313 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2314 GDI_X, DX + toolbutton_info[i].x,
2315 GDI_Y, DY + toolbutton_info[i].y,
2316 GDI_WIDTH, toolbutton_info[i].width,
2317 GDI_HEIGHT, toolbutton_info[i].height,
2318 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2319 GDI_STATE, GD_BUTTON_UNPRESSED,
2320 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2321 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2322 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2323 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2324 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2325 GDI_DECORATION_SHIFTING, 1, 1,
2326 GDI_EVENT_MASK, event_mask,
2327 GDI_CALLBACK_ACTION, HandleToolButtons,
2328 GDI_CALLBACK_INFO, DoNotDisplayInfoText,
2332 Error(ERR_EXIT, "cannot create gadget");
2334 tool_gadget[id] = gi;
2338 static void UnmapToolButtons()
2342 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2343 UnmapGadget(tool_gadget[i]);
2346 static void HandleToolButtons(struct GadgetInfo *gi)
2348 request_gadget_id = gi->custom_id;
2351 int el2gfx(int element)
2355 case EL_LEERRAUM: return -1;
2356 case EL_ERDREICH: return GFX_ERDREICH;
2357 case EL_MAUERWERK: return GFX_MAUERWERK;
2358 case EL_FELSBODEN: return GFX_FELSBODEN;
2359 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2360 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2361 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2362 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2363 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2364 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2365 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2366 case EL_SPIELER1: return GFX_SPIELER1;
2367 case EL_SPIELER2: return GFX_SPIELER2;
2368 case EL_SPIELER3: return GFX_SPIELER3;
2369 case EL_SPIELER4: return GFX_SPIELER4;
2370 case EL_KAEFER: return GFX_KAEFER;
2371 case EL_KAEFER_RIGHT: return GFX_KAEFER_RIGHT;
2372 case EL_KAEFER_UP: return GFX_KAEFER_UP;
2373 case EL_KAEFER_LEFT: return GFX_KAEFER_LEFT;
2374 case EL_KAEFER_DOWN: return GFX_KAEFER_DOWN;
2375 case EL_FLIEGER: return GFX_FLIEGER;
2376 case EL_FLIEGER_RIGHT: return GFX_FLIEGER_RIGHT;
2377 case EL_FLIEGER_UP: return GFX_FLIEGER_UP;
2378 case EL_FLIEGER_LEFT: return GFX_FLIEGER_LEFT;
2379 case EL_FLIEGER_DOWN: return GFX_FLIEGER_DOWN;
2380 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2381 case EL_BUTTERFLY_RIGHT: return GFX_BUTTERFLY_RIGHT;
2382 case EL_BUTTERFLY_UP: return GFX_BUTTERFLY_UP;
2383 case EL_BUTTERFLY_LEFT: return GFX_BUTTERFLY_LEFT;
2384 case EL_BUTTERFLY_DOWN: return GFX_BUTTERFLY_DOWN;
2385 case EL_FIREFLY: return GFX_FIREFLY;
2386 case EL_FIREFLY_RIGHT: return GFX_FIREFLY_RIGHT;
2387 case EL_FIREFLY_UP: return GFX_FIREFLY_UP;
2388 case EL_FIREFLY_LEFT: return GFX_FIREFLY_LEFT;
2389 case EL_FIREFLY_DOWN: return GFX_FIREFLY_DOWN;
2390 case EL_MAMPFER: return GFX_MAMPFER;
2391 case EL_ROBOT: return GFX_ROBOT;
2392 case EL_BETON: return GFX_BETON;
2393 case EL_DIAMANT: return GFX_DIAMANT;
2394 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2395 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2396 case EL_TROPFEN: return GFX_TROPFEN;
2397 case EL_BOMBE: return GFX_BOMBE;
2398 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2399 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2400 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2401 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2402 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2403 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2404 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2405 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2406 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2407 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2408 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2409 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2410 case EL_LIFE: return GFX_LIFE;
2411 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2412 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2413 case EL_BADEWANNE: return GFX_BADEWANNE;
2414 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2415 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2416 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2417 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2418 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2419 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2420 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2421 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2422 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2423 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2424 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2425 case EL_PFORTE1: return GFX_PFORTE1;
2426 case EL_PFORTE2: return GFX_PFORTE2;
2427 case EL_PFORTE3: return GFX_PFORTE3;
2428 case EL_PFORTE4: return GFX_PFORTE4;
2429 case EL_PFORTE1X: return GFX_PFORTE1X;
2430 case EL_PFORTE2X: return GFX_PFORTE2X;
2431 case EL_PFORTE3X: return GFX_PFORTE3X;
2432 case EL_PFORTE4X: return GFX_PFORTE4X;
2433 case EL_DYNAMITE_INACTIVE: return GFX_DYNAMIT_AUS;
2434 case EL_PACMAN: return GFX_PACMAN;
2435 case EL_PACMAN_RIGHT: return GFX_PACMAN_RIGHT;
2436 case EL_PACMAN_UP: return GFX_PACMAN_UP;
2437 case EL_PACMAN_LEFT: return GFX_PACMAN_LEFT;
2438 case EL_PACMAN_DOWN: return GFX_PACMAN_DOWN;
2439 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2440 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2441 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2442 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2443 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2444 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2445 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2446 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2447 case EL_MAUER_X: return GFX_MAUER_X;
2448 case EL_MAUER_Y: return GFX_MAUER_Y;
2449 case EL_MAUER_XY: return GFX_MAUER_XY;
2450 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2451 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2452 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2453 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2454 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2455 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2456 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2457 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2458 case EL_MAMPFER2: return GFX_MAMPFER2;
2459 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2460 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2461 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2462 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2463 case EL_DYNABOMB_ACTIVE_1: return GFX_DYNABOMB;
2464 case EL_DYNABOMB_ACTIVE_2: return GFX_DYNABOMB;
2465 case EL_DYNABOMB_ACTIVE_3: return GFX_DYNABOMB;
2466 case EL_DYNABOMB_ACTIVE_4: return GFX_DYNABOMB;
2467 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2468 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2469 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2470 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2471 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2472 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2473 case EL_MOLE: return GFX_MOLE;
2474 case EL_PINGUIN: return GFX_PINGUIN;
2475 case EL_SCHWEIN: return GFX_SCHWEIN;
2476 case EL_DRACHE: return GFX_DRACHE;
2477 case EL_SONDE: return GFX_SONDE;
2478 case EL_PFEIL_LEFT: return GFX_PFEIL_LEFT;
2479 case EL_PFEIL_RIGHT: return GFX_PFEIL_RIGHT;
2480 case EL_PFEIL_UP: return GFX_PFEIL_UP;
2481 case EL_PFEIL_DOWN: return GFX_PFEIL_DOWN;
2482 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2483 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2484 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2485 case EL_SP_ZONK: return GFX_SP_ZONK;
2486 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2487 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2488 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2489 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2490 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2491 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2492 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2493 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2494 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2495 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2496 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2497 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2498 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2499 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2500 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2501 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2502 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2503 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2504 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2505 case EL_PEARL: return GFX_PEARL;
2506 case EL_CRYSTAL: return GFX_CRYSTAL;
2507 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2508 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2509 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2510 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2511 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2512 case EL_SHIELD_PASSIVE: return GFX_SHIELD_PASSIVE;
2513 case EL_SHIELD_ACTIVE: return GFX_SHIELD_ACTIVE;
2514 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2515 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2516 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2517 case EL_SWITCHGATE_SWITCH_1:return GFX_SWITCHGATE_SWITCH_1;
2518 case EL_SWITCHGATE_SWITCH_2:return GFX_SWITCHGATE_SWITCH_2;
2519 case EL_BELT1_LEFT: return GFX_BELT1_LEFT;
2520 case EL_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2521 case EL_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2522 case EL_BELT1_SWITCH_LEFT: return GFX_BELT1_SWITCH_LEFT;
2523 case EL_BELT1_SWITCH_MIDDLE:return GFX_BELT1_SWITCH_MIDDLE;
2524 case EL_BELT1_SWITCH_RIGHT: return GFX_BELT1_SWITCH_RIGHT;
2525 case EL_BELT2_LEFT: return GFX_BELT2_LEFT;
2526 case EL_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2527 case EL_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2528 case EL_BELT2_SWITCH_LEFT: return GFX_BELT2_SWITCH_LEFT;
2529 case EL_BELT2_SWITCH_MIDDLE:return GFX_BELT2_SWITCH_MIDDLE;
2530 case EL_BELT2_SWITCH_RIGHT: return GFX_BELT2_SWITCH_RIGHT;
2531 case EL_BELT3_LEFT: return GFX_BELT3_LEFT;
2532 case EL_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2533 case EL_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2534 case EL_BELT3_SWITCH_LEFT: return GFX_BELT3_SWITCH_LEFT;
2535 case EL_BELT3_SWITCH_MIDDLE:return GFX_BELT3_SWITCH_MIDDLE;
2536 case EL_BELT3_SWITCH_RIGHT: return GFX_BELT3_SWITCH_RIGHT;
2537 case EL_BELT4_LEFT: return GFX_BELT4_LEFT;
2538 case EL_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2539 case EL_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2540 case EL_BELT4_SWITCH_LEFT: return GFX_BELT4_SWITCH_LEFT;
2541 case EL_BELT4_SWITCH_MIDDLE:return GFX_BELT4_SWITCH_MIDDLE;
2542 case EL_BELT4_SWITCH_RIGHT: return GFX_BELT4_SWITCH_RIGHT;
2543 case EL_LANDMINE: return GFX_LANDMINE;
2544 case EL_ENVELOPE: return GFX_ENVELOPE;
2545 case EL_LIGHT_SWITCH_OFF: return GFX_LIGHT_SWITCH_OFF;
2546 case EL_LIGHT_SWITCH_ON: return GFX_LIGHT_SWITCH_ON;
2547 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2548 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2549 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2550 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2551 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2552 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2553 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2554 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2555 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2556 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2557 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2558 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2559 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2560 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2561 case EL_MOLE_UP: return GFX_MOLE_UP;
2562 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2563 case EL_STEEL_SLANTED: return GFX_STEEL_SLANTED;
2564 case EL_SAND_INVISIBLE: return GFX_SAND_INVISIBLE;
2565 case EL_DX_UNKNOWN_15: return GFX_DX_UNKNOWN_15;
2566 case EL_DX_UNKNOWN_42: return GFX_DX_UNKNOWN_42;
2567 case EL_TIMEGATE_OPEN: return GFX_TIMEGATE_OPEN;
2568 case EL_TIMEGATE_CLOSED: return GFX_TIMEGATE_CLOSED;
2569 case EL_TIMEGATE_SWITCH_ON: return GFX_TIMEGATE_SWITCH;
2570 case EL_TIMEGATE_SWITCH_OFF:return GFX_TIMEGATE_SWITCH;
2574 if (IS_CHAR(element))
2575 return GFX_CHAR_START + (element - EL_CHAR_START);
2576 else if (element >= EL_SP_START && element <= EL_SP_END)
2578 int nr_element = element - EL_SP_START;
2579 int gfx_per_line = 8;
2581 (nr_element / gfx_per_line) * SP_PER_LINE +
2582 (nr_element % gfx_per_line);
2584 return GFX_START_ROCKSSP + nr_graphic;