#define HEALTH_INC_DELAY 9
#define HEALTH_DELAY(x) ((x) ? HEALTH_DEC_DELAY : HEALTH_INC_DELAY)
+#define BEGIN_NO_HEADLESS \
+ { \
+ boolean last_headless = program.headless; \
+ \
+ program.headless = FALSE; \
+
+#define END_NO_HEADLESS \
+ program.headless = last_headless; \
+ } \
+
/* forward declaration for internal use */
static int MovingOrBlocked2Element_MM(int, int);
static void Bang_MM(int, int);
static void ContinueMoving_MM(int, int);
static void Moving2Blocked_MM(int, int, int *, int *);
+/* bitmap for laser beam detection */
+static Bitmap *laser_bitmap = NULL;
+
+/* element masks for scanning pixels of MM elements */
+static const char mm_masks[10][16][16 + 1] =
+{
+ {
+ " ",
+ " XXXXX ",
+ " XXXXXXX ",
+ " XXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX",
+ " XXXXXXXXXXXXXX",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ },
+ {
+ " ",
+ " XXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ },
+ {
+ " ",
+ " XXXXXX ",
+ " XXXXXXXXX ",
+ " XXXXXXXXXXX ",
+ "XXXXXXXXXXXXX ",
+ "XXXXXXXXXXXXX ",
+ "XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ },
+ {
+ " ",
+ " XXXXXX ",
+ " XXXXXXXX ",
+ " XXXXXXXXXX ",
+ " XXXXXXXXXXX ",
+ " XXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXX XXXXX ",
+ },
+ {
+ " XXXXXX XXXXXX ",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ " ",
+ " ",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ " XXXXXX XXXXXX ",
+ },
+ {
+ " XXXXXX XXXXXX ",
+ "XXXXXXX XXXXXXX",
+ "XXXXXXX XXXXXXX",
+ "XXXXXXX XXXXXXX",
+ "XXXXXXX XXXXXXX",
+ "XXXXXXX XXXXXXX",
+ "XXXXXXX XXXXXXX",
+ " XXXXXX XXXXXX ",
+ " XXXXXX XXXXXX ",
+ "XXXXXXX XXXXXXX",
+ "XXXXXXX XXXXXXX",
+ "XXXXXXX XXXXXXX",
+ "XXXXXXX XXXXXXX",
+ "XXXXXXX XXXXXXX",
+ "XXXXXXX XXXXXXX",
+ " XXXXXX XXXXXX ",
+ },
+ {
+ " XX XXXXX ",
+ " XXX XXXX ",
+ " XXXX XXX X",
+ " XXXXXXXXX XX",
+ " XXXXXXXXX XXX",
+ "XXXXXXXXX XXXX",
+ "XXXXXXXX XXXXX",
+ " XXXX XXX ",
+ " XXX XXXX ",
+ "XXXXX XXXXXXXX",
+ "XXXX XXXXXXXXX",
+ "XXX XXXXXXXXX ",
+ "XX XXXXXXXXX ",
+ "X XXX XXXX ",
+ " XXXX XXX ",
+ " XXXXX XX ",
+ },
+ {
+ " XXXXX XX ",
+ " XXXX XXX ",
+ "X XXX XXXX ",
+ "XX XXXXXXXXX ",
+ "XXX XXXXXXXXX ",
+ "XXXX XXXXXXXXX",
+ "XXXXX XXXXXXXX",
+ " XXX XXXX ",
+ " XXXX XXX ",
+ "XXXXXXXX XXXXX",
+ "XXXXXXXXX XXXX",
+ " XXXXXXXXX XXX",
+ " XXXXXXXXX XX",
+ " XXXX XXX X",
+ " XXX XXXX ",
+ " XX XXXXX ",
+ },
+ {
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ "XXXXXXXXXXXXXXXX",
+ },
+ {
+ " ",
+ " XXXX ",
+ " XXXXXXXX ",
+ " XXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXXXX ",
+ " XXXXXXXXXX ",
+ " XXXXXXXX ",
+ " XXXX ",
+ " ",
+ },
+};
static int get_element_angle(int element)
{
return (reflected_angle + 16) % 16;
}
+static void DrawLaserLines(struct XY *points, int num_points, int mode)
+{
+ Pixel pixel_drawto = (mode == DL_LASER_ENABLED ? pen_ray : pen_bg);
+ Pixel pixel_buffer = (mode == DL_LASER_ENABLED ? WHITE_PIXEL : BLACK_PIXEL);
+
+ DrawLines(drawto, points, num_points, pixel_drawto);
+
+ BEGIN_NO_HEADLESS
+ {
+ DrawLines(laser_bitmap, points, num_points, pixel_buffer);
+ }
+ END_NO_HEADLESS
+}
+
+static boolean CheckLaserPixel(int x, int y)
+{
+ Pixel pixel;
+
+ BEGIN_NO_HEADLESS
+ {
+ pixel = ReadPixel(laser_bitmap, x, y);
+ }
+ END_NO_HEADLESS
+
+ return (pixel == WHITE_PIXEL);
+}
+
static void InitMovDir_MM(int x, int y)
{
int element = Feld[x][y];
laser.num_beamers = 0;
laser.beamer_edge[0] = 0;
+ laser.dest_element = EL_EMPTY;
+ laser.wall_mask = 0;
+
AddLaserEdge(LX, LY); /* set laser starting edge */
pen_ray = GetPixelFromRGB(window,
{
int i, x, y;
+ BEGIN_NO_HEADLESS
+ {
+ /* initialize laser bitmap to current playfield (screen) size */
+ ReCreateBitmap(&laser_bitmap, drawto->width, drawto->height);
+ ClearRectangle(laser_bitmap, 0, 0, drawto->width, drawto->height);
+ }
+ END_NO_HEADLESS
+
/* set global game control values */
game_mm.num_cycle = 0;
game_mm.num_pacman = 0;
}
else
{
- int graphic_mask = getMaskFromElement(element);
- Bitmap *bitmap;
- int src_x, src_y;
- int mask_x, mask_y;
-
- getGraphicSource(graphic_mask, 0, &bitmap, &src_x, &src_y);
+ int pos = getMaskFromElement(element) - IMG_MM_MASK_MCDUFFIN_RIGHT;
- mask_x = src_x + dx;
- mask_y = src_y + dy;
-
- pixel = (ReadPixel(bitmap, mask_x, mask_y) ? 1 : 0);
+ pixel = (mm_masks[pos][dy / 2][dx / 2] == 'X' ? 1 : 0);
}
}
else
if (rf)
DrawLaser(rf - 1, DL_LASER_ENABLED);
- Ct = CT = Counter();
+ Ct = CT = FrameCounter;
#if 0
if (!IN_LEV_FIELD(ELX, ELY))
#endif
/* now draw the laser to the backbuffer and (if enabled) to the screen */
- DrawLines(drawto, &laser.edge[start_edge], num_edges,
- (mode == DL_LASER_ENABLED ? pen_ray : pen_bg));
+ DrawLaserLines(&laser.edge[start_edge], num_edges, mode);
redraw_mask |= REDRAW_FIELD;
{
if (Store[x][y] == EL_BOMB)
{
- laser.num_damages--;
DrawLaser(0, DL_LASER_DISABLED);
- laser.num_edges = 0;
+ InitLaser();
Bang_MM(laser.start_edge.x, laser.start_edge.y);
Store[x][y] = EL_EMPTY;
game_mm.game_over = TRUE;
game_mm.game_over_cause = GAME_OVER_BOMB;
+
+ laser.overloaded = FALSE;
}
else if (IS_MCDUFFIN(Store[x][y]))
{
if (bits & HIT_POS_CENTER)
{
- if (ReadPixel(drawto, SX + obx + 15, SY + oby + 15) == pen_ray)
+ if (CheckLaserPixel(SX + obx + 15,
+ SY + oby + 15))
return TRUE;
}
if (bits & HIT_POS_EDGE)
{
for (i = 0; i < 4; i++)
- if (ReadPixel(drawto,
- SX + obx + 31 * (i % 2),
- SY + oby + 31 * (i / 2)) == pen_ray)
+ if (CheckLaserPixel(SX + obx + 31 * (i % 2),
+ SY + oby + 31 * (i / 2)))
return TRUE;
}
if (bits & HIT_POS_BETWEEN)
{
for (i = 0; i < 4; i++)
- if (ReadPixel(drawto,
- SX + 4 + obx + 22 * (i % 2),
- SY + 4 + oby + 22 * (i / 2)) == pen_ray)
+ if (CheckLaserPixel(SX + 4 + obx + 22 * (i % 2),
+ SY + 4 + oby + 22 * (i / 2)))
return TRUE;
}
if (color_status == STATIC_COLORS)
return;
- CC = Counter();
+ CC = FrameCounter;
- if (CC < Cc || CC > Cc + 50)
+ if (CC < Cc || CC > Cc + 2)
{
Cc = CC;
laser.redraw = FALSE;
#endif
- CT = Counter();
+ CT = FrameCounter;
if (game_mm.num_pacman && FrameReached(&pacman_delay, PACMAN_MOVE_DELAY))
{
CT -= Ct;
- if (element == EL_BOMB && CT > 1500)
+ if (element == EL_BOMB && CT > 75)
{
if (game_mm.cheat_no_explosion)
return;
return;
}
- if (element == EL_FUSE_ON && CT > 500)
+ if (element == EL_FUSE_ON && CT > 25)
{
laser.fuse_off = TRUE;
laser.fuse_x = ELX;
DrawGraphic_MM(ELX, ELY, IMG_MM_FUSE);
}
- if (element == EL_BALL_GRAY && CT > 1500)
+ if (element == EL_BALL_GRAY && CT > 75)
{
static int new_elements[] =
{
return;
}
- if (IS_WALL_ICE(element) && CT > 1000)
+ if (IS_WALL_ICE(element) && CT > 50)
{
PlayLevelSound_MM(ELX, ELY, element, MM_ACTION_SHRINKING);
return;
}
- if (IS_WALL_AMOEBA(element) && CT > 1200)
+ if (IS_WALL_AMOEBA(element) && CT > 60)
{
int k1, k2, k3, dx, dy, de, dm;
int element2 = Feld[ELX][ELY];
{
if (laser.wall_mask & (1 << i))
{
- if (ReadPixel(drawto,
- SX + ELX * TILEX + 14 + (i % 2) * 2,
- SY + ELY * TILEY + 31 * (i / 2)) == pen_ray)
+ if (CheckLaserPixel(SX + ELX * TILEX + 14 + (i % 2) * 2,
+ SY + ELY * TILEY + 31 * (i / 2)))
break;
- if (ReadPixel(drawto,
- SX + ELX * TILEX + 31 * (i % 2),
- SY + ELY * TILEY + 14 + (i / 2) * 2) == pen_ray)
+
+ if (CheckLaserPixel(SX + ELX * TILEX + 31 * (i % 2),
+ SY + ELY * TILEY + 14 + (i / 2) * 2))
break;
}
}
{
if (laser.wall_mask & (1 << i))
{
- if (ReadPixel(drawto,
- SX + ELX * TILEX + 31 * (i % 2),
- SY + ELY * TILEY + 31 * (i / 2)) == pen_ray)
+ if (CheckLaserPixel(SX + ELX * TILEX + 31 * (i % 2),
+ SY + ELY * TILEY + 31 * (i / 2)))
break;
}
}
if (laser.num_beamers > 0 ||
k1 < 1 || k2 < 4 || k3 < 4 ||
- ReadPixel(drawto, SX + ELX * TILEX + 14, SY + ELY * TILEY + 14)
- == pen_ray)
+ CheckLaserPixel(SX + ELX * TILEX + 14,
+ SY + ELY * TILEY + 14))
{
laser.num_edges = r;
laser.num_damages = d;
}
if ((element == EL_BLOCK_WOOD || element == EL_BLOCK_STONE) &&
- laser.stops_inside_element && CT > 1500)
+ laser.stops_inside_element && CT > 75)
{
int x, y;
int k;
return;
}
- if (element == EL_FUEL_FULL && CT > 200)
+ if (element == EL_FUEL_FULL && CT > 10)
{
for (i = game_mm.energy_left; i <= MAX_LASER_ENERGY; i+=2)
{
getGraphicSource(graphic, 0, &bitmap, &src_x, &src_y);
- CT = Counter();
+ CT = FrameCounter;
ox = SX + ox * TILEX;
oy = SY + oy * TILEY;
BlitBitmap(bitmap, window,
src_x, src_y, TILEX, TILEY,
ox + i * mx, oy + i * my);
- Ct = Ct + Counter() - CT;
+ Ct = Ct + FrameCounter - CT;
}
DrawField_MM(nx, ny);