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 UnmapToolButtons();
48 static void HandleToolButtons(struct GadgetInfo *);
50 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
51 static int request_gadget_id = -1;
53 void SetDrawtoField(int mode)
55 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
66 drawto_field = fieldbuffer;
68 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
79 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
86 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
88 if (setup.direct_draw && game_status == PLAYING)
89 redraw_mask &= ~REDRAW_MAIN;
91 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
92 redraw_mask |= REDRAW_FIELD;
94 if (redraw_mask & REDRAW_FIELD)
95 redraw_mask &= ~REDRAW_TILES;
100 /* synchronize X11 graphics at this point; if we would synchronize the
101 display immediately after the buffer switching (after the XFlush),
102 this could mean that we have to wait for the graphics to complete,
103 although we could go on doing calculations for the next frame */
105 XSync(display, FALSE);
107 if (redraw_mask & REDRAW_ALL)
109 XCopyArea(display, backbuffer, window, gc,
110 0, 0, WIN_XSIZE, WIN_YSIZE,
115 if (redraw_mask & REDRAW_FIELD)
117 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
119 XCopyArea(display, backbuffer, window, gc,
120 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
125 int fx = FX, fy = FY;
127 if (setup.soft_scrolling)
129 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
130 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
133 if (setup.soft_scrolling ||
134 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
135 ABS(ScreenMovPos) == ScrollStepSize ||
136 redraw_tiles > REDRAWTILES_THRESHOLD)
138 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
142 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
144 (setup.soft_scrolling ?
145 "setup.soft_scrolling" :
146 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
147 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
148 ABS(ScreenGfxPos) == ScrollStepSize ?
149 "ABS(ScreenGfxPos) == ScrollStepSize" :
150 "redraw_tiles > REDRAWTILES_THRESHOLD"));
155 redraw_mask &= ~REDRAW_MAIN;
158 if (redraw_mask & REDRAW_DOORS)
160 if (redraw_mask & REDRAW_DOOR_1)
161 XCopyArea(display, backbuffer, window, gc,
162 DX, DY, DXSIZE, DYSIZE,
164 if (redraw_mask & REDRAW_DOOR_2)
166 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
167 XCopyArea(display,backbuffer,window,gc,
168 VX,VY, VXSIZE,VYSIZE,
172 if (redraw_mask & REDRAW_VIDEO_1)
173 XCopyArea(display,backbuffer,window,gc,
174 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
175 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
176 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
177 if (redraw_mask & REDRAW_VIDEO_2)
178 XCopyArea(display,backbuffer,window,gc,
179 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
180 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
181 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
182 if (redraw_mask & REDRAW_VIDEO_3)
183 XCopyArea(display,backbuffer,window,gc,
184 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
185 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
186 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
189 if (redraw_mask & REDRAW_DOOR_3)
190 XCopyArea(display, backbuffer, window, gc,
191 EX, EY, EXSIZE, EYSIZE,
193 redraw_mask &= ~REDRAW_DOORS;
196 if (redraw_mask & REDRAW_MICROLEVEL)
198 XCopyArea(display,backbuffer,window,gc,
199 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
200 MICROLEV_XPOS, MICROLEV_YPOS);
201 XCopyArea(display,backbuffer,window,gc,
202 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
203 SX, MICROLABEL_YPOS);
204 redraw_mask &= ~REDRAW_MICROLEVEL;
207 if (redraw_mask & REDRAW_TILES)
209 for(x=0; x<SCR_FIELDX; x++)
210 for(y=0; y<SCR_FIELDY; y++)
211 if (redraw[redraw_x1 + x][redraw_y1 + y])
212 XCopyArea(display, buffer, window, gc,
213 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
214 SX + x * TILEX, SY + y * TILEY);
219 for(x=0; x<MAX_BUF_XSIZE; x++)
220 for(y=0; y<MAX_BUF_YSIZE; y++)
229 long fading_delay = 300;
231 if (setup.fading && (redraw_mask & REDRAW_FIELD))
238 XFillRectangle(display,window,gc,
239 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
242 for(i=0;i<2*FULL_SYSIZE;i++)
244 for(y=0;y<FULL_SYSIZE;y++)
246 XCopyArea(display,backbuffer,window,gc,
247 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
255 for(i=1;i<FULL_SYSIZE;i+=2)
256 XCopyArea(display,backbuffer,window,gc,
257 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
263 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
264 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
265 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
269 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
270 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
271 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
275 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
276 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
277 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
281 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
282 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
283 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
287 redraw_mask &= ~REDRAW_MAIN;
296 XFillRectangle(display, backbuffer, gc,
297 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
299 if (setup.soft_scrolling && game_status == PLAYING)
301 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
302 SetDrawtoField(DRAW_BUFFERED);
305 SetDrawtoField(DRAW_BACKBUFFER);
307 if (setup.direct_draw && game_status == PLAYING)
309 XFillRectangle(display, window, gc,
310 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
311 SetDrawtoField(DRAW_DIRECT);
314 redraw_mask |= REDRAW_FIELD;
317 int getFontWidth(int font_size, int font_type)
319 return (font_size == FS_BIG ? FONT1_XSIZE :
320 font_type == FC_SPECIAL1 ? FONT3_XSIZE :
321 font_type == FC_SPECIAL2 ? FONT4_XSIZE :
322 font_type == FC_SPECIAL3 ? FONT5_XSIZE :
326 int getFontHeight(int font_size, int font_type)
328 return (font_size == FS_BIG ? FONT1_YSIZE :
329 font_type == FC_SPECIAL1 ? FONT3_YSIZE :
330 font_type == FC_SPECIAL2 ? FONT4_YSIZE :
331 font_type == FC_SPECIAL3 ? FONT5_YSIZE :
335 void DrawTextFCentered(int y, int font_type, char *format, ...)
337 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
338 int font_width = getFontWidth(FS_SMALL, font_type);
341 va_start(ap, format);
342 vsprintf(buffer, format, ap);
345 DrawText(SX + (SXSIZE - strlen(buffer) * font_width) / 2, SY + y,
346 buffer, FS_SMALL, font_type);
349 void DrawTextF(int x, int y, int font_type, char *format, ...)
351 char buffer[FULL_SXSIZE / FONT5_XSIZE + 10];
354 va_start(ap, format);
355 vsprintf(buffer, format, ap);
358 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
361 void DrawText(int x, int y, char *text, int font_size, int font_type)
363 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
366 redraw_mask |= REDRAW_FIELD;
368 redraw_mask |= REDRAW_DOOR_1;
371 void DrawTextExt(Drawable d, GC gc, int x, int y,
372 char *text, int font_size, int font_type)
374 int font_width, font_height, font_start;
376 boolean print_inverse = FALSE;
378 if (font_size != FS_SMALL && font_size != FS_BIG)
379 font_size = FS_SMALL;
380 if (font_type < FC_RED || font_type > FC_SPECIAL3)
383 font_width = getFontWidth(font_size, font_type);
384 font_height = getFontHeight(font_size, font_type);
386 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
387 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
388 FONT_LINES_PER_FONT);
390 if (font_type == FC_SPECIAL3)
391 font_start += (FONT4_YSIZE - FONT2_YSIZE) * FONT_LINES_PER_FONT;
397 if (c == '~' && font_size == FS_SMALL)
399 print_inverse = TRUE;
403 if (c >= 'a' && c <= 'z')
405 else if (c == 'ä' || c == 'Ä')
407 else if (c == 'ö' || c == 'Ö')
409 else if (c == 'ü' || c == 'Ü')
412 if (c >= 32 && c <= 95)
414 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
415 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
416 int dest_x = x, dest_y = y;
420 XCopyArea(display, pix[font_pixmap], d, gc,
421 FONT_CHARS_PER_LINE * font_width,
422 3 * font_height + font_start,
423 font_width, font_height, x, y);
425 XSetClipOrigin(display, clip_gc[font_pixmap],
426 dest_x - src_x, dest_y - src_y);
427 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
428 0, 0, font_width, font_height, dest_x, dest_y);
431 XCopyArea(display, pix[font_pixmap], d, gc,
432 src_x, src_y, font_width, font_height, dest_x, dest_y);
439 void DrawAllPlayers()
443 for(i=0; i<MAX_PLAYERS; i++)
444 if (stored_player[i].active)
445 DrawPlayer(&stored_player[i]);
448 void DrawPlayerField(int x, int y)
450 if (!IS_PLAYER(x, y))
453 DrawPlayer(PLAYERINFO(x, y));
456 void DrawPlayer(struct PlayerInfo *player)
458 int jx = player->jx, jy = player->jy;
459 int last_jx = player->last_jx, last_jy = player->last_jy;
460 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
461 int sx = SCREENX(jx), sy = SCREENY(jy);
462 int sxx = 0, syy = 0;
463 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
465 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
467 if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
471 if (!IN_LEV_FIELD(jx,jy))
473 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
474 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
475 printf("DrawPlayerField(): This should never happen!\n");
480 if (element == EL_EXPLODING)
483 /* draw things in the field the player is leaving, if needed */
485 if (player_is_moving)
487 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
489 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
490 DrawLevelFieldThruMask(last_jx, last_jy);
492 else if (last_element == EL_DYNAMITE_ACTIVE)
493 DrawDynamite(last_jx, last_jy);
495 DrawLevelField(last_jx, last_jy);
497 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
501 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
502 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
504 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
507 DrawLevelField(next_jx, next_jy);
511 if (!IN_SCR_FIELD(sx, sy))
514 if (setup.direct_draw)
515 SetDrawtoField(DRAW_BUFFERED);
517 /* draw things behind the player, if needed */
520 DrawLevelElement(jx, jy, Store[jx][jy]);
521 else if (!IS_ACTIVE_BOMB(element))
522 DrawLevelField(jx, jy);
524 /* draw player himself */
526 if (game.emulation == EMU_SUPAPLEX)
528 static int last_dir = MV_LEFT;
529 int action = (player->programmed_action ? player->programmed_action :
531 boolean action_moving =
533 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
534 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
536 graphic = GFX_SP_MURPHY;
540 if (player->MovDir == MV_LEFT)
541 graphic = GFX_MURPHY_PUSH_LEFT;
542 else if (player->MovDir == MV_RIGHT)
543 graphic = GFX_MURPHY_PUSH_RIGHT;
544 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
545 graphic = GFX_MURPHY_PUSH_LEFT;
546 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
547 graphic = GFX_MURPHY_PUSH_RIGHT;
549 else if (player->snapped)
551 if (player->MovDir == MV_LEFT)
552 graphic = GFX_MURPHY_SNAP_LEFT;
553 else if (player->MovDir == MV_RIGHT)
554 graphic = GFX_MURPHY_SNAP_RIGHT;
555 else if (player->MovDir == MV_UP)
556 graphic = GFX_MURPHY_SNAP_UP;
557 else if (player->MovDir == MV_DOWN)
558 graphic = GFX_MURPHY_SNAP_DOWN;
560 else if (action_moving)
562 if (player->MovDir == MV_LEFT)
563 graphic = GFX_MURPHY_GO_LEFT;
564 else if (player->MovDir == MV_RIGHT)
565 graphic = GFX_MURPHY_GO_RIGHT;
566 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
567 graphic = GFX_MURPHY_GO_LEFT;
568 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
569 graphic = GFX_MURPHY_GO_RIGHT;
571 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
574 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
575 last_dir = player->MovDir;
579 if (player->MovDir == MV_LEFT)
581 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
582 else if (player->MovDir == MV_RIGHT)
584 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
585 else if (player->MovDir == MV_UP)
586 graphic = GFX_SPIELER1_UP;
587 else /* MV_DOWN || MV_NO_MOVING */
588 graphic = GFX_SPIELER1_DOWN;
590 graphic += player->index_nr * 3 * HEROES_PER_LINE;
591 graphic += player->Frame;
596 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
597 sxx = player->GfxPos;
599 syy = player->GfxPos;
602 if (!setup.soft_scrolling && ScreenMovPos)
605 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
607 if (player->Pushing && player->GfxPos)
609 int px = SCREENX(next_jx), py = SCREENY(next_jy);
611 if (element == EL_SOKOBAN_FELD_LEER ||
612 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
613 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
617 int element = Feld[next_jx][next_jy];
618 int graphic = el2gfx(element);
620 if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK) && sxx)
622 int phase = (player->GfxPos / (TILEX / 4));
624 if (player->MovDir == MV_LEFT)
627 graphic += (phase + 4) % 4;
630 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
634 /* draw things in front of player (active dynamite or dynabombs) */
636 if (IS_ACTIVE_BOMB(element))
638 graphic = el2gfx(element);
640 if (element == EL_DYNAMITE_ACTIVE)
642 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
647 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
651 if (game.emulation == EMU_SUPAPLEX)
652 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
654 DrawGraphicThruMask(sx, sy, graphic + phase);
657 if (player_is_moving && last_element == EL_EXPLODING)
659 int phase = Frame[last_jx][last_jy];
663 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
664 GFX_EXPLOSION + ((phase - 1) / delay - 1));
667 /* draw elements that stay over the player */
668 /* handle the field the player is leaving ... */
669 if (player_is_moving && IS_OVER_PLAYER(last_element))
670 DrawLevelField(last_jx, last_jy);
671 /* ... and the field the player is entering */
672 if (IS_OVER_PLAYER(element))
673 DrawLevelField(jx, jy);
675 if (setup.direct_draw)
677 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
678 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
679 int x_size = TILEX * (1 + ABS(jx - last_jx));
680 int y_size = TILEY * (1 + ABS(jy - last_jy));
682 XCopyArea(display, drawto_field, window, gc,
683 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
684 SetDrawtoField(DRAW_DIRECT);
687 MarkTileDirty(sx,sy);
690 static int getGraphicAnimationPhase(int frames, int delay, int mode)
694 if (mode == ANIM_OSCILLATE)
696 int max_anim_frames = 2 * frames - 2;
697 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
698 phase = (phase < frames ? phase : max_anim_frames - phase);
701 phase = (FrameCounter % (delay * frames)) / delay;
703 if (mode == ANIM_REVERSE)
709 void DrawGraphicAnimationExt(int x, int y, int graphic,
710 int frames, int delay, int mode, int mask_mode)
712 int phase = getGraphicAnimationPhase(frames, delay, mode);
714 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
716 if (mask_mode == USE_MASKING)
717 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
719 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
723 void DrawGraphicAnimation(int x, int y, int graphic,
724 int frames, int delay, int mode)
726 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
729 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
730 int frames, int delay, int mode)
732 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
735 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
737 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
739 graphic -= GFX_START_ROCKSSCREEN;
740 *pixmap_nr = PIX_BACK;
741 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
742 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
744 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
746 graphic -= GFX_START_ROCKSHEROES;
747 *pixmap_nr = PIX_HEROES;
748 *x = (graphic % HEROES_PER_LINE) * TILEX;
749 *y = (graphic / HEROES_PER_LINE) * TILEY;
751 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
753 graphic -= GFX_START_ROCKSSP;
755 *x = (graphic % SP_PER_LINE) * TILEX;
756 *y = (graphic / SP_PER_LINE) * TILEY;
758 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
760 graphic -= GFX_START_ROCKSDC;
762 *x = (graphic % DC_PER_LINE) * TILEX;
763 *y = (graphic / DC_PER_LINE) * TILEY;
765 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
767 graphic -= GFX_START_ROCKSFONT;
768 *pixmap_nr = PIX_BIGFONT;
769 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
770 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
771 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
781 void DrawGraphic(int x, int y, int graphic)
784 if (!IN_SCR_FIELD(x,y))
786 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
787 printf("DrawGraphic(): This should never happen!\n");
792 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
796 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
801 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
802 XCopyArea(display, pix[pixmap_nr], d, gc,
803 src_x, src_y, TILEX, TILEY, x, y);
806 void DrawGraphicThruMask(int x, int y, int graphic)
809 if (!IN_SCR_FIELD(x,y))
811 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
812 printf("DrawGraphicThruMask(): This should never happen!\n");
817 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
821 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
829 if (graphic == GFX_LEERRAUM)
832 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
833 src_pixmap = pix[pixmap_nr];
834 drawing_gc = clip_gc[pixmap_nr];
836 if (tile_clipmask[tile] != None)
838 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
839 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
840 XCopyArea(display, src_pixmap, d, tile_clip_gc,
841 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
846 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
849 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
850 XCopyArea(display, src_pixmap, d, drawing_gc,
851 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
855 void DrawMiniGraphic(int x, int y, int graphic)
857 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
858 MarkTileDirty(x/2, y/2);
861 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
863 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
865 graphic -= GFX_START_ROCKSSCREEN;
866 *pixmap = pix[PIX_BACK];
867 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
868 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
870 else if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
872 graphic -= GFX_START_ROCKSSP;
873 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
874 *pixmap = pix[PIX_SP];
875 *x = MINI_SP_STARTX + (graphic % MINI_SP_PER_LINE) * MINI_TILEX;
876 *y = MINI_SP_STARTY + (graphic / MINI_SP_PER_LINE) * MINI_TILEY;
878 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
880 graphic -= GFX_START_ROCKSDC;
881 *pixmap = pix[PIX_DC];
882 *x = MINI_DC_STARTX + (graphic % MINI_DC_PER_LINE) * MINI_TILEX;
883 *y = MINI_DC_STARTY + (graphic / MINI_DC_PER_LINE) * MINI_TILEY;
885 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
887 graphic -= GFX_START_ROCKSFONT;
888 *pixmap = pix[PIX_SMALLFONT];
889 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
890 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
891 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
895 *pixmap = pix[PIX_SP];
901 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
906 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
907 XCopyArea(display, pixmap, d, gc,
908 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
911 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
912 int cut_mode, int mask_mode)
914 int width = TILEX, height = TILEY;
916 int src_x, src_y, dest_x, dest_y;
924 DrawGraphic(x, y, graphic);
928 if (dx || dy) /* Verschiebung der Grafik? */
930 if (x < BX1) /* Element kommt von links ins Bild */
937 else if (x > BX2) /* Element kommt von rechts ins Bild */
943 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
949 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
951 else if (dx) /* allg. Bewegung in x-Richtung */
952 MarkTileDirty(x + SIGN(dx), y);
954 if (y < BY1) /* Element kommt von oben ins Bild */
956 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
964 else if (y > BY2) /* Element kommt von unten ins Bild */
970 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
976 else if (dy > 0 && cut_mode == CUT_ABOVE)
978 if (y == BY2) /* Element unterhalb des Bildes */
984 MarkTileDirty(x, y + 1);
985 } /* Element verläßt unten das Bild */
986 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
988 else if (dy) /* allg. Bewegung in y-Richtung */
989 MarkTileDirty(x, y + SIGN(dy));
992 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
993 src_pixmap = pix[pixmap_nr];
994 drawing_gc = clip_gc[pixmap_nr];
999 dest_x = FX + x * TILEX + dx;
1000 dest_y = FY + y * TILEY + dy;
1003 if (!IN_SCR_FIELD(x,y))
1005 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1006 printf("DrawGraphicShifted(): This should never happen!\n");
1011 if (mask_mode == USE_MASKING)
1013 if (tile_clipmask[tile] != None)
1015 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
1016 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1017 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1018 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1023 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1026 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1027 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1028 src_x, src_y, width, height, dest_x, dest_y);
1032 XCopyArea(display, src_pixmap, drawto_field, gc,
1033 src_x, src_y, width, height, dest_x, dest_y);
1038 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1041 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1044 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1045 int cut_mode, int mask_mode)
1047 int ux = LEVELX(x), uy = LEVELY(y);
1048 int graphic = el2gfx(element);
1049 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1050 int phase4 = phase8 / 2;
1051 int phase2 = phase8 / 4;
1052 int dir = MovDir[ux][uy];
1054 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1056 graphic += 4 * !phase2;
1060 else if (dir == MV_LEFT)
1062 else if (dir == MV_DOWN)
1065 else if (element == EL_SP_SNIKSNAK)
1068 graphic = GFX_SP_SNIKSNAK_LEFT;
1069 else if (dir == MV_RIGHT)
1070 graphic = GFX_SP_SNIKSNAK_RIGHT;
1071 else if (dir == MV_UP)
1072 graphic = GFX_SP_SNIKSNAK_UP;
1074 graphic = GFX_SP_SNIKSNAK_DOWN;
1076 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1078 else if (element == EL_SP_ELECTRON)
1080 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1082 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1083 element == EL_SCHWEIN || element == EL_DRACHE)
1086 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1087 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1088 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1089 else if (dir == MV_RIGHT)
1090 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1091 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1092 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1093 else if (dir == MV_UP)
1094 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1095 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1096 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1098 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1099 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1100 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1104 else if (element == EL_SONDE)
1106 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1108 else if (element == EL_SALZSAEURE)
1110 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1112 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1116 else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
1117 IS_GEM(element)) && !cut_mode)
1119 if (uy >= lev_fieldy-1 || !IS_BELT(Feld[ux][uy+1]))
1121 if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
1124 graphic += (4 - phase4) % 4;
1125 else if (dir == MV_RIGHT)
1128 graphic += phase2 * 2;
1130 else if (element != EL_SP_INFOTRON)
1134 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1135 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1137 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1139 else if (IS_AMOEBOID(element))
1141 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1142 graphic += (x + 2 * y + 4) % 4;
1144 else if (element == EL_MAUER_LEBT)
1146 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1148 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1149 links_massiv = TRUE;
1150 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1151 rechts_massiv = TRUE;
1153 if (links_massiv && rechts_massiv)
1154 graphic = GFX_MAUERWERK;
1155 else if (links_massiv)
1156 graphic = GFX_MAUER_R;
1157 else if (rechts_massiv)
1158 graphic = GFX_MAUER_L;
1162 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1163 else if (mask_mode == USE_MASKING)
1164 DrawGraphicThruMask(x, y, graphic);
1166 DrawGraphic(x, y, graphic);
1169 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1170 int cut_mode, int mask_mode)
1172 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1173 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1174 cut_mode, mask_mode);
1177 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1180 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1183 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1186 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1189 void DrawScreenElementThruMask(int x, int y, int element)
1191 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1194 void DrawLevelElementThruMask(int x, int y, int element)
1196 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1199 void DrawLevelFieldThruMask(int x, int y)
1201 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1204 void ErdreichAnbroeckeln(int x, int y)
1206 int i, width, height, cx,cy;
1207 int ux = LEVELX(x), uy = LEVELY(y);
1208 int element, graphic;
1210 static int xy[4][2] =
1218 if (!IN_LEV_FIELD(ux, uy))
1221 element = Feld[ux][uy];
1223 if (element == EL_ERDREICH)
1225 if (!IN_SCR_FIELD(x, y))
1228 graphic = GFX_ERDENRAND;
1234 uxx = ux + xy[i][0];
1235 uyy = uy + xy[i][1];
1236 if (!IN_LEV_FIELD(uxx, uyy))
1239 element = Feld[uxx][uyy];
1241 if (element == EL_ERDREICH)
1244 if (i == 1 || i == 2)
1248 cx = (i == 2 ? TILEX - snip : 0);
1256 cy = (i == 3 ? TILEY - snip : 0);
1259 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1260 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1261 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1262 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1265 MarkTileDirty(x, y);
1269 graphic = GFX_ERDENRAND;
1273 int xx, yy, uxx, uyy;
1277 uxx = ux + xy[i][0];
1278 uyy = uy + xy[i][1];
1280 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1281 !IN_SCR_FIELD(xx, yy))
1284 if (i == 1 || i == 2)
1288 cx = (i == 1 ? TILEX - snip : 0);
1296 cy = (i==0 ? TILEY-snip : 0);
1299 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1300 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1301 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1302 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1304 MarkTileDirty(xx, yy);
1309 void DrawScreenElement(int x, int y, int element)
1311 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1312 ErdreichAnbroeckeln(x, y);
1315 void DrawLevelElement(int x, int y, int element)
1317 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1318 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1321 void DrawScreenField(int x, int y)
1323 int ux = LEVELX(x), uy = LEVELY(y);
1326 if (!IN_LEV_FIELD(ux, uy))
1328 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1329 element = EL_LEERRAUM;
1331 element = BorderElement;
1333 DrawScreenElement(x, y, element);
1337 element = Feld[ux][uy];
1339 if (IS_MOVING(ux, uy))
1341 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1342 boolean cut_mode = NO_CUTTING;
1344 if (Store[ux][uy] == EL_MORAST_LEER ||
1345 Store[ux][uy] == EL_SIEB_LEER ||
1346 Store[ux][uy] == EL_SIEB2_LEER ||
1347 Store[ux][uy] == EL_AMOEBE_NASS)
1348 cut_mode = CUT_ABOVE;
1349 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1350 Store[ux][uy] == EL_SIEB_VOLL ||
1351 Store[ux][uy] == EL_SIEB2_VOLL)
1352 cut_mode = CUT_BELOW;
1354 if (cut_mode == CUT_ABOVE)
1355 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1357 DrawScreenElement(x, y, EL_LEERRAUM);
1360 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1362 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1364 if (Store[ux][uy] == EL_SALZSAEURE)
1365 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1367 else if (IS_BLOCKED(ux, uy))
1372 boolean cut_mode = NO_CUTTING;
1374 Blocked2Moving(ux, uy, &oldx, &oldy);
1377 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1378 MovDir[oldx][oldy] == MV_RIGHT);
1380 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1381 Store[oldx][oldy] == EL_SIEB_LEER ||
1382 Store[oldx][oldy] == EL_SIEB2_LEER ||
1383 Store[oldx][oldy] == EL_AMOEBE_NASS)
1384 cut_mode = CUT_ABOVE;
1386 DrawScreenElement(x, y, EL_LEERRAUM);
1387 element = Feld[oldx][oldy];
1390 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1392 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1394 else if (IS_DRAWABLE(element))
1395 DrawScreenElement(x, y, element);
1397 DrawScreenElement(x, y, EL_LEERRAUM);
1400 void DrawLevelField(int x, int y)
1402 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1403 DrawScreenField(SCREENX(x), SCREENY(y));
1404 else if (IS_MOVING(x, y))
1408 Moving2Blocked(x, y, &newx, &newy);
1409 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1410 DrawScreenField(SCREENX(newx), SCREENY(newy));
1412 else if (IS_BLOCKED(x, y))
1416 Blocked2Moving(x, y, &oldx, &oldy);
1417 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1418 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1422 void DrawMiniElement(int x, int y, int element)
1428 DrawMiniGraphic(x, y, -1);
1432 graphic = el2gfx(element);
1433 DrawMiniGraphic(x, y, graphic);
1436 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1438 int x = sx + scroll_x, y = sy + scroll_y;
1440 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1441 DrawMiniElement(sx, sy, EL_LEERRAUM);
1442 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1443 DrawMiniElement(sx, sy, Feld[x][y]);
1446 int steel_type, steel_position;
1449 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1450 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1451 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1452 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1453 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1454 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1457 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1458 steel_position = (x == -1 && y == -1 ? 0 :
1459 x == lev_fieldx && y == -1 ? 1 :
1460 x == -1 && y == lev_fieldy ? 2 :
1461 x == lev_fieldx && y == lev_fieldy ? 3 :
1462 x == -1 || x == lev_fieldx ? 4 :
1463 y == -1 || y == lev_fieldy ? 5 : -1);
1465 if (steel_position != -1)
1466 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1470 void DrawMicroElement(int xpos, int ypos, int element)
1474 if (element == EL_LEERRAUM)
1477 graphic = el2gfx(element);
1479 if (graphic >= GFX_START_ROCKSSP && graphic <= GFX_END_ROCKSSP)
1481 graphic -= GFX_START_ROCKSSP;
1482 graphic -= ((graphic / SP_PER_LINE) * SP_PER_LINE) / 2;
1483 XCopyArea(display, pix[PIX_SP], drawto, gc,
1484 MICRO_SP_STARTX + (graphic % MICRO_SP_PER_LINE) * MICRO_TILEX,
1485 MICRO_SP_STARTY + (graphic / MICRO_SP_PER_LINE) * MICRO_TILEY,
1486 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1488 else if (graphic >= GFX_START_ROCKSDC && graphic <= GFX_END_ROCKSDC)
1490 graphic -= GFX_START_ROCKSDC;
1491 XCopyArea(display, pix[PIX_DC], drawto, gc,
1492 MICRO_DC_STARTX + (graphic % MICRO_DC_PER_LINE) * MICRO_TILEX,
1493 MICRO_DC_STARTY + (graphic / MICRO_DC_PER_LINE) * MICRO_TILEY,
1494 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1497 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1498 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1499 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1500 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1509 for(x=BX1; x<=BX2; x++)
1510 for(y=BY1; y<=BY2; y++)
1511 DrawScreenField(x, y);
1513 redraw_mask |= REDRAW_FIELD;
1516 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1520 for(x=0; x<size_x; x++)
1521 for(y=0; y<size_y; y++)
1522 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1524 redraw_mask |= REDRAW_FIELD;
1527 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1531 XFillRectangle(display, drawto, gc,
1532 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1534 if (lev_fieldx < STD_LEV_FIELDX)
1535 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1536 if (lev_fieldy < STD_LEV_FIELDY)
1537 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1539 xpos += MICRO_TILEX;
1540 ypos += MICRO_TILEY;
1542 for(x=-1; x<=STD_LEV_FIELDX; x++)
1544 for(y=-1; y<=STD_LEV_FIELDY; y++)
1546 int lx = from_x + x, ly = from_y + y;
1548 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1549 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1551 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1552 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1557 redraw_mask |= REDRAW_MICROLEVEL;
1560 #define MICROLABEL_EMPTY 0
1561 #define MICROLABEL_LEVEL_NAME 1
1562 #define MICROLABEL_CREATED_BY 2
1563 #define MICROLABEL_LEVEL_AUTHOR 3
1564 #define MICROLABEL_IMPORTED_FROM 4
1565 #define MICROLABEL_LEVEL_IMPORT_INFO 5
1567 #define MAX_MICROLABEL_SIZE (SXSIZE / FONT4_XSIZE)
1569 static void DrawMicroLevelLabelExt(int mode)
1571 char label_text[MAX_MICROLABEL_SIZE + 1];
1573 XFillRectangle(display, drawto,gc,
1574 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1576 strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1577 mode == MICROLABEL_CREATED_BY ? "created by" :
1578 mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1579 mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1580 mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1581 leveldir[leveldir_nr].imported_from : ""),
1582 MAX_MICROLABEL_SIZE);
1583 label_text[MAX_MICROLABEL_SIZE] = '\0';
1585 if (strlen(label_text) > 0)
1587 int lxpos = SX + (SXSIZE - strlen(label_text) * FONT4_XSIZE) / 2;
1588 int lypos = MICROLABEL_YPOS;
1590 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1593 redraw_mask |= REDRAW_MICROLEVEL;
1596 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1598 static unsigned long scroll_delay = 0;
1599 static unsigned long label_delay = 0;
1600 static int from_x, from_y, scroll_direction;
1601 static int label_state, label_counter;
1605 from_x = from_y = 0;
1606 scroll_direction = MV_RIGHT;
1610 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1611 DrawMicroLevelLabelExt(label_state);
1613 /* initialize delay counters */
1614 DelayReached(&scroll_delay, 0);
1615 DelayReached(&label_delay, 0);
1620 /* scroll micro level, if needed */
1621 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1622 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1624 switch (scroll_direction)
1630 scroll_direction = MV_UP;
1634 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1637 scroll_direction = MV_DOWN;
1644 scroll_direction = MV_RIGHT;
1648 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1651 scroll_direction = MV_LEFT;
1658 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1661 /* redraw micro level label, if needed */
1662 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1663 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1664 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1665 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1667 int max_label_counter = 23;
1669 if (leveldir[leveldir_nr].imported_from != NULL)
1670 max_label_counter += 14;
1672 label_counter = (label_counter + 1) % max_label_counter;
1673 label_state = (label_counter >= 0 && label_counter <= 7 ?
1674 MICROLABEL_LEVEL_NAME :
1675 label_counter >= 9 && label_counter <= 12 ?
1676 MICROLABEL_CREATED_BY :
1677 label_counter >= 14 && label_counter <= 21 ?
1678 MICROLABEL_LEVEL_AUTHOR :
1679 label_counter >= 23 && label_counter <= 26 ?
1680 MICROLABEL_IMPORTED_FROM :
1681 label_counter >= 28 && label_counter <= 35 ?
1682 MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1683 DrawMicroLevelLabelExt(label_state);
1687 int REQ_in_range(int x, int y)
1689 if (y > DY+249 && y < DY+278)
1691 if (x > DX+1 && x < DX+48)
1693 else if (x > DX+51 && x < DX+98)
1699 boolean Request(char *text, unsigned int req_state)
1701 int mx, my, ty, result = -1;
1702 unsigned int old_door_state;
1705 /* pause network game while waiting for request to answer */
1706 if (options.network &&
1707 game_status == PLAYING &&
1708 req_state & REQUEST_WAIT_FOR)
1709 SendToServer_PausePlaying();
1712 old_door_state = GetDoorState();
1716 CloseDoor(DOOR_CLOSE_1);
1718 /* save old door content */
1719 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1720 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1721 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1723 /* clear door drawing field */
1724 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1726 /* write text for request */
1727 for(ty=0; ty<13; ty++)
1735 for(tl=0,tx=0; tx<7; tl++,tx++)
1738 if (!tc || tc == 32)
1749 DrawTextExt(drawto, gc,
1750 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1751 txt, FS_SMALL, FC_YELLOW);
1752 text += tl + (tc == 32 ? 1 : 0);
1755 if (req_state & REQ_ASK)
1757 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1758 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1760 else if (req_state & REQ_CONFIRM)
1762 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1764 else if (req_state & REQ_PLAYER)
1766 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1767 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1768 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1769 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1772 /* copy request gadgets to door backbuffer */
1773 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1774 DX, DY, DXSIZE, DYSIZE,
1775 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1777 OpenDoor(DOOR_OPEN_1);
1783 if (!(req_state & REQUEST_WAIT_FOR))
1786 if (game_status != MAINMENU)
1789 button_status = MB_RELEASED;
1791 request_gadget_id = -1;
1795 if (XPending(display))
1799 XNextEvent(display, &event);
1807 if (event.type == MotionNotify)
1814 if (!XQueryPointer(display, window, &root, &child,
1815 &root_x, &root_y, &win_x, &win_y, &mask))
1821 motion_status = TRUE;
1822 mx = ((XMotionEvent *) &event)->x;
1823 my = ((XMotionEvent *) &event)->y;
1827 motion_status = FALSE;
1828 mx = ((XButtonEvent *) &event)->x;
1829 my = ((XButtonEvent *) &event)->y;
1830 if (event.type==ButtonPress)
1831 button_status = ((XButtonEvent *) &event)->button;
1833 button_status = MB_RELEASED;
1836 /* this sets 'request_gadget_id' */
1837 HandleGadgets(mx, my, button_status);
1839 switch(request_gadget_id)
1841 case TOOL_CTRL_ID_YES:
1844 case TOOL_CTRL_ID_NO:
1847 case TOOL_CTRL_ID_CONFIRM:
1848 result = TRUE | FALSE;
1851 case TOOL_CTRL_ID_PLAYER_1:
1854 case TOOL_CTRL_ID_PLAYER_2:
1857 case TOOL_CTRL_ID_PLAYER_3:
1860 case TOOL_CTRL_ID_PLAYER_4:
1872 switch(XLookupKeysym((XKeyEvent *)&event,
1873 ((XKeyEvent *)&event)->state))
1886 if (req_state & REQ_PLAYER)
1891 key_joystick_mapping = 0;
1895 HandleOtherEvents(&event);
1899 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1901 int joy = AnyJoystick();
1903 if (joy & JOY_BUTTON_1)
1905 else if (joy & JOY_BUTTON_2)
1911 /* don't eat all CPU time */
1915 if (game_status != MAINMENU)
1920 if (!(req_state & REQ_STAY_OPEN))
1922 CloseDoor(DOOR_CLOSE_1);
1924 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1926 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1927 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1928 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1929 OpenDoor(DOOR_OPEN_1);
1936 /* continue network game after request */
1937 if (options.network &&
1938 game_status == PLAYING &&
1939 req_state & REQUEST_WAIT_FOR)
1940 SendToServer_ContinuePlaying();
1946 unsigned int OpenDoor(unsigned int door_state)
1948 unsigned int new_door_state;
1950 if (door_state & DOOR_COPY_BACK)
1952 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1953 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1954 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1955 door_state &= ~DOOR_COPY_BACK;
1958 new_door_state = MoveDoor(door_state);
1960 return(new_door_state);
1963 unsigned int CloseDoor(unsigned int door_state)
1965 unsigned int new_door_state;
1967 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1968 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1969 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1970 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1972 new_door_state = MoveDoor(door_state);
1974 return(new_door_state);
1977 unsigned int GetDoorState()
1979 return(MoveDoor(DOOR_GET_STATE));
1982 unsigned int MoveDoor(unsigned int door_state)
1984 static int door1 = DOOR_OPEN_1;
1985 static int door2 = DOOR_CLOSE_2;
1986 static unsigned long door_delay = 0;
1987 int x, start, stepsize = 2;
1988 unsigned long door_delay_value = stepsize * 5;
1990 if (door_state == DOOR_GET_STATE)
1991 return(door1 | door2);
1993 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1994 door_state &= ~DOOR_OPEN_1;
1995 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1996 door_state &= ~DOOR_CLOSE_1;
1997 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1998 door_state &= ~DOOR_OPEN_2;
1999 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2000 door_state &= ~DOOR_CLOSE_2;
2002 if (setup.quick_doors)
2005 door_delay_value = 0;
2006 StopSound(SND_OEFFNEN);
2009 if (door_state & DOOR_ACTION)
2011 if (!(door_state & DOOR_NO_DELAY))
2012 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2014 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2016 for(x=start; x<=DXSIZE; x+=stepsize)
2018 WaitUntilDelayReached(&door_delay, door_delay_value);
2020 if (door_state & DOOR_ACTION_1)
2022 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2023 int j = (DXSIZE - i) / 3;
2025 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2026 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2027 DXSIZE,DYSIZE - i/2, DX, DY);
2029 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2031 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2032 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2033 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2034 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2035 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2036 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2038 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2039 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2040 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2041 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2042 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2043 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2045 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2046 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2048 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2049 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2051 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2052 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2053 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2054 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2055 DX + DXSIZE - i, DY + 77 + j);
2056 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2057 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2058 DX + DXSIZE - i, DY + 203 + j);
2060 redraw_mask |= REDRAW_DOOR_1;
2063 if (door_state & DOOR_ACTION_2)
2065 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2066 int j = (VXSIZE - i) / 3;
2068 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2069 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2070 VXSIZE, VYSIZE - i/2, VX, VY);
2072 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2074 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2075 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2076 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2077 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2078 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2079 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2080 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2081 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2083 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2084 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2085 VX, VY + VYSIZE / 2 - j);
2086 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2087 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2088 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2089 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2090 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2092 redraw_mask |= REDRAW_DOOR_2;
2097 if (game_status == MAINMENU)
2102 if (setup.quick_doors)
2103 StopSound(SND_OEFFNEN);
2105 if (door_state & DOOR_ACTION_1)
2106 door1 = door_state & DOOR_ACTION_1;
2107 if (door_state & DOOR_ACTION_2)
2108 door2 = door_state & DOOR_ACTION_2;
2110 return (door1 | door2);
2113 void DrawSpecialEditorDoor()
2115 /* draw bigger toolbox window */
2116 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2117 DOOR_GFX_PAGEX7, 0, 108, 56, EX - 4, EY - 12);
2119 redraw_mask |= REDRAW_ALL;
2122 void UndrawSpecialEditorDoor()
2124 /* draw normal tape recorder window */
2125 XCopyArea(display, pix[PIX_BACK], drawto, gc,
2126 562, 344, 108, 56, EX - 4, EY - 12);
2128 redraw_mask |= REDRAW_ALL;
2131 int ReadPixel(Drawable d, int x, int y)
2133 XImage *pixel_image;
2134 unsigned long pixel_value;
2136 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2137 pixel_value = XGetPixel(pixel_image, 0, 0);
2139 XDestroyImage(pixel_image);
2144 /* ---------- new tool button stuff ---------------------------------------- */
2146 /* graphic position values for tool buttons */
2147 #define TOOL_BUTTON_YES_XPOS 2
2148 #define TOOL_BUTTON_YES_YPOS 250
2149 #define TOOL_BUTTON_YES_GFX_YPOS 0
2150 #define TOOL_BUTTON_YES_XSIZE 46
2151 #define TOOL_BUTTON_YES_YSIZE 28
2152 #define TOOL_BUTTON_NO_XPOS 52
2153 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2154 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2155 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2156 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2157 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2158 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2159 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2160 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2161 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2162 #define TOOL_BUTTON_PLAYER_XSIZE 30
2163 #define TOOL_BUTTON_PLAYER_YSIZE 30
2164 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2165 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2166 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2167 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2168 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2169 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2170 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2171 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2172 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2173 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2174 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2175 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2176 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2177 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2178 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2179 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2180 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2181 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2182 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2183 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2192 } toolbutton_info[NUM_TOOL_BUTTONS] =
2195 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2196 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2197 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2202 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2203 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2204 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2209 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2210 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2211 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2212 TOOL_CTRL_ID_CONFIRM,
2216 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2217 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2218 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2219 TOOL_CTRL_ID_PLAYER_1,
2223 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2224 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2225 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2226 TOOL_CTRL_ID_PLAYER_2,
2230 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2231 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2232 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2233 TOOL_CTRL_ID_PLAYER_3,
2237 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2238 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2239 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2240 TOOL_CTRL_ID_PLAYER_4,
2245 static void DoNotDisplayInfoText(void *ptr)
2250 void CreateToolButtons()
2254 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2256 Pixmap gd_pixmap = pix[PIX_DOOR];
2257 Pixmap deco_pixmap = None;
2258 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2259 struct GadgetInfo *gi;
2260 unsigned long event_mask;
2261 int gd_xoffset, gd_yoffset;
2262 int gd_x1, gd_x2, gd_y;
2265 event_mask = GD_EVENT_RELEASED;
2267 gd_xoffset = toolbutton_info[i].xpos;
2268 gd_yoffset = toolbutton_info[i].ypos;
2269 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2270 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2271 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2273 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2275 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2276 &deco_pixmap, &deco_x, &deco_y);
2277 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2278 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2281 gi = CreateGadget(GDI_CUSTOM_ID, id,
2282 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2283 GDI_X, DX + toolbutton_info[i].x,
2284 GDI_Y, DY + toolbutton_info[i].y,
2285 GDI_WIDTH, toolbutton_info[i].width,
2286 GDI_HEIGHT, toolbutton_info[i].height,
2287 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2288 GDI_STATE, GD_BUTTON_UNPRESSED,
2289 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2290 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2291 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2292 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2293 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2294 GDI_DECORATION_SHIFTING, 1, 1,
2295 GDI_EVENT_MASK, event_mask,
2296 GDI_CALLBACK_ACTION, HandleToolButtons,
2297 GDI_CALLBACK_INFO, DoNotDisplayInfoText,
2301 Error(ERR_EXIT, "cannot create gadget");
2303 tool_gadget[id] = gi;
2307 static void UnmapToolButtons()
2311 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2312 UnmapGadget(tool_gadget[i]);
2315 static void HandleToolButtons(struct GadgetInfo *gi)
2317 request_gadget_id = gi->custom_id;
2320 int el2gfx(int element)
2324 case EL_LEERRAUM: return -1;
2325 case EL_ERDREICH: return GFX_ERDREICH;
2326 case EL_MAUERWERK: return GFX_MAUERWERK;
2327 case EL_FELSBODEN: return GFX_FELSBODEN;
2328 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2329 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2330 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2331 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2332 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2333 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2334 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2335 case EL_SPIELER1: return GFX_SPIELER1;
2336 case EL_SPIELER2: return GFX_SPIELER2;
2337 case EL_SPIELER3: return GFX_SPIELER3;
2338 case EL_SPIELER4: return GFX_SPIELER4;
2339 case EL_KAEFER: return GFX_KAEFER;
2340 case EL_KAEFER_R: return GFX_KAEFER_R;
2341 case EL_KAEFER_O: return GFX_KAEFER_O;
2342 case EL_KAEFER_L: return GFX_KAEFER_L;
2343 case EL_KAEFER_U: return GFX_KAEFER_U;
2344 case EL_FLIEGER: return GFX_FLIEGER;
2345 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2346 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2347 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2348 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2349 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2350 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2351 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2352 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2353 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2354 case EL_FIREFLY: return GFX_FIREFLY;
2355 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2356 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2357 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2358 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2359 case EL_MAMPFER: return GFX_MAMPFER;
2360 case EL_ROBOT: return GFX_ROBOT;
2361 case EL_BETON: return GFX_BETON;
2362 case EL_DIAMANT: return GFX_DIAMANT;
2363 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2364 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2365 case EL_TROPFEN: return GFX_TROPFEN;
2366 case EL_BOMBE: return GFX_BOMBE;
2367 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2368 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2369 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2370 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2371 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2372 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2373 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2374 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2375 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2376 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2377 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2378 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2379 case EL_LIFE: return GFX_LIFE;
2380 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2381 case EL_DYNAMITE_ACTIVE: return GFX_DYNAMIT;
2382 case EL_BADEWANNE: return GFX_BADEWANNE;
2383 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2384 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2385 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2386 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2387 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2388 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2389 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2390 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2391 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2392 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2393 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2394 case EL_PFORTE1: return GFX_PFORTE1;
2395 case EL_PFORTE2: return GFX_PFORTE2;
2396 case EL_PFORTE3: return GFX_PFORTE3;
2397 case EL_PFORTE4: return GFX_PFORTE4;
2398 case EL_PFORTE1X: return GFX_PFORTE1X;
2399 case EL_PFORTE2X: return GFX_PFORTE2X;
2400 case EL_PFORTE3X: return GFX_PFORTE3X;
2401 case EL_PFORTE4X: return GFX_PFORTE4X;
2402 case EL_DYNAMITE_INACTIVE: return GFX_DYNAMIT_AUS;
2403 case EL_PACMAN: return GFX_PACMAN;
2404 case EL_PACMAN_R: return GFX_PACMAN_R;
2405 case EL_PACMAN_O: return GFX_PACMAN_O;
2406 case EL_PACMAN_L: return GFX_PACMAN_L;
2407 case EL_PACMAN_U: return GFX_PACMAN_U;
2408 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2409 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2410 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2411 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2412 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2413 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2414 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2415 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2416 case EL_MAUER_X: return GFX_MAUER_X;
2417 case EL_MAUER_Y: return GFX_MAUER_Y;
2418 case EL_MAUER_XY: return GFX_MAUER_XY;
2419 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2420 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2421 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2422 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2423 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2424 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2425 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2426 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2427 case EL_MAMPFER2: return GFX_MAMPFER2;
2428 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2429 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2430 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2431 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2432 case EL_DYNABOMB_ACTIVE_1: return GFX_DYNABOMB;
2433 case EL_DYNABOMB_ACTIVE_2: return GFX_DYNABOMB;
2434 case EL_DYNABOMB_ACTIVE_3: return GFX_DYNABOMB;
2435 case EL_DYNABOMB_ACTIVE_4: return GFX_DYNABOMB;
2436 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2437 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2438 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2439 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2440 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2441 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2442 case EL_MAULWURF: return GFX_MAULWURF;
2443 case EL_PINGUIN: return GFX_PINGUIN;
2444 case EL_SCHWEIN: return GFX_SCHWEIN;
2445 case EL_DRACHE: return GFX_DRACHE;
2446 case EL_SONDE: return GFX_SONDE;
2447 case EL_PFEIL_L: return GFX_PFEIL_L;
2448 case EL_PFEIL_R: return GFX_PFEIL_R;
2449 case EL_PFEIL_O: return GFX_PFEIL_O;
2450 case EL_PFEIL_U: return GFX_PFEIL_U;
2451 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2452 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2453 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2454 case EL_SP_ZONK: return GFX_SP_ZONK;
2455 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2456 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2457 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2458 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2459 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2460 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2461 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2462 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2463 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2464 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2465 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2466 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2467 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2468 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2469 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2470 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2471 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2472 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2473 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2474 case EL_PEARL: return GFX_PEARL;
2475 case EL_CRYSTAL: return GFX_CRYSTAL;
2476 case EL_WALL_PEARL: return GFX_WALL_PEARL;
2477 case EL_WALL_CRYSTAL: return GFX_WALL_CRYSTAL;
2478 case EL_DOOR_WHITE: return GFX_DOOR_WHITE;
2479 case EL_DOOR_WHITE_GRAY: return GFX_DOOR_WHITE_GRAY;
2480 case EL_KEY_WHITE: return GFX_KEY_WHITE;
2481 case EL_FORCE_FIELD: return GFX_FORCE_FIELD;
2482 case EL_EXTRA_TIME: return GFX_EXTRA_TIME;
2483 case EL_SWITCHGATE_OPEN: return GFX_SWITCHGATE_OPEN;
2484 case EL_SWITCHGATE_CLOSED: return GFX_SWITCHGATE_CLOSED;
2485 case EL_SWITCHGATE_SWITCH_L:return GFX_SWITCHGATE_SWITCH_L;
2486 case EL_SWITCHGATE_SWITCH_R:return GFX_SWITCHGATE_SWITCH_R;
2487 case EL_TIME_GATE: return GFX_TIME_GATE;
2488 case EL_TIME_GATE_WHEEL: return GFX_TIME_GATE_WHEEL;
2489 case EL_BELT1_LEFT: return GFX_BELT1_LEFT;
2490 case EL_BELT1_MIDDLE: return GFX_BELT1_MIDDLE;
2491 case EL_BELT1_RIGHT: return GFX_BELT1_RIGHT;
2492 case EL_BELT1_SWITCH_L: return GFX_BELT1_SWITCH_L;
2493 case EL_BELT1_SWITCH_M: return GFX_BELT1_SWITCH_M;
2494 case EL_BELT1_SWITCH_R: return GFX_BELT1_SWITCH_R;
2495 case EL_BELT2_LEFT: return GFX_BELT2_LEFT;
2496 case EL_BELT2_MIDDLE: return GFX_BELT2_MIDDLE;
2497 case EL_BELT2_RIGHT: return GFX_BELT2_RIGHT;
2498 case EL_BELT2_SWITCH_L: return GFX_BELT2_SWITCH_L;
2499 case EL_BELT2_SWITCH_M: return GFX_BELT2_SWITCH_M;
2500 case EL_BELT2_SWITCH_R: return GFX_BELT2_SWITCH_R;
2501 case EL_BELT3_LEFT: return GFX_BELT3_LEFT;
2502 case EL_BELT3_MIDDLE: return GFX_BELT3_MIDDLE;
2503 case EL_BELT3_RIGHT: return GFX_BELT3_RIGHT;
2504 case EL_BELT3_SWITCH_L: return GFX_BELT3_SWITCH_L;
2505 case EL_BELT3_SWITCH_M: return GFX_BELT3_SWITCH_M;
2506 case EL_BELT3_SWITCH_R: return GFX_BELT3_SWITCH_R;
2507 case EL_BELT4_LEFT: return GFX_BELT4_LEFT;
2508 case EL_BELT4_MIDDLE: return GFX_BELT4_MIDDLE;
2509 case EL_BELT4_RIGHT: return GFX_BELT4_RIGHT;
2510 case EL_BELT4_SWITCH_L: return GFX_BELT4_SWITCH_L;
2511 case EL_BELT4_SWITCH_M: return GFX_BELT4_SWITCH_M;
2512 case EL_BELT4_SWITCH_R: return GFX_BELT4_SWITCH_R;
2513 case EL_LANDMINE: return GFX_LANDMINE;
2514 case EL_ENVELOPE: return GFX_ENVELOPE;
2515 case EL_LIGHT_SWITCH: return GFX_LIGHT_SWITCH;
2516 case EL_SIGN_EXCLAMATION: return GFX_SIGN_EXCLAMATION;
2517 case EL_SIGN_RADIOACTIVITY: return GFX_SIGN_RADIOACTIVITY;
2518 case EL_SIGN_STOP: return GFX_SIGN_STOP;
2519 case EL_SIGN_WHEELCHAIR: return GFX_SIGN_WHEELCHAIR;
2520 case EL_SIGN_PARKING: return GFX_SIGN_PARKING;
2521 case EL_SIGN_ONEWAY: return GFX_SIGN_ONEWAY;
2522 case EL_SIGN_HEART: return GFX_SIGN_HEART;
2523 case EL_SIGN_TRIANGLE: return GFX_SIGN_TRIANGLE;
2524 case EL_SIGN_ROUND: return GFX_SIGN_ROUND;
2525 case EL_SIGN_EXIT: return GFX_SIGN_EXIT;
2526 case EL_SIGN_YINYANG: return GFX_SIGN_YINYANG;
2527 case EL_SIGN_OTHER: return GFX_SIGN_OTHER;
2528 case EL_MOLE_LEFT: return GFX_MOLE_LEFT;
2529 case EL_MOLE_RIGHT: return GFX_MOLE_RIGHT;
2530 case EL_MOLE_UP: return GFX_MOLE_UP;
2531 case EL_MOLE_DOWN: return GFX_MOLE_DOWN;
2532 case EL_STEEL_SLANTED: return GFX_STEEL_SLANTED;
2533 case EL_SAND_INVISIBLE: return GFX_SAND_INVISIBLE;
2537 if (IS_CHAR(element))
2538 return GFX_CHAR_START + (element - EL_CHAR_START);
2539 else if (element >= EL_SP_START && element <= EL_SP_END)
2541 int nr_element = element - EL_SP_START;
2542 int gfx_per_line = 8;
2544 (nr_element / gfx_per_line) * SP_PER_LINE +
2545 (nr_element % gfx_per_line);
2547 return GFX_START_ROCKSSP + nr_graphic;