+void DrawLevelFieldCrumbledSand(int x, int y)
+{
+#if 1
+ int graphic;
+
+ if (!IN_LEV_FIELD(x, y))
+ return;
+
+ graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
+
+ DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
+#else
+ DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
+#endif
+}
+
+void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
+ int step_frame)
+{
+#if 1
+ int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
+ int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
+#else
+ int graphic1 = el_act_dir2img(EL_SAND, ACTION_DIGGING, direction);
+ int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
+#endif
+ int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
+ int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
+ int sx = SCREENX(x), sy = SCREENY(y);
+
+ DrawGraphic(sx, sy, graphic1, frame1);
+ DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
+}
+
+void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
+{
+ int sx = SCREENX(x), sy = SCREENY(y);
+ static int xy[4][2] =
+ {
+ { 0, -1 },
+ { -1, 0 },
+ { +1, 0 },
+ { 0, +1 }
+ };
+ int i;
+
+ for(i=0; i<4; i++)
+ {
+ int xx = x + xy[i][0];
+ int yy = y + xy[i][1];
+ int sxx = sx + xy[i][0];
+ int syy = sy + xy[i][1];
+
+ if (!IN_LEV_FIELD(xx, yy) ||
+ !IN_SCR_FIELD(sxx, syy) ||
+ !GFX_CRUMBLED(Feld[xx][yy]) ||
+ IS_MOVING(xx, yy))
+ continue;
+
+ DrawLevelField(xx, yy);
+ }
+}
+
+static int getBorderElement(int x, int y)
+{
+ int border[7][2] =
+ {
+ { EL_STEELWALL_TOPLEFT, EL_INVISIBLE_STEELWALL_TOPLEFT },
+ { EL_STEELWALL_TOPRIGHT, EL_INVISIBLE_STEELWALL_TOPRIGHT },
+ { EL_STEELWALL_BOTTOMLEFT, EL_INVISIBLE_STEELWALL_BOTTOMLEFT },
+ { EL_STEELWALL_BOTTOMRIGHT, EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
+ { EL_STEELWALL_VERTICAL, EL_INVISIBLE_STEELWALL_VERTICAL },
+ { EL_STEELWALL_HORIZONTAL, EL_INVISIBLE_STEELWALL_HORIZONTAL },
+ { EL_STEELWALL, EL_INVISIBLE_STEELWALL }
+ };
+ int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
+ int steel_position = (x == -1 && y == -1 ? 0 :
+ x == lev_fieldx && y == -1 ? 1 :
+ x == -1 && y == lev_fieldy ? 2 :
+ x == lev_fieldx && y == lev_fieldy ? 3 :
+ x == -1 || x == lev_fieldx ? 4 :
+ y == -1 || y == lev_fieldy ? 5 : 6);
+
+ return border[steel_position][steel_type];
+}
+
+void DrawScreenElement(int x, int y, int element)
+{
+ DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
+ DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
+}
+
+void DrawLevelElement(int x, int y, int element)
+{
+ if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
+ DrawScreenElement(SCREENX(x), SCREENY(y), element);
+}
+
+void DrawScreenField(int x, int y)
+{
+ int lx = LEVELX(x), ly = LEVELY(y);
+ int element, content;
+
+ if (!IN_LEV_FIELD(lx, ly))
+ {
+ if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
+ element = EL_EMPTY;
+ else
+ element = getBorderElement(lx, ly);
+
+ DrawScreenElement(x, y, element);
+ return;
+ }
+
+ element = Feld[lx][ly];
+ content = Store[lx][ly];
+
+ if (IS_MOVING(lx, ly))
+ {
+ int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
+ boolean cut_mode = NO_CUTTING;
+
+ if (element == EL_QUICKSAND_EMPTYING ||
+ element == EL_MAGIC_WALL_EMPTYING ||
+ element == EL_BD_MAGIC_WALL_EMPTYING ||
+ element == EL_AMOEBA_DROPPING)
+ cut_mode = CUT_ABOVE;
+ else if (element == EL_QUICKSAND_FILLING ||
+ element == EL_MAGIC_WALL_FILLING ||
+ element == EL_BD_MAGIC_WALL_FILLING)
+ cut_mode = CUT_BELOW;
+
+ if (cut_mode == CUT_ABOVE)
+ DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
+ else
+ DrawScreenElement(x, y, EL_EMPTY);
+
+ if (horiz_move)
+ DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
+ else if (cut_mode == NO_CUTTING)
+ DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
+ else
+ DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
+
+ if (content == EL_ACID)
+ DrawLevelElementThruMask(lx, ly + 1, EL_ACID);
+ }
+ else if (IS_BLOCKED(lx, ly))
+ {
+ int oldx, oldy;
+ int sx, sy;
+ int horiz_move;
+ boolean cut_mode = NO_CUTTING;
+ int element_old, content_old;
+
+ Blocked2Moving(lx, ly, &oldx, &oldy);
+ sx = SCREENX(oldx);
+ sy = SCREENY(oldy);
+ horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
+ MovDir[oldx][oldy] == MV_RIGHT);
+
+ element_old = Feld[oldx][oldy];
+ content_old = Store[oldx][oldy];
+
+ if (element_old == EL_QUICKSAND_EMPTYING ||
+ element_old == EL_MAGIC_WALL_EMPTYING ||
+ element_old == EL_BD_MAGIC_WALL_EMPTYING ||
+ element_old == EL_AMOEBA_DROPPING)
+ cut_mode = CUT_ABOVE;
+
+ DrawScreenElement(x, y, EL_EMPTY);
+
+ if (horiz_move)
+ DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
+ NO_CUTTING);
+ else if (cut_mode == NO_CUTTING)
+ DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
+ cut_mode);
+ else
+ DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
+ cut_mode);
+ }
+ else if (IS_DRAWABLE(element))
+ DrawScreenElement(x, y, element);
+ else
+ DrawScreenElement(x, y, EL_EMPTY);
+}
+
+void DrawLevelField(int x, int y)
+{
+ if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
+ DrawScreenField(SCREENX(x), SCREENY(y));
+ else if (IS_MOVING(x, y))
+ {
+ int newx,newy;
+
+ Moving2Blocked(x, y, &newx, &newy);
+ if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
+ DrawScreenField(SCREENX(newx), SCREENY(newy));
+ }
+ else if (IS_BLOCKED(x, y))
+ {
+ int oldx, oldy;
+
+ Blocked2Moving(x, y, &oldx, &oldy);
+ if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
+ DrawScreenField(SCREENX(oldx), SCREENY(oldy));
+ }
+}
+
+void DrawMiniElement(int x, int y, int element)
+{
+ int graphic;
+
+ graphic = el2edimg(element);
+ DrawMiniGraphic(x, y, graphic);
+}
+
+void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
+{
+ int x = sx + scroll_x, y = sy + scroll_y;
+
+ if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
+ DrawMiniElement(sx, sy, EL_EMPTY);
+ else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
+ DrawMiniElement(sx, sy, Feld[x][y]);
+ else
+ DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
+}
+
+void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
+ int x, int y, int xsize, int ysize, int font_nr)
+{
+ int font_width = getFontWidth(font_nr);
+ int font_height = getFontHeight(font_nr);
+ int graphic = IMG_GAME_ENVELOPE_1_BACKGROUND + envelope_nr;
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+ int dst_x = SX + startx + x * font_width;
+ int dst_y = SY + starty + y * font_height;
+ int width = graphic_info[graphic].width;
+ int height = graphic_info[graphic].height;
+ int inner_width = MAX(width - 2 * font_width, font_width);
+ int inner_height = MAX(height - 2 * font_height, font_height);
+ int inner_sx = (width >= 3 * font_width ? font_width : 0);
+ int inner_sy = (height >= 3 * font_height ? font_height : 0);
+ boolean draw_masked = graphic_info[graphic].draw_masked;
+
+ getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
+
+ if (src_bitmap == NULL || width < font_width || height < font_height)
+ {
+ ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
+ return;
+ }
+
+ src_x += (x == 0 ? 0 : x == xsize - 1 ? width - font_width :
+ inner_sx + (x - 1) * font_width % inner_width);
+ src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
+ inner_sy + (y - 1) * font_height % inner_height);
+
+ if (draw_masked)
+ {
+ SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
+ dst_x - src_x, dst_y - src_y);
+ BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
+ dst_x, dst_y);
+ }
+ else
+ BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
+ dst_x, dst_y);
+}
+
+#if 1
+
+void AnimateEnvelope(int envelope_nr)
+{
+}
+
+void ShowEnvelope(int envelope_nr)
+{
+ int element = EL_ENVELOPE_1 + envelope_nr;
+ int graphic = IMG_GAME_ENVELOPE_1_BACKGROUND + envelope_nr;
+ int sound_opening = element_info[element].sound[ACTION_OPENING];
+ int sound_closing = element_info[element].sound[ACTION_CLOSING];
+ boolean draw_masked = graphic_info[graphic].draw_masked;
+ int anim_mode = graphic_info[graphic].anim_mode;
+ int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
+ int font_nr = FONT_TEXT_1 + envelope_nr;
+ int font_width = getFontWidth(font_nr);
+ int font_height = getFontHeight(font_nr);
+ boolean ffwd_delay = (tape.playing && tape.fast_forward);
+ unsigned long anim_delay = 0;
+ int anim_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
+ int wait_delay_value = (ffwd_delay ? 500 : 1000);
+ int start_pos_vertically = 0;
+ int i, x, y;
+
+ game.envelope_active = TRUE;
+
+ if (anim_mode != ANIM_NONE)
+ PlaySoundStereo(sound_opening, SOUND_MIDDLE);
+
+ if (anim_mode == ANIM_DEFAULT)
+ {
+ /* open envelope window horizontally */
+ for (i = 0; i <= level.envelope_xsize[envelope_nr]; i++)
+ {
+ int xsize = i + 2;
+ int ysize = 2;
+ int startx = (SXSIZE - xsize * font_width) / 2;
+ int starty = (SYSIZE - ysize * font_height) / 2;
+
+ SetDrawtoField(DRAW_BUFFERED);
+
+ BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
+
+ SetDrawtoField(DRAW_BACKBUFFER);
+
+ for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
+ DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
+ font_nr);
+
+ redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
+ BackToFront();
+
+ WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
+ }
+ }
+
+ if (anim_mode == ANIM_NONE)
+ start_pos_vertically = level.envelope_ysize[envelope_nr];
+
+ /* open envelope window vertically */
+ for (i = start_pos_vertically; i <= level.envelope_ysize[envelope_nr]; i++)
+ {
+ int xsize = level.envelope_xsize[envelope_nr] + 2;
+ int ysize = i + 2;
+ int startx = (SXSIZE - xsize * font_width) / 2;
+ int starty = (SYSIZE - ysize * font_height) / 2;
+
+ SetDrawtoField(DRAW_BUFFERED);
+
+ BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
+
+ SetDrawtoField(DRAW_BACKBUFFER);
+
+ for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
+ DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
+ font_nr);
+
+ DrawTextToTextArea(SX + startx + font_width, SY + starty + font_height,
+ level.envelope_text[envelope_nr], font_nr,
+ level.envelope_xsize[envelope_nr], i, mask_mode);
+
+ redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
+ BackToFront();
+
+ WaitUntilDelayReached(&anim_delay, anim_delay_value);
+ }
+
+ if (tape.playing)
+ Delay(wait_delay_value);
+ else
+ WaitForEventToContinue();
+
+ if (anim_mode != ANIM_NONE)
+ PlaySoundStereo(sound_closing, SOUND_MIDDLE);
+
+ if (anim_mode != ANIM_NONE)
+ {
+ /* close envelope window vertically */
+ for (i = level.envelope_ysize[envelope_nr]; i >= 0; i--)
+ {
+ int xsize = level.envelope_xsize[envelope_nr] + 2;
+ int ysize = i + 2;
+ int startx = (SXSIZE - xsize * font_width) / 2;
+ int starty = (SYSIZE - ysize * font_height) / 2;
+
+ SetDrawtoField(DRAW_BUFFERED);
+
+ BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
+
+ SetDrawtoField(DRAW_BACKBUFFER);
+
+ for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
+ DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
+ font_nr);
+
+ DrawTextToTextArea(SX + startx + font_width, SY + starty + font_height,
+ level.envelope_text[envelope_nr], font_nr,
+ level.envelope_xsize[envelope_nr], i, mask_mode);
+
+ redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
+ BackToFront();
+
+ WaitUntilDelayReached(&anim_delay, anim_delay_value);
+ }
+ }
+
+ if (anim_mode == ANIM_DEFAULT)
+ {
+ /* close envelope window horizontally */
+ for (i = level.envelope_xsize[envelope_nr]; i >= 0; i--)
+ {
+ int xsize = i + 2;
+ int ysize = 2;
+ int startx = (SXSIZE - xsize * font_width) / 2;
+ int starty = (SYSIZE - ysize * font_height) / 2;
+
+ SetDrawtoField(DRAW_BUFFERED);
+
+ BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
+
+ SetDrawtoField(DRAW_BACKBUFFER);
+
+ for (y=0; y < ysize; y++) for (x=0; x < xsize; x++)
+ DrawEnvelopeBackground(envelope_nr, startx, starty, x, y, xsize, ysize,
+ font_nr);
+
+ redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
+ BackToFront();
+
+ WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
+ }
+ }
+
+ game.envelope_active = FALSE;