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];
462 if (!player->active || player->gone ||
463 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
467 if (!IN_LEV_FIELD(jx,jy))
469 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
470 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
471 printf("DrawPlayerField(): This should never happen!\n");
476 if (element == EL_EXPLODING)
479 /* draw things in the field the player is leaving, if needed */
481 if (last_jx != jx || last_jy != jy)
483 if (Store[last_jx][last_jy] && IS_DRAWABLE(Feld[last_jx][last_jy]))
485 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
486 DrawLevelFieldThruMask(last_jx, last_jy);
488 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
489 DrawDynamite(last_jx, last_jy);
491 DrawLevelField(last_jx, last_jy);
493 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
497 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
498 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
500 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
503 DrawLevelField(next_jx, next_jy);
507 if (!IN_SCR_FIELD(sx, sy))
510 if (setup.direct_draw)
511 SetDrawtoField(DRAW_BUFFERED);
513 /* draw things behind the player, if needed */
516 DrawLevelElement(jx, jy, Store[jx][jy]);
517 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
518 DrawLevelField(jx, jy);
520 /* draw player himself */
522 if (game_emulation == EMU_SUPAPLEX)
524 static int last_dir = MV_LEFT;
525 boolean action_moving =
526 ((player->action & (MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)) &&
527 !(player->action & ~(MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN)));
529 graphic = GFX_SP_MURPHY;
533 if (player->MovDir == MV_LEFT)
534 graphic = GFX_MURPHY_PUSH_LEFT;
535 else if (player->MovDir == MV_RIGHT)
536 graphic = GFX_MURPHY_PUSH_RIGHT;
537 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
538 graphic = GFX_MURPHY_PUSH_LEFT;
539 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
540 graphic = GFX_MURPHY_PUSH_RIGHT;
542 else if (player->snapped)
544 if (player->MovDir == MV_LEFT)
545 graphic = GFX_MURPHY_SNAP_LEFT;
546 else if (player->MovDir == MV_RIGHT)
547 graphic = GFX_MURPHY_SNAP_RIGHT;
548 else if (player->MovDir == MV_UP)
549 graphic = GFX_MURPHY_SNAP_UP;
550 else if (player->MovDir == MV_DOWN)
551 graphic = GFX_MURPHY_SNAP_DOWN;
553 else if (action_moving)
555 if (player->MovDir == MV_LEFT)
556 graphic = GFX_MURPHY_GO_LEFT;
557 else if (player->MovDir == MV_RIGHT)
558 graphic = GFX_MURPHY_GO_RIGHT;
559 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
560 graphic = GFX_MURPHY_GO_LEFT;
561 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
562 graphic = GFX_MURPHY_GO_RIGHT;
564 graphic += getGraphicAnimationPhase(3, 2, ANIM_OSCILLATE);
567 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
568 last_dir = player->MovDir;
572 if (player->MovDir == MV_LEFT)
574 (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
575 else if (player->MovDir == MV_RIGHT)
577 (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
578 else if (player->MovDir == MV_UP)
579 graphic = GFX_SPIELER1_UP;
580 else /* MV_DOWN || MV_NO_MOVING */
581 graphic = GFX_SPIELER1_DOWN;
583 graphic += player->index_nr * 3 * HEROES_PER_LINE;
584 graphic += player->Frame;
589 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
590 sxx = player->GfxPos;
592 syy = player->GfxPos;
595 if (!setup.soft_scrolling && ScreenMovPos)
598 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
600 if (player->Pushing && player->GfxPos)
602 int px = SCREENX(next_jx), py = SCREENY(next_jy);
604 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
605 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
606 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
610 int element = Feld[next_jx][next_jy];
611 int graphic = el2gfx(element);
613 if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK) && sxx)
615 int phase = (player->GfxPos / (TILEX / 4));
617 if (player->MovDir == MV_LEFT)
620 graphic += (phase + 4) % 4;
623 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
627 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
629 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
631 graphic = el2gfx(element);
633 if (element == EL_DYNAMIT)
635 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
640 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
644 if (game_emulation == EMU_SUPAPLEX)
645 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
647 DrawGraphicThruMask(sx, sy, graphic + phase);
650 if ((last_jx != jx || last_jy != jy) &&
651 Feld[last_jx][last_jy] == EL_EXPLODING)
653 int phase = Frame[last_jx][last_jy];
657 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
658 GFX_EXPLOSION + ((phase - 1) / delay - 1));
661 if (setup.direct_draw)
663 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
664 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
665 int x_size = TILEX * (1 + ABS(jx - last_jx));
666 int y_size = TILEY * (1 + ABS(jy - last_jy));
668 XCopyArea(display, drawto_field, window, gc,
669 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
670 SetDrawtoField(DRAW_DIRECT);
673 MarkTileDirty(sx,sy);
676 static int getGraphicAnimationPhase(int frames, int delay, int mode)
680 if (mode == ANIM_OSCILLATE)
682 int max_anim_frames = 2 * frames - 2;
683 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
684 phase = (phase < frames ? phase : max_anim_frames - phase);
687 phase = (FrameCounter % (delay * frames)) / delay;
689 if (mode == ANIM_REVERSE)
695 void DrawGraphicAnimationExt(int x, int y, int graphic,
696 int frames, int delay, int mode, int mask_mode)
698 int phase = getGraphicAnimationPhase(frames, delay, mode);
700 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
702 if (mask_mode == USE_MASKING)
703 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
705 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
709 void DrawGraphicAnimation(int x, int y, int graphic,
710 int frames, int delay, int mode)
712 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
715 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
716 int frames, int delay, int mode)
718 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
721 void getGraphicSource(int graphic, int *pixmap_nr, int *x, int *y)
723 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
725 graphic -= GFX_START_ROCKSSCREEN;
726 *pixmap_nr = PIX_BACK;
727 *x = SX + (graphic % GFX_PER_LINE) * TILEX;
728 *y = SY + (graphic / GFX_PER_LINE) * TILEY;
730 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
732 graphic -= GFX_START_ROCKSMORE;
733 *pixmap_nr = PIX_MORE;
734 *x = (graphic % MORE_PER_LINE) * TILEX;
735 *y = (graphic / MORE_PER_LINE) * TILEY;
737 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
739 graphic -= GFX_START_ROCKSHEROES;
740 *pixmap_nr = PIX_HEROES;
741 *x = (graphic % HEROES_PER_LINE) * TILEX;
742 *y = (graphic / HEROES_PER_LINE) * TILEY;
744 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
746 graphic -= GFX_START_ROCKSFONT;
747 *pixmap_nr = PIX_BIGFONT;
748 *x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
749 *y = ((graphic / FONT_CHARS_PER_LINE) * TILEY +
750 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY);
754 *pixmap_nr = PIX_MORE;
760 void DrawGraphic(int x, int y, int graphic)
763 if (!IN_SCR_FIELD(x,y))
765 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
766 printf("DrawGraphic(): This should never happen!\n");
771 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
775 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
783 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
784 XCopyArea(display, pix[pixmap_nr], d, gc,
785 src_x, src_y, TILEX, TILEY, x, y);
789 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
791 graphic -= GFX_START_ROCKSSCREEN;
792 XCopyArea(display, pix[PIX_BACK], d, gc,
793 SX + (graphic % GFX_PER_LINE) * TILEX,
794 SY + (graphic / GFX_PER_LINE) * TILEY,
797 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
799 graphic -= GFX_START_ROCKSMORE;
800 XCopyArea(display, pix[PIX_MORE], d, gc,
801 (graphic % MORE_PER_LINE) * TILEX,
802 (graphic / MORE_PER_LINE) * TILEY,
805 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
807 graphic -= GFX_START_ROCKSHEROES;
808 XCopyArea(display, pix[PIX_HEROES], d, gc,
809 (graphic % HEROES_PER_LINE) * TILEX,
810 (graphic / HEROES_PER_LINE) * TILEY,
813 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
815 graphic -= GFX_START_ROCKSFONT;
816 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
817 (graphic % FONT_CHARS_PER_LINE) * TILEX,
818 (graphic / FONT_CHARS_PER_LINE) * TILEY +
819 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
823 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
829 void DrawGraphicThruMask(int x, int y, int graphic)
832 if (!IN_SCR_FIELD(x,y))
834 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
835 printf("DrawGraphicThruMask(): This should never happen!\n");
840 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
844 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
855 if (graphic == GFX_LEERRAUM)
858 getGraphicSource(graphic, &pixmap_nr, &src_x, &src_y);
859 src_pixmap = pix[pixmap_nr];
860 drawing_gc = clip_gc[pixmap_nr];
869 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
871 src_pixmap = pix[PIX_BACK];
872 drawing_gc = clip_gc[PIX_BACK];
873 graphic -= GFX_START_ROCKSSCREEN;
874 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
875 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
877 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
879 src_pixmap = pix[PIX_MORE];
880 drawing_gc = clip_gc[PIX_MORE];
881 graphic -= GFX_START_ROCKSMORE;
882 src_x = (graphic % MORE_PER_LINE) * TILEX;
883 src_y = (graphic / MORE_PER_LINE) * TILEY;
885 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
887 src_pixmap = pix[PIX_HEROES];
888 drawing_gc = clip_gc[PIX_HEROES];
889 graphic -= GFX_START_ROCKSHEROES;
890 src_x = (graphic % HEROES_PER_LINE) * TILEX;
891 src_y = (graphic / HEROES_PER_LINE) * TILEY;
895 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
902 if (tile_clipmask[tile] != None)
904 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
905 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
906 XCopyArea(display, src_pixmap, d, tile_clip_gc,
907 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
912 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
915 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
916 XCopyArea(display, src_pixmap, d, drawing_gc,
917 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
921 void DrawMiniGraphic(int x, int y, int graphic)
923 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
924 MarkTileDirty(x/2, y/2);
927 void getMiniGraphicSource(int graphic, Pixmap *pixmap, int *x, int *y)
929 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
931 graphic -= GFX_START_ROCKSSCREEN;
932 *pixmap = pix[PIX_BACK];
933 *x = MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX;
934 *y = MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY;
936 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
938 graphic -= GFX_START_ROCKSMORE;
939 *pixmap = pix[PIX_MORE];
940 *x = MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX;
941 *y = MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY;
943 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
945 graphic -= GFX_START_ROCKSFONT;
946 *pixmap = pix[PIX_SMALLFONT];
947 *x = (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE;
948 *y = ((graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
949 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT);
953 *pixmap = pix[PIX_MORE];
954 *x = MINI_MORE_STARTX;
955 *y = MINI_MORE_STARTY;
959 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
967 getMiniGraphicSource(graphic, &pixmap, &src_x, &src_y);
968 XCopyArea(display, pixmap, d, gc,
969 src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
973 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
975 graphic -= GFX_START_ROCKSSCREEN;
976 XCopyArea(display, pix[PIX_BACK], d, gc,
977 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
978 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
979 MINI_TILEX, MINI_TILEY, x, y);
981 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
983 graphic -= GFX_START_ROCKSMORE;
984 XCopyArea(display, pix[PIX_MORE], d, gc,
985 MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
986 MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
987 MINI_TILEX, MINI_TILEY, x, y);
989 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
991 graphic -= GFX_START_ROCKSFONT;
992 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
993 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
994 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
995 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
996 MINI_TILEX, MINI_TILEY, x, y);
999 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
1005 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
1006 int cut_mode, int mask_mode)
1008 int width = TILEX, height = TILEY;
1010 int src_x, src_y, dest_x, dest_y;
1017 DrawGraphic(x, y, graphic);
1021 if (dx || dy) /* Verschiebung der Grafik? */
1023 if (x < BX1) /* Element kommt von links ins Bild */
1030 else if (x > BX2) /* Element kommt von rechts ins Bild */
1036 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
1042 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
1044 else if (dx) /* allg. Bewegung in x-Richtung */
1045 MarkTileDirty(x + SIGN(dx), y);
1047 if (y < BY1) /* Element kommt von oben ins Bild */
1049 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
1057 else if (y > BY2) /* Element kommt von unten ins Bild */
1063 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
1069 else if (dy > 0 && cut_mode == CUT_ABOVE)
1071 if (y == BY2) /* Element unterhalb des Bildes */
1077 MarkTileDirty(x, y + 1);
1078 } /* Element verläßt unten das Bild */
1079 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
1081 else if (dy) /* allg. Bewegung in y-Richtung */
1082 MarkTileDirty(x, y + SIGN(dy));
1085 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
1087 src_pixmap = pix[PIX_BACK];
1088 drawing_gc = clip_gc[PIX_BACK];
1089 graphic -= GFX_START_ROCKSSCREEN;
1090 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
1091 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
1093 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1095 src_pixmap = pix[PIX_MORE];
1096 drawing_gc = clip_gc[PIX_MORE];
1097 graphic -= GFX_START_ROCKSMORE;
1098 src_x = (graphic % MORE_PER_LINE) * TILEX + cx;
1099 src_y = (graphic / MORE_PER_LINE) * TILEY + cy;
1101 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
1103 src_pixmap = pix[PIX_HEROES];
1104 drawing_gc = clip_gc[PIX_HEROES];
1105 graphic -= GFX_START_ROCKSHEROES;
1106 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
1107 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
1109 else /* big font graphics currently not allowed (and not needed) */
1112 dest_x = FX + x * TILEX + dx;
1113 dest_y = FY + y * TILEY + dy;
1116 if (!IN_SCR_FIELD(x,y))
1118 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
1119 printf("DrawGraphicShifted(): This should never happen!\n");
1124 if (mask_mode == USE_MASKING)
1126 if (tile_clipmask[tile] != None)
1128 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
1129 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
1130 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
1131 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
1136 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
1139 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
1140 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
1141 src_x, src_y, width, height, dest_x, dest_y);
1145 XCopyArea(display, src_pixmap, drawto_field, gc,
1146 src_x, src_y, width, height, dest_x, dest_y);
1151 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
1154 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
1157 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
1158 int cut_mode, int mask_mode)
1160 int ux = LEVELX(x), uy = LEVELY(y);
1161 int graphic = el2gfx(element);
1162 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
1163 int phase4 = phase8 / 2;
1164 int phase2 = phase8 / 4;
1165 int dir = MovDir[ux][uy];
1167 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
1169 graphic += 4 * !phase2;
1173 else if (dir == MV_LEFT)
1175 else if (dir == MV_DOWN)
1178 else if (element == EL_SP_SNIKSNAK)
1181 graphic = GFX_SP_SNIKSNAK_LEFT;
1182 else if (dir == MV_RIGHT)
1183 graphic = GFX_SP_SNIKSNAK_RIGHT;
1184 else if (dir == MV_UP)
1185 graphic = GFX_SP_SNIKSNAK_UP;
1187 graphic = GFX_SP_SNIKSNAK_DOWN;
1189 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
1191 else if (element == EL_SP_ELECTRON)
1193 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1195 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1196 element == EL_SCHWEIN || element == EL_DRACHE)
1199 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1200 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1201 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1202 else if (dir == MV_RIGHT)
1203 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1204 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1205 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1206 else if (dir == MV_UP)
1207 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1208 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1209 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1211 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1212 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1213 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1217 else if (element == EL_SONDE)
1219 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1221 else if (element == EL_SALZSAEURE)
1223 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1225 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1229 else if ((element == EL_FELSBROCKEN || element == EL_SP_ZONK ||
1230 IS_GEM(element)) && !cut_mode)
1232 if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
1235 graphic += (4 - phase4) % 4;
1236 else if (dir == MV_RIGHT)
1239 graphic += phase2 * 2;
1241 else if (element != EL_SP_INFOTRON)
1245 if (element == EL_SP_ZONK)
1248 graphic += (4 - phase4) % 4;
1249 else if (dir == MV_RIGHT)
1252 graphic += phase2 * 2;
1254 else if (element != EL_SP_INFOTRON)
1255 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1259 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1260 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1262 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1264 else if (IS_AMOEBOID(element))
1266 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1267 graphic += (x + 2 * y + 4) % 4;
1269 else if (element == EL_MAUER_LEBT)
1271 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1273 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1274 links_massiv = TRUE;
1275 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1276 rechts_massiv = TRUE;
1278 if (links_massiv && rechts_massiv)
1279 graphic = GFX_MAUERWERK;
1280 else if (links_massiv)
1281 graphic = GFX_MAUER_R;
1282 else if (rechts_massiv)
1283 graphic = GFX_MAUER_L;
1287 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1288 else if (mask_mode == USE_MASKING)
1289 DrawGraphicThruMask(x, y, graphic);
1291 DrawGraphic(x, y, graphic);
1294 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1295 int cut_mode, int mask_mode)
1297 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1298 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1299 cut_mode, mask_mode);
1302 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1305 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1308 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1311 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1314 void DrawScreenElementThruMask(int x, int y, int element)
1316 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1319 void DrawLevelElementThruMask(int x, int y, int element)
1321 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1324 void DrawLevelFieldThruMask(int x, int y)
1326 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1329 void ErdreichAnbroeckeln(int x, int y)
1331 int i, width, height, cx,cy;
1332 int ux = LEVELX(x), uy = LEVELY(y);
1333 int element, graphic;
1335 static int xy[4][2] =
1343 if (!IN_LEV_FIELD(ux, uy))
1346 element = Feld[ux][uy];
1348 if (element == EL_ERDREICH)
1350 if (!IN_SCR_FIELD(x, y))
1353 graphic = GFX_ERDENRAND;
1359 uxx = ux + xy[i][0];
1360 uyy = uy + xy[i][1];
1361 if (!IN_LEV_FIELD(uxx, uyy))
1364 element = Feld[uxx][uyy];
1366 if (element == EL_ERDREICH)
1369 if (i == 1 || i == 2)
1373 cx = (i == 2 ? TILEX - snip : 0);
1381 cy = (i == 3 ? TILEY - snip : 0);
1384 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1385 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1386 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1387 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1390 MarkTileDirty(x, y);
1394 graphic = GFX_ERDENRAND;
1398 int xx, yy, uxx, uyy;
1402 uxx = ux + xy[i][0];
1403 uyy = uy + xy[i][1];
1405 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1406 !IN_SCR_FIELD(xx, yy))
1409 if (i == 1 || i == 2)
1413 cx = (i == 1 ? TILEX - snip : 0);
1421 cy = (i==0 ? TILEY-snip : 0);
1424 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1425 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1426 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1427 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1429 MarkTileDirty(xx, yy);
1434 void DrawScreenElement(int x, int y, int element)
1436 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1437 ErdreichAnbroeckeln(x, y);
1440 void DrawLevelElement(int x, int y, int element)
1442 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1443 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1446 void DrawScreenField(int x, int y)
1448 int ux = LEVELX(x), uy = LEVELY(y);
1451 if (!IN_LEV_FIELD(ux, uy))
1453 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1454 element = EL_LEERRAUM;
1456 element = BorderElement;
1458 DrawScreenElement(x, y, element);
1462 element = Feld[ux][uy];
1464 if (IS_MOVING(ux, uy))
1466 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1467 boolean cut_mode = NO_CUTTING;
1469 if (Store[ux][uy] == EL_MORAST_LEER ||
1470 Store[ux][uy] == EL_SIEB_LEER ||
1471 Store[ux][uy] == EL_SIEB2_LEER ||
1472 Store[ux][uy] == EL_AMOEBE_NASS)
1473 cut_mode = CUT_ABOVE;
1474 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1475 Store[ux][uy] == EL_SIEB_VOLL ||
1476 Store[ux][uy] == EL_SIEB2_VOLL)
1477 cut_mode = CUT_BELOW;
1479 if (cut_mode == CUT_ABOVE)
1480 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1482 DrawScreenElement(x, y, EL_LEERRAUM);
1485 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1487 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1489 if (Store[ux][uy] == EL_SALZSAEURE)
1490 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1492 else if (IS_BLOCKED(ux, uy))
1497 boolean cut_mode = NO_CUTTING;
1499 Blocked2Moving(ux, uy, &oldx, &oldy);
1502 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1503 MovDir[oldx][oldy] == MV_RIGHT);
1505 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1506 Store[oldx][oldy] == EL_SIEB_LEER ||
1507 Store[oldx][oldy] == EL_SIEB2_LEER ||
1508 Store[oldx][oldy] == EL_AMOEBE_NASS)
1509 cut_mode = CUT_ABOVE;
1511 DrawScreenElement(x, y, EL_LEERRAUM);
1512 element = Feld[oldx][oldy];
1515 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1517 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1519 else if (IS_DRAWABLE(element))
1520 DrawScreenElement(x, y, element);
1522 DrawScreenElement(x, y, EL_LEERRAUM);
1525 void DrawLevelField(int x, int y)
1527 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1528 DrawScreenField(SCREENX(x), SCREENY(y));
1529 else if (IS_MOVING(x, y))
1533 Moving2Blocked(x, y, &newx, &newy);
1534 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1535 DrawScreenField(SCREENX(newx), SCREENY(newy));
1537 else if (IS_BLOCKED(x, y))
1541 Blocked2Moving(x, y, &oldx, &oldy);
1542 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1543 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1547 void DrawMiniElement(int x, int y, int element)
1553 DrawMiniGraphic(x, y, -1);
1557 graphic = el2gfx(element);
1558 DrawMiniGraphic(x, y, graphic);
1561 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1563 int x = sx + scroll_x, y = sy + scroll_y;
1565 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1566 DrawMiniElement(sx, sy, EL_LEERRAUM);
1567 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1568 DrawMiniElement(sx, sy, Feld[x][y]);
1571 int steel_type, steel_position;
1574 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1575 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1576 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1577 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1578 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1579 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1582 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1583 steel_position = (x == -1 && y == -1 ? 0 :
1584 x == lev_fieldx && y == -1 ? 1 :
1585 x == -1 && y == lev_fieldy ? 2 :
1586 x == lev_fieldx && y == lev_fieldy ? 3 :
1587 x == -1 || x == lev_fieldx ? 4 :
1588 y == -1 || y == lev_fieldy ? 5 : -1);
1590 if (steel_position != -1)
1591 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1595 if (x == -1 && y == -1)
1596 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_LEFT);
1597 else if (x == lev_fieldx && y == -1)
1598 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_RIGHT);
1599 else if (x == -1 && y == lev_fieldy)
1600 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_LEFT);
1601 else if (x == lev_fieldx && y == lev_fieldy)
1602 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_RIGHT);
1603 else if (x == -1 || x == lev_fieldx)
1604 DrawMiniGraphic(sx, sy, GFX_STEEL_VERTICAL);
1605 else if (y == -1 || y == lev_fieldy)
1606 DrawMiniGraphic(sx, sy, GFX_STEEL_HORIZONTAL);
1613 void DrawMicroElement(int xpos, int ypos, int element)
1617 if (element == EL_LEERRAUM)
1620 graphic = el2gfx(element);
1622 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1624 graphic -= GFX_START_ROCKSMORE;
1625 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1626 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1627 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1628 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1631 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1632 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1633 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1634 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1643 for(x=BX1; x<=BX2; x++)
1644 for(y=BY1; y<=BY2; y++)
1645 DrawScreenField(x, y);
1647 if (setup.soft_scrolling)
1648 XCopyArea(display, fieldbuffer, backbuffer, gc,
1649 FX, FY, SXSIZE, SYSIZE, SX, SY);
1651 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1654 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1658 for(x=0; x<size_x; x++)
1659 for(y=0; y<size_y; y++)
1660 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1662 redraw_mask |= REDRAW_FIELD;
1665 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1669 /* determine border element for this level */
1672 XFillRectangle(display, drawto, gc,
1673 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1675 if (lev_fieldx < STD_LEV_FIELDX)
1676 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1677 if (lev_fieldy < STD_LEV_FIELDY)
1678 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1680 xpos += MICRO_TILEX;
1681 ypos += MICRO_TILEY;
1683 for(x=-1; x<=STD_LEV_FIELDX; x++)
1685 for(y=-1; y<=STD_LEV_FIELDY; y++)
1687 int lx = from_x + x, ly = from_y + y;
1689 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1690 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1692 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1693 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1698 redraw_mask |= REDRAW_MICROLEVEL;
1701 static void DrawMicroLevelLabelExt(int mode)
1703 char label_text[100];
1705 XFillRectangle(display, drawto,gc,
1706 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1708 strcpy(label_text, (mode == 1 ? level.name :
1709 mode == 2 ? "created by" :
1710 mode == 3 ? level.author : ""));
1712 if (strlen(label_text) > 0)
1714 int size, lxpos, lypos;
1716 label_text[SXSIZE / FONT4_XSIZE] = '\0';
1718 size = strlen(label_text);
1719 lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1720 lypos = MICROLABEL_YPOS;
1722 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1725 redraw_mask |= REDRAW_MICROLEVEL;
1728 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1730 static unsigned long scroll_delay = 0;
1731 static unsigned long label_delay = 0;
1732 static int from_x, from_y, scroll_direction;
1733 static int label_state, label_counter;
1737 from_x = from_y = 0;
1738 scroll_direction = MV_RIGHT;
1742 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1743 DrawMicroLevelLabelExt(label_state);
1745 /* initialize delay counters */
1746 DelayReached(&scroll_delay, 0);
1747 DelayReached(&label_delay, 0);
1752 /* scroll micro level, if needed */
1753 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1754 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1756 switch (scroll_direction)
1762 scroll_direction = MV_UP;
1766 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1769 scroll_direction = MV_DOWN;
1776 scroll_direction = MV_RIGHT;
1780 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1783 scroll_direction = MV_LEFT;
1790 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1793 /* redraw micro level label, if needed */
1794 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1795 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1796 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1797 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1799 label_counter = (label_counter + 1) % 23;
1800 label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1801 label_counter >= 9 && label_counter <= 12 ? 2 :
1802 label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1803 DrawMicroLevelLabelExt(label_state);
1807 int REQ_in_range(int x, int y)
1809 if (y > DY+249 && y < DY+278)
1811 if (x > DX+1 && x < DX+48)
1813 else if (x > DX+51 && x < DX+98)
1819 boolean Request(char *text, unsigned int req_state)
1821 int mx, my, ty, result = -1;
1822 unsigned int old_door_state;
1825 /* pause network game while waiting for request to answer */
1826 if (options.network &&
1827 game_status == PLAYING &&
1828 req_state & REQUEST_WAIT_FOR)
1829 SendToServer_PausePlaying();
1832 old_door_state = GetDoorState();
1836 CloseDoor(DOOR_CLOSE_1);
1838 /* save old door content */
1839 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1840 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1841 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1843 /* clear door drawing field */
1845 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1846 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1848 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1851 /* write text for request */
1852 for(ty=0; ty<13; ty++)
1860 for(tl=0,tx=0; tx<7; tl++,tx++)
1863 if (!tc || tc == 32)
1875 DrawTextExt(pix[PIX_DB_DOOR], gc,
1876 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1877 txt, FS_SMALL, FC_YELLOW);
1879 DrawTextExt(drawto, gc,
1880 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1881 txt, FS_SMALL, FC_YELLOW);
1883 text += tl + (tc == 32 ? 1 : 0);
1887 if (req_state & REQ_ASK)
1889 DrawYesNoButton(BUTTON_OK, DB_INIT);
1890 DrawYesNoButton(BUTTON_NO, DB_INIT);
1892 else if (req_state & REQ_CONFIRM)
1894 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1896 else if (req_state & REQ_PLAYER)
1898 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1899 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1900 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1901 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1905 if (req_state & REQ_ASK)
1907 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1908 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1910 else if (req_state & REQ_CONFIRM)
1912 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1914 else if (req_state & REQ_PLAYER)
1916 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1917 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1918 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1919 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1922 /* copy request gadgets to door backbuffer */
1923 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1924 DX, DY, DXSIZE, DYSIZE,
1925 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1929 OpenDoor(DOOR_OPEN_1);
1932 if (!(req_state & REQUEST_WAIT_FOR))
1935 if (game_status != MAINMENU)
1938 button_status = MB_RELEASED;
1940 request_gadget_id = -1;
1944 if (XPending(display))
1948 XNextEvent(display, &event);
1961 if (event.type == MotionNotify)
1968 if (!XQueryPointer(display, window, &root, &child,
1969 &root_x, &root_y, &win_x, &win_y, &mask))
1975 motion_status = TRUE;
1976 mx = ((XMotionEvent *) &event)->x;
1977 my = ((XMotionEvent *) &event)->y;
1981 motion_status = FALSE;
1982 mx = ((XButtonEvent *) &event)->x;
1983 my = ((XButtonEvent *) &event)->y;
1984 if (event.type==ButtonPress)
1985 button_status = ((XButtonEvent *) &event)->button;
1987 button_status = MB_RELEASED;
1993 if (req_state & REQ_ASK)
1994 choice = CheckYesNoButtons(mx,my,button_status);
1995 else if (req_state & REQ_CONFIRM)
1996 choice = CheckConfirmButton(mx,my,button_status);
1998 choice = CheckPlayerButtons(mx,my,button_status);
2008 case BUTTON_CONFIRM:
2009 result = TRUE | FALSE;
2012 case BUTTON_PLAYER_1:
2015 case BUTTON_PLAYER_2:
2018 case BUTTON_PLAYER_3:
2021 case BUTTON_PLAYER_4:
2030 /* this sets 'request_gadget_id' */
2031 HandleGadgets(mx, my, button_status);
2033 switch(request_gadget_id)
2035 case TOOL_CTRL_ID_YES:
2038 case TOOL_CTRL_ID_NO:
2041 case TOOL_CTRL_ID_CONFIRM:
2042 result = TRUE | FALSE;
2045 case TOOL_CTRL_ID_PLAYER_1:
2048 case TOOL_CTRL_ID_PLAYER_2:
2051 case TOOL_CTRL_ID_PLAYER_3:
2054 case TOOL_CTRL_ID_PLAYER_4:
2067 switch(XLookupKeysym((XKeyEvent *)&event,
2068 ((XKeyEvent *)&event)->state))
2081 if (req_state & REQ_PLAYER)
2086 key_joystick_mapping = 0;
2090 HandleOtherEvents(&event);
2094 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2096 int joy = AnyJoystick();
2098 if (joy & JOY_BUTTON_1)
2100 else if (joy & JOY_BUTTON_2)
2106 /* don't eat all CPU time */
2110 if (game_status != MAINMENU)
2115 if (!(req_state & REQ_STAY_OPEN))
2117 CloseDoor(DOOR_CLOSE_1);
2119 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2121 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
2122 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2123 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2124 OpenDoor(DOOR_OPEN_1);
2131 /* continue network game after request */
2132 if (options.network &&
2133 game_status == PLAYING &&
2134 req_state & REQUEST_WAIT_FOR)
2135 SendToServer_ContinuePlaying();
2141 unsigned int OpenDoor(unsigned int door_state)
2143 unsigned int new_door_state;
2145 if (door_state & DOOR_COPY_BACK)
2147 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
2148 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2149 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2150 door_state &= ~DOOR_COPY_BACK;
2153 new_door_state = MoveDoor(door_state);
2155 return(new_door_state);
2158 unsigned int CloseDoor(unsigned int door_state)
2160 unsigned int new_door_state;
2162 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2163 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2164 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2165 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2167 new_door_state = MoveDoor(door_state);
2169 return(new_door_state);
2172 unsigned int GetDoorState()
2174 return(MoveDoor(DOOR_GET_STATE));
2177 unsigned int MoveDoor(unsigned int door_state)
2179 static int door1 = DOOR_OPEN_1;
2180 static int door2 = DOOR_CLOSE_2;
2181 static unsigned long door_delay = 0;
2182 int x, start, stepsize = 2;
2183 unsigned long door_delay_value = stepsize * 5;
2185 if (door_state == DOOR_GET_STATE)
2186 return(door1 | door2);
2188 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2189 door_state &= ~DOOR_OPEN_1;
2190 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2191 door_state &= ~DOOR_CLOSE_1;
2192 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2193 door_state &= ~DOOR_OPEN_2;
2194 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2195 door_state &= ~DOOR_CLOSE_2;
2197 if (setup.quick_doors)
2200 door_delay_value = 0;
2201 StopSound(SND_OEFFNEN);
2204 if (door_state & DOOR_ACTION)
2206 if (!(door_state & DOOR_NO_DELAY))
2207 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2209 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2211 for(x=start; x<=DXSIZE; x+=stepsize)
2213 WaitUntilDelayReached(&door_delay, door_delay_value);
2215 if (door_state & DOOR_ACTION_1)
2217 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2218 int j = (DXSIZE - i) / 3;
2220 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2221 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2222 DXSIZE,DYSIZE - i/2, DX, DY);
2224 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2226 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2227 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2228 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2229 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2230 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2231 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2233 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2234 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2235 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2236 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2237 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2238 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2240 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2241 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2243 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2244 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2246 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2247 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2248 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2249 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2250 DX + DXSIZE - i, DY + 77 + j);
2251 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2252 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2253 DX + DXSIZE - i, DY + 203 + j);
2255 redraw_mask |= REDRAW_DOOR_1;
2258 if (door_state & DOOR_ACTION_2)
2260 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2261 int j = (VXSIZE - i) / 3;
2263 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2264 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2265 VXSIZE, VYSIZE - i/2, VX, VY);
2267 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2269 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2270 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2271 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2272 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2273 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2274 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2275 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2276 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2278 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2279 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2280 VX, VY + VYSIZE / 2 - j);
2281 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2282 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2283 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2284 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2285 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2287 redraw_mask |= REDRAW_DOOR_2;
2295 XCopyArea(display, drawto, window, gc, DX, DY, DXSIZE, DYSIZE, DX, DY);
2300 if (game_status == MAINMENU)
2305 if (setup.quick_doors)
2306 StopSound(SND_OEFFNEN);
2308 if (door_state & DOOR_ACTION_1)
2309 door1 = door_state & DOOR_ACTION_1;
2310 if (door_state & DOOR_ACTION_2)
2311 door2 = door_state & DOOR_ACTION_2;
2313 return(door1 | door2);
2316 int ReadPixel(Drawable d, int x, int y)
2318 XImage *pixel_image;
2319 unsigned long pixel_value;
2321 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2322 pixel_value = XGetPixel(pixel_image, 0, 0);
2324 XDestroyImage(pixel_image);
2329 /* ---------- new tool button stuff ---------------------------------------- */
2331 /* graphic position values for tool buttons */
2332 #define TOOL_BUTTON_YES_XPOS 2
2333 #define TOOL_BUTTON_YES_YPOS 250
2334 #define TOOL_BUTTON_YES_GFX_YPOS 0
2335 #define TOOL_BUTTON_YES_XSIZE 46
2336 #define TOOL_BUTTON_YES_YSIZE 28
2337 #define TOOL_BUTTON_NO_XPOS 52
2338 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2339 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2340 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2341 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2342 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2343 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2344 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2345 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2346 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2347 #define TOOL_BUTTON_PLAYER_XSIZE 30
2348 #define TOOL_BUTTON_PLAYER_YSIZE 30
2349 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2350 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2351 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2352 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2353 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2354 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2355 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2356 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2357 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2358 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2359 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2360 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2361 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2362 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2363 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2364 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2365 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2366 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2367 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2368 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2377 } toolbutton_info[NUM_TOOL_BUTTONS] =
2380 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2381 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2382 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2387 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2388 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2389 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2394 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2395 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2396 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2397 TOOL_CTRL_ID_CONFIRM,
2401 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2402 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2403 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2404 TOOL_CTRL_ID_PLAYER_1,
2408 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2409 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2410 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2411 TOOL_CTRL_ID_PLAYER_2,
2415 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2416 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2417 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2418 TOOL_CTRL_ID_PLAYER_3,
2422 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2423 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2424 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2425 TOOL_CTRL_ID_PLAYER_4,
2430 void CreateToolButtons()
2434 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2436 Pixmap gd_pixmap = pix[PIX_DOOR];
2437 Pixmap deco_pixmap = None;
2438 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2439 struct GadgetInfo *gi;
2440 unsigned long event_mask;
2441 int gd_xoffset, gd_yoffset;
2442 int gd_x1, gd_x2, gd_y;
2445 event_mask = GD_EVENT_RELEASED;
2447 gd_xoffset = toolbutton_info[i].xpos;
2448 gd_yoffset = toolbutton_info[i].ypos;
2449 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2450 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2451 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2453 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2455 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2456 &deco_pixmap, &deco_x, &deco_y);
2457 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2458 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2461 gi = CreateGadget(GDI_CUSTOM_ID, id,
2462 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2463 GDI_X, DX + toolbutton_info[i].x,
2464 GDI_Y, DY + toolbutton_info[i].y,
2465 GDI_WIDTH, toolbutton_info[i].width,
2466 GDI_HEIGHT, toolbutton_info[i].height,
2467 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2468 GDI_STATE, GD_BUTTON_UNPRESSED,
2469 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2470 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2471 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2472 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2473 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2474 GDI_DECORATION_SHIFTING, 1, 1,
2475 GDI_EVENT_MASK, event_mask,
2476 GDI_CALLBACK_ACTION, HandleToolButtons,
2480 Error(ERR_EXIT, "cannot create gadget");
2482 tool_gadget[id] = gi;
2486 static void UnmapToolButtons()
2490 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2491 UnmapGadget(tool_gadget[i]);
2494 static void HandleToolButtons(struct GadgetInfo *gi)
2496 request_gadget_id = gi->custom_id;
2500 int id = gi->custom_id;
2502 if (game_status != PLAYING)
2507 case GAME_CTRL_ID_STOP:
2510 CloseDoor(DOOR_CLOSE_1);
2511 game_status = MAINMENU;
2516 if (Request("Do you really want to quit the game ?",
2517 REQ_ASK | REQ_STAY_CLOSED))
2520 if (options.network)
2521 SendToServer_StopPlaying();
2525 game_status = MAINMENU;
2530 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2533 case GAME_CTRL_ID_PAUSE:
2534 if (options.network)
2538 SendToServer_ContinuePlaying();
2540 SendToServer_PausePlaying();
2547 case GAME_CTRL_ID_PLAY:
2551 if (options.network)
2552 SendToServer_ContinuePlaying();
2556 tape.pausing = FALSE;
2557 DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
2562 case SOUND_CTRL_ID_MUSIC:
2563 if (setup.sound_music)
2565 setup.sound_music = FALSE;
2566 FadeSound(background_loop[level_nr % num_bg_loops]);
2568 else if (sound_loops_allowed)
2570 setup.sound = setup.sound_music = TRUE;
2571 PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
2575 case SOUND_CTRL_ID_LOOPS:
2576 if (setup.sound_loops)
2577 setup.sound_loops = FALSE;
2578 else if (sound_loops_allowed)
2579 setup.sound = setup.sound_loops = TRUE;
2582 case SOUND_CTRL_ID_SIMPLE:
2583 if (setup.sound_simple)
2584 setup.sound_simple = FALSE;
2585 else if (sound_status==SOUND_AVAILABLE)
2586 setup.sound = setup.sound_simple = TRUE;
2598 int el2gfx(int element)
2602 case EL_LEERRAUM: return -1;
2603 case EL_ERDREICH: return GFX_ERDREICH;
2604 case EL_MAUERWERK: return GFX_MAUERWERK;
2605 case EL_FELSBODEN: return GFX_FELSBODEN;
2606 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2607 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2608 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2609 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2610 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2611 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2612 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2613 case EL_SPIELER1: return GFX_SPIELER1;
2614 case EL_SPIELER2: return GFX_SPIELER2;
2615 case EL_SPIELER3: return GFX_SPIELER3;
2616 case EL_SPIELER4: return GFX_SPIELER4;
2617 case EL_KAEFER: return GFX_KAEFER;
2618 case EL_KAEFER_R: return GFX_KAEFER_R;
2619 case EL_KAEFER_O: return GFX_KAEFER_O;
2620 case EL_KAEFER_L: return GFX_KAEFER_L;
2621 case EL_KAEFER_U: return GFX_KAEFER_U;
2622 case EL_FLIEGER: return GFX_FLIEGER;
2623 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2624 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2625 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2626 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2627 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2628 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2629 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2630 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2631 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2632 case EL_FIREFLY: return GFX_FIREFLY;
2633 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2634 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2635 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2636 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2637 case EL_MAMPFER: return GFX_MAMPFER;
2638 case EL_ROBOT: return GFX_ROBOT;
2639 case EL_BETON: return GFX_BETON;
2640 case EL_DIAMANT: return GFX_DIAMANT;
2641 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2642 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2643 case EL_TROPFEN: return GFX_TROPFEN;
2644 case EL_BOMBE: return GFX_BOMBE;
2645 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2646 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2647 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2648 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2649 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2650 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2651 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2652 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2653 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2654 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2655 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2656 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2657 case EL_LIFE: return GFX_LIFE;
2658 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2659 case EL_DYNAMIT: return GFX_DYNAMIT;
2660 case EL_BADEWANNE: return GFX_BADEWANNE;
2661 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2662 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2663 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2664 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2665 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2666 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2667 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2668 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2669 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2670 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2671 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2672 case EL_PFORTE1: return GFX_PFORTE1;
2673 case EL_PFORTE2: return GFX_PFORTE2;
2674 case EL_PFORTE3: return GFX_PFORTE3;
2675 case EL_PFORTE4: return GFX_PFORTE4;
2676 case EL_PFORTE1X: return GFX_PFORTE1X;
2677 case EL_PFORTE2X: return GFX_PFORTE2X;
2678 case EL_PFORTE3X: return GFX_PFORTE3X;
2679 case EL_PFORTE4X: return GFX_PFORTE4X;
2680 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
2681 case EL_PACMAN: return GFX_PACMAN;
2682 case EL_PACMAN_R: return GFX_PACMAN_R;
2683 case EL_PACMAN_O: return GFX_PACMAN_O;
2684 case EL_PACMAN_L: return GFX_PACMAN_L;
2685 case EL_PACMAN_U: return GFX_PACMAN_U;
2686 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2687 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2688 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2689 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2690 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2691 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2692 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2693 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2694 case EL_MAUER_X: return GFX_MAUER_X;
2695 case EL_MAUER_Y: return GFX_MAUER_Y;
2696 case EL_MAUER_XY: return GFX_MAUER_XY;
2697 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2698 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2699 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2700 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2701 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2702 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2703 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2704 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2705 case EL_MAMPFER2: return GFX_MAMPFER2;
2706 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2707 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2708 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2709 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2710 case EL_DYNABOMB: return GFX_DYNABOMB;
2711 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2712 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2713 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2714 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2715 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2716 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2717 case EL_MAULWURF: return GFX_MAULWURF;
2718 case EL_PINGUIN: return GFX_PINGUIN;
2719 case EL_SCHWEIN: return GFX_SCHWEIN;
2720 case EL_DRACHE: return GFX_DRACHE;
2721 case EL_SONDE: return GFX_SONDE;
2722 case EL_PFEIL_L: return GFX_PFEIL_L;
2723 case EL_PFEIL_R: return GFX_PFEIL_R;
2724 case EL_PFEIL_O: return GFX_PFEIL_O;
2725 case EL_PFEIL_U: return GFX_PFEIL_U;
2726 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2727 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2728 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2729 case EL_SP_ZONK: return GFX_SP_ZONK;
2730 /* ^^^^^^^^^^ non-standard position in supaplex graphic set! */
2731 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2732 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2736 if (IS_CHAR(element))
2737 return GFX_CHAR_START + (element - EL_CHAR_START);
2738 else if (element >= EL_SP_START && element <= EL_SP_END)
2740 int nr_element = element - EL_SP_START;
2741 int gfx_per_line = 8;
2743 (nr_element / gfx_per_line) * MORE_PER_LINE +
2744 (nr_element % gfx_per_line);
2746 return GFX_START_ROCKSMORE + nr_graphic;