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;
98 if (redraw_mask & REDRAW_FIELD ||
99 (ScreenGfxPos && setup.soft_scrolling && game_status == PLAYING))
100 redraw_mask &= ~REDRAW_TILES;
106 /* synchronize X11 graphics at this point; if we would synchronize the
107 display immediately after the buffer switching (after the XFlush),
108 this could mean that we have to wait for the graphics to complete,
109 although we could go on doing calculations for the next frame */
111 XSync(display, FALSE);
115 wait_for_vsync = TRUE;
119 if (redraw_mask & REDRAW_ALL)
121 XCopyArea(display, backbuffer, window, gc,
122 0, 0, WIN_XSIZE, WIN_YSIZE,
127 if (redraw_mask & REDRAW_FIELD)
129 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
131 XCopyArea(display, backbuffer, window, gc,
132 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
137 int fx = FX, fy = FY;
139 if (setup.soft_scrolling)
141 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
142 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
145 if (setup.soft_scrolling ||
146 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
147 ABS(ScreenMovPos) == ScrollStepSize ||
148 redraw_tiles > REDRAWTILES_THRESHOLD)
150 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
154 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
156 (setup.soft_scrolling ?
157 "setup.soft_scrolling" :
158 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
159 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
160 ABS(ScreenGfxPos) == ScrollStepSize ?
161 "ABS(ScreenGfxPos) == ScrollStepSize" :
162 "redraw_tiles > REDRAWTILES_THRESHOLD"));
167 redraw_mask &= ~REDRAW_MAIN;
170 if (redraw_mask & REDRAW_DOORS)
172 if (redraw_mask & REDRAW_DOOR_1)
173 XCopyArea(display, backbuffer, window, gc,
174 DX, DY, DXSIZE, DYSIZE,
176 if (redraw_mask & REDRAW_DOOR_2)
178 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
179 XCopyArea(display,backbuffer,window,gc,
180 VX,VY, VXSIZE,VYSIZE,
184 if (redraw_mask & REDRAW_VIDEO_1)
185 XCopyArea(display,backbuffer,window,gc,
186 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
187 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
188 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
189 if (redraw_mask & REDRAW_VIDEO_2)
190 XCopyArea(display,backbuffer,window,gc,
191 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
192 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
193 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
194 if (redraw_mask & REDRAW_VIDEO_3)
195 XCopyArea(display,backbuffer,window,gc,
196 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
197 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
198 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
201 if (redraw_mask & REDRAW_DOOR_3)
202 XCopyArea(display, backbuffer, window, gc,
203 EX, EY, EXSIZE, EYSIZE,
205 redraw_mask &= ~REDRAW_DOORS;
208 if (redraw_mask & REDRAW_MICROLEVEL)
210 XCopyArea(display,backbuffer,window,gc,
211 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
212 MICROLEV_XPOS, MICROLEV_YPOS);
213 XCopyArea(display,backbuffer,window,gc,
214 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
215 SX, MICROLABEL_YPOS);
216 redraw_mask &= ~REDRAW_MICROLEVEL;
219 if (redraw_mask & REDRAW_TILES)
221 for(x=0; x<SCR_FIELDX; x++)
222 for(y=0; y<SCR_FIELDY; y++)
223 if (redraw[redraw_x1 + x][redraw_y1 + y])
224 XCopyArea(display, buffer, window, gc,
225 FX + x * TILEX, FX + y * TILEY, TILEX, TILEY,
226 SX + x * TILEX, SY + y * TILEY);
231 for(x=0; x<MAX_BUF_XSIZE; x++)
232 for(y=0; y<MAX_BUF_YSIZE; y++)
241 long fading_delay = 300;
243 if (setup.fading && (redraw_mask & REDRAW_FIELD))
250 XFillRectangle(display,window,gc,
251 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
254 for(i=0;i<2*FULL_SYSIZE;i++)
256 for(y=0;y<FULL_SYSIZE;y++)
258 XCopyArea(display,backbuffer,window,gc,
259 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
267 for(i=1;i<FULL_SYSIZE;i+=2)
268 XCopyArea(display,backbuffer,window,gc,
269 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
275 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
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,-1);
282 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
283 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
287 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
288 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
289 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
293 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
294 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
295 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
299 redraw_mask &= ~REDRAW_MAIN;
308 XFillRectangle(display, backbuffer, gc,
309 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
311 if (setup.soft_scrolling && game_status == PLAYING)
313 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
314 SetDrawtoField(DRAW_BUFFERED);
317 SetDrawtoField(DRAW_BACKBUFFER);
319 if (setup.direct_draw && game_status == PLAYING)
321 XFillRectangle(display, window, gc,
322 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
323 SetDrawtoField(DRAW_DIRECT);
326 redraw_mask |= REDRAW_FIELD;
329 void DrawTextFCentered(int y, int font_type, char *format, ...)
331 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
335 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
336 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
338 va_start(ap, format);
339 vsprintf(buffer, format, ap);
342 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
343 buffer, FS_SMALL, font_type);
346 void DrawTextF(int x, int y, int font_type, char *format, ...)
348 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
351 va_start(ap, format);
352 vsprintf(buffer, format, ap);
355 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
358 void DrawText(int x, int y, char *text, int font_size, int font_type)
360 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
363 redraw_mask |= REDRAW_FIELD;
365 redraw_mask |= REDRAW_DOOR_1;
368 void DrawTextExt(Drawable d, GC gc, int x, int y,
369 char *text, int font_size, int font_type)
371 int font_width, font_height, font_start;
373 boolean print_inverse = FALSE;
375 if (font_size != FS_SMALL && font_size != FS_BIG)
376 font_size = FS_SMALL;
377 if (font_type < FC_RED || font_type > FC_SPECIAL2)
380 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
381 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
382 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
383 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
384 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
385 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
386 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
387 FONT_LINES_PER_FONT);
393 if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW)
395 print_inverse = TRUE;
399 if (c >= 'a' && c <= 'z')
401 else if (c == 'ä' || c == 'Ä')
403 else if (c == 'ö' || c == 'Ö')
405 else if (c == 'ü' || c == 'Ü')
408 if (c >= 32 && c <= 95)
410 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
411 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
412 int dest_x = x, dest_y = y;
416 XCopyArea(display, pix[font_pixmap], d, gc,
417 FONT_CHARS_PER_LINE * font_width,
418 3 * font_height + font_start,
419 font_width, font_height, x, y);
421 XSetClipOrigin(display, clip_gc[font_pixmap],
422 dest_x - src_x, dest_y - src_y);
423 XCopyArea(display, pix[font_pixmap], d, clip_gc[font_pixmap],
424 0, 0, font_width, font_height, dest_x, dest_y);
427 XCopyArea(display, pix[font_pixmap], d, gc,
428 src_x, src_y, font_width, font_height, dest_x, dest_y);
435 void DrawAllPlayers()
439 for(i=0; i<MAX_PLAYERS; i++)
440 if (stored_player[i].active)
441 DrawPlayer(&stored_player[i]);
444 void DrawPlayerField(int x, int y)
449 DrawPlayer(PLAYERINFO(x,y));
452 void DrawPlayer(struct PlayerInfo *player)
454 int jx = player->jx, jy = player->jy;
455 int last_jx = player->last_jx, last_jy = player->last_jy;
456 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
457 int sx = SCREENX(jx), sy = SCREENY(jy);
458 int sxx = 0, syy = 0;
459 int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
461 boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
463 if (!player->active || player->gone ||
464 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
468 if (!IN_LEV_FIELD(jx,jy))
470 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
471 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
472 printf("DrawPlayerField(): This should never happen!\n");
477 if (element == EL_EXPLODING)
480 /* draw things in the field the player is leaving, if needed */
483 if (last_jx != jx || last_jy != jy)
486 if (player_is_moving)
488 if (Store[last_jx][last_jy] && IS_DRAWABLE(last_element))
490 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
491 DrawLevelFieldThruMask(last_jx, last_jy);
493 else if (last_element == EL_DYNAMIT)
494 DrawDynamite(last_jx, last_jy);
496 DrawLevelField(last_jx, last_jy);
498 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
502 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
503 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
505 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
508 DrawLevelField(next_jx, next_jy);
512 if (!IN_SCR_FIELD(sx, sy))
515 if (setup.direct_draw)
516 SetDrawtoField(DRAW_BUFFERED);
518 /* draw things behind the player, if needed */
521 DrawLevelElement(jx, jy, Store[jx][jy]);
522 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
523 DrawLevelField(jx, jy);
525 /* draw player himself */
527 if (game_emulation == EMU_SUPAPLEX)
529 static int last_dir = MV_LEFT;
530 int action = (player->programmed_action ? player->programmed_action :
532 boolean action_moving =
534 ((action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
535 !(action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN))));
537 graphic = GFX_SP_MURPHY;
541 if (player->MovDir == MV_LEFT)
542 graphic = GFX_MURPHY_PUSH_LEFT;
543 else if (player->MovDir == MV_RIGHT)
544 graphic = GFX_MURPHY_PUSH_RIGHT;
545 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
546 graphic = GFX_MURPHY_PUSH_LEFT;
547 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
548 graphic = GFX_MURPHY_PUSH_RIGHT;
550 else if (player->snapped)
552 if (player->MovDir == MV_LEFT)
553 graphic = GFX_MURPHY_SNAP_LEFT;
554 else if (player->MovDir == MV_RIGHT)
555 graphic = GFX_MURPHY_SNAP_RIGHT;
556 else if (player->MovDir == MV_UP)
557 graphic = GFX_MURPHY_SNAP_UP;
558 else if (player->MovDir == MV_DOWN)
559 graphic = GFX_MURPHY_SNAP_DOWN;
561 else if (action_moving)
563 if (player->MovDir == MV_LEFT)
564 graphic = GFX_MURPHY_GO_LEFT;
565 else if (player->MovDir == MV_RIGHT)
566 graphic = GFX_MURPHY_GO_RIGHT;
567 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
568 graphic = GFX_MURPHY_GO_LEFT;
569 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
570 graphic = GFX_MURPHY_GO_RIGHT;
572 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
575 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
576 last_dir = player->MovDir;
580 if (player->MovDir == MV_LEFT)
582 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
583 else if (player->MovDir == MV_RIGHT)
585 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
586 else if (player->MovDir == MV_UP)
587 graphic = GFX_SPIELER1_UP;
588 else /* MV_DOWN || MV_NO_MOVING */
589 graphic = GFX_SPIELER1_DOWN;
591 graphic += player->index_nr * 3 * HEROES_PER_LINE;
592 graphic += player->Frame;
597 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
598 sxx = player->GfxPos;
600 syy = player->GfxPos;
603 if (!setup.soft_scrolling && ScreenMovPos)
606 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
608 if (player->Pushing && player->GfxPos)
610 int px = SCREENX(next_jx), py = SCREENY(next_jy);
612 if (element == EL_SOKOBAN_FELD_LEER ||
613 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
614 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
618 int element = Feld[next_jx][next_jy];
619 int graphic = el2gfx(element);
621 if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK) && sxx)
623 int phase = (player->GfxPos / (TILEX / 4));
625 if (player->MovDir == MV_LEFT)
628 graphic += (phase + 4) % 4;
631 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
635 /* draw things in front of player (EL_DYNAMIT or EL_DYNABOMB) */
637 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
639 graphic = el2gfx(element);
641 if (element == EL_DYNAMIT)
643 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
648 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
652 if (game_emulation == EMU_SUPAPLEX)
653 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
655 DrawGraphicThruMask(sx, sy, graphic + phase);
659 if ((last_jx != jx || last_jy != jy) && last_element == EL_EXPLODING)
662 if (player_is_moving && last_element == EL_EXPLODING)
664 int phase = Frame[last_jx][last_jy];
668 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
669 GFX_EXPLOSION + ((phase - 1) / delay - 1));
672 /* draw elements that stay over the player */
673 /* handle the field the player is leaving ... */
674 if (player_is_moving && IS_OVER_PLAYER(last_element))
675 DrawLevelField(last_jx, last_jy);
676 /* ... and the field the player is entering */
677 if (IS_OVER_PLAYER(element))
678 DrawLevelField(jx, jy);
680 if (setup.direct_draw)
682 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
683 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
684 int x_size = TILEX * (1 + ABS(jx - last_jx));
685 int y_size = TILEY * (1 + ABS(jy - last_jy));
687 XCopyArea(display, drawto_field, window, gc,
688 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
689 SetDrawtoField(DRAW_DIRECT);
692 MarkTileDirty(sx,sy);
695 static int getGraphicAnimationPhase(int frames, int delay, int mode)
699 if (mode == ANIM_OSCILLATE)
701 int max_anim_frames = 2 * frames - 2;
702 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
703 phase = (phase < frames ? phase : max_anim_frames - phase);
706 phase = (FrameCounter % (delay * frames)) / delay;
708 if (mode == ANIM_REVERSE)
714 void DrawGraphicAnimationExt(int x, int y, int graphic,
715 int frames, int delay, int mode, int mask_mode)
717 int phase = getGraphicAnimationPhase(frames, delay, mode);
719 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
721 if (mask_mode == USE_MASKING)
722 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
724 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
728 void DrawGraphicAnimation(int x, int y, int graphic,
729 int frames, int delay, int mode)
731 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
734 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
735 int frames, int delay, int mode)
737 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
740 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
742 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
744 graphic -= GFX_START_ROCKSSCREEN;
745 *pixmap_nr = PIX_BACK;
746 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
747 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
749 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
751 graphic -= GFX_START_ROCKSMORE;
752 *pixmap_nr = PIX_MORE;
753 *x = (graphic % MORE_PER_LINE) * TILEX;
754 *y = (graphic / MORE_PER_LINE) * TILEY;
756 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
758 graphic -= GFX_START_ROCKSHEROES;
759 *pixmap_nr = PIX_HEROES;
760 *x = (graphic % HEROES_PER_LINE) * TILEX;
761 *y = (graphic / HEROES_PER_LINE) * TILEY;
763 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
765 graphic -= GFX_START_ROCKSFONT;
766 *pixmap_nr = PIX_BIGFONT;
767 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
768 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
769 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
773 *pixmap_nr = PIX_MORE;
779 void DrawGraphic(int x, int y, int graphic)
782 if (!IN_SCR_FIELD(x,y))
784 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
785 printf("DrawGraphic(): This should never happen!\n");
790 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
794 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
802 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
803 XCopyArea(display, pix[pixmap_nr], d, gc,
804 src_x, src_y, TILEX, TILEY, x, y);
808 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
810 graphic -= GFX_START_ROCKSSCREEN;
811 XCopyArea(display, pix[PIX_BACK], d, gc,
812 SX + (graphic % GFX_PER_LINE) * TILEX,
813 SY + (graphic / GFX_PER_LINE) * TILEY,
816 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
818 graphic -= GFX_START_ROCKSMORE;
819 XCopyArea(display, pix[PIX_MORE], d, gc,
820 (graphic % MORE_PER_LINE) * TILEX,
821 (graphic / MORE_PER_LINE) * TILEY,
824 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
826 graphic -= GFX_START_ROCKSHEROES;
827 XCopyArea(display, pix[PIX_HEROES], d, gc,
828 (graphic % HEROES_PER_LINE) * TILEX,
829 (graphic / HEROES_PER_LINE) * TILEY,
832 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
834 graphic -= GFX_START_ROCKSFONT;
835 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
836 (graphic % FONT_CHARS_PER_LINE) * TILEX,
837 (graphic / FONT_CHARS_PER_LINE) * TILEY +
838 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
842 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
848 void DrawGraphicThruMask(int x, int y, int graphic)
851 if (!IN_SCR_FIELD(x,y))
853 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
854 printf("DrawGraphicThruMask(): This should never happen!\n");
859 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
863 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
874 if (graphic == GFX_LEERRAUM)
877 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
878 src_pixmap = pix[pixmap_nr];
879 drawing_gc = clip_gc[pixmap_nr];
888 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
890 src_pixmap = pix[PIX_BACK];
891 drawing_gc = clip_gc[PIX_BACK];
892 graphic -= GFX_START_ROCKSSCREEN;
893 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
894 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
896 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
898 src_pixmap = pix[PIX_MORE];
899 drawing_gc = clip_gc[PIX_MORE];
900 graphic -= GFX_START_ROCKSMORE;
901 src_x = (graphic % MORE_PER_LINE) * TILEX;
902 src_y = (graphic / MORE_PER_LINE) * TILEY;
904 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
906 src_pixmap = pix[PIX_HEROES];
907 drawing_gc = clip_gc[PIX_HEROES];
908 graphic -= GFX_START_ROCKSHEROES;
909 src_x = (graphic % HEROES_PER_LINE) * TILEX;
910 src_y = (graphic / HEROES_PER_LINE) * TILEY;
914 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
921 if (tile_clipmask[tile] != None)
923 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
924 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
925 XCopyArea(display, src_pixmap, d, tile_clip_gc,
926 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
931 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
934 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
935 XCopyArea(display, src_pixmap, d, drawing_gc,
936 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
940 void DrawMiniGraphic(int x, int y, int graphic)
942 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
943 MarkTileDirty(x/2, y/2);
946 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
948 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
950 graphic -= GFX_START_ROCKSSCREEN;
951 *pixmap = pix[PIX_BACK];
952 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
953 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
955 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
957 graphic -= GFX_START_ROCKSMORE;
958 graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
959 *pixmap = pix[PIX_MORE];
960 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
961 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
963 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
965 graphic -= GFX_START_ROCKSFONT;
966 *pixmap = pix[PIX_SMALLFONT];
967 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
968 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
969 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
973 *pixmap = pix[PIX_MORE];
974 *x = MINI_MORE_STARTX;
975 *y = MINI_MORE_STARTY;
979 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
987 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
988 XCopyArea(display, pixmap, d, gc,
989 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
993 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
995 graphic -= GFX_START_ROCKSSCREEN;
996 XCopyArea(display, pix[PIX_BACK], d, gc,
997 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
998 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
999 MINI_TILEX, MINI_TILEY, x, y);
1001 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1003 graphic -= GFX_START_ROCKSMORE;
1004 XCopyArea(display, pix[PIX_MORE], d, gc,
1005 MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
1006 MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
1007 MINI_TILEX, MINI_TILEY, x, y);
1009 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
1011 graphic -= GFX_START_ROCKSFONT;
1012 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
1013 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
1014 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
1015 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
1016 MINI_TILEX, MINI_TILEY, x, y);
1019 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
1025 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1026 int cut_mode, int mask_mode)
1028 int width = TILEX, height = TILEY;
1030 int src_x, src_y, dest_x, dest_y;
1037 DrawGraphic(x, y, graphic);
1041 if (dx || dy) /* Verschiebung der Grafik? */
1043 if (x < BX1) /* Element kommt von links ins Bild */
1050 else if (x > BX2) /* Element kommt von rechts ins Bild */
1056 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1062 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1064 else if (dx) /* allg. Bewegung in x-Richtung */
1065 MarkTileDirty(x + SIGN(dx), y);
1067 if (y < BY1) /* Element kommt von oben ins Bild */
1069 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1077 else if (y > BY2) /* Element kommt von unten ins Bild */
1083 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1089 else if (dy > 0 && cut_mode == CUT_ABOVE)
1091 if (y == BY2) /* Element unterhalb des Bildes */
1097 MarkTileDirty(x, y + 1);
1098 } /* Element verläßt unten das Bild */
1099 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1101 else if (dy) /* allg. Bewegung in y-Richtung */
1102 MarkTileDirty(x, y + SIGN(dy));
1105 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
1107 src_pixmap = pix[PIX_BACK];
1108 drawing_gc = clip_gc[PIX_BACK];
1109 graphic -= GFX_START_ROCKSSCREEN;
1110 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
1111 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
1113 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1115 src_pixmap = pix[PIX_MORE];
1116 drawing_gc = clip_gc[PIX_MORE];
1117 graphic -= GFX_START_ROCKSMORE;
1118 src_x = (graphic % MORE_PER_LINE) * TILEX + cx;
1119 src_y = (graphic / MORE_PER_LINE) * TILEY + cy;
1121 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
1123 src_pixmap = pix[PIX_HEROES];
1124 drawing_gc = clip_gc[PIX_HEROES];
1125 graphic -= GFX_START_ROCKSHEROES;
1126 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
1127 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
1129 else /* big font graphics currently not allowed (and not needed) */
1132 dest_x = FX + x * TILEX + dx;
1133 dest_y = FY + y * TILEY + dy;
1136 if (!IN_SCR_FIELD(x,y))
1138 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1139 printf("DrawGraphicShifted(): This should never happen!\n");
1144 if (mask_mode == USE_MASKING)
1146 if (tile_clipmask[tile] != None)
1148 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
1149 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1150 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1151 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1156 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1159 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1160 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1161 src_x, src_y, width, height, dest_x, dest_y);
1165 XCopyArea(display, src_pixmap, drawto_field, gc,
1166 src_x, src_y, width, height, dest_x, dest_y);
1171 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1174 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1177 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1178 int cut_mode, int mask_mode)
1180 int ux = LEVELX(x), uy = LEVELY(y);
1181 int graphic = el2gfx(element);
1182 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1183 int phase4 = phase8 / 2;
1184 int phase2 = phase8 / 4;
1185 int dir = MovDir[ux][uy];
1187 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1189 graphic += 4 * !phase2;
1193 else if (dir == MV_LEFT)
1195 else if (dir == MV_DOWN)
1198 else if (element == EL_SP_SNIKSNAK)
1201 graphic = GFX_SP_SNIKSNAK_LEFT;
1202 else if (dir == MV_RIGHT)
1203 graphic = GFX_SP_SNIKSNAK_RIGHT;
1204 else if (dir == MV_UP)
1205 graphic = GFX_SP_SNIKSNAK_UP;
1207 graphic = GFX_SP_SNIKSNAK_DOWN;
1209 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1211 else if (element == EL_SP_ELECTRON)
1213 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1215 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1216 element == EL_SCHWEIN || element == EL_DRACHE)
1219 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1220 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1221 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1222 else if (dir == MV_RIGHT)
1223 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1224 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1225 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1226 else if (dir == MV_UP)
1227 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1228 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1229 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1231 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1232 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1233 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1237 else if (element == EL_SONDE)
1239 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1241 else if (element == EL_SALZSAEURE)
1243 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1245 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1249 else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
1250 IS_GEM(element)) && !cut_mode)
1252 if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
1255 graphic += (4 - phase4) % 4;
1256 else if (dir == MV_RIGHT)
1259 graphic += phase2 * 2;
1261 else if (element != EL_SP_INFOTRON)
1265 if (element == EL_SP_ZONK)
1268 graphic += (4 - phase4) % 4;
1269 else if (dir == MV_RIGHT)
1272 graphic += phase2 * 2;
1274 else if (element != EL_SP_INFOTRON)
1275 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1279 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1280 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1282 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1284 else if (IS_AMOEBOID(element))
1286 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1287 graphic += (x + 2 * y + 4) % 4;
1289 else if (element == EL_MAUER_LEBT)
1291 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1293 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1294 links_massiv = TRUE;
1295 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1296 rechts_massiv = TRUE;
1298 if (links_massiv && rechts_massiv)
1299 graphic = GFX_MAUERWERK;
1300 else if (links_massiv)
1301 graphic = GFX_MAUER_R;
1302 else if (rechts_massiv)
1303 graphic = GFX_MAUER_L;
1307 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1308 else if (mask_mode == USE_MASKING)
1309 DrawGraphicThruMask(x, y, graphic);
1311 DrawGraphic(x, y, graphic);
1314 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1315 int cut_mode, int mask_mode)
1317 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1318 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1319 cut_mode, mask_mode);
1322 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1325 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1328 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1331 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1334 void DrawScreenElementThruMask(int x, int y, int element)
1336 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1339 void DrawLevelElementThruMask(int x, int y, int element)
1341 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1344 void DrawLevelFieldThruMask(int x, int y)
1346 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1349 void ErdreichAnbroeckeln(int x, int y)
1351 int i, width, height, cx,cy;
1352 int ux = LEVELX(x), uy = LEVELY(y);
1353 int element, graphic;
1355 static int xy[4][2] =
1363 if (!IN_LEV_FIELD(ux, uy))
1366 element = Feld[ux][uy];
1368 if (element == EL_ERDREICH)
1370 if (!IN_SCR_FIELD(x, y))
1373 graphic = GFX_ERDENRAND;
1379 uxx = ux + xy[i][0];
1380 uyy = uy + xy[i][1];
1381 if (!IN_LEV_FIELD(uxx, uyy))
1384 element = Feld[uxx][uyy];
1386 if (element == EL_ERDREICH)
1389 if (i == 1 || i == 2)
1393 cx = (i == 2 ? TILEX - snip : 0);
1401 cy = (i == 3 ? TILEY - snip : 0);
1404 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1405 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1406 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1407 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1410 MarkTileDirty(x, y);
1414 graphic = GFX_ERDENRAND;
1418 int xx, yy, uxx, uyy;
1422 uxx = ux + xy[i][0];
1423 uyy = uy + xy[i][1];
1425 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1426 !IN_SCR_FIELD(xx, yy))
1429 if (i == 1 || i == 2)
1433 cx = (i == 1 ? TILEX - snip : 0);
1441 cy = (i==0 ? TILEY-snip : 0);
1444 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1445 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1446 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1447 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1449 MarkTileDirty(xx, yy);
1454 void DrawScreenElement(int x, int y, int element)
1456 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1457 ErdreichAnbroeckeln(x, y);
1460 void DrawLevelElement(int x, int y, int element)
1462 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1463 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1466 void DrawScreenField(int x, int y)
1468 int ux = LEVELX(x), uy = LEVELY(y);
1471 if (!IN_LEV_FIELD(ux, uy))
1473 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1474 element = EL_LEERRAUM;
1476 element = BorderElement;
1478 DrawScreenElement(x, y, element);
1482 element = Feld[ux][uy];
1484 if (IS_MOVING(ux, uy))
1486 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1487 boolean cut_mode = NO_CUTTING;
1489 if (Store[ux][uy] == EL_MORAST_LEER ||
1490 Store[ux][uy] == EL_SIEB_LEER ||
1491 Store[ux][uy] == EL_SIEB2_LEER ||
1492 Store[ux][uy] == EL_AMOEBE_NASS)
1493 cut_mode = CUT_ABOVE;
1494 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1495 Store[ux][uy] == EL_SIEB_VOLL ||
1496 Store[ux][uy] == EL_SIEB2_VOLL)
1497 cut_mode = CUT_BELOW;
1499 if (cut_mode == CUT_ABOVE)
1500 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1502 DrawScreenElement(x, y, EL_LEERRAUM);
1505 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1507 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1509 if (Store[ux][uy] == EL_SALZSAEURE)
1510 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1512 else if (IS_BLOCKED(ux, uy))
1517 boolean cut_mode = NO_CUTTING;
1519 Blocked2Moving(ux, uy, &oldx, &oldy);
1522 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1523 MovDir[oldx][oldy] == MV_RIGHT);
1525 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1526 Store[oldx][oldy] == EL_SIEB_LEER ||
1527 Store[oldx][oldy] == EL_SIEB2_LEER ||
1528 Store[oldx][oldy] == EL_AMOEBE_NASS)
1529 cut_mode = CUT_ABOVE;
1531 DrawScreenElement(x, y, EL_LEERRAUM);
1532 element = Feld[oldx][oldy];
1535 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1537 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1539 else if (IS_DRAWABLE(element))
1540 DrawScreenElement(x, y, element);
1542 DrawScreenElement(x, y, EL_LEERRAUM);
1545 void DrawLevelField(int x, int y)
1547 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1548 DrawScreenField(SCREENX(x), SCREENY(y));
1549 else if (IS_MOVING(x, y))
1553 Moving2Blocked(x, y, &newx, &newy);
1554 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1555 DrawScreenField(SCREENX(newx), SCREENY(newy));
1557 else if (IS_BLOCKED(x, y))
1561 Blocked2Moving(x, y, &oldx, &oldy);
1562 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1563 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1567 void DrawMiniElement(int x, int y, int element)
1573 DrawMiniGraphic(x, y, -1);
1577 graphic = el2gfx(element);
1578 DrawMiniGraphic(x, y, graphic);
1581 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1583 int x = sx + scroll_x, y = sy + scroll_y;
1585 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1586 DrawMiniElement(sx, sy, EL_LEERRAUM);
1587 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1588 DrawMiniElement(sx, sy, Feld[x][y]);
1591 int steel_type, steel_position;
1594 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1595 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1596 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1597 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1598 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1599 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1602 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1603 steel_position = (x == -1 && y == -1 ? 0 :
1604 x == lev_fieldx && y == -1 ? 1 :
1605 x == -1 && y == lev_fieldy ? 2 :
1606 x == lev_fieldx && y == lev_fieldy ? 3 :
1607 x == -1 || x == lev_fieldx ? 4 :
1608 y == -1 || y == lev_fieldy ? 5 : -1);
1610 if (steel_position != -1)
1611 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1615 if (x == -1 && y == -1)
1616 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_LEFT);
1617 else if (x == lev_fieldx && y == -1)
1618 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_RIGHT);
1619 else if (x == -1 && y == lev_fieldy)
1620 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_LEFT);
1621 else if (x == lev_fieldx && y == lev_fieldy)
1622 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_RIGHT);
1623 else if (x == -1 || x == lev_fieldx)
1624 DrawMiniGraphic(sx, sy, GFX_STEEL_VERTICAL);
1625 else if (y == -1 || y == lev_fieldy)
1626 DrawMiniGraphic(sx, sy, GFX_STEEL_HORIZONTAL);
1633 void DrawMicroElement(int xpos, int ypos, int element)
1637 if (element == EL_LEERRAUM)
1640 graphic = el2gfx(element);
1642 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1644 graphic -= GFX_START_ROCKSMORE;
1645 graphic -= ((graphic / MORE_PER_LINE) * MORE_PER_LINE) / 2;
1646 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1647 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1648 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1649 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1652 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1653 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1654 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1655 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1664 for(x=BX1; x<=BX2; x++)
1665 for(y=BY1; y<=BY2; y++)
1666 DrawScreenField(x, y);
1668 if (setup.soft_scrolling)
1669 XCopyArea(display, fieldbuffer, backbuffer, gc,
1670 FX, FY, SXSIZE, SYSIZE, SX, SY);
1672 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1675 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1679 for(x=0; x<size_x; x++)
1680 for(y=0; y<size_y; y++)
1681 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1683 redraw_mask |= REDRAW_FIELD;
1686 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1690 /* determine border element for this level */
1693 XFillRectangle(display, drawto, gc,
1694 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1696 if (lev_fieldx < STD_LEV_FIELDX)
1697 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1698 if (lev_fieldy < STD_LEV_FIELDY)
1699 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1701 xpos += MICRO_TILEX;
1702 ypos += MICRO_TILEY;
1704 for(x=-1; x<=STD_LEV_FIELDX; x++)
1706 for(y=-1; y<=STD_LEV_FIELDY; y++)
1708 int lx = from_x + x, ly = from_y + y;
1710 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1711 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1713 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1714 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1719 redraw_mask |= REDRAW_MICROLEVEL;
1722 static void DrawMicroLevelLabelExt(int mode)
1724 char label_text[100];
1726 XFillRectangle(display, drawto,gc,
1727 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1729 strcpy(label_text, (mode == 1 ? level.name :
1730 mode == 2 ? "created by" :
1731 mode == 3 ? level.author : ""));
1733 if (strlen(label_text) > 0)
1735 int size, lxpos, lypos;
1737 label_text[SXSIZE / FONT4_XSIZE] = '\0';
1739 size = strlen(label_text);
1740 lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1741 lypos = MICROLABEL_YPOS;
1743 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1746 redraw_mask |= REDRAW_MICROLEVEL;
1749 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1751 static unsigned long scroll_delay = 0;
1752 static unsigned long label_delay = 0;
1753 static int from_x, from_y, scroll_direction;
1754 static int label_state, label_counter;
1758 from_x = from_y = 0;
1759 scroll_direction = MV_RIGHT;
1763 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1764 DrawMicroLevelLabelExt(label_state);
1766 /* initialize delay counters */
1767 DelayReached(&scroll_delay, 0);
1768 DelayReached(&label_delay, 0);
1773 /* scroll micro level, if needed */
1774 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1775 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1777 switch (scroll_direction)
1783 scroll_direction = MV_UP;
1787 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1790 scroll_direction = MV_DOWN;
1797 scroll_direction = MV_RIGHT;
1801 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1804 scroll_direction = MV_LEFT;
1811 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1814 /* redraw micro level label, if needed */
1815 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1816 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1817 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1818 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1820 label_counter = (label_counter + 1) % 23;
1821 label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1822 label_counter >= 9 && label_counter <= 12 ? 2 :
1823 label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1824 DrawMicroLevelLabelExt(label_state);
1828 int REQ_in_range(int x, int y)
1830 if (y > DY+249 && y < DY+278)
1832 if (x > DX+1 && x < DX+48)
1834 else if (x > DX+51 && x < DX+98)
1840 boolean Request(char *text, unsigned int req_state)
1842 int mx, my, ty, result = -1;
1843 unsigned int old_door_state;
1846 /* pause network game while waiting for request to answer */
1847 if (options.network &&
1848 game_status == PLAYING &&
1849 req_state & REQUEST_WAIT_FOR)
1850 SendToServer_PausePlaying();
1853 old_door_state = GetDoorState();
1857 CloseDoor(DOOR_CLOSE_1);
1859 /* save old door content */
1860 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1861 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1862 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1864 /* clear door drawing field */
1865 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1867 /* write text for request */
1868 for(ty=0; ty<13; ty++)
1876 for(tl=0,tx=0; tx<7; tl++,tx++)
1879 if (!tc || tc == 32)
1890 DrawTextExt(drawto, gc,
1891 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1892 txt, FS_SMALL, FC_YELLOW);
1893 text += tl + (tc == 32 ? 1 : 0);
1896 if (req_state & REQ_ASK)
1898 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1899 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1901 else if (req_state & REQ_CONFIRM)
1903 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1905 else if (req_state & REQ_PLAYER)
1907 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1908 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1909 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1910 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1913 /* copy request gadgets to door backbuffer */
1914 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1915 DX, DY, DXSIZE, DYSIZE,
1916 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1918 OpenDoor(DOOR_OPEN_1);
1921 if (!(req_state & REQUEST_WAIT_FOR))
1924 if (game_status != MAINMENU)
1927 button_status = MB_RELEASED;
1929 request_gadget_id = -1;
1933 if (XPending(display))
1937 XNextEvent(display, &event);
1945 if (event.type == MotionNotify)
1952 if (!XQueryPointer(display, window, &root, &child,
1953 &root_x, &root_y, &win_x, &win_y, &mask))
1959 motion_status = TRUE;
1960 mx = ((XMotionEvent *) &event)->x;
1961 my = ((XMotionEvent *) &event)->y;
1965 motion_status = FALSE;
1966 mx = ((XButtonEvent *) &event)->x;
1967 my = ((XButtonEvent *) &event)->y;
1968 if (event.type==ButtonPress)
1969 button_status = ((XButtonEvent *) &event)->button;
1971 button_status = MB_RELEASED;
1974 /* this sets 'request_gadget_id' */
1975 HandleGadgets(mx, my, button_status);
1977 switch(request_gadget_id)
1979 case TOOL_CTRL_ID_YES:
1982 case TOOL_CTRL_ID_NO:
1985 case TOOL_CTRL_ID_CONFIRM:
1986 result = TRUE | FALSE;
1989 case TOOL_CTRL_ID_PLAYER_1:
1992 case TOOL_CTRL_ID_PLAYER_2:
1995 case TOOL_CTRL_ID_PLAYER_3:
1998 case TOOL_CTRL_ID_PLAYER_4:
2010 switch(XLookupKeysym((XKeyEvent *)&event,
2011 ((XKeyEvent *)&event)->state))
2024 if (req_state & REQ_PLAYER)
2029 key_joystick_mapping = 0;
2033 HandleOtherEvents(&event);
2037 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2039 int joy = AnyJoystick();
2041 if (joy & JOY_BUTTON_1)
2043 else if (joy & JOY_BUTTON_2)
2049 /* don't eat all CPU time */
2053 if (game_status != MAINMENU)
2058 if (!(req_state & REQ_STAY_OPEN))
2060 CloseDoor(DOOR_CLOSE_1);
2062 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2064 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
2065 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2066 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2067 OpenDoor(DOOR_OPEN_1);
2074 /* continue network game after request */
2075 if (options.network &&
2076 game_status == PLAYING &&
2077 req_state & REQUEST_WAIT_FOR)
2078 SendToServer_ContinuePlaying();
2084 unsigned int OpenDoor(unsigned int door_state)
2086 unsigned int new_door_state;
2088 if (door_state & DOOR_COPY_BACK)
2090 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
2091 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2092 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2093 door_state &= ~DOOR_COPY_BACK;
2096 new_door_state = MoveDoor(door_state);
2098 return(new_door_state);
2101 unsigned int CloseDoor(unsigned int door_state)
2103 unsigned int new_door_state;
2105 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2106 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2107 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2108 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2110 new_door_state = MoveDoor(door_state);
2112 return(new_door_state);
2115 unsigned int GetDoorState()
2117 return(MoveDoor(DOOR_GET_STATE));
2120 unsigned int MoveDoor(unsigned int door_state)
2122 static int door1 = DOOR_OPEN_1;
2123 static int door2 = DOOR_CLOSE_2;
2124 static unsigned long door_delay = 0;
2125 int x, start, stepsize = 2;
2126 unsigned long door_delay_value = stepsize * 5;
2128 if (door_state == DOOR_GET_STATE)
2129 return(door1 | door2);
2131 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2132 door_state &= ~DOOR_OPEN_1;
2133 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2134 door_state &= ~DOOR_CLOSE_1;
2135 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2136 door_state &= ~DOOR_OPEN_2;
2137 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2138 door_state &= ~DOOR_CLOSE_2;
2140 if (setup.quick_doors)
2143 door_delay_value = 0;
2144 StopSound(SND_OEFFNEN);
2147 if (door_state & DOOR_ACTION)
2149 if (!(door_state & DOOR_NO_DELAY))
2150 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2152 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2154 for(x=start; x<=DXSIZE; x+=stepsize)
2156 WaitUntilDelayReached(&door_delay, door_delay_value);
2158 if (door_state & DOOR_ACTION_1)
2160 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2161 int j = (DXSIZE - i) / 3;
2163 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2164 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2165 DXSIZE,DYSIZE - i/2, DX, DY);
2167 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2169 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2170 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2171 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2172 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2173 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2174 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2176 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2177 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2178 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2179 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2180 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2181 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2183 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2184 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2186 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2187 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2189 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2190 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2191 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2192 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2193 DX + DXSIZE - i, DY + 77 + j);
2194 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2195 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2196 DX + DXSIZE - i, DY + 203 + j);
2198 redraw_mask |= REDRAW_DOOR_1;
2201 if (door_state & DOOR_ACTION_2)
2203 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2204 int j = (VXSIZE - i) / 3;
2206 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2207 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2208 VXSIZE, VYSIZE - i/2, VX, VY);
2210 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2212 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2213 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2214 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2215 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2216 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2217 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2218 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2219 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2221 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2222 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2223 VX, VY + VYSIZE / 2 - j);
2224 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2225 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2226 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2227 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2228 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2230 redraw_mask |= REDRAW_DOOR_2;
2238 XCopyArea(display, drawto, window, gc, DX, DY, DXSIZE, DYSIZE, DX, DY);
2243 if (game_status == MAINMENU)
2248 if (setup.quick_doors)
2249 StopSound(SND_OEFFNEN);
2251 if (door_state & DOOR_ACTION_1)
2252 door1 = door_state & DOOR_ACTION_1;
2253 if (door_state & DOOR_ACTION_2)
2254 door2 = door_state & DOOR_ACTION_2;
2256 return(door1 | door2);
2259 int ReadPixel(Drawable d, int x, int y)
2261 XImage *pixel_image;
2262 unsigned long pixel_value;
2264 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2265 pixel_value = XGetPixel(pixel_image, 0, 0);
2267 XDestroyImage(pixel_image);
2272 /* ---------- new tool button stuff ---------------------------------------- */
2274 /* graphic position values for tool buttons */
2275 #define TOOL_BUTTON_YES_XPOS 2
2276 #define TOOL_BUTTON_YES_YPOS 250
2277 #define TOOL_BUTTON_YES_GFX_YPOS 0
2278 #define TOOL_BUTTON_YES_XSIZE 46
2279 #define TOOL_BUTTON_YES_YSIZE 28
2280 #define TOOL_BUTTON_NO_XPOS 52
2281 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2282 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2283 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2284 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2285 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2286 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2287 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2288 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2289 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2290 #define TOOL_BUTTON_PLAYER_XSIZE 30
2291 #define TOOL_BUTTON_PLAYER_YSIZE 30
2292 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2293 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2294 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2295 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2296 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2297 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2298 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2299 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2300 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2301 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2302 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2303 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2304 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2305 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2306 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2307 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2308 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2309 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2310 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2311 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2320 } toolbutton_info[NUM_TOOL_BUTTONS] =
2323 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2324 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2325 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2330 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2331 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2332 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2337 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2338 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2339 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2340 TOOL_CTRL_ID_CONFIRM,
2344 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2345 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2346 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2347 TOOL_CTRL_ID_PLAYER_1,
2351 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2352 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2353 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2354 TOOL_CTRL_ID_PLAYER_2,
2358 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2359 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2360 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2361 TOOL_CTRL_ID_PLAYER_3,
2365 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2366 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2367 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2368 TOOL_CTRL_ID_PLAYER_4,
2373 void CreateToolButtons()
2377 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2379 Pixmap gd_pixmap = pix[PIX_DOOR];
2380 Pixmap deco_pixmap = None;
2381 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2382 struct GadgetInfo *gi;
2383 unsigned long event_mask;
2384 int gd_xoffset, gd_yoffset;
2385 int gd_x1, gd_x2, gd_y;
2388 event_mask = GD_EVENT_RELEASED;
2390 gd_xoffset = toolbutton_info[i].xpos;
2391 gd_yoffset = toolbutton_info[i].ypos;
2392 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2393 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2394 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2396 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2398 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2399 &deco_pixmap, &deco_x, &deco_y);
2400 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2401 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2404 gi = CreateGadget(GDI_CUSTOM_ID, id,
2405 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2406 GDI_X, DX + toolbutton_info[i].x,
2407 GDI_Y, DY + toolbutton_info[i].y,
2408 GDI_WIDTH, toolbutton_info[i].width,
2409 GDI_HEIGHT, toolbutton_info[i].height,
2410 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2411 GDI_STATE, GD_BUTTON_UNPRESSED,
2412 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2413 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2414 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2415 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2416 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2417 GDI_DECORATION_SHIFTING, 1, 1,
2418 GDI_EVENT_MASK, event_mask,
2419 GDI_CALLBACK_ACTION, HandleToolButtons,
2423 Error(ERR_EXIT, "cannot create gadget");
2425 tool_gadget[id] = gi;
2429 static void UnmapToolButtons()
2433 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2434 UnmapGadget(tool_gadget[i]);
2437 static void HandleToolButtons(struct GadgetInfo *gi)
2439 request_gadget_id = gi->custom_id;
2443 int id = gi->custom_id;
2445 if (game_status != PLAYING)
2450 case GAME_CTRL_ID_STOP:
2453 CloseDoor(DOOR_CLOSE_1);
2454 game_status = MAINMENU;
2459 if (Request("Do you really want to quit the game ?",
2460 REQ_ASK | REQ_STAY_CLOSED))
2463 if (options.network)
2464 SendToServer_StopPlaying();
2468 game_status = MAINMENU;
2473 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2476 case GAME_CTRL_ID_PAUSE:
2477 if (options.network)
2481 SendToServer_ContinuePlaying();
2483 SendToServer_PausePlaying();
2490 case GAME_CTRL_ID_PLAY:
2494 if (options.network)
2495 SendToServer_ContinuePlaying();
2499 tape.pausing = FALSE;
2500 DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
2505 case SOUND_CTRL_ID_MUSIC:
2506 if (setup.sound_music)
2508 setup.sound_music = FALSE;
2509 FadeSound(background_loop[level_nr % num_bg_loops]);
2511 else if (sound_loops_allowed)
2513 setup.sound = setup.sound_music = TRUE;
2514 PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
2518 case SOUND_CTRL_ID_LOOPS:
2519 if (setup.sound_loops)
2520 setup.sound_loops = FALSE;
2521 else if (sound_loops_allowed)
2522 setup.sound = setup.sound_loops = TRUE;
2525 case SOUND_CTRL_ID_SIMPLE:
2526 if (setup.sound_simple)
2527 setup.sound_simple = FALSE;
2528 else if (sound_status==SOUND_AVAILABLE)
2529 setup.sound = setup.sound_simple = TRUE;
2541 int el2gfx(int element)
2545 case EL_LEERRAUM: return -1;
2546 case EL_ERDREICH: return GFX_ERDREICH;
2547 case EL_MAUERWERK: return GFX_MAUERWERK;
2548 case EL_FELSBODEN: return GFX_FELSBODEN;
2549 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2550 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2551 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2552 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2553 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2554 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2555 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2556 case EL_SPIELER1: return GFX_SPIELER1;
2557 case EL_SPIELER2: return GFX_SPIELER2;
2558 case EL_SPIELER3: return GFX_SPIELER3;
2559 case EL_SPIELER4: return GFX_SPIELER4;
2560 case EL_KAEFER: return GFX_KAEFER;
2561 case EL_KAEFER_R: return GFX_KAEFER_R;
2562 case EL_KAEFER_O: return GFX_KAEFER_O;
2563 case EL_KAEFER_L: return GFX_KAEFER_L;
2564 case EL_KAEFER_U: return GFX_KAEFER_U;
2565 case EL_FLIEGER: return GFX_FLIEGER;
2566 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2567 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2568 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2569 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2570 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2571 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2572 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2573 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2574 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2575 case EL_FIREFLY: return GFX_FIREFLY;
2576 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2577 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2578 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2579 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2580 case EL_MAMPFER: return GFX_MAMPFER;
2581 case EL_ROBOT: return GFX_ROBOT;
2582 case EL_BETON: return GFX_BETON;
2583 case EL_DIAMANT: return GFX_DIAMANT;
2584 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2585 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2586 case EL_TROPFEN: return GFX_TROPFEN;
2587 case EL_BOMBE: return GFX_BOMBE;
2588 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2589 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2590 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2591 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2592 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2593 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2594 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2595 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2596 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2597 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2598 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2599 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2600 case EL_LIFE: return GFX_LIFE;
2601 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2602 case EL_DYNAMIT: return GFX_DYNAMIT;
2603 case EL_BADEWANNE: return GFX_BADEWANNE;
2604 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2605 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2606 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2607 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2608 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2609 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2610 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2611 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2612 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2613 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2614 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2615 case EL_PFORTE1: return GFX_PFORTE1;
2616 case EL_PFORTE2: return GFX_PFORTE2;
2617 case EL_PFORTE3: return GFX_PFORTE3;
2618 case EL_PFORTE4: return GFX_PFORTE4;
2619 case EL_PFORTE1X: return GFX_PFORTE1X;
2620 case EL_PFORTE2X: return GFX_PFORTE2X;
2621 case EL_PFORTE3X: return GFX_PFORTE3X;
2622 case EL_PFORTE4X: return GFX_PFORTE4X;
2623 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
2624 case EL_PACMAN: return GFX_PACMAN;
2625 case EL_PACMAN_R: return GFX_PACMAN_R;
2626 case EL_PACMAN_O: return GFX_PACMAN_O;
2627 case EL_PACMAN_L: return GFX_PACMAN_L;
2628 case EL_PACMAN_U: return GFX_PACMAN_U;
2629 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2630 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2631 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2632 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2633 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2634 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2635 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2636 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2637 case EL_MAUER_X: return GFX_MAUER_X;
2638 case EL_MAUER_Y: return GFX_MAUER_Y;
2639 case EL_MAUER_XY: return GFX_MAUER_XY;
2640 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2641 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2642 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2643 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2644 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2645 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2646 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2647 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2648 case EL_MAMPFER2: return GFX_MAMPFER2;
2649 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2650 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2651 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2652 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2653 case EL_DYNABOMB: return GFX_DYNABOMB;
2654 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2655 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2656 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2657 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2658 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2659 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2660 case EL_MAULWURF: return GFX_MAULWURF;
2661 case EL_PINGUIN: return GFX_PINGUIN;
2662 case EL_SCHWEIN: return GFX_SCHWEIN;
2663 case EL_DRACHE: return GFX_DRACHE;
2664 case EL_SONDE: return GFX_SONDE;
2665 case EL_PFEIL_L: return GFX_PFEIL_L;
2666 case EL_PFEIL_R: return GFX_PFEIL_R;
2667 case EL_PFEIL_O: return GFX_PFEIL_O;
2668 case EL_PFEIL_U: return GFX_PFEIL_U;
2669 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2670 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2671 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2672 case EL_SP_ZONK: return GFX_SP_ZONK;
2673 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2674 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2675 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2676 case EL_EM_GATE_1: return GFX_EM_GATE_1;
2677 case EL_EM_GATE_2: return GFX_EM_GATE_2;
2678 case EL_EM_GATE_3: return GFX_EM_GATE_3;
2679 case EL_EM_GATE_4: return GFX_EM_GATE_4;
2680 case EL_EM_GATE_1X: return GFX_EM_GATE_1X;
2681 case EL_EM_GATE_2X: return GFX_EM_GATE_2X;
2682 case EL_EM_GATE_3X: return GFX_EM_GATE_3X;
2683 case EL_EM_GATE_4X: return GFX_EM_GATE_4X;
2684 case EL_EM_KEY_1_FILE: return GFX_EM_KEY_1;
2685 case EL_EM_KEY_2_FILE: return GFX_EM_KEY_2;
2686 case EL_EM_KEY_3_FILE: return GFX_EM_KEY_3;
2687 case EL_EM_KEY_4_FILE: return GFX_EM_KEY_4;
2688 case EL_EM_KEY_1: return GFX_EM_KEY_1;
2689 case EL_EM_KEY_2: return GFX_EM_KEY_2;
2690 case EL_EM_KEY_3: return GFX_EM_KEY_3;
2691 case EL_EM_KEY_4: return GFX_EM_KEY_4;
2695 if (IS_CHAR(element))
2696 return GFX_CHAR_START + (element - EL_CHAR_START);
2697 else if (element >= EL_SP_START && element <= EL_SP_END)
2699 int nr_element = element - EL_SP_START;
2700 int gfx_per_line = 8;
2702 (nr_element / gfx_per_line) * MORE_PER_LINE +
2703 (nr_element % gfx_per_line);
2705 return GFX_START_ROCKSMORE + nr_graphic;