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 void SetDrawtoField(int mode)
36 if (mode == DRAW_BUFFERED && setup.soft_scrolling)
47 drawto_field = fieldbuffer;
49 else /* DRAW_DIRECT, DRAW_BACKBUFFER */
60 drawto_field = (mode == DRAW_DIRECT ? window : backbuffer);
67 Drawable buffer = (drawto_field == window ? backbuffer : drawto_field);
69 if (setup.direct_draw && game_status == PLAYING)
70 redraw_mask &= ~REDRAW_MAIN;
72 if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
73 redraw_mask |= REDRAW_FIELD;
75 if (redraw_mask & REDRAW_FIELD)
76 redraw_mask &= ~REDRAW_TILES;
79 if (redraw_mask & REDRAW_FIELD ||
80 (ScreenGfxPos && setup.soft_scrolling && game_status == PLAYING))
81 redraw_mask &= ~REDRAW_TILES;
87 /* synchronize X11 graphics at this point; if we would synchronize the
88 display immediately after the buffer switching (after the XFlush),
89 this could mean that we have to wait for the graphics to complete,
90 although we could go on doing calculations for the next frame */
92 XSync(display, FALSE);
96 wait_for_vsync = TRUE;
100 if (redraw_mask & REDRAW_ALL)
102 XCopyArea(display,backbuffer,window,gc,
103 0,0, WIN_XSIZE,WIN_YSIZE,
108 if (redraw_mask & REDRAW_FIELD)
110 if (game_status != PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER)
111 XCopyArea(display,backbuffer,window,gc,
112 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
116 int fx = FX, fy = FY;
118 if (setup.soft_scrolling)
120 fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
121 fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0);
124 if (setup.soft_scrolling ||
125 ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
126 ABS(ScreenMovPos) == ScrollStepSize ||
127 redraw_tiles > REDRAWTILES_THRESHOLD)
129 XCopyArea(display, buffer, window, gc, fx, fy, SXSIZE, SYSIZE, SX, SY);
133 printf("redrawing all (ScreenGfxPos == %d) because %s\n",
135 (setup.soft_scrolling ?
136 "setup.soft_scrolling" :
137 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
138 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
139 ABS(ScreenGfxPos) == ScrollStepSize ?
140 "ABS(ScreenGfxPos) == ScrollStepSize" :
141 "redraw_tiles > REDRAWTILES_THRESHOLD"));
146 redraw_mask &= ~REDRAW_MAIN;
149 if (redraw_mask & REDRAW_DOORS)
151 if (redraw_mask & REDRAW_DOOR_1)
152 XCopyArea(display,backbuffer,window,gc,
153 DX,DY, DXSIZE,DYSIZE,
155 if (redraw_mask & REDRAW_DOOR_2)
157 if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
158 XCopyArea(display,backbuffer,window,gc,
159 VX,VY, VXSIZE,VYSIZE,
163 if (redraw_mask & REDRAW_VIDEO_1)
164 XCopyArea(display,backbuffer,window,gc,
165 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
166 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
167 VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
168 if (redraw_mask & REDRAW_VIDEO_2)
169 XCopyArea(display,backbuffer,window,gc,
170 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
171 VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
172 VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
173 if (redraw_mask & REDRAW_VIDEO_3)
174 XCopyArea(display,backbuffer,window,gc,
175 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
176 VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
177 VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
180 if (redraw_mask & REDRAW_DOOR_3)
181 XCopyArea(display, backbuffer, window, gc,
182 EX, EY, EXSIZE, EYSIZE,
184 redraw_mask &= ~REDRAW_DOORS;
187 if (redraw_mask & REDRAW_MICROLEVEL)
189 XCopyArea(display,backbuffer,window,gc,
190 MICROLEV_XPOS, MICROLEV_YPOS, MICROLEV_XSIZE, MICROLEV_YSIZE,
191 MICROLEV_XPOS, MICROLEV_YPOS);
192 XCopyArea(display,backbuffer,window,gc,
193 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE,
194 SX, MICROLABEL_YPOS);
195 redraw_mask &= ~REDRAW_MICROLEVEL;
198 if (redraw_mask & REDRAW_TILES)
200 for(x=0; x<SCR_FIELDX; x++)
201 for(y=0; y<SCR_FIELDY; y++)
202 if (redraw[redraw_x1 + x][redraw_y1 + y])
203 XCopyArea(display,buffer,window,gc,
204 FX+x*TILEX,FX+y*TILEY, TILEX,TILEY,
205 SX+x*TILEX,SY+y*TILEY);
210 for(x=0; x<MAX_BUF_XSIZE; x++)
211 for(y=0; y<MAX_BUF_YSIZE; y++)
220 long fading_delay = 300;
222 if (setup.fading && (redraw_mask & REDRAW_FIELD))
229 XFillRectangle(display,window,gc,
230 REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
233 for(i=0;i<2*FULL_SYSIZE;i++)
235 for(y=0;y<FULL_SYSIZE;y++)
237 XCopyArea(display,backbuffer,window,gc,
238 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
246 for(i=1;i<FULL_SYSIZE;i+=2)
247 XCopyArea(display,backbuffer,window,gc,
248 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
254 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
255 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
256 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
260 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
261 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
262 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
266 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
267 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
268 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
272 XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
273 XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
274 REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
278 redraw_mask &= ~REDRAW_MAIN;
287 XFillRectangle(display, backbuffer, gc,
288 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
290 if (setup.soft_scrolling && game_status == PLAYING)
292 XFillRectangle(display, fieldbuffer, gc, 0, 0, FXSIZE, FYSIZE);
293 SetDrawtoField(DRAW_BUFFERED);
296 SetDrawtoField(DRAW_BACKBUFFER);
298 if (setup.direct_draw && game_status == PLAYING)
300 XFillRectangle(display, window, gc,
301 REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
302 SetDrawtoField(DRAW_DIRECT);
305 redraw_mask |= REDRAW_FIELD;
308 void DrawTextFCentered(int y, int font_type, char *format, ...)
310 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
314 font_xsize = (font_type < FC_SPECIAL1 ? FONT2_XSIZE :
315 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
317 va_start(ap, format);
318 vsprintf(buffer, format, ap);
321 DrawText(SX + (SXSIZE - strlen(buffer) * font_xsize) / 2, SY + y,
322 buffer, FS_SMALL, font_type);
325 void DrawTextF(int x, int y, int font_type, char *format, ...)
327 char buffer[FULL_SXSIZE / FONT3_XSIZE + 10];
330 va_start(ap, format);
331 vsprintf(buffer, format, ap);
334 DrawText(SX + x, SY + y, buffer, FS_SMALL, font_type);
337 void DrawText(int x, int y, char *text, int font_size, int font_type)
339 DrawTextExt(drawto, gc, x, y, text, font_size, font_type);
342 redraw_mask |= REDRAW_FIELD;
344 redraw_mask |= REDRAW_DOOR_1;
347 void DrawTextExt(Drawable d, GC gc, int x, int y,
348 char *text, int font_size, int font_type)
350 int font_width, font_height, font_start;
352 boolean print_inverse = FALSE;
354 if (font_size != FS_SMALL && font_size != FS_BIG)
355 font_size = FS_SMALL;
356 if (font_type < FC_RED || font_type > FC_SPECIAL2)
359 font_width = (font_size == FS_BIG ? FONT1_XSIZE :
360 font_type < FC_SPECIAL1 ? FONT2_XSIZE :
361 font_type < FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
362 font_height = (font_size == FS_BIG ? FONT1_XSIZE :
363 font_type < FC_SPECIAL2 ? FONT2_XSIZE : FONT4_XSIZE);
364 font_pixmap = (font_size == FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
365 font_start = (font_type * (font_size == FS_BIG ? FONT1_YSIZE : FONT2_YSIZE) *
366 FONT_LINES_PER_FONT);
372 if (c == '~' && font_size == FS_SMALL && font_type <= FC_YELLOW)
374 print_inverse = TRUE;
378 if (c >= 'a' && c <= 'z')
380 else if (c == 'ä' || c == 'Ä')
382 else if (c == 'ö' || c == 'Ö')
384 else if (c == 'ü' || c == 'Ü')
387 if (c >= 32 && c <= 95)
389 int src_x = ((c - 32) % FONT_CHARS_PER_LINE) * font_width;
390 int src_y = ((c - 32) / FONT_CHARS_PER_LINE) * font_height + font_start;
391 int dest_x = x, dest_y = y;
395 XCopyArea(display, pix[font_pixmap], d, gc,
396 FONT_CHARS_PER_LINE * font_width,
397 3 * font_height + font_start,
398 font_width, font_height, x, y);
400 XSetClipOrigin(display, clip_gc[font_pixmap],
401 dest_x - src_x, dest_y - src_y);
402 XCopyArea(display, pix[font_pixmap], drawto, clip_gc[font_pixmap],
403 0, 0, font_width, font_height, dest_x, dest_y);
406 XCopyArea(display, pix[font_pixmap], d, gc,
407 src_x, src_y, font_width, font_height, dest_x, dest_y);
414 void DrawAllPlayers()
418 for(i=0; i<MAX_PLAYERS; i++)
419 if (stored_player[i].active)
420 DrawPlayer(&stored_player[i]);
423 void DrawPlayerField(int x, int y)
428 DrawPlayer(PLAYERINFO(x,y));
431 void DrawPlayer(struct PlayerInfo *player)
433 int jx = player->jx, jy = player->jy;
434 int last_jx = player->last_jx, last_jy = player->last_jy;
435 int next_jx = jx + (jx - last_jx), next_jy = jy + (jy - last_jy);
436 int sx = SCREENX(jx), sy = SCREENY(jy);
437 int sxx = 0, syy = 0;
438 int element = Feld[jx][jy];
441 if (!player->active || player->gone ||
442 !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
446 if (!IN_LEV_FIELD(jx,jy))
448 printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
449 printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
450 printf("DrawPlayerField(): This should never happen!\n");
455 if (element == EL_EXPLODING)
458 /* draw things in the field the player is leaving, if needed */
460 if (last_jx != jx || last_jy != jy)
462 if (Store[last_jx][last_jy])
464 DrawLevelElement(last_jx, last_jy, Store[last_jx][last_jy]);
465 DrawLevelFieldThruMask(last_jx, last_jy);
467 else if (Feld[last_jx][last_jy] == EL_DYNAMIT)
468 DrawDynamite(last_jx, last_jy);
470 DrawLevelField(last_jx, last_jy);
472 if (player->Pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
476 if (Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
477 DrawLevelElement(next_jx, next_jy, EL_SOKOBAN_FELD_LEER);
479 DrawLevelElement(next_jx, next_jy, EL_LEERRAUM);
482 DrawLevelField(next_jx, next_jy);
486 if (!IN_SCR_FIELD(sx, sy))
489 if (setup.direct_draw)
490 SetDrawtoField(DRAW_BUFFERED);
492 /* draw things behind the player, if needed */
495 DrawLevelElement(jx, jy, Store[jx][jy]);
496 else if (element != EL_DYNAMIT && element != EL_DYNABOMB)
497 DrawLevelField(jx, jy);
499 /* draw player himself */
501 if (player->MovDir == MV_LEFT)
502 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_LEFT : GFX_SPIELER1_LEFT);
503 else if (player->MovDir == MV_RIGHT)
504 graphic = (player->Pushing ? GFX_SPIELER1_PUSH_RIGHT : GFX_SPIELER1_RIGHT);
505 else if (player->MovDir == MV_UP)
506 graphic = GFX_SPIELER1_UP;
507 else /* MV_DOWN || MV_NO_MOVING */
508 graphic = GFX_SPIELER1_DOWN;
510 graphic += player->index_nr * 3*HEROES_PER_LINE;
511 graphic += player->Frame;
515 if (player->MovDir == MV_LEFT || player->MovDir == MV_RIGHT)
516 sxx = player->GfxPos;
518 syy = player->GfxPos;
521 if (!setup.soft_scrolling && ScreenMovPos)
524 DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, NO_CUTTING);
526 if (player->Pushing && player->GfxPos)
528 int px = SCREENX(next_jx), py = SCREENY(next_jy);
530 if (Feld[jx][jy] == EL_SOKOBAN_FELD_LEER ||
531 Feld[next_jx][next_jy] == EL_SOKOBAN_FELD_VOLL)
532 DrawGraphicShiftedThruMask(px, py, sxx, syy, GFX_SOKOBAN_OBJEKT,
536 int element = Feld[next_jx][next_jy];
537 int graphic = el2gfx(element);
539 if (element == EL_FELSBROCKEN && sxx)
541 int phase = (player->GfxPos / (TILEX/4));
543 if (player->MovDir == MV_LEFT)
546 graphic += (phase+4)%4;
549 DrawGraphicShifted(px, py, sxx, syy, graphic, NO_CUTTING, NO_MASKING);
553 /* draw things in front of player (EL_DYNAMIT || EL_DYNABOMB) */
555 if (element == EL_DYNAMIT || element == EL_DYNABOMB)
557 graphic = el2gfx(element);
559 if (element == EL_DYNAMIT)
561 if ((phase = (96 - MovDelay[jx][jy]) / 12) > 6)
566 if ((phase = ((96 - MovDelay[jx][jy]) / 6) % 8) > 3)
570 if (game_emulation == EMU_SUPAPLEX)
571 DrawGraphic(sx, sy, GFX_SP_DISK_RED);
573 DrawGraphicThruMask(sx, sy, graphic + phase);
576 if ((last_jx != jx || last_jy != jy) &&
577 Feld[last_jx][last_jy] == EL_EXPLODING)
579 int phase = Frame[last_jx][last_jy];
583 DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy),
584 GFX_EXPLOSION + ((phase - 1) / delay - 1));
587 if (setup.direct_draw)
589 int dest_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
590 int dest_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
591 int x_size = TILEX * (1 + ABS(jx - last_jx));
592 int y_size = TILEY * (1 + ABS(jy - last_jy));
594 XCopyArea(display, drawto_field, window, gc,
595 dest_x, dest_y, x_size, y_size, dest_x, dest_y);
596 SetDrawtoField(DRAW_DIRECT);
599 MarkTileDirty(sx,sy);
602 static int getGraphicAnimationPhase(int frames, int delay, int mode)
606 if (mode == ANIM_OSCILLATE)
608 int max_anim_frames = 2 * frames - 2;
609 phase = (FrameCounter % (delay * max_anim_frames)) / delay;
610 phase = (phase < frames ? phase : max_anim_frames - phase);
613 phase = (FrameCounter % (delay * frames)) / delay;
615 if (mode == ANIM_REVERSE)
621 void DrawGraphicAnimationExt(int x, int y, int graphic,
622 int frames, int delay, int mode, int mask_mode)
624 int phase = getGraphicAnimationPhase(frames, delay, mode);
626 if (!(FrameCounter % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
628 if (mask_mode == USE_MASKING)
629 DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic + phase);
631 DrawGraphic(SCREENX(x), SCREENY(y), graphic + phase);
635 void DrawGraphicAnimation(int x, int y, int graphic,
636 int frames, int delay, int mode)
638 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, NO_MASKING);
641 void DrawGraphicAnimationThruMask(int x, int y, int graphic,
642 int frames, int delay, int mode)
644 DrawGraphicAnimationExt(x, y, graphic, frames, delay, mode, USE_MASKING);
647 void DrawGraphic(int x, int y, int graphic)
650 if (!IN_SCR_FIELD(x,y))
652 printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
653 printf("DrawGraphic(): This should never happen!\n");
658 DrawGraphicExt(drawto_field, gc, FX + x*TILEX, FY + y*TILEY, graphic);
662 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
664 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
666 graphic -= GFX_START_ROCKSSCREEN;
667 XCopyArea(display, pix[PIX_BACK], d, gc,
668 SX + (graphic % GFX_PER_LINE) * TILEX,
669 SY + (graphic / GFX_PER_LINE) * TILEY,
672 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
674 graphic -= GFX_START_ROCKSMORE;
675 XCopyArea(display, pix[PIX_MORE], d, gc,
676 (graphic % MORE_PER_LINE) * TILEX,
677 (graphic / MORE_PER_LINE) * TILEY,
680 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
682 graphic -= GFX_START_ROCKSHEROES;
683 XCopyArea(display, pix[PIX_HEROES], d, gc,
684 (graphic % HEROES_PER_LINE) * TILEX,
685 (graphic / HEROES_PER_LINE) * TILEY,
688 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
690 graphic -= GFX_START_ROCKSFONT;
691 XCopyArea(display, pix[PIX_BIGFONT], d, gc,
692 (graphic % FONT_CHARS_PER_LINE) * TILEX,
693 (graphic / FONT_CHARS_PER_LINE) * TILEY +
694 FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY,
698 XFillRectangle(display, d, gc, x, y, TILEX, TILEY);
701 void DrawGraphicThruMask(int x, int y, int graphic)
704 if (!IN_SCR_FIELD(x,y))
706 printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
707 printf("DrawGraphicThruMask(): This should never happen!\n");
712 DrawGraphicThruMaskExt(drawto_field, FX + x*TILEX, FY + y*TILEY, graphic);
716 void DrawGraphicThruMaskExt(Drawable d, int dest_x, int dest_y, int graphic)
723 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
725 src_pixmap = pix[PIX_BACK];
726 drawing_gc = clip_gc[PIX_BACK];
727 graphic -= GFX_START_ROCKSSCREEN;
728 src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
729 src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
731 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
733 src_pixmap = pix[PIX_MORE];
734 drawing_gc = clip_gc[PIX_MORE];
735 graphic -= GFX_START_ROCKSMORE;
736 src_x = (graphic % MORE_PER_LINE) * TILEX;
737 src_y = (graphic / MORE_PER_LINE) * TILEY;
739 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
741 src_pixmap = pix[PIX_HEROES];
742 drawing_gc = clip_gc[PIX_HEROES];
743 graphic -= GFX_START_ROCKSHEROES;
744 src_x = (graphic % HEROES_PER_LINE) * TILEX;
745 src_y = (graphic / HEROES_PER_LINE) * TILEY;
749 DrawGraphicExt(d, gc, dest_x,dest_y, graphic);
753 if (tile_clipmask[tile] != None)
755 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
756 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
757 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
758 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
763 printf("DrawGraphicThruMask(): tile '%d' needs clipping!\n", tile);
766 XSetClipOrigin(display, drawing_gc, dest_x-src_x, dest_y-src_y);
767 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
768 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
772 void DrawMiniGraphic(int x, int y, int graphic)
774 DrawMiniGraphicExt(drawto,gc, SX + x*MINI_TILEX, SY + y*MINI_TILEY, graphic);
775 MarkTileDirty(x/2, y/2);
778 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
780 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
782 graphic -= GFX_START_ROCKSSCREEN;
783 XCopyArea(display, pix[PIX_BACK], d, gc,
784 MINI_GFX_STARTX + (graphic % MINI_GFX_PER_LINE) * MINI_TILEX,
785 MINI_GFX_STARTY + (graphic / MINI_GFX_PER_LINE) * MINI_TILEY,
786 MINI_TILEX, MINI_TILEY, x, y);
788 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
790 graphic -= GFX_START_ROCKSMORE;
791 XCopyArea(display, pix[PIX_MORE], d, gc,
792 MINI_MORE_STARTX + (graphic % MINI_MORE_PER_LINE) * MINI_TILEX,
793 MINI_MORE_STARTY + (graphic / MINI_MORE_PER_LINE) * MINI_TILEY,
794 MINI_TILEX, MINI_TILEY, x, y);
796 else if (graphic >= GFX_START_ROCKSFONT && graphic <= GFX_END_ROCKSFONT)
798 graphic -= GFX_START_ROCKSFONT;
799 XCopyArea(display, pix[PIX_SMALLFONT], d, gc,
800 (graphic % FONT_CHARS_PER_LINE) * FONT4_XSIZE,
801 (graphic / FONT_CHARS_PER_LINE) * FONT4_YSIZE +
802 FC_SPECIAL2 * FONT2_YSIZE * FONT_LINES_PER_FONT,
803 MINI_TILEX, MINI_TILEY, x, y);
806 XFillRectangle(display, d, gc, x, y, MINI_TILEX, MINI_TILEY);
809 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic,
810 int cut_mode, int mask_mode)
812 int width = TILEX, height = TILEY;
814 int src_x, src_y, dest_x, dest_y;
821 DrawGraphic(x, y, graphic);
825 if (dx || dy) /* Verschiebung der Grafik? */
827 if (x < BX1) /* Element kommt von links ins Bild */
834 else if (x > BX2) /* Element kommt von rechts ins Bild */
840 else if (x==BX1 && dx < 0) /* Element verläßt links das Bild */
846 else if (x==BX2 && dx > 0) /* Element verläßt rechts das Bild */
848 else if (dx) /* allg. Bewegung in x-Richtung */
849 MarkTileDirty(x + SIGN(dx), y);
851 if (y < BY1) /* Element kommt von oben ins Bild */
853 if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
861 else if (y > BY2) /* Element kommt von unten ins Bild */
867 else if (y==BY1 && dy < 0) /* Element verläßt oben das Bild */
873 else if (dy > 0 && cut_mode == CUT_ABOVE)
875 if (y == BY2) /* Element unterhalb des Bildes */
881 MarkTileDirty(x, y + 1);
882 } /* Element verläßt unten das Bild */
883 else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
885 else if (dy) /* allg. Bewegung in y-Richtung */
886 MarkTileDirty(x, y + SIGN(dy));
889 if (graphic >= GFX_START_ROCKSSCREEN && graphic <= GFX_END_ROCKSSCREEN)
891 src_pixmap = pix[PIX_BACK];
892 drawing_gc = clip_gc[PIX_BACK];
893 graphic -= GFX_START_ROCKSSCREEN;
894 src_x = SX + (graphic % GFX_PER_LINE) * TILEX + cx;
895 src_y = SY + (graphic / GFX_PER_LINE) * TILEY + cy;
897 else if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
899 src_pixmap = pix[PIX_MORE];
900 drawing_gc = clip_gc[PIX_MORE];
901 graphic -= GFX_START_ROCKSMORE;
902 src_x = (graphic % MORE_PER_LINE) * TILEX + cx;
903 src_y = (graphic / MORE_PER_LINE) * TILEY + cy;
905 else if (graphic >= GFX_START_ROCKSHEROES && graphic <= GFX_END_ROCKSHEROES)
907 src_pixmap = pix[PIX_HEROES];
908 drawing_gc = clip_gc[PIX_HEROES];
909 graphic -= GFX_START_ROCKSHEROES;
910 src_x = (graphic % HEROES_PER_LINE) * TILEX + cx;
911 src_y = (graphic / HEROES_PER_LINE) * TILEY + cy;
913 else /* big font graphics currently not allowed (and not needed) */
916 dest_x = FX + x * TILEX + dx;
917 dest_y = FY + y * TILEY + dy;
920 if (!IN_SCR_FIELD(x,y))
922 printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
923 printf("DrawGraphicShifted(): This should never happen!\n");
928 if (mask_mode == USE_MASKING)
930 if (tile_clipmask[tile] != None)
932 XSetClipMask(display, tile_clip_gc, tile_clipmask[tile]);
933 XSetClipOrigin(display, tile_clip_gc, dest_x, dest_y);
934 XCopyArea(display, src_pixmap, drawto_field, tile_clip_gc,
935 src_x, src_y, TILEX, TILEY, dest_x, dest_y);
940 printf("DrawGraphicShifted(): tile '%d' needs clipping!\n", tile);
943 XSetClipOrigin(display, drawing_gc, dest_x - src_x, dest_y - src_y);
944 XCopyArea(display, src_pixmap, drawto_field, drawing_gc,
945 src_x, src_y, width, height, dest_x, dest_y);
949 XCopyArea(display, src_pixmap, drawto_field, gc,
950 src_x, src_y, width, height, dest_x, dest_y);
955 void DrawGraphicShiftedThruMask(int x,int y, int dx,int dy, int graphic,
958 DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode, USE_MASKING);
961 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
962 int cut_mode, int mask_mode)
964 int ux = LEVELX(x), uy = LEVELY(y);
965 int graphic = el2gfx(element);
966 int phase8 = ABS(MovPos[ux][uy]) / (TILEX / 8);
967 int phase4 = phase8 / 2;
968 int phase2 = phase8 / 4;
969 int dir = MovDir[ux][uy];
971 if (element == EL_PACMAN || element == EL_KAEFER || element == EL_FLIEGER)
973 graphic += 4 * !phase2;
977 else if (dir == MV_LEFT)
979 else if (dir == MV_DOWN)
982 else if (element == EL_SP_SNIKSNAK)
985 graphic = GFX_SP_SNIKSNAK_LEFT;
986 else if (dir == MV_RIGHT)
987 graphic = GFX_SP_SNIKSNAK_RIGHT;
988 else if (dir == MV_UP)
989 graphic = GFX_SP_SNIKSNAK_UP;
991 graphic = GFX_SP_SNIKSNAK_DOWN;
993 graphic += (phase8 < 4 ? phase8 : 7 - phase8);
995 else if (element == EL_SP_ELECTRON)
997 graphic = GFX2_SP_ELECTRON + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
999 else if (element == EL_MAULWURF || element == EL_PINGUIN ||
1000 element == EL_SCHWEIN || element == EL_DRACHE)
1003 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_LEFT :
1004 element == EL_PINGUIN ? GFX_PINGUIN_LEFT :
1005 element == EL_SCHWEIN ? GFX_SCHWEIN_LEFT : GFX_DRACHE_LEFT);
1006 else if (dir == MV_RIGHT)
1007 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_RIGHT :
1008 element == EL_PINGUIN ? GFX_PINGUIN_RIGHT :
1009 element == EL_SCHWEIN ? GFX_SCHWEIN_RIGHT : GFX_DRACHE_RIGHT);
1010 else if (dir == MV_UP)
1011 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_UP :
1012 element == EL_PINGUIN ? GFX_PINGUIN_UP :
1013 element == EL_SCHWEIN ? GFX_SCHWEIN_UP : GFX_DRACHE_UP);
1015 graphic = (element == EL_MAULWURF ? GFX_MAULWURF_DOWN :
1016 element == EL_PINGUIN ? GFX_PINGUIN_DOWN :
1017 element == EL_SCHWEIN ? GFX_SCHWEIN_DOWN : GFX_DRACHE_DOWN);
1021 else if (element == EL_SONDE)
1023 graphic = GFX_SONDE_START + getGraphicAnimationPhase(8, 2, ANIM_NORMAL);
1025 else if (element == EL_SALZSAEURE)
1027 graphic = GFX_GEBLUBBER + getGraphicAnimationPhase(4, 10, ANIM_NORMAL);
1029 else if (element == EL_BUTTERFLY || element == EL_FIREFLY)
1033 else if ((element == EL_FELSBROCKEN || IS_GEM(element)) && !cut_mode)
1035 if (element != EL_SP_INFOTRON)
1036 graphic += phase2 * (element == EL_FELSBROCKEN ? 2 : 1);
1038 else if (element == EL_SIEB_LEER || element == EL_SIEB2_LEER ||
1039 element == EL_SIEB_VOLL || element == EL_SIEB2_VOLL)
1041 graphic += 3 + getGraphicAnimationPhase(4, 4, ANIM_REVERSE);
1043 else if (IS_AMOEBOID(element))
1045 graphic = (element == EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
1046 graphic += (x + 2 * y + 4) % 4;
1048 else if (element == EL_MAUER_LEBT)
1050 boolean links_massiv = FALSE, rechts_massiv = FALSE;
1052 if (!IN_LEV_FIELD(ux-1, uy) || IS_MAUER(Feld[ux-1][uy]))
1053 links_massiv = TRUE;
1054 if (!IN_LEV_FIELD(ux+1, uy) || IS_MAUER(Feld[ux+1][uy]))
1055 rechts_massiv = TRUE;
1057 if (links_massiv && rechts_massiv)
1058 graphic = GFX_MAUERWERK;
1059 else if (links_massiv)
1060 graphic = GFX_MAUER_R;
1061 else if (rechts_massiv)
1062 graphic = GFX_MAUER_L;
1066 DrawGraphicShifted(x, y, dx, dy, graphic, cut_mode, mask_mode);
1067 else if (mask_mode == USE_MASKING)
1068 DrawGraphicThruMask(x, y, graphic);
1070 DrawGraphic(x, y, graphic);
1073 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
1074 int cut_mode, int mask_mode)
1076 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1077 DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
1078 cut_mode, mask_mode);
1081 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
1084 DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1087 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
1090 DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
1093 void DrawScreenElementThruMask(int x, int y, int element)
1095 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1098 void DrawLevelElementThruMask(int x, int y, int element)
1100 DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
1103 void DrawLevelFieldThruMask(int x, int y)
1105 DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
1108 void ErdreichAnbroeckeln(int x, int y)
1110 int i, width, height, cx,cy;
1111 int ux = LEVELX(x), uy = LEVELY(y);
1112 int element, graphic;
1114 static int xy[4][2] =
1122 if (!IN_LEV_FIELD(ux, uy))
1125 element = Feld[ux][uy];
1127 if (element == EL_ERDREICH)
1129 if (!IN_SCR_FIELD(x, y))
1132 graphic = GFX_ERDENRAND;
1138 uxx = ux + xy[i][0];
1139 uyy = uy + xy[i][1];
1140 if (!IN_LEV_FIELD(uxx, uyy))
1143 element = Feld[uxx][uyy];
1145 if (element == EL_ERDREICH)
1148 if (i == 1 || i == 2)
1152 cx = (i == 2 ? TILEX - snip : 0);
1160 cy = (i == 3 ? TILEY - snip : 0);
1163 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1164 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1165 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1166 width, height, FX + x * TILEX + cx, FY + y * TILEY + cy);
1169 MarkTileDirty(x, y);
1173 graphic = GFX_ERDENRAND;
1177 int xx, yy, uxx, uyy;
1181 uxx = ux + xy[i][0];
1182 uyy = uy + xy[i][1];
1184 if (!IN_LEV_FIELD(uxx, uyy) || Feld[uxx][uyy] != EL_ERDREICH ||
1185 !IN_SCR_FIELD(xx, yy))
1188 if (i == 1 || i == 2)
1192 cx = (i == 1 ? TILEX - snip : 0);
1200 cy = (i==0 ? TILEY-snip : 0);
1203 XCopyArea(display, pix[PIX_BACK], drawto_field, gc,
1204 SX + (graphic % GFX_PER_LINE) * TILEX + cx,
1205 SY + (graphic / GFX_PER_LINE) * TILEY + cy,
1206 width, height, FX + xx * TILEX + cx, FY + yy * TILEY + cy);
1208 MarkTileDirty(xx, yy);
1213 void DrawScreenElement(int x, int y, int element)
1215 DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1216 ErdreichAnbroeckeln(x, y);
1219 void DrawLevelElement(int x, int y, int element)
1221 if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1222 DrawScreenElement(SCREENX(x), SCREENY(y), element);
1225 void DrawScreenField(int x, int y)
1227 int ux = LEVELX(x), uy = LEVELY(y);
1230 if (!IN_LEV_FIELD(ux, uy))
1232 if (ux < -1 || ux > lev_fieldx || uy < -1 || uy > lev_fieldy)
1233 element = EL_LEERRAUM;
1235 element = BorderElement;
1237 DrawScreenElement(x, y, element);
1241 element = Feld[ux][uy];
1243 if (IS_MOVING(ux, uy))
1245 int horiz_move = (MovDir[ux][uy] == MV_LEFT || MovDir[ux][uy] == MV_RIGHT);
1246 boolean cut_mode = NO_CUTTING;
1248 if (Store[ux][uy] == EL_MORAST_LEER ||
1249 Store[ux][uy] == EL_SIEB_LEER ||
1250 Store[ux][uy] == EL_SIEB2_LEER ||
1251 Store[ux][uy] == EL_AMOEBE_NASS)
1252 cut_mode = CUT_ABOVE;
1253 else if (Store[ux][uy] == EL_MORAST_VOLL ||
1254 Store[ux][uy] == EL_SIEB_VOLL ||
1255 Store[ux][uy] == EL_SIEB2_VOLL)
1256 cut_mode = CUT_BELOW;
1258 if (cut_mode == CUT_ABOVE)
1259 DrawScreenElementShifted(x, y, 0, 0, Store[ux][uy], NO_CUTTING);
1261 DrawScreenElement(x, y, EL_LEERRAUM);
1264 DrawScreenElementShifted(x, y, MovPos[ux][uy], 0, element, NO_CUTTING);
1266 DrawScreenElementShifted(x, y, 0, MovPos[ux][uy], element, cut_mode);
1268 if (Store[ux][uy] == EL_SALZSAEURE)
1269 DrawLevelElementThruMask(ux, uy + 1, EL_SALZSAEURE);
1271 else if (IS_BLOCKED(ux, uy))
1276 boolean cut_mode = NO_CUTTING;
1278 Blocked2Moving(ux, uy, &oldx, &oldy);
1281 horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1282 MovDir[oldx][oldy] == MV_RIGHT);
1284 if (Store[oldx][oldy] == EL_MORAST_LEER ||
1285 Store[oldx][oldy] == EL_SIEB_LEER ||
1286 Store[oldx][oldy] == EL_SIEB2_LEER ||
1287 Store[oldx][oldy] == EL_AMOEBE_NASS)
1288 cut_mode = CUT_ABOVE;
1290 DrawScreenElement(x, y, EL_LEERRAUM);
1291 element = Feld[oldx][oldy];
1294 DrawScreenElementShifted(sx,sy, MovPos[oldx][oldy],0,element,NO_CUTTING);
1296 DrawScreenElementShifted(sx,sy, 0,MovPos[oldx][oldy],element,cut_mode);
1298 else if (IS_DRAWABLE(element))
1299 DrawScreenElement(x, y, element);
1301 DrawScreenElement(x, y, EL_LEERRAUM);
1304 void DrawLevelField(int x, int y)
1306 if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1307 DrawScreenField(SCREENX(x), SCREENY(y));
1308 else if (IS_MOVING(x, y))
1312 Moving2Blocked(x, y, &newx, &newy);
1313 if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1314 DrawScreenField(SCREENX(newx), SCREENY(newy));
1316 else if (IS_BLOCKED(x, y))
1320 Blocked2Moving(x, y, &oldx, &oldy);
1321 if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1322 DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1326 void DrawMiniElement(int x, int y, int element)
1332 DrawMiniGraphic(x, y, -1);
1336 graphic = el2gfx(element);
1337 DrawMiniGraphic(x, y, graphic);
1340 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1342 int x = sx + scroll_x, y = sy + scroll_y;
1344 if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1345 DrawMiniElement(sx, sy, EL_LEERRAUM);
1346 else if (x == -1 || x == lev_fieldx || y == -1 || y == lev_fieldy)
1347 DrawMiniElement(sx, sy, EL_BETON);
1349 DrawMiniElement(sx, sy, Feld[x][y]);
1352 void DrawMicroElement(int xpos, int ypos, int element)
1356 if (element == EL_LEERRAUM)
1359 graphic = el2gfx(element);
1361 if (graphic >= GFX_START_ROCKSMORE && graphic <= GFX_END_ROCKSMORE)
1363 graphic -= GFX_START_ROCKSMORE;
1364 XCopyArea(display, pix[PIX_MORE], drawto, gc,
1365 MICRO_MORE_STARTX + (graphic % MICRO_MORE_PER_LINE) *MICRO_TILEX,
1366 MICRO_MORE_STARTY + (graphic / MICRO_MORE_PER_LINE) *MICRO_TILEY,
1367 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1370 XCopyArea(display, pix[PIX_BACK], drawto, gc,
1371 MICRO_GFX_STARTX + (graphic % MICRO_GFX_PER_LINE) * MICRO_TILEX,
1372 MICRO_GFX_STARTY + (graphic / MICRO_GFX_PER_LINE) * MICRO_TILEY,
1373 MICRO_TILEX, MICRO_TILEY, xpos, ypos);
1382 for(x=BX1; x<=BX2; x++)
1383 for(y=BY1; y<=BY2; y++)
1384 DrawScreenField(x, y);
1386 if (setup.soft_scrolling)
1387 XCopyArea(display, fieldbuffer, backbuffer, gc,
1388 FX, FY, SXSIZE, SYSIZE, SX, SY);
1390 redraw_mask |= (REDRAW_FIELD | REDRAW_FROM_BACKBUFFER);
1393 void DrawMiniLevel(int scroll_x, int scroll_y)
1397 for(x=0; x<ED_FIELDX; x++)
1398 for(y=0; y<ED_FIELDY; y++)
1399 DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1401 redraw_mask |= REDRAW_FIELD;
1404 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1408 /* determine border element for this level */
1411 XFillRectangle(display, drawto, gc,
1412 xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1414 if (lev_fieldx < STD_LEV_FIELDX)
1415 xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1416 if (lev_fieldy < STD_LEV_FIELDY)
1417 ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1419 xpos += MICRO_TILEX;
1420 ypos += MICRO_TILEY;
1422 for(x=-1; x<=STD_LEV_FIELDX; x++)
1424 for(y=-1; y<=STD_LEV_FIELDY; y++)
1426 int lx = from_x + x, ly = from_y + y;
1428 if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1429 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1431 else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1)
1432 DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1437 redraw_mask |= REDRAW_MICROLEVEL;
1440 static void DrawMicroLevelLabelExt(int mode)
1442 char label_text[100];
1444 XFillRectangle(display, drawto,gc,
1445 SX, MICROLABEL_YPOS, SXSIZE, FONT4_YSIZE);
1447 strcpy(label_text, (mode == 1 ? level.name :
1448 mode == 2 ? "created by" :
1449 mode == 3 ? level.author : ""));
1451 if (strlen(label_text) > 0)
1453 int size, lxpos, lypos;
1455 label_text[SXSIZE / FONT4_XSIZE] = '\0';
1457 size = strlen(label_text);
1458 lxpos = SX + (SXSIZE - size * FONT4_XSIZE) / 2;
1459 lypos = MICROLABEL_YPOS;
1461 DrawText(lxpos, lypos, label_text, FS_SMALL, FC_SPECIAL2);
1464 redraw_mask |= REDRAW_MICROLEVEL;
1467 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1469 static unsigned long scroll_delay = 0;
1470 static unsigned long label_delay = 0;
1471 static int from_x, from_y, scroll_direction;
1472 static int label_state, label_counter;
1476 from_x = from_y = 0;
1477 scroll_direction = MV_RIGHT;
1481 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1482 DrawMicroLevelLabelExt(label_state);
1484 /* initialize delay counters */
1485 DelayReached(&scroll_delay, 0);
1486 DelayReached(&label_delay, 0);
1491 /* scroll micro level, if needed */
1492 if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1493 DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1495 switch (scroll_direction)
1501 scroll_direction = MV_UP;
1505 if (from_x < lev_fieldx - STD_LEV_FIELDX)
1508 scroll_direction = MV_DOWN;
1515 scroll_direction = MV_RIGHT;
1519 if (from_y < lev_fieldy - STD_LEV_FIELDY)
1522 scroll_direction = MV_LEFT;
1529 DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1532 /* redraw micro level label, if needed */
1533 if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1534 strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1535 strcmp(level.author, leveldir[leveldir_nr].name) != 0 &&
1536 DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1538 label_counter = (label_counter + 1) % 23;
1539 label_state = (label_counter >= 0 && label_counter <= 7 ? 1 :
1540 label_counter >= 9 && label_counter <= 12 ? 2 :
1541 label_counter >= 14 && label_counter <= 21 ? 3 : 0);
1542 DrawMicroLevelLabelExt(label_state);
1546 int REQ_in_range(int x, int y)
1548 if (y > DY+249 && y < DY+278)
1550 if (x > DX+1 && x < DX+48)
1552 else if (x > DX+51 && x < DX+98)
1558 boolean Request(char *text, unsigned int req_state)
1560 int mx, my, ty, result = -1;
1561 unsigned int old_door_state;
1564 /* pause network game while waiting for request to answer */
1565 if (options.network &&
1566 game_status == PLAYING &&
1567 req_state & REQUEST_WAIT_FOR)
1568 SendToServer_PausePlaying();
1571 old_door_state = GetDoorState();
1573 CloseDoor(DOOR_CLOSE_1);
1575 /* Alten Türinhalt sichern */
1576 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1577 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
1578 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
1580 /* Fragetext schreiben */
1581 XFillRectangle(display, pix[PIX_DB_DOOR], gc,
1582 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE);
1584 for(ty=0; ty<13; ty++)
1592 for(tl=0,tx=0; tx<7; tl++,tx++)
1595 if (!tc || tc == 32)
1606 DrawTextExt(pix[PIX_DB_DOOR], gc,
1607 DOOR_GFX_PAGEX1 + 51 - (tl * 14)/2, SY + ty * 16,
1608 txt, FS_SMALL, FC_YELLOW);
1609 text += tl + (tc == 32 ? 1 : 0);
1612 if (req_state & REQ_ASK)
1614 DrawYesNoButton(BUTTON_OK, DB_INIT);
1615 DrawYesNoButton(BUTTON_NO, DB_INIT);
1617 else if (req_state & REQ_CONFIRM)
1619 DrawConfirmButton(BUTTON_CONFIRM, DB_INIT);
1621 else if (req_state & REQ_PLAYER)
1623 DrawPlayerButton(BUTTON_PLAYER_1, DB_INIT);
1624 DrawPlayerButton(BUTTON_PLAYER_2, DB_INIT);
1625 DrawPlayerButton(BUTTON_PLAYER_3, DB_INIT);
1626 DrawPlayerButton(BUTTON_PLAYER_4, DB_INIT);
1629 OpenDoor(DOOR_OPEN_1);
1632 if (!(req_state & REQUEST_WAIT_FOR))
1635 if (game_status != MAINMENU)
1638 button_status = MB_RELEASED;
1642 if (XPending(display))
1646 XNextEvent(display, &event);
1656 if (event.type == MotionNotify)
1658 motion_status = TRUE;
1659 mx = ((XMotionEvent *) &event)->x;
1660 my = ((XMotionEvent *) &event)->y;
1664 motion_status = FALSE;
1665 mx = ((XButtonEvent *) &event)->x;
1666 my = ((XButtonEvent *) &event)->y;
1667 if (event.type==ButtonPress)
1668 button_status = ((XButtonEvent *) &event)->button;
1670 button_status = MB_RELEASED;
1673 if (req_state & REQ_ASK)
1674 choice = CheckYesNoButtons(mx,my,button_status);
1675 else if (req_state & REQ_CONFIRM)
1676 choice = CheckConfirmButton(mx,my,button_status);
1678 choice = CheckPlayerButtons(mx,my,button_status);
1688 case BUTTON_CONFIRM:
1689 result = TRUE | FALSE;
1692 case BUTTON_PLAYER_1:
1695 case BUTTON_PLAYER_2:
1698 case BUTTON_PLAYER_3:
1701 case BUTTON_PLAYER_4:
1712 switch(XLookupKeysym((XKeyEvent *)&event,
1713 ((XKeyEvent *)&event)->state))
1726 if (req_state & REQ_PLAYER)
1731 key_joystick_mapping = 0;
1735 HandleOtherEvents(&event);
1739 else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
1741 int joy = AnyJoystick();
1743 if (joy & JOY_BUTTON_1)
1745 else if (joy & JOY_BUTTON_2)
1751 /* don't eat all CPU time */
1755 if (game_status != MAINMENU)
1758 if (!(req_state & REQ_STAY_OPEN))
1760 CloseDoor(DOOR_CLOSE_1);
1762 if (!(req_state & REQ_STAY_CLOSED) && (old_door_state & DOOR_OPEN_1))
1764 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1765 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1766 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1767 OpenDoor(DOOR_OPEN_1);
1772 /* continue network game after request */
1773 if (options.network &&
1774 game_status == PLAYING &&
1775 req_state & REQUEST_WAIT_FOR)
1776 SendToServer_ContinuePlaying();
1782 unsigned int OpenDoor(unsigned int door_state)
1784 unsigned int new_door_state;
1786 if (door_state & DOOR_COPY_BACK)
1788 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
1789 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE + VYSIZE,
1790 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1791 door_state &= ~DOOR_COPY_BACK;
1794 new_door_state = MoveDoor(door_state);
1796 return(new_door_state);
1799 unsigned int CloseDoor(unsigned int door_state)
1801 unsigned int new_door_state;
1803 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1804 DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
1805 XCopyArea(display, backbuffer, pix[PIX_DB_DOOR], gc,
1806 VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
1808 new_door_state = MoveDoor(door_state);
1810 return(new_door_state);
1813 unsigned int GetDoorState()
1815 return(MoveDoor(DOOR_GET_STATE));
1818 unsigned int MoveDoor(unsigned int door_state)
1820 static int door1 = DOOR_OPEN_1;
1821 static int door2 = DOOR_CLOSE_2;
1822 static unsigned long door_delay = 0;
1823 int x, start, stepsize = 2;
1824 unsigned long door_delay_value = stepsize * 5;
1826 if (door_state == DOOR_GET_STATE)
1827 return(door1 | door2);
1829 if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1830 door_state &= ~DOOR_OPEN_1;
1831 else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1832 door_state &= ~DOOR_CLOSE_1;
1833 if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1834 door_state &= ~DOOR_OPEN_2;
1835 else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1836 door_state &= ~DOOR_CLOSE_2;
1838 if (setup.quick_doors)
1841 door_delay_value = 0;
1842 StopSound(SND_OEFFNEN);
1845 if (door_state & DOOR_ACTION)
1847 if (!(door_state & DOOR_NO_DELAY))
1848 PlaySoundStereo(SND_OEFFNEN, PSND_MAX_RIGHT);
1850 start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1852 for(x=start; x<=DXSIZE; x+=stepsize)
1854 WaitUntilDelayReached(&door_delay, door_delay_value);
1856 if (door_state & DOOR_ACTION_1)
1858 int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1859 int j = (DXSIZE - i) / 3;
1861 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1862 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i/2,
1863 DXSIZE,DYSIZE - i/2, DX, DY);
1865 XFillRectangle(display, drawto, gc, DX, DY + DYSIZE - i/2, DXSIZE,i/2);
1867 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1868 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1869 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1870 DXSIZE, DOOR_GFX_PAGEY1, i, 77, DX + DXSIZE - i, DY + j);
1871 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1872 DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63, DX + DXSIZE - i,
1874 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1875 DX - DXSIZE + i, DY - (DOOR_GFX_PAGEY1 + j));
1876 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1877 DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j, DX, DY);
1878 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1879 DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63, DX, DY + 140 - j);
1881 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1882 DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
1884 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1885 DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
1887 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1888 DX - i, (DY + j) - DOOR_GFX_PAGEY1);
1889 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1890 DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
1891 DX + DXSIZE - i, DY + 77 + j);
1892 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1893 DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
1894 DX + DXSIZE - i, DY + 203 + j);
1896 redraw_mask |= REDRAW_DOOR_1;
1899 if (door_state & DOOR_ACTION_2)
1901 int i = (door_state & DOOR_OPEN_2 ? VXSIZE - x : x);
1902 int j = (VXSIZE - i) / 3;
1904 XCopyArea(display, pix[PIX_DB_DOOR], drawto, gc,
1905 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i/2,
1906 VXSIZE, VYSIZE - i/2, VX, VY);
1908 XFillRectangle(display, drawto, gc, VX, VY + VYSIZE-i/2, VXSIZE, i/2);
1910 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1911 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1912 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1913 VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2, VX + VXSIZE-i, VY+j);
1914 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1915 VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
1916 XCopyArea(display, pix[PIX_DOOR], drawto,clip_gc[PIX_DOOR],
1917 VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j, VX, VY);
1919 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1920 VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2,
1921 VX, VY + VYSIZE / 2 - j);
1922 XSetClipOrigin(display, clip_gc[PIX_DOOR],
1923 VX - i, (VY + j) - DOOR_GFX_PAGEY2);
1924 XCopyArea(display, pix[PIX_DOOR], drawto, clip_gc[PIX_DOOR],
1925 VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2, i, VYSIZE / 2 - j,
1926 VX + VXSIZE - i, VY + VYSIZE / 2 + j);
1928 redraw_mask |= REDRAW_DOOR_2;
1933 if (game_status == MAINMENU)
1938 if (setup.quick_doors)
1939 StopSound(SND_OEFFNEN);
1941 if (door_state & DOOR_ACTION_1)
1942 door1 = door_state & DOOR_ACTION_1;
1943 if (door_state & DOOR_ACTION_2)
1944 door2 = door_state & DOOR_ACTION_2;
1946 return(door1 | door2);
1949 int ReadPixel(Drawable d, int x, int y)
1951 XImage *pixel_image;
1952 unsigned long pixel_value;
1954 pixel_image = XGetImage(display, d, x, y, 1, 1, AllPlanes, ZPixmap);
1955 pixel_value = XGetPixel(pixel_image, 0, 0);
1957 XDestroyImage(pixel_image);
1962 int el2gfx(int element)
1966 case EL_LEERRAUM: return -1;
1967 case EL_ERDREICH: return GFX_ERDREICH;
1968 case EL_MAUERWERK: return GFX_MAUERWERK;
1969 case EL_FELSBODEN: return GFX_FELSBODEN;
1970 case EL_FELSBROCKEN: return GFX_FELSBROCKEN;
1971 case EL_SCHLUESSEL: return GFX_SCHLUESSEL;
1972 case EL_EDELSTEIN: return GFX_EDELSTEIN;
1973 case EL_AUSGANG_ZU: return GFX_AUSGANG_ZU;
1974 case EL_AUSGANG_ACT: return GFX_AUSGANG_ACT;
1975 case EL_AUSGANG_AUF: return GFX_AUSGANG_AUF;
1976 case EL_SPIELFIGUR: return GFX_SPIELFIGUR;
1977 case EL_SPIELER1: return GFX_SPIELER1;
1978 case EL_SPIELER2: return GFX_SPIELER2;
1979 case EL_SPIELER3: return GFX_SPIELER3;
1980 case EL_SPIELER4: return GFX_SPIELER4;
1981 case EL_KAEFER: return GFX_KAEFER;
1982 case EL_KAEFER_R: return GFX_KAEFER_R;
1983 case EL_KAEFER_O: return GFX_KAEFER_O;
1984 case EL_KAEFER_L: return GFX_KAEFER_L;
1985 case EL_KAEFER_U: return GFX_KAEFER_U;
1986 case EL_FLIEGER: return GFX_FLIEGER;
1987 case EL_FLIEGER_R: return GFX_FLIEGER_R;
1988 case EL_FLIEGER_O: return GFX_FLIEGER_O;
1989 case EL_FLIEGER_L: return GFX_FLIEGER_L;
1990 case EL_FLIEGER_U: return GFX_FLIEGER_U;
1991 case EL_BUTTERFLY: return GFX_BUTTERFLY;
1992 case EL_BUTTERFLY_R: return GFX_BUTTERFLY_R;
1993 case EL_BUTTERFLY_O: return GFX_BUTTERFLY_O;
1994 case EL_BUTTERFLY_L: return GFX_BUTTERFLY_L;
1995 case EL_BUTTERFLY_U: return GFX_BUTTERFLY_U;
1996 case EL_FIREFLY: return GFX_FIREFLY;
1997 case EL_FIREFLY_R: return GFX_FIREFLY_R;
1998 case EL_FIREFLY_O: return GFX_FIREFLY_O;
1999 case EL_FIREFLY_L: return GFX_FIREFLY_L;
2000 case EL_FIREFLY_U: return GFX_FIREFLY_U;
2001 case EL_MAMPFER: return GFX_MAMPFER;
2002 case EL_ROBOT: return GFX_ROBOT;
2003 case EL_BETON: return GFX_BETON;
2004 case EL_DIAMANT: return GFX_DIAMANT;
2005 case EL_MORAST_LEER: return GFX_MORAST_LEER;
2006 case EL_MORAST_VOLL: return GFX_MORAST_VOLL;
2007 case EL_TROPFEN: return GFX_TROPFEN;
2008 case EL_BOMBE: return GFX_BOMBE;
2009 case EL_SIEB_INAKTIV: return GFX_SIEB_INAKTIV;
2010 case EL_SIEB_LEER: return GFX_SIEB_LEER;
2011 case EL_SIEB_VOLL: return GFX_SIEB_VOLL;
2012 case EL_SIEB_TOT: return GFX_SIEB_TOT;
2013 case EL_SALZSAEURE: return GFX_SALZSAEURE;
2014 case EL_AMOEBE_TOT: return GFX_AMOEBE_TOT;
2015 case EL_AMOEBE_NASS: return GFX_AMOEBE_NASS;
2016 case EL_AMOEBE_NORM: return GFX_AMOEBE_NORM;
2017 case EL_AMOEBE_VOLL: return GFX_AMOEBE_VOLL;
2018 case EL_AMOEBE_BD: return GFX_AMOEBE_BD;
2019 case EL_AMOEBA2DIAM: return GFX_AMOEBA2DIAM;
2020 case EL_KOKOSNUSS: return GFX_KOKOSNUSS;
2021 case EL_LIFE: return GFX_LIFE;
2022 case EL_LIFE_ASYNC: return GFX_LIFE_ASYNC;
2023 case EL_DYNAMIT: return GFX_DYNAMIT;
2024 case EL_BADEWANNE: return GFX_BADEWANNE;
2025 case EL_BADEWANNE1: return GFX_BADEWANNE1;
2026 case EL_BADEWANNE2: return GFX_BADEWANNE2;
2027 case EL_BADEWANNE3: return GFX_BADEWANNE3;
2028 case EL_BADEWANNE4: return GFX_BADEWANNE4;
2029 case EL_BADEWANNE5: return GFX_BADEWANNE5;
2030 case EL_ABLENK_AUS: return GFX_ABLENK_AUS;
2031 case EL_ABLENK_EIN: return GFX_ABLENK_EIN;
2032 case EL_SCHLUESSEL1: return GFX_SCHLUESSEL1;
2033 case EL_SCHLUESSEL2: return GFX_SCHLUESSEL2;
2034 case EL_SCHLUESSEL3: return GFX_SCHLUESSEL3;
2035 case EL_SCHLUESSEL4: return GFX_SCHLUESSEL4;
2036 case EL_PFORTE1: return GFX_PFORTE1;
2037 case EL_PFORTE2: return GFX_PFORTE2;
2038 case EL_PFORTE3: return GFX_PFORTE3;
2039 case EL_PFORTE4: return GFX_PFORTE4;
2040 case EL_PFORTE1X: return GFX_PFORTE1X;
2041 case EL_PFORTE2X: return GFX_PFORTE2X;
2042 case EL_PFORTE3X: return GFX_PFORTE3X;
2043 case EL_PFORTE4X: return GFX_PFORTE4X;
2044 case EL_DYNAMIT_AUS: return GFX_DYNAMIT_AUS;
2045 case EL_PACMAN: return GFX_PACMAN;
2046 case EL_PACMAN_R: return GFX_PACMAN_R;
2047 case EL_PACMAN_O: return GFX_PACMAN_O;
2048 case EL_PACMAN_L: return GFX_PACMAN_L;
2049 case EL_PACMAN_U: return GFX_PACMAN_U;
2050 case EL_UNSICHTBAR: return GFX_UNSICHTBAR;
2051 case EL_ERZ_EDEL: return GFX_ERZ_EDEL;
2052 case EL_ERZ_DIAM: return GFX_ERZ_DIAM;
2053 case EL_BIRNE_AUS: return GFX_BIRNE_AUS;
2054 case EL_BIRNE_EIN: return GFX_BIRNE_EIN;
2055 case EL_ZEIT_VOLL: return GFX_ZEIT_VOLL;
2056 case EL_ZEIT_LEER: return GFX_ZEIT_LEER;
2057 case EL_MAUER_LEBT: return GFX_MAUER_LEBT;
2058 case EL_MAUER_X: return GFX_MAUER_X;
2059 case EL_MAUER_Y: return GFX_MAUER_Y;
2060 case EL_MAUER_XY: return GFX_MAUER_XY;
2061 case EL_EDELSTEIN_BD: return GFX_EDELSTEIN_BD;
2062 case EL_EDELSTEIN_GELB: return GFX_EDELSTEIN_GELB;
2063 case EL_EDELSTEIN_ROT: return GFX_EDELSTEIN_ROT;
2064 case EL_EDELSTEIN_LILA: return GFX_EDELSTEIN_LILA;
2065 case EL_ERZ_EDEL_BD: return GFX_ERZ_EDEL_BD;
2066 case EL_ERZ_EDEL_GELB: return GFX_ERZ_EDEL_GELB;
2067 case EL_ERZ_EDEL_ROT: return GFX_ERZ_EDEL_ROT;
2068 case EL_ERZ_EDEL_LILA: return GFX_ERZ_EDEL_LILA;
2069 case EL_MAMPFER2: return GFX_MAMPFER2;
2070 case EL_SIEB2_INAKTIV: return GFX_SIEB2_INAKTIV;
2071 case EL_SIEB2_LEER: return GFX_SIEB2_LEER;
2072 case EL_SIEB2_VOLL: return GFX_SIEB2_VOLL;
2073 case EL_SIEB2_TOT: return GFX_SIEB2_TOT;
2074 case EL_DYNABOMB: return GFX_DYNABOMB;
2075 case EL_DYNABOMB_NR: return GFX_DYNABOMB_NR;
2076 case EL_DYNABOMB_SZ: return GFX_DYNABOMB_SZ;
2077 case EL_DYNABOMB_XL: return GFX_DYNABOMB_XL;
2078 case EL_SOKOBAN_OBJEKT: return GFX_SOKOBAN_OBJEKT;
2079 case EL_SOKOBAN_FELD_LEER: return GFX_SOKOBAN_FELD_LEER;
2080 case EL_SOKOBAN_FELD_VOLL: return GFX_SOKOBAN_FELD_VOLL;
2081 case EL_MAULWURF: return GFX_MAULWURF;
2082 case EL_PINGUIN: return GFX_PINGUIN;
2083 case EL_SCHWEIN: return GFX_SCHWEIN;
2084 case EL_DRACHE: return GFX_DRACHE;
2085 case EL_SONDE: return GFX_SONDE;
2086 case EL_PFEIL_L: return GFX_PFEIL_L;
2087 case EL_PFEIL_R: return GFX_PFEIL_R;
2088 case EL_PFEIL_O: return GFX_PFEIL_O;
2089 case EL_PFEIL_U: return GFX_PFEIL_U;
2090 case EL_SPEED_PILL: return GFX_SPEED_PILL;
2091 case EL_SP_TERMINAL_ACTIVE: return GFX_SP_TERMINAL;
2092 case EL_SP_BUG_ACTIVE: return GFX_SP_BUG_ACTIVE;
2093 case EL_INVISIBLE_STEEL: return GFX_INVISIBLE_STEEL;
2097 if (IS_CHAR(element))
2098 return GFX_CHAR_START + (element - EL_CHAR_START);
2099 else if (element >= EL_SP_START && element <= EL_SP_END)
2101 int nr_element = element - EL_SP_START;
2102 int gfx_per_line = 8;
2104 (nr_element / gfx_per_line) * MORE_PER_LINE +
2105 (nr_element % gfx_per_line);
2107 return GFX_START_ROCKSMORE + nr_graphic;