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_ANY_LEFT;
557 else if (player->MovDir == MV_RIGHT)
558 graphic = GFX_MURPHY_ANY_RIGHT;
559 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_LEFT)
560 graphic = GFX_MURPHY_ANY_LEFT;
561 else if (player->MovDir & (MV_UP | MV_DOWN) && last_dir == MV_RIGHT)
562 graphic = GFX_MURPHY_ANY_RIGHT;
564 graphic -= getGraphicAnimationPhase(2, 4, ANIM_NORMAL);
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 && 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 || IS_GEM(element)) && !cut_mode)
1231 if (element != EL_SP_INFOTRON)
1232 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1234 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1235 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1237 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1239 else if (IS_AMOEBOID(element))
1241 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1242 graphic += (x + 2 * y + 4) % 4;
1244 else if (element == EL_MAUER_LEBT)
1246 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1248 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1249 links_massiv = TRUE;
1250 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1251 rechts_massiv = TRUE;
1253 if (links_massiv && rechts_massiv)
1254 graphic = GFX_MAUERWERK;
1255 else if (links_massiv)
1256 graphic = GFX_MAUER_R;
1257 else if (rechts_massiv)
1258 graphic = GFX_MAUER_L;
1262 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1263 else if (mask_mode == USE_MASKING)
1264 DrawGraphicThruMask(x, y, graphic);
1266 DrawGraphic(x, y, graphic);
1269 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1270 int cut_mode, int mask_mode)
1272 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1273 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1274 cut_mode, mask_mode);
1277 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1280 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1283 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1286 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1289 void DrawScreenElementThruMask(int x, int y, int element)
1291 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1294 void DrawLevelElementThruMask(int x, int y, int element)
1296 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1299 void DrawLevelFieldThruMask(int x, int y)
1301 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1304 void ErdreichAnbroeckeln(int x, int y)
1306 int i, width, height, cx,cy;
1307 int ux = LEVELX(x), uy = LEVELY(y);
1308 int element, graphic;
1310 static int xy[4][2] =
1318 if (!IN_LEV_FIELD(ux, uy))
1321 element = Feld[ux][uy];
1323 if (element == EL_ERDREICH)
1325 if (!IN_SCR_FIELD(x, y))
1328 graphic = GFX_ERDENRAND;
1334 uxx = ux + xy[i][0];
1335 uyy = uy + xy[i][1];
1336 if (!IN_LEV_FIELD(uxx, uyy))
1339 element = Feld[uxx][uyy];
1341 if (element == EL_ERDREICH)
1344 if (i == 1 || i == 2)
1348 cx = (i == 2 ? TILEX - snip : 0);
1356 cy = (i == 3 ? TILEY - snip : 0);
1359 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1360 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1361 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1362 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1365 MarkTileDirty(x, y);
1369 graphic = GFX_ERDENRAND;
1373 int xx, yy, uxx, uyy;
1377 uxx = ux + xy[i][0];
1378 uyy = uy + xy[i][1];
1380 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1381 !IN_SCR_FIELD(xx, yy))
1384 if (i == 1 || i == 2)
1388 cx = (i == 1 ? TILEX - snip : 0);
1396 cy = (i==0 ? TILEY-snip : 0);
1399 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1400 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1401 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1402 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1404 MarkTileDirty(xx, yy);
1409 void DrawScreenElement(int x, int y, int element)
1411 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1412 ErdreichAnbroeckeln(x, y);
1415 void DrawLevelElement(int x, int y, int element)
1417 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1418 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1421 void DrawScreenField(int x, int y)
1423 int ux = LEVELX(x), uy = LEVELY(y);
1426 if (!IN_LEV_FIELD(ux, uy))
1428 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1429 element = EL_LEERRAUM;
1431 element = BorderElement;
1433 DrawScreenElement(x, y, element);
1437 element = Feld[ux][uy];
1439 if (IS_MOVING(ux, uy))
1441 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1442 boolean cut_mode = NO_CUTTING;
1444 if (Store[ux][uy] == EL_MORAST_LEER ||
1445 Store[ux][uy] == EL_SIEB_LEER ||
1446 Store[ux][uy] == EL_SIEB2_LEER ||
1447 Store[ux][uy] == EL_AMOEBE_NASS)
1448 cut_mode = CUT_ABOVE;
1449 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1450 Store[ux][uy] == EL_SIEB_VOLL ||
1451 Store[ux][uy] == EL_SIEB2_VOLL)
1452 cut_mode = CUT_BELOW;
1454 if (cut_mode == CUT_ABOVE)
1455 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1457 DrawScreenElement(x, y, EL_LEERRAUM);
1460 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1462 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1464 if (Store[ux][uy] == EL_SALZSAEURE)
1465 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1467 else if (IS_BLOCKED(ux, uy))
1472 boolean cut_mode = NO_CUTTING;
1474 Blocked2Moving(ux, uy, &oldx, &oldy);
1477 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1478 MovDir[oldx][oldy] == MV_RIGHT);
1480 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1481 Store[oldx][oldy] == EL_SIEB_LEER ||
1482 Store[oldx][oldy] == EL_SIEB2_LEER ||
1483 Store[oldx][oldy] == EL_AMOEBE_NASS)
1484 cut_mode = CUT_ABOVE;
1486 DrawScreenElement(x, y, EL_LEERRAUM);
1487 element = Feld[oldx][oldy];
1490 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1492 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1494 else if (IS_DRAWABLE(element))
1495 DrawScreenElement(x, y, element);
1497 DrawScreenElement(x, y, EL_LEERRAUM);
1500 void DrawLevelField(int x, int y)
1502 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1503 DrawScreenField(SCREENX(x), SCREENY(y));
1504 else if (IS_MOVING(x, y))
1508 Moving2Blocked(x, y, &newx, &newy);
1509 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1510 DrawScreenField(SCREENX(newx), SCREENY(newy));
1512 else if (IS_BLOCKED(x, y))
1516 Blocked2Moving(x, y, &oldx, &oldy);
1517 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1518 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1522 void DrawMiniElement(int x, int y, int element)
1528 DrawMiniGraphic(x, y, -1);
1532 graphic = el2gfx(element);
1533 DrawMiniGraphic(x, y, graphic);
1536 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1538 int x = sx + scroll_x, y = sy + scroll_y;
1540 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1541 DrawMiniElement(sx, sy, EL_LEERRAUM);
1542 else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1543 DrawMiniElement(sx, sy, Feld[x][y]);
1546 int steel_type, steel_position;
1549 { GFX_VSTEEL_UPPER_LEFT, GFX_ISTEEL_UPPER_LEFT },
1550 { GFX_VSTEEL_UPPER_RIGHT, GFX_ISTEEL_UPPER_RIGHT },
1551 { GFX_VSTEEL_LOWER_LEFT, GFX_ISTEEL_LOWER_LEFT },
1552 { GFX_VSTEEL_LOWER_RIGHT, GFX_ISTEEL_LOWER_RIGHT },
1553 { GFX_VSTEEL_VERTICAL, GFX_ISTEEL_VERTICAL },
1554 { GFX_VSTEEL_HORIZONTAL, GFX_ISTEEL_HORIZONTAL }
1557 steel_type = (BorderElement == EL_BETON ? 0 : 1);
1558 steel_position = (x == -1 && y == -1 ? 0 :
1559 x == lev_fieldx && y == -1 ? 1 :
1560 x == -1 && y == lev_fieldy ? 2 :
1561 x == lev_fieldx && y == lev_fieldy ? 3 :
1562 x == -1 || x == lev_fieldx ? 4 :
1563 y == -1 || y == lev_fieldy ? 5 : -1);
1565 if (steel_position != -1)
1566 DrawMiniGraphic(sx, sy, border[steel_position][steel_type]);
1570 if (x == -1 && y == -1)
1571 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_LEFT);
1572 else if (x == lev_fieldx && y == -1)
1573 DrawMiniGraphic(sx, sy, GFX_STEEL_UPPER_RIGHT);
1574 else if (x == -1 && y == lev_fieldy)
1575 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_LEFT);
1576 else if (x == lev_fieldx && y == lev_fieldy)
1577 DrawMiniGraphic(sx, sy, GFX_STEEL_LOWER_RIGHT);
1578 else if (x == -1 || x == lev_fieldx)
1579 DrawMiniGraphic(sx, sy, GFX_STEEL_VERTICAL);
1580 else if (y == -1 || y == lev_fieldy)
1581 DrawMiniGraphic(sx, sy, GFX_STEEL_HORIZONTAL);
1588 void DrawMicroElement(int xpos, int ypos, int element)
1592 if (element == EL_LEERRAUM)
1595 graphic = el2gfx(element);
1597 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1599 graphic -= GFX_START_ROCKSMORE;
1600 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1601 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1602 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1603 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1606 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1607 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1608 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1609 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1618 for(x=BX1; x<=BX2; x++)
1619 for(y=BY1; y<=BY2; y++)
1620 DrawScreenField(x, y);
1622 if (setup.soft_scrolling)
1623 XCopyArea(display, fieldbuffer, backbuffer, gc,
1624 FX, FY, SXSIZE, SYSIZE, SX, SY);
1626 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1629 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1633 for(x=0; x<size_x; x++)
1634 for(y=0; y<size_y; y++)
1635 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1637 redraw_mask |= REDRAW_FIELD;
1640 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1644 /* determine border element for this level */
1647 XFillRectangle(display, drawto, gc,
1648 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1650 if (lev_fieldx < STD_LEV_FIELDX)
1651 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1652 if (lev_fieldy < STD_LEV_FIELDY)
1653 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1655 xpos += MICRO_TILEX;
1656 ypos += MICRO_TILEY;
1658 for(x=-1; x<=STD_LEV_FIELDX; x++)
1660 for(y=-1; y<=STD_LEV_FIELDY; y++)
1662 int lx = from_x + x, ly = from_y + y;
1664 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1665 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1667 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1668 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1673 redraw_mask |= REDRAW_MICROLEVEL;
1676 static void DrawMicroLevelLabelExt(int mode)
1678 char label_text[100];
1680 XFillRectangle(display, drawto,gc,
1681 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1683 strcpy(label_text, (mode == 1 ? level.name :
1684 mode == 2 ? "created by" :
1685 mode == 3 ? level.author : ""));
1687 if (strlen(label_text) > 0)
1689 int size, lxpos, lypos;
1691 label_text[SXSIZE / FONT4_XSIZE] = '\0';
1693 size = strlen(label_text);
1694 lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1695 lypos = MICROLABEL_YPOS;
1697 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1700 redraw_mask |= REDRAW_MICROLEVEL;
1703 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1705 static unsigned long scroll_delay = 0;
1706 static unsigned long label_delay = 0;
1707 static int from_x, from_y, scroll_direction;
1708 static int label_state, label_counter;
1712 from_x = from_y = 0;
1713 scroll_direction = MV_RIGHT;
1717 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1718 DrawMicroLevelLabelExt(label_state);
1720 /* initialize delay counters */
1721 DelayReached(&scroll_delay, 0);
1722 DelayReached(&label_delay, 0);
1727 /* scroll micro level, if needed */
1728 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1729 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1731 switch (scroll_direction)
1737 scroll_direction = MV_UP;
1741 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1744 scroll_direction = MV_DOWN;
1751 scroll_direction = MV_RIGHT;
1755 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1758 scroll_direction = MV_LEFT;
1765 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1768 /* redraw micro level label, if needed */
1769 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1770 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1771 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1772 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1774 label_counter = (label_counter + 1) % 23;
1775 label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1776 label_counter >= 9 && label_counter <= 12 ? 2 :
1777 label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1778 DrawMicroLevelLabelExt(label_state);
1782 int REQ_in_range(int x, int y)
1784 if (y > DY+249 && y < DY+278)
1786 if (x > DX+1 && x < DX+48)
1788 else if (x > DX+51 && x < DX+98)
1794 boolean Request(char *text, unsigned int req_state)
1796 int mx, my, ty, result = -1;
1797 unsigned int old_door_state;
1800 /* pause network game while waiting for request to answer */
1801 if (options.network &&
1802 game_status == PLAYING &&
1803 req_state & REQUEST_WAIT_FOR)
1804 SendToServer_PausePlaying();
1807 old_door_state = GetDoorState();
1811 CloseDoor(DOOR_CLOSE_1);
1813 /* save old door content */
1814 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1815 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1816 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1818 /* clear door drawing field */
1820 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1821 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1823 XFillRectangle(display, drawto, gc, DX, DY, DXSIZE, DYSIZE);
1826 /* write text for request */
1827 for(ty=0; ty<13; ty++)
1835 for(tl=0,tx=0; tx<7; tl++,tx++)
1838 if (!tc || tc == 32)
1850 DrawTextExt(pix[PIX_DB_DOOR], gc,
1851 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1852 txt, FS_SMALL, FC_YELLOW);
1854 DrawTextExt(drawto, gc,
1855 DX + 51 - (tl * 14)/2, DY + 8 + ty * 16,
1856 txt, FS_SMALL, FC_YELLOW);
1858 text += tl + (tc == 32 ? 1 : 0);
1862 if (req_state & REQ_ASK)
1864 DrawYesNoButton(BUTTON_OK, DB_INIT);
1865 DrawYesNoButton(BUTTON_NO, DB_INIT);
1867 else if (req_state & REQ_CONFIRM)
1869 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1871 else if (req_state & REQ_PLAYER)
1873 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1874 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1875 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1876 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1880 if (req_state & REQ_ASK)
1882 MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
1883 MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
1885 else if (req_state & REQ_CONFIRM)
1887 MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
1889 else if (req_state & REQ_PLAYER)
1891 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
1892 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
1893 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
1894 MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
1897 /* copy request gadgets to door backbuffer */
1898 XCopyArea(display, drawto, pix[PIX_DB_DOOR], gc,
1899 DX, DY, DXSIZE, DYSIZE,
1900 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1904 OpenDoor(DOOR_OPEN_1);
1907 if (!(req_state & REQUEST_WAIT_FOR))
1910 if (game_status != MAINMENU)
1913 button_status = MB_RELEASED;
1915 request_gadget_id = -1;
1919 if (XPending(display))
1923 XNextEvent(display, &event);
1936 if (event.type == MotionNotify)
1943 if (!XQueryPointer(display, window, &root, &child,
1944 &root_x, &root_y, &win_x, &win_y, &mask))
1950 motion_status = TRUE;
1951 mx = ((XMotionEvent *) &event)->x;
1952 my = ((XMotionEvent *) &event)->y;
1956 motion_status = FALSE;
1957 mx = ((XButtonEvent *) &event)->x;
1958 my = ((XButtonEvent *) &event)->y;
1959 if (event.type==ButtonPress)
1960 button_status = ((XButtonEvent *) &event)->button;
1962 button_status = MB_RELEASED;
1968 if (req_state & REQ_ASK)
1969 choice = CheckYesNoButtons(mx,my,button_status);
1970 else if (req_state & REQ_CONFIRM)
1971 choice = CheckConfirmButton(mx,my,button_status);
1973 choice = CheckPlayerButtons(mx,my,button_status);
1983 case BUTTON_CONFIRM:
1984 result = TRUE | FALSE;
1987 case BUTTON_PLAYER_1:
1990 case BUTTON_PLAYER_2:
1993 case BUTTON_PLAYER_3:
1996 case BUTTON_PLAYER_4:
2005 /* this sets 'request_gadget_id' */
2006 HandleGadgets(mx, my, button_status);
2008 switch(request_gadget_id)
2010 case TOOL_CTRL_ID_YES:
2013 case TOOL_CTRL_ID_NO:
2016 case TOOL_CTRL_ID_CONFIRM:
2017 result = TRUE | FALSE;
2020 case TOOL_CTRL_ID_PLAYER_1:
2023 case TOOL_CTRL_ID_PLAYER_2:
2026 case TOOL_CTRL_ID_PLAYER_3:
2029 case TOOL_CTRL_ID_PLAYER_4:
2042 switch(XLookupKeysym((XKeyEvent *)&event,
2043 ((XKeyEvent *)&event)->state))
2056 if (req_state & REQ_PLAYER)
2061 key_joystick_mapping = 0;
2065 HandleOtherEvents(&event);
2069 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2071 int joy = AnyJoystick();
2073 if (joy & JOY_BUTTON_1)
2075 else if (joy & JOY_BUTTON_2)
2081 /* don't eat all CPU time */
2085 if (game_status != MAINMENU)
2090 if (!(req_state & REQ_STAY_OPEN))
2092 CloseDoor(DOOR_CLOSE_1);
2094 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
2096 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
2097 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
2098 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
2099 OpenDoor(DOOR_OPEN_1);
2106 /* continue network game after request */
2107 if (options.network &&
2108 game_status == PLAYING &&
2109 req_state & REQUEST_WAIT_FOR)
2110 SendToServer_ContinuePlaying();
2116 unsigned int OpenDoor(unsigned int door_state)
2118 unsigned int new_door_state;
2120 if (door_state & DOOR_COPY_BACK)
2122 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
2123 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
2124 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2125 door_state &= ~DOOR_COPY_BACK;
2128 new_door_state = MoveDoor(door_state);
2130 return(new_door_state);
2133 unsigned int CloseDoor(unsigned int door_state)
2135 unsigned int new_door_state;
2137 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2138 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2139 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
2140 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2142 new_door_state = MoveDoor(door_state);
2144 return(new_door_state);
2147 unsigned int GetDoorState()
2149 return(MoveDoor(DOOR_GET_STATE));
2152 unsigned int MoveDoor(unsigned int door_state)
2154 static int door1 = DOOR_OPEN_1;
2155 static int door2 = DOOR_CLOSE_2;
2156 static unsigned long door_delay = 0;
2157 int x, start, stepsize = 2;
2158 unsigned long door_delay_value = stepsize * 5;
2160 if (door_state == DOOR_GET_STATE)
2161 return(door1 | door2);
2163 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2164 door_state &= ~DOOR_OPEN_1;
2165 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2166 door_state &= ~DOOR_CLOSE_1;
2167 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2168 door_state &= ~DOOR_OPEN_2;
2169 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2170 door_state &= ~DOOR_CLOSE_2;
2172 if (setup.quick_doors)
2175 door_delay_value = 0;
2176 StopSound(SND_OEFFNEN);
2179 if (door_state & DOOR_ACTION)
2181 if (!(door_state & DOOR_NO_DELAY))
2182 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
2184 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2186 for(x=start; x<=DXSIZE; x+=stepsize)
2188 WaitUntilDelayReached(&door_delay, door_delay_value);
2190 if (door_state & DOOR_ACTION_1)
2192 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
2193 int j = (DXSIZE - i) / 3;
2195 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2196 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
2197 DXSIZE,DYSIZE - i/2, DX, DY);
2199 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
2201 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2202 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2203 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2204 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
2205 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2206 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
2208 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2209 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
2210 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2211 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
2212 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2213 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
2215 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2216 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2218 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2219 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2221 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2222 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2223 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2224 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2225 DX + DXSIZE - i, DY + 77 + j);
2226 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2227 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2228 DX + DXSIZE - i, DY + 203 + j);
2230 redraw_mask |= REDRAW_DOOR_1;
2233 if (door_state & DOOR_ACTION_2)
2235 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
2236 int j = (VXSIZE - i) / 3;
2238 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
2239 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
2240 VXSIZE, VYSIZE - i/2, VX, VY);
2242 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
2244 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2245 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2246 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2247 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
2248 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2249 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2250 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
2251 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
2253 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2254 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
2255 VX, VY + VYSIZE / 2 - j);
2256 XSetClipOrigin(display, clip_gc[PIX_DOOR],
2257 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2258 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
2259 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
2260 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2262 redraw_mask |= REDRAW_DOOR_2;
2270 XCopyArea(display, drawto, window, gc, DX, DY, DXSIZE, DYSIZE, DX, DY);
2275 if (game_status == MAINMENU)
2280 if (setup.quick_doors)
2281 StopSound(SND_OEFFNEN);
2283 if (door_state & DOOR_ACTION_1)
2284 door1 = door_state & DOOR_ACTION_1;
2285 if (door_state & DOOR_ACTION_2)
2286 door2 = door_state & DOOR_ACTION_2;
2288 return(door1 | door2);
2291 int ReadPixel(Drawable d, int x, int y)
2293 XImage *pixel_image;
2294 unsigned long pixel_value;
2296 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
2297 pixel_value = XGetPixel(pixel_image, 0, 0);
2299 XDestroyImage(pixel_image);
2304 /* ---------- new tool button stuff ---------------------------------------- */
2306 /* graphic position values for tool buttons */
2307 #define TOOL_BUTTON_YES_XPOS 2
2308 #define TOOL_BUTTON_YES_YPOS 250
2309 #define TOOL_BUTTON_YES_GFX_YPOS 0
2310 #define TOOL_BUTTON_YES_XSIZE 46
2311 #define TOOL_BUTTON_YES_YSIZE 28
2312 #define TOOL_BUTTON_NO_XPOS 52
2313 #define TOOL_BUTTON_NO_YPOS TOOL_BUTTON_YES_YPOS
2314 #define TOOL_BUTTON_NO_GFX_YPOS TOOL_BUTTON_YES_GFX_YPOS
2315 #define TOOL_BUTTON_NO_XSIZE TOOL_BUTTON_YES_XSIZE
2316 #define TOOL_BUTTON_NO_YSIZE TOOL_BUTTON_YES_YSIZE
2317 #define TOOL_BUTTON_CONFIRM_XPOS TOOL_BUTTON_YES_XPOS
2318 #define TOOL_BUTTON_CONFIRM_YPOS TOOL_BUTTON_YES_YPOS
2319 #define TOOL_BUTTON_CONFIRM_GFX_YPOS 30
2320 #define TOOL_BUTTON_CONFIRM_XSIZE 96
2321 #define TOOL_BUTTON_CONFIRM_YSIZE TOOL_BUTTON_YES_YSIZE
2322 #define TOOL_BUTTON_PLAYER_XSIZE 30
2323 #define TOOL_BUTTON_PLAYER_YSIZE 30
2324 #define TOOL_BUTTON_PLAYER_GFX_XPOS 5
2325 #define TOOL_BUTTON_PLAYER_GFX_YPOS 185
2326 #define TOOL_BUTTON_PLAYER_XPOS (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2327 #define TOOL_BUTTON_PLAYER_YPOS (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2328 #define TOOL_BUTTON_PLAYER1_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2329 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2330 #define TOOL_BUTTON_PLAYER2_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2331 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2332 #define TOOL_BUTTON_PLAYER3_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2333 + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2334 #define TOOL_BUTTON_PLAYER4_XPOS (TOOL_BUTTON_PLAYER_XPOS \
2335 + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2336 #define TOOL_BUTTON_PLAYER1_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2337 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2338 #define TOOL_BUTTON_PLAYER2_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2339 + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2340 #define TOOL_BUTTON_PLAYER3_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2341 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2342 #define TOOL_BUTTON_PLAYER4_YPOS (TOOL_BUTTON_PLAYER_YPOS \
2343 + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2352 } toolbutton_info[NUM_TOOL_BUTTONS] =
2355 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_GFX_YPOS,
2356 TOOL_BUTTON_YES_XPOS, TOOL_BUTTON_YES_YPOS,
2357 TOOL_BUTTON_YES_XSIZE, TOOL_BUTTON_YES_YSIZE,
2362 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_GFX_YPOS,
2363 TOOL_BUTTON_NO_XPOS, TOOL_BUTTON_NO_YPOS,
2364 TOOL_BUTTON_NO_XSIZE, TOOL_BUTTON_NO_YSIZE,
2369 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_GFX_YPOS,
2370 TOOL_BUTTON_CONFIRM_XPOS, TOOL_BUTTON_CONFIRM_YPOS,
2371 TOOL_BUTTON_CONFIRM_XSIZE, TOOL_BUTTON_CONFIRM_YSIZE,
2372 TOOL_CTRL_ID_CONFIRM,
2376 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2377 TOOL_BUTTON_PLAYER1_XPOS, TOOL_BUTTON_PLAYER1_YPOS,
2378 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2379 TOOL_CTRL_ID_PLAYER_1,
2383 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2384 TOOL_BUTTON_PLAYER2_XPOS, TOOL_BUTTON_PLAYER2_YPOS,
2385 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2386 TOOL_CTRL_ID_PLAYER_2,
2390 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2391 TOOL_BUTTON_PLAYER3_XPOS, TOOL_BUTTON_PLAYER3_YPOS,
2392 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2393 TOOL_CTRL_ID_PLAYER_3,
2397 TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2398 TOOL_BUTTON_PLAYER4_XPOS, TOOL_BUTTON_PLAYER4_YPOS,
2399 TOOL_BUTTON_PLAYER_XSIZE, TOOL_BUTTON_PLAYER_YSIZE,
2400 TOOL_CTRL_ID_PLAYER_4,
2405 void CreateToolButtons()
2409 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2411 Pixmap gd_pixmap = pix[PIX_DOOR];
2412 Pixmap deco_pixmap = None;
2413 int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2414 struct GadgetInfo *gi;
2415 unsigned long event_mask;
2416 int gd_xoffset, gd_yoffset;
2417 int gd_x1, gd_x2, gd_y;
2420 event_mask = GD_EVENT_RELEASED;
2422 gd_xoffset = toolbutton_info[i].xpos;
2423 gd_yoffset = toolbutton_info[i].ypos;
2424 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2425 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2426 gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2428 if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2430 getMiniGraphicSource(GFX_SPIELER1 + id - TOOL_CTRL_ID_PLAYER_1,
2431 &deco_pixmap, &deco_x, &deco_y);
2432 deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2433 deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2436 gi = CreateGadget(GDI_CUSTOM_ID, id,
2437 GDI_INFO_TEXT, toolbutton_info[i].infotext,
2438 GDI_X, DX + toolbutton_info[i].x,
2439 GDI_Y, DY + toolbutton_info[i].y,
2440 GDI_WIDTH, toolbutton_info[i].width,
2441 GDI_HEIGHT, toolbutton_info[i].height,
2442 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2443 GDI_STATE, GD_BUTTON_UNPRESSED,
2444 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
2445 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
2446 GDI_DECORATION_DESIGN, deco_pixmap, deco_x, deco_y,
2447 GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2448 GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2449 GDI_DECORATION_SHIFTING, 1, 1,
2450 GDI_EVENT_MASK, event_mask,
2451 GDI_CALLBACK_ACTION, HandleToolButtons,
2455 Error(ERR_EXIT, "cannot create gadget");
2457 tool_gadget[id] = gi;
2461 static void UnmapToolButtons()
2465 for (i=0; i<NUM_TOOL_BUTTONS; i++)
2466 UnmapGadget(tool_gadget[i]);
2469 static void HandleToolButtons(struct GadgetInfo *gi)
2471 request_gadget_id = gi->custom_id;
2475 int id = gi->custom_id;
2477 if (game_status != PLAYING)
2482 case GAME_CTRL_ID_STOP:
2485 CloseDoor(DOOR_CLOSE_1);
2486 game_status = MAINMENU;
2491 if (Request("Do you really want to quit the game ?",
2492 REQ_ASK | REQ_STAY_CLOSED))
2495 if (options.network)
2496 SendToServer_StopPlaying();
2500 game_status = MAINMENU;
2505 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2508 case GAME_CTRL_ID_PAUSE:
2509 if (options.network)
2513 SendToServer_ContinuePlaying();
2515 SendToServer_PausePlaying();
2522 case GAME_CTRL_ID_PLAY:
2526 if (options.network)
2527 SendToServer_ContinuePlaying();
2531 tape.pausing = FALSE;
2532 DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
2537 case SOUND_CTRL_ID_MUSIC:
2538 if (setup.sound_music)
2540 setup.sound_music = FALSE;
2541 FadeSound(background_loop[level_nr % num_bg_loops]);
2543 else if (sound_loops_allowed)
2545 setup.sound = setup.sound_music = TRUE;
2546 PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
2550 case SOUND_CTRL_ID_LOOPS:
2551 if (setup.sound_loops)
2552 setup.sound_loops = FALSE;
2553 else if (sound_loops_allowed)
2554 setup.sound = setup.sound_loops = TRUE;
2557 case SOUND_CTRL_ID_SIMPLE:
2558 if (setup.sound_simple)
2559 setup.sound_simple = FALSE;
2560 else if (sound_status==SOUND_AVAILABLE)
2561 setup.sound = setup.sound_simple = TRUE;
2573 int el2gfx(int element)
2577 case EL_LEERRAUM: return -1;
2578 case EL_ERDREICH: return GFX_ERDREICH;
2579 case EL_MAUERWERK: return GFX_MAUERWERK;
2580 case EL_FELSBODEN: return GFX_FELSBODEN;
2581 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
2582 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
2583 case EL_EDELSTEIN: return GFX_EDELSTEIN;
2584 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
2585 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
2586 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
2587 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
2588 case EL_SPIELER1: return GFX_SPIELER1;
2589 case EL_SPIELER2: return GFX_SPIELER2;
2590 case EL_SPIELER3: return GFX_SPIELER3;
2591 case EL_SPIELER4: return GFX_SPIELER4;
2592 case EL_KAEFER: return GFX_KAEFER;
2593 case EL_KAEFER_R: return GFX_KAEFER_R;
2594 case EL_KAEFER_O: return GFX_KAEFER_O;
2595 case EL_KAEFER_L: return GFX_KAEFER_L;
2596 case EL_KAEFER_U: return GFX_KAEFER_U;
2597 case EL_FLIEGER: return GFX_FLIEGER;
2598 case EL_FLIEGER_R: return GFX_FLIEGER_R;
2599 case EL_FLIEGER_O: return GFX_FLIEGER_O;
2600 case EL_FLIEGER_L: return GFX_FLIEGER_L;
2601 case EL_FLIEGER_U: return GFX_FLIEGER_U;
2602 case EL_BUTTERFLY: return GFX_BUTTERFLY;
2603 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
2604 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
2605 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
2606 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
2607 case EL_FIREFLY: return GFX_FIREFLY;
2608 case EL_FIREFLY_R: return GFX_FIREFLY_R;
2609 case EL_FIREFLY_O: return GFX_FIREFLY_O;
2610 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2611 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2612 case EL_MAMPFER: return GFX_MAMPFER;
2613 case EL_ROBOT: return GFX_ROBOT;
2614 case EL_BETON: return GFX_BETON;
2615 case EL_DIAMANT: return GFX_DIAMANT;
2616 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2617 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2618 case EL_TROPFEN: return GFX_TROPFEN;
2619 case EL_BOMBE: return GFX_BOMBE;
2620 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2621 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2622 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2623 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2624 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2625 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2626 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2627 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2628 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2629 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2630 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2631 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2632 case EL_LIFE: return GFX_LIFE;
2633 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2634 case EL_DYNAMIT: return GFX_DYNAMIT;
2635 case EL_BADEWANNE: return GFX_BADEWANNE;
2636 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2637 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2638 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2639 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2640 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2641 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2642 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2643 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2644 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2645 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2646 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2647 case EL_PFORTE1: return GFX_PFORTE1;
2648 case EL_PFORTE2: return GFX_PFORTE2;
2649 case EL_PFORTE3: return GFX_PFORTE3;
2650 case EL_PFORTE4: return GFX_PFORTE4;
2651 case EL_PFORTE1X: return GFX_PFORTE1X;
2652 case EL_PFORTE2X: return GFX_PFORTE2X;
2653 case EL_PFORTE3X: return GFX_PFORTE3X;
2654 case EL_PFORTE4X: return GFX_PFORTE4X;
2655 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
2656 case EL_PACMAN: return GFX_PACMAN;
2657 case EL_PACMAN_R: return GFX_PACMAN_R;
2658 case EL_PACMAN_O: return GFX_PACMAN_O;
2659 case EL_PACMAN_L: return GFX_PACMAN_L;
2660 case EL_PACMAN_U: return GFX_PACMAN_U;
2661 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2662 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2663 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2664 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2665 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2666 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2667 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2668 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2669 case EL_MAUER_X: return GFX_MAUER_X;
2670 case EL_MAUER_Y: return GFX_MAUER_Y;
2671 case EL_MAUER_XY: return GFX_MAUER_XY;
2672 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2673 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2674 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2675 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2676 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2677 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2678 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2679 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2680 case EL_MAMPFER2: return GFX_MAMPFER2;
2681 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2682 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2683 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2684 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2685 case EL_DYNABOMB: return GFX_DYNABOMB;
2686 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2687 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2688 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2689 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2690 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2691 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2692 case EL_MAULWURF: return GFX_MAULWURF;
2693 case EL_PINGUIN: return GFX_PINGUIN;
2694 case EL_SCHWEIN: return GFX_SCHWEIN;
2695 case EL_DRACHE: return GFX_DRACHE;
2696 case EL_SONDE: return GFX_SONDE;
2697 case EL_PFEIL_L: return GFX_PFEIL_L;
2698 case EL_PFEIL_R: return GFX_PFEIL_R;
2699 case EL_PFEIL_O: return GFX_PFEIL_O;
2700 case EL_PFEIL_U: return GFX_PFEIL_U;
2701 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2702 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2703 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2704 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2705 case EL_BLACK_ORB: return GFX_BLACK_ORB;
2709 if (IS_CHAR(element))
2710 return GFX_CHAR_START + (element - EL_CHAR_START);
2711 else if (element >= EL_SP_START && element <= EL_SP_END)
2713 int nr_element = element - EL_SP_START;
2714 int gfx_per_line = 8;
2716 (nr_element / gfx_per_line) * MORE_PER_LINE +
2717 (nr_element % gfx_per_line);
2719 return GFX_START_ROCKSMORE + nr_graphic;