#include "libgame/libgame.h"
#include "game.h"
+#include "init.h"
#include "tools.h"
#include "screens.h"
-#include "init.h"
#include "files.h"
#include "tape.h"
#include "network.h"
static struct ChangingElementInfo changing_element_list[] =
{
- { EL_NUT_BREAKING, EL_EMERALD, 6, NULL, NULL, NULL },
- { EL_PEARL_BREAKING, EL_EMPTY, 8, NULL, NULL, NULL },
- { EL_EXIT_OPENING, EL_EXIT_OPEN, 29, NULL, NULL, NULL },
-
- { EL_SWITCHGATE_OPENING, EL_SWITCHGATE_OPEN, 29, NULL, NULL, NULL },
- { EL_SWITCHGATE_CLOSING, EL_SWITCHGATE_CLOSED, 29, NULL, NULL, NULL },
-
- { EL_TIMEGATE_OPENING, EL_TIMEGATE_OPEN, 29, NULL, NULL, NULL },
- { EL_TIMEGATE_CLOSING, EL_TIMEGATE_CLOSED, 29, NULL, NULL, NULL },
-
- { EL_ACID_SPLASH_LEFT, EL_EMPTY, 8, NULL, NULL, NULL },
- { EL_ACID_SPLASH_RIGHT, EL_EMPTY, 8, NULL, NULL, NULL },
-
- { EL_SP_BUGGY_BASE, EL_SP_BUGGY_BASE_ACTIVATING, 0,
- InitBuggyBase, NULL, NULL },
- { EL_SP_BUGGY_BASE_ACTIVATING,EL_SP_BUGGY_BASE_ACTIVE, 0,
- InitBuggyBase, NULL, NULL },
- { EL_SP_BUGGY_BASE_ACTIVE, EL_SP_BUGGY_BASE, 0,
- InitBuggyBase, WarnBuggyBase, NULL },
-
- { EL_TRAP, EL_TRAP_ACTIVE, 0,
- InitTrap, NULL, ActivateTrap },
- { EL_TRAP_ACTIVE, EL_TRAP, 31,
- NULL, ChangeActiveTrap, NULL },
-
- { EL_ROBOT_WHEEL_ACTIVE, EL_ROBOT_WHEEL, 0,
- InitRobotWheel, RunRobotWheel, StopRobotWheel },
+ {
+ EL_NUT_BREAKING,
+ EL_EMERALD,
+ 6,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_PEARL_BREAKING,
+ EL_EMPTY,
+ 8,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_EXIT_OPENING,
+ EL_EXIT_OPEN,
+ 29,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_SWITCHGATE_OPENING,
+ EL_SWITCHGATE_OPEN,
+ 29,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_SWITCHGATE_CLOSING,
+ EL_SWITCHGATE_CLOSED,
+ 29,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_TIMEGATE_OPENING,
+ EL_TIMEGATE_OPEN,
+ 29,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_TIMEGATE_CLOSING,
+ EL_TIMEGATE_CLOSED,
+ 29,
+ NULL,
+ NULL,
+ NULL
+ },
- { EL_TIMEGATE_SWITCH_ACTIVE, EL_TIMEGATE_SWITCH, 0,
- InitTimegateWheel, RunTimegateWheel, NULL },
+ {
+ EL_ACID_SPLASH_LEFT,
+ EL_EMPTY,
+ 8,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_ACID_SPLASH_RIGHT,
+ EL_EMPTY,
+ 8,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ EL_SP_BUGGY_BASE,
+ EL_SP_BUGGY_BASE_ACTIVATING,
+ 0,
+ InitBuggyBase,
+ NULL,
+ NULL
+ },
+ {
+ EL_SP_BUGGY_BASE_ACTIVATING,
+ EL_SP_BUGGY_BASE_ACTIVE,
+ 0,
+ InitBuggyBase,
+ NULL,
+ NULL
+ },
+ {
+ EL_SP_BUGGY_BASE_ACTIVE,
+ EL_SP_BUGGY_BASE,
+ 0,
+ InitBuggyBase,
+ WarnBuggyBase,
+ NULL
+ },
+ {
+ EL_TRAP,
+ EL_TRAP_ACTIVE,
+ 0,
+ InitTrap,
+ NULL,
+ ActivateTrap
+ },
+ {
+ EL_TRAP_ACTIVE,
+ EL_TRAP,
+ 31,
+ NULL,
+ ChangeActiveTrap,
+ NULL
+ },
+ {
+ EL_ROBOT_WHEEL_ACTIVE,
+ EL_ROBOT_WHEEL,
+ 0,
+ InitRobotWheel,
+ RunRobotWheel,
+ StopRobotWheel
+ },
+ {
+ EL_TIMEGATE_SWITCH_ACTIVE,
+ EL_TIMEGATE_SWITCH,
+ 0,
+ InitTimegateWheel,
+ RunTimegateWheel,
+ NULL
+ },
- { EL_UNDEFINED, EL_UNDEFINED, -1, NULL }
+ {
+ EL_UNDEFINED,
+ EL_UNDEFINED,
+ -1,
+ NULL,
+ NULL,
+ NULL
+ }
};
static struct ChangingElementInfo changing_element[MAX_NUM_ELEMENTS];
{
int i;
+ /* set game engine from tape file when re-playing, else from level file */
game.engine_version = (tape.playing ? tape.engine_version :
level.game_version);
+ /* dynamically adjust element properties according to game engine version */
+ InitElementPropertiesEngine(game.engine_version);
+
#if 0
printf("level %d: level version == %06d\n", level_nr, level.game_version);
printf(" tape version == %06d [%s] [file: %06d]\n",
game.initial_move_delay_value =
(level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED);
+#if 0
/* dynamically adjust element properties according to game engine version */
{
static int ep_em_slippery_wall[] =
};
static int ep_em_slippery_wall_num = SIZEOF_ARRAY_INT(ep_em_slippery_wall);
+ /* special EM style gems behaviour */
for (i=0; i<ep_em_slippery_wall_num; i++)
- {
- if (level.em_slippery_gems) /* special EM style gems behaviour */
- Properties2[ep_em_slippery_wall[i]] |=
- EP_BIT_EM_SLIPPERY_WALL;
- else
- Properties2[ep_em_slippery_wall[i]] &=
- ~EP_BIT_EM_SLIPPERY_WALL;
- }
+ SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
+ level.em_slippery_gems);
/* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
- if (level.em_slippery_gems && game.engine_version > VERSION_IDENT(2,0,1))
- Properties2[EL_EXPANDABLE_WALL_GROWING] |= EP_BIT_EM_SLIPPERY_WALL;
- else
- Properties2[EL_EXPANDABLE_WALL_GROWING] &=~EP_BIT_EM_SLIPPERY_WALL;
+ SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
+ (level.em_slippery_gems &&
+ game.engine_version > VERSION_IDENT(2,0,1)));
}
+#endif
/* initialize changing elements information */
for (i=0; i<MAX_NUM_ELEMENTS; i++)
changing_element[i].post_change_function = NULL;
}
+ /* add changing elements from pre-defined list */
i = 0;
while (changing_element_list[i].base_element != EL_UNDEFINED)
{
i++;
}
+
+ /* add changing elements from custom element configuration */
+ for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ struct CustomElementChangeInfo *change = &level.custom_element[i].change;
+ int element = EL_CUSTOM_START + i;
+
+ /* only add custom elements that change after fixed/random frame delay */
+ if (!IS_CHANGEABLE(element) ||
+ (!HAS_CHANGE_EVENT(element, CE_DELAY_FIXED) &&
+ !HAS_CHANGE_EVENT(element, CE_DELAY_RANDOM)))
+ continue;
+
+ changing_element[element].base_element = element;
+ changing_element[element].next_element = change->successor;
+ changing_element[element].change_delay = 0;
+
+ if (HAS_CHANGE_EVENT(element, CE_DELAY_FIXED))
+ changing_element[element].change_delay +=
+ change->delay_fixed * change->delay_frames;
+
+ if (HAS_CHANGE_EVENT(element, CE_DELAY_RANDOM));
+ /* random frame delay added at runtime for each element individually */
+ }
}
player->is_moving = FALSE;
player->is_waiting = FALSE;
+ player->is_digging = FALSE;
+ player->is_collecting = FALSE;
player->move_delay = game.initial_move_delay;
player->move_delay_value = game.initial_move_delay_value;
AllPlayersGone = FALSE;
- game.yam_content_nr = 0;
+ game.yamyam_content_nr = 0;
game.magic_wall_active = FALSE;
game.magic_wall_time_left = 0;
game.light_time_left = 0;
{
Feld[x][y] = Ur[x][y];
MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
- Store[x][y] = Store2[x][y] = StorePlayer[x][y] = 0;
+ Store[x][y] = Store2[x][y] = StorePlayer[x][y] = Back[x][y] = 0;
AmoebaNr[x][y] = 0;
JustStopped[x][y] = 0;
Stop[x][y] = FALSE;
else
{
DrawTextExt(drawto, DX + XX_EMERALDS, DY + YY_EMERALDS,
- int2str(level_nr, 3), FONT_LEVEL_NUMBER, FONT_OPAQUE);
+ int2str(level_nr, 3), FONT_LEVEL_NUMBER, BLIT_OPAQUE);
BlitBitmap(drawto, drawto,
DX + XX_EMERALDS, DY + YY_EMERALDS + 1,
getFontWidth(FONT_LEVEL_NUMBER) * 3,
OpenDoor(DOOR_OPEN_ALL);
- PlaySoundStereo(SND_GAME_STARTING, SOUND_MAX_RIGHT);
+ PlaySoundStereo(SND_GAME_STARTING, SOUND_MIDDLE);
if (setup.sound_music)
PlayMusic(level_nr);
- KeyboardAutoRepeatOff();
+ KeyboardAutoRepeatOffUnlessAutoplay();
if (options.debug)
{
local_player->LevelSolved = FALSE;
- PlaySoundStereo(SND_GAME_WINNING, SOUND_MAX_RIGHT);
+ PlaySoundStereo(SND_GAME_WINNING, SOUND_MIDDLE);
if (TimeLeft)
{
if (!tape.playing && setup.sound_loops)
- PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MAX_RIGHT,
+ PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MIDDLE,
SND_CTRL_PLAY_LOOP);
while (TimeLeft > 0)
{
if (!tape.playing && !setup.sound_loops)
- PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_RIGHT);
+ PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MIDDLE);
if (TimeLeft > 0 && !(TimeLeft % 10))
- RaiseScore(level.score[SC_ZEITBONUS]);
+ RaiseScore(level.score[SC_TIME_BONUS]);
if (TimeLeft > 100 && !(TimeLeft % 10))
TimeLeft -= 10;
else
else if (level.time == 0) /* level without time limit */
{
if (!tape.playing && setup.sound_loops)
- PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MAX_RIGHT,
+ PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MIDDLE,
SND_CTRL_PLAY_LOOP);
while (TimePlayed < 999)
{
if (!tape.playing && !setup.sound_loops)
- PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_RIGHT);
+ PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MIDDLE);
if (TimePlayed < 999 && !(TimePlayed % 10))
- RaiseScore(level.score[SC_ZEITBONUS]);
+ RaiseScore(level.score[SC_TIME_BONUS]);
if (TimePlayed < 900 && !(TimePlayed % 10))
TimePlayed += 10;
else
if ((hi_pos = NewHiScore()) >= 0)
{
- game_status = HALLOFFAME;
+ game_status = GAME_MODE_SCORES;
DrawHallOfFame(hi_pos);
if (raise_level)
{
}
else
{
- game_status = MAINMENU;
+ game_status = GAME_MODE_MAIN;
if (raise_level)
{
level_nr++;
static void RemoveField(int x, int y)
{
Feld[x][y] = EL_EMPTY;
+ GfxElement[x][y] = EL_UNDEFINED;
MovPos[x][y] = 0;
MovDir[x][y] = 0;
MovDelay[x][y] = 0;
if (!IN_SCR_FIELD(sx, sy) || IS_PLAYER(x, y))
return;
- if (Store[x][y])
+ if (IS_WALKABLE_INSIDE(Back[x][y]))
+ return;
+
+ if (Back[x][y])
+ DrawGraphic(sx, sy, el2img(Back[x][y]), 0);
+ else if (Store[x][y])
DrawGraphic(sx, sy, el2img(Store[x][y]), 0);
frame = getGraphicAnimationFrame(graphic, GfxFrame[x][y]);
#if 1
- if (Store[x][y])
+ if (Back[x][y] || Store[x][y])
DrawGraphicThruMask(sx, sy, graphic, frame);
else
DrawGraphic(sx, sy, graphic, frame);
{
int center_element = Feld[ex][ey];
+ /* remove things displayed in background while burning dynamite */
+ if (!IS_INDESTRUCTIBLE(Back[ex][ey]))
+ Back[ex][ey] = 0;
+
if (IS_MOVING(ex, ey) || IS_BLOCKED(ex, ey))
{
/* put moving element to center field (and let it explode there) */
Feld[ex][ey] = center_element;
}
- for (y=ey-1; y<=ey+1; y++) for(x=ex-1; x<=ex+1; x++)
+ for (y = ey - 1; y <= ey + 1; y++) for(x = ex - 1; x <= ex + 1; x++)
{
int element;
RemoveMovingField(x, y);
}
- if (IS_INDESTRUCTIBLE(element) || element == EL_FLAMES)
+#if 1
+ if (IS_EXPLOSION_PROOF(element))
continue;
+#else
+ if ((IS_INDESTRUCTIBLE(element) &&
+ (game.engine_version < VERSION_IDENT(2,2,0) ||
+ (!IS_WALKABLE_OVER(element) && !IS_WALKABLE_UNDER(element)))) ||
+ element == EL_FLAMES)
+ continue;
+#endif
if (IS_PLAYER(x, y) && SHIELD_ON(PLAYERINFO(x, y)))
{
continue;
}
+ /* save walkable background elements while explosion on same tile */
+ if (IS_INDESTRUCTIBLE(element))
+ Back[x][y] = element;
+
+ /* ignite explodable elements reached by other explosion */
if (element == EL_EXPLOSION)
element = Store2[x][y];
Store[x][y] = EL_BD_DIAMOND;
else if (center_element == EL_SP_ELECTRON)
Store[x][y] = EL_SP_INFOTRON;
- else if (center_element == EL_YAMYAM)
- Store[x][y] = level.yam_content[game.yam_content_nr][x-ex+1][y-ey+1];
else if (center_element == EL_AMOEBA_TO_DIAMOND)
Store[x][y] = level.amoeba_content;
+ else if (center_element == EL_YAMYAM)
+ Store[x][y] =
+ level.yamyam_content[game.yamyam_content_nr][x - ex + 1][y - ey + 1];
+ else if (IS_CUSTOM_ELEMENT(center_element))
+ Store[x][y] =
+ CUSTOM_ELEMENT_INFO(center_element).content[x - ex + 1][y - ey + 1];
else if (element == EL_WALL_EMERALD)
Store[x][y] = EL_EMERALD;
else if (element == EL_WALL_DIAMOND)
Store[x][y] = EL_PEARL;
else if (element == EL_WALL_CRYSTAL)
Store[x][y] = EL_CRYSTAL;
- else if (!IS_PFORTE(Store[x][y]))
+ else
Store[x][y] = EL_EMPTY;
if (x != ex || y != ey ||
}
Feld[x][y] = EL_EXPLOSION;
+ GfxElement[x][y] = EL_UNDEFINED;
MovDir[x][y] = MovPos[x][y] = 0;
AmoebaNr[x][y] = 0;
ExplodePhase[x][y] = 1;
}
if (center_element == EL_YAMYAM)
- game.yam_content_nr = (game.yam_content_nr + 1) % level.num_yam_contents;
+ game.yamyam_content_nr =
+ (game.yamyam_content_nr + 1) % level.num_yamyam_contents;
return;
}
if (IS_PLAYER(x, y))
KillHeroUnlessProtected(x, y);
- else if (IS_EXPLOSIVE(element))
+ else if (CAN_EXPLODE(element))
{
Feld[x][y] = Store2[x][y];
Store2[x][y] = 0;
element = Feld[x][y] = Store[x][y];
Store[x][y] = Store2[x][y] = 0;
+
+ if (Back[x][y] && IS_INDESTRUCTIBLE(Back[x][y]))
+ element = Feld[x][y] = Back[x][y];
+ Back[x][y] = 0;
+
MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0;
InitField(x, y, FALSE);
- if (CAN_MOVE(element) || COULD_MOVE(element))
+ if (CAN_MOVE(element))
InitMovDir(x, y);
DrawLevelField(x, y);
int frame = getGraphicAnimationFrame(graphic, phase - delay);
if (phase == delay)
- DrawCrumbledSand(SCREENX(x), SCREENY(y));
+ DrawLevelFieldCrumbledSand(x, y);
- if (IS_PFORTE(Store[x][y]))
+ if (IS_WALKABLE_OVER(Back[x][y]) && Back[x][y] != EL_EMPTY)
{
- DrawLevelElement(x, y, Store[x][y]);
+ DrawLevelElement(x, y, Back[x][y]);
DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
}
- else
+ else if (IS_WALKABLE_UNDER(Back[x][y]))
+ {
+ DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame);
+ DrawLevelElementThruMask(x, y, Back[x][y]);
+ }
+ else if (!IS_WALKABLE_INSIDE(Back[x][y]))
DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame);
}
}
if (!lastline && object_hit) /* check which object was hit */
{
- if (CAN_CHANGE(element) &&
+ if (CAN_PASS_MAGIC_WALL(element) &&
(smashed == EL_MAGIC_WALL ||
smashed == EL_BD_MAGIC_WALL))
{
if (IN_LEV_FIELD(left_x, left_y) &&
(IS_FREE_OR_PLAYER(left_x, left_y) ||
- IS_MAMPF2(Feld[left_x][left_y])))
+ IS_FOOD_DARK_YAMYAM(Feld[left_x][left_y])))
can_turn_left = TRUE;
if (IN_LEV_FIELD(right_x, right_y) &&
(IS_FREE_OR_PLAYER(right_x, right_y) ||
- IS_MAMPF2(Feld[right_x][right_y])))
+ IS_FOOD_DARK_YAMYAM(Feld[right_x][right_y])))
can_turn_right = TRUE;
if (can_turn_left && can_turn_right)
int rnd = RND(rnd_value);
if (IN_LEV_FIELD(left_x, left_y) &&
- (IS_FREE(left_x, left_y) || IS_GEM(Feld[left_x][left_y])))
+ (IS_FREE(left_x, left_y) || IS_FOOD_PIG(Feld[left_x][left_y])))
can_turn_left = TRUE;
if (IN_LEV_FIELD(right_x, right_y) &&
- (IS_FREE(right_x, right_y) || IS_GEM(Feld[right_x][right_y])))
+ (IS_FREE(right_x, right_y) || IS_FOOD_PIG(Feld[right_x][right_y])))
can_turn_right = TRUE;
if (IN_LEV_FIELD(move_x, move_y) &&
- (IS_FREE(move_x, move_y) || IS_GEM(Feld[move_x][move_y])))
+ (IS_FREE(move_x, move_y) || IS_FOOD_PIG(Feld[move_x][move_y])))
can_move_on = TRUE;
if (can_turn_left &&
MovDir[x][y] = back_dir;
if (!IS_FREE(x+move_xy[MovDir[x][y]].x, y+move_xy[MovDir[x][y]].y) &&
- !IS_GEM(Feld[x+move_xy[MovDir[x][y]].x][y+move_xy[MovDir[x][y]].y]))
+ !IS_FOOD_PIG(Feld[x+move_xy[MovDir[x][y]].x][y+move_xy[MovDir[x][y]].y]))
MovDir[x][y] = old_move_dir;
MovDelay[x][y] = 0;
Feld[newx][newy] == EL_ACID ||
(element == EL_PENGUIN &&
(Feld[newx][newy] == EL_EXIT_OPEN ||
- IS_MAMPF3(Feld[newx][newy])))))
+ IS_FOOD_PENGUIN(Feld[newx][newy])))))
return;
MovDir[x][y] =
Feld[newx][newy] == EL_ACID ||
(element == EL_PENGUIN &&
(Feld[newx][newy] == EL_EXIT_OPEN ||
- IS_MAMPF3(Feld[newx][newy])))))
+ IS_FOOD_PENGUIN(Feld[newx][newy])))))
return;
MovDir[x][y] = old_move_dir;
void StartMoving(int x, int y)
{
- static boolean use_spring_bug = TRUE;
+ boolean use_spring_bug = (game.engine_version < VERSION_IDENT(2,2,0));
boolean started_moving = FALSE; /* some elements can fall _and_ move */
int element = Feld[x][y];
Store[x][y] = 0;
}
}
- else if (CAN_CHANGE(element) &&
+ else if (CAN_PASS_MAGIC_WALL(element) &&
(Feld[x][y+1] == EL_MAGIC_WALL_ACTIVE ||
Feld[x][y+1] == EL_BD_MAGIC_WALL_ACTIVE))
{
if (!MovDelay[x][y]) /* start new movement phase */
{
- /* all objects that can change their move direction after each step */
- /* (MAMPFER, MAMPFER2 and PACMAN go straight until they hit a wall */
+ /* all objects that can change their move direction after each step
+ (YAMYAM, DARK_YAMYAM and PACMAN go straight until they hit a wall */
if (element != EL_YAMYAM &&
element != EL_DARK_YAMYAM &&
int sx = SCREENX(xx), sy = SCREENY(yy);
int flame_graphic = graphic + (i - 1);
- if (!IN_LEV_FIELD(xx, yy) ||
- IS_SOLID(Feld[xx][yy]) || Feld[xx][yy] == EL_EXPLOSION)
+ if (!IN_LEV_FIELD(xx, yy) || IS_DRAGONFIRE_PROOF(Feld[xx][yy]))
break;
if (MovDelay[x][y])
{
int flamed = MovingOrBlocked2Element(xx, yy);
- if (IS_ENEMY(flamed) || IS_EXPLOSIVE(flamed))
+ if (IS_ENEMY(flamed) || CAN_EXPLODE(flamed))
Bang(xx, yy);
else
RemoveMovingField(xx, yy);
Feld[x][y] = EL_EMPTY;
DrawLevelField(x, y);
- PlaySoundLevel(newx, newy, SND_CLASS_EXIT_PASSING);
+ PlaySoundLevel(newx, newy, SND_PENGUIN_PASSING);
if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
DrawGraphicThruMask(SCREENX(newx),SCREENY(newy), el2img(element), 0);
return;
}
- else if (IS_MAMPF3(Feld[newx][newy]))
+ else if (IS_FOOD_PENGUIN(Feld[newx][newy]))
{
if (DigField(local_player, newx, newy, 0, 0, DF_DIG) == MF_MOVING)
DrawLevelField(newx, newy);
}
else if (element == EL_PIG && IN_LEV_FIELD(newx, newy))
{
- if (IS_GEM(Feld[newx][newy]))
+ if (IS_FOOD_PIG(Feld[newx][newy]))
{
if (IS_MOVING(newx, newy))
RemoveMovingField(newx, newy);
PlaySoundLevel(x, y, SND_YAMYAM_DIGGING);
}
else if (element == EL_DARK_YAMYAM && IN_LEV_FIELD(newx, newy) &&
- IS_MAMPF2(Feld[newx][newy]))
+ IS_FOOD_DARK_YAMYAM(Feld[newx][newy]))
{
if (AmoebaNr[newx][newy])
{
yy = y + xy[i][1];
if (IN_LEV_FIELD(xx, yy) && Feld[xx][yy] == EL_SAND)
- DrawLevelField(xx, yy); /* for "DrawCrumbledSand()" */
+ DrawLevelField(xx, yy); /* for "crumbled sand" */
}
}
{
if (MovDir[x][y] == MV_LEFT)
{
- if (IN_LEV_FIELD(x - 1, y) && IS_MAUER(Feld[x - 1][y]))
+ if (IN_LEV_FIELD(x - 1, y) && IS_WALL(Feld[x - 1][y]))
DrawLevelField(x - 1, y);
}
else if (MovDir[x][y] == MV_RIGHT)
{
- if (IN_LEV_FIELD(x + 1, y) && IS_MAUER(Feld[x + 1][y]))
+ if (IN_LEV_FIELD(x + 1, y) && IS_WALL(Feld[x + 1][y]))
DrawLevelField(x + 1, y);
}
else if (MovDir[x][y] == MV_UP)
{
- if (IN_LEV_FIELD(x, y - 1) && IS_MAUER(Feld[x][y - 1]))
+ if (IN_LEV_FIELD(x, y - 1) && IS_WALL(Feld[x][y - 1]))
DrawLevelField(x, y - 1);
}
else
{
- if (IN_LEV_FIELD(x, y + 1) && IS_MAUER(Feld[x][y + 1]))
+ if (IN_LEV_FIELD(x, y + 1) && IS_WALL(Feld[x][y + 1]))
DrawLevelField(x, y + 1);
}
if (element == EL_EXPANDABLE_WALL && (links_frei || rechts_frei))
DrawLevelField(ax, ay);
- if (!IN_LEV_FIELD(ax, ay-1) || IS_MAUER(Feld[ax][ay-1]))
+ if (!IN_LEV_FIELD(ax, ay-1) || IS_WALL(Feld[ax][ay-1]))
oben_massiv = TRUE;
- if (!IN_LEV_FIELD(ax, ay+1) || IS_MAUER(Feld[ax][ay+1]))
+ if (!IN_LEV_FIELD(ax, ay+1) || IS_WALL(Feld[ax][ay+1]))
unten_massiv = TRUE;
- if (!IN_LEV_FIELD(ax-1, ay) || IS_MAUER(Feld[ax-1][ay]))
+ if (!IN_LEV_FIELD(ax-1, ay) || IS_WALL(Feld[ax-1][ay]))
links_massiv = TRUE;
- if (!IN_LEV_FIELD(ax+1, ay) || IS_MAUER(Feld[ax+1][ay]))
+ if (!IN_LEV_FIELD(ax+1, ay) || IS_WALL(Feld[ax+1][ay]))
rechts_massiv = TRUE;
if (((oben_massiv && unten_massiv) ||
/* if new animation frame was drawn, correct crumbled sand border */
if (IS_NEW_FRAME(GfxFrame[x][y], graphic))
- DrawCrumbledSand(SCREENX(x), SCREENY(y));
+ DrawLevelFieldCrumbledSand(x, y);
}
static void ChangeElement(int x, int y)
{
int element = Feld[x][y];
+ if (IS_MOVING(x, y)) /* never change a running system :-) */
+ return;
+
if (MovDelay[x][y] == 0) /* initialize element change */
{
MovDelay[x][y] = changing_element[element].change_delay + 1;
+ if (IS_CUSTOM_ELEMENT(element) &&
+ HAS_CHANGE_EVENT(element, CE_DELAY_RANDOM))
+ {
+ int i = element - EL_CUSTOM_START;
+ int max_random_delay = level.custom_element[i].change.delay_random;
+ int delay_frames = level.custom_element[i].change.delay_frames;
+
+ MovDelay[x][y] += RND(max_random_delay * delay_frames);
+ }
+
ResetGfxAnimation(x, y);
ResetRandomAnimationValue(x, y);
ResetGfxAnimation(x, y);
ResetRandomAnimationValue(x, y);
+#if 1
+ InitField(x, y, FALSE);
+ if (CAN_MOVE(element))
+ InitMovDir(x, y);
+#endif
DrawLevelField(x, y);
if (changing_element[element].post_change_function)
byte *recorded_player_action;
byte summarized_player_action = 0;
- if (game_status != PLAYING)
+ if (game_status != GAME_MODE_PLAYING)
return;
action_delay_value =
HandleNetworking();
#endif
- if (game_status != PLAYING)
+ if (game_status != GAME_MODE_PLAYING)
return;
if (!network_player_action_received)
element = Feld[x][y];
graphic = el2img(element);
+#if 0
+ if (element == -1)
+ {
+ printf("::: %d,%d: %d [%d]\n", x, y, element, FrameCounter);
+
+ element = graphic = 0;
+ }
+#endif
+
if (graphic_info[graphic].anim_global_sync)
GfxFrame[x][y] = FrameCounter;
MauerAbleger(x, y);
else if (element == EL_FLAMES)
CheckForDragon(x, y);
+#if 0
else if (IS_AUTO_CHANGING(element))
ChangeElement(x, y);
+#endif
else if (element == EL_EXPLOSION)
; /* drawing of correct explosion animation is handled separately */
- else if (IS_ANIMATED(graphic))
+ else if (IS_ANIMATED(graphic) && !IS_AUTO_CHANGING(element))
DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+#if 1
+ /* this may take place after moving, therefore element may have changed */
+ if (IS_AUTO_CHANGING(Feld[x][y]))
+ ChangeElement(x, y);
+#endif
+
if (IS_BELT_ACTIVE(element))
PlaySoundLevelAction(x, y, ACTION_ACTIVE);
TimeLeft--;
if (TimeLeft <= 10 && setup.time_limit)
- PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MAX_RIGHT);
+ PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE);
DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2);
if (field_under_player_is_free &&
!player_is_moving_to_valid_field &&
- !IS_TUBE(Feld[jx][jy]))
+ !IS_WALKABLE_INSIDE(Feld[jx][jy]))
player->programmed_action = MV_DOWN;
}
}
+/*
+ MoveFigureOneStep()
+ -----------------------------------------------------------------------------
+ dx, dy: direction (non-diagonal) to try to move the player to
+ real_dx, real_dy: direction as read from input device (can be diagonal)
+*/
+
boolean MoveFigureOneStep(struct PlayerInfo *player,
int dx, int dy, int real_dx, int real_dy)
{
else if (old_jx == jx && old_jy != jy)
player->MovDir = (old_jy < jy ? MV_DOWN : MV_UP);
- DrawLevelField(jx, jy); /* for "DrawCrumbledSand()" */
+ DrawLevelField(jx, jy); /* for "crumbled sand" */
player->last_move_dir = player->MovDir;
player->is_moving = TRUE;
if (player->MovPos == 0)
{
- if (IS_QUICK_GATE(Feld[last_jx][last_jy]))
+ if (IS_PASSABLE(Feld[last_jx][last_jy]))
{
/* continue with normal speed after quickly moving through gate */
HALVE_PLAYER_SPEED(player);
if (!player->active)
return;
- if (IS_PFORTE(Feld[jx][jy]))
- Feld[jx][jy] = EL_EMPTY;
+ /* remove accessible field at the player's position */
+ Feld[jx][jy] = EL_EMPTY;
/* deactivate shield (else Bang()/Explode() would not work right) */
player->shield_normal_time_left = 0;
ExitY = ZY = jy;
}
+/*
+ checkDiagonalPushing()
+ -----------------------------------------------------------------------------
+ check if diagonal input device direction results in pushing of object
+ (by checking if the alternative direction is walkable, diggable, ...)
+*/
+
+static boolean checkDiagonalPushing(struct PlayerInfo *player,
+ int x, int y, int real_dx, int real_dy)
+{
+ int jx, jy, dx, dy, xx, yy;
+
+ if (real_dx == 0 || real_dy == 0) /* no diagonal direction => push */
+ return TRUE;
+
+ /* diagonal direction: check alternative direction */
+ jx = player->jx;
+ jy = player->jy;
+ dx = x - jx;
+ dy = y - jy;
+ xx = jx + (dx == 0 ? real_dx : 0);
+ yy = jy + (dy == 0 ? real_dy : 0);
+
+ return (!IN_LEV_FIELD(xx, yy) || IS_SOLID_FOR_PUSHING(Feld[xx][yy]));
+}
+
+/*
+ DigField()
+ -----------------------------------------------------------------------------
+ x, y: field next to player (non-diagonal) to try to dig to
+ real_dx, real_dy: direction as read from input device (can be diagonal)
+*/
+
int DigField(struct PlayerInfo *player,
int x, int y, int real_dx, int real_dy, int mode)
{
int element;
if (player->MovPos == 0)
+ {
player->is_digging = FALSE;
+ player->is_collecting = FALSE;
+ }
if (player->MovPos == 0)
player->Pushing = FALSE;
{
player->Switching = FALSE;
player->push_delay = 0;
+
return MF_NO_ACTION;
}
if (IS_MOVING(x, y) || IS_PLAYER(x, y))
return MF_NO_ACTION;
- if (IS_TUBE(Feld[jx][jy]))
+#if 0
+ if (IS_TUBE(Feld[jx][jy]) || IS_TUBE(Back[jx][jy]))
+#else
+ if (IS_TUBE(Feld[jx][jy]) ||
+ (IS_TUBE(Back[jx][jy]) && game.engine_version >= VERSION_IDENT(2,2,0)))
+#endif
{
int i = 0;
+ int tube_element = (IS_TUBE(Feld[jx][jy]) ? Feld[jx][jy] : Back[jx][jy]);
int tube_leave_directions[][2] =
{
{ EL_TUBE_ANY, MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
{ -1, MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN }
};
- while (tube_leave_directions[i][0] != Feld[jx][jy])
+ while (tube_leave_directions[i][0] != tube_element)
{
i++;
if (tube_leave_directions[i][0] == -1) /* should not happen */
element = Feld[x][y];
+#if 1
+ if (mode == DF_SNAP && !IS_SNAPPABLE(element) &&
+ game.engine_version >= VERSION_IDENT(2,2,0))
+ return MF_NO_ACTION;
+#endif
+
switch (element)
{
case EL_EMPTY:
case EL_SP_BASE:
case EL_SP_BUGGY_BASE:
case EL_SP_BUGGY_BASE_ACTIVATING:
+ RemoveField(x, y);
#if 1
- if (mode != DF_SNAP && element == EL_SAND)
- GfxElement[x][y] = Feld[x][y];
+ if (mode != DF_SNAP && element != EL_EMPTY)
+ {
+ GfxElement[x][y] = (CAN_BE_CRUMBLED(element) ? EL_SAND : element);
+ player->is_digging = TRUE;
+ }
#endif
- RemoveField(x, y);
PlaySoundLevelElementAction(x, y, element, ACTION_DIGGING);
break;
case EL_PEARL:
case EL_CRYSTAL:
RemoveField(x, y);
+#if 1
+ if (mode != DF_SNAP)
+ {
+ GfxElement[x][y] = element;
+ player->is_collecting = TRUE;
+ }
+#endif
local_player->gems_still_needed -= (element == EL_DIAMOND ? 3 :
element == EL_PEARL ? 5 :
element == EL_CRYSTAL ? 8 : 1);
TimeLeft += 10;
DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2);
}
- PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, SOUND_MAX_RIGHT);
+ PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, SOUND_MIDDLE);
break;
case EL_SHIELD_NORMAL:
player->Pushing = TRUE;
+#if 0
+ if (element == EL_ROCK)
+ printf("::: wanna push [%d] [%d]\n",
+ FrameCounter, player->push_delay_value);
+#endif
+
if (!IN_LEV_FIELD(x+dx, y+dy) || !IS_FREE(x+dx, y+dy))
return MF_NO_ACTION;
- if (real_dy)
- {
- if (IN_LEV_FIELD(jx, jy+real_dy) && !IS_SOLID(Feld[jx][jy+real_dy]))
- return MF_NO_ACTION;
- }
+ if (!checkDiagonalPushing(player, x, y, real_dx, real_dy))
+ return MF_NO_ACTION;
if (player->push_delay == 0)
player->push_delay = FrameCounter;
break;
case EL_SP_PORT_LEFT:
- case EL_SP_GRAVITY_PORT_LEFT:
case EL_SP_PORT_RIGHT:
- case EL_SP_GRAVITY_PORT_RIGHT:
case EL_SP_PORT_UP:
- case EL_SP_GRAVITY_PORT_UP:
case EL_SP_PORT_DOWN:
- case EL_SP_GRAVITY_PORT_DOWN:
case EL_SP_PORT_HORIZONTAL:
case EL_SP_PORT_VERTICAL:
case EL_SP_PORT_ANY:
+ case EL_SP_GRAVITY_PORT_LEFT:
+ case EL_SP_GRAVITY_PORT_RIGHT:
+ case EL_SP_GRAVITY_PORT_UP:
+ case EL_SP_GRAVITY_PORT_DOWN:
if ((dx == -1 &&
element != EL_SP_PORT_LEFT &&
element != EL_SP_GRAVITY_PORT_LEFT &&
TimeLeft += 10;
DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2);
DrawLevelField(x, y);
- PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MAX_RIGHT);
+ PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MIDDLE);
return MF_ACTION;
break;
|| !IS_SB_ELEMENT(element))))
return MF_NO_ACTION;
- if (dx && real_dy)
- {
- if (IN_LEV_FIELD(jx, jy+real_dy) && !IS_SOLID(Feld[jx][jy+real_dy]))
- return MF_NO_ACTION;
- }
- else if (dy && real_dx)
- {
- if (IN_LEV_FIELD(jx+real_dx, jy) && !IS_SOLID(Feld[jx+real_dx][jy]))
- return MF_NO_ACTION;
- }
+ if (!checkDiagonalPushing(player, x, y, real_dx, real_dy))
+ return MF_NO_ACTION;
if (player->push_delay == 0)
player->push_delay = FrameCounter;
break;
default:
- if (IS_PUSHABLE(element))
+
+ if (IS_WALKABLE(element))
+ {
+ break;
+ }
+ else if (IS_DIGGABLE(element))
+ {
+ RemoveField(x, y);
+#if 1
+ if (mode != DF_SNAP)
+ {
+ GfxElement[x][y] =
+ (CAN_BE_CRUMBLED(element) ? EL_SAND : GFX_ELEMENT(element));
+ player->is_digging = TRUE;
+ }
+#endif
+ PlaySoundLevelElementAction(x, y, element, ACTION_DIGGING);
+
+ break;
+ }
+ else if (IS_COLLECTIBLE(element))
+ {
+ RemoveField(x, y);
+#if 1
+ if (mode != DF_SNAP)
+ {
+ GfxElement[x][y] = element;
+ player->is_collecting = TRUE;
+ }
+#endif
+ PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
+
+ break;
+ }
+ else if (IS_PUSHABLE(element))
{
if (mode == DF_SNAP)
return MF_NO_ACTION;
if (!IN_LEV_FIELD(x+dx, y+dy) || !IS_FREE(x+dx, y+dy))
return MF_NO_ACTION;
- if (dx && real_dy)
- {
- if (IN_LEV_FIELD(jx, jy+real_dy) && !IS_SOLID(Feld[jx][jy+real_dy]))
- return MF_NO_ACTION;
- }
- else if (dy && real_dx)
- {
- if (IN_LEV_FIELD(jx+real_dx, jy) && !IS_SOLID(Feld[jx+real_dx][jy]))
- return MF_NO_ACTION;
- }
+ if (!checkDiagonalPushing(player, x, y, real_dx, real_dy))
+ return MF_NO_ACTION;
if (player->push_delay == 0)
player->push_delay = FrameCounter;
player->push_delay = 0;
- if (Feld[x][y] != element) /* really digged something */
- player->is_digging = TRUE;
+ if (Feld[x][y] != element) /* really digged/collected something */
+ player->is_collecting = !player->is_digging;
return MF_MOVING;
}
int jx = player->jx, jy = player->jy;
int x = jx + dx, y = jy + dy;
+ if (player->MovPos && game.engine_version >= VERSION_IDENT(2,2,0))
+ return FALSE;
+
if (!player->active || !IN_LEV_FIELD(x, y))
return FALSE;
player->snapped = FALSE;
if (player->MovPos == 0)
+ {
player->is_digging = FALSE;
+ player->is_collecting = FALSE;
+ }
return FALSE;
}
dy < 0 ? MV_UP :
dy > 0 ? MV_DOWN : MV_NO_MOVING);
- if (!DigField(player, x, y, 0, 0, DF_SNAP))
+ if (DigField(player, x, y, 0, 0, DF_SNAP) == MF_NO_ACTION)
return FALSE;
player->snapped = TRUE;
player->is_digging = FALSE;
+ player->is_collecting = FALSE;
+
DrawLevelField(x, y);
BackToFront();
IS_ACTIVE_BOMB(element) || element == EL_EXPLOSION)
return FALSE;
+#if 0
+ if (element != EL_EMPTY)
+ return FALSE;
+#endif
+
if (element != EL_EMPTY)
+ {
+#if 0
Store[jx][jy] = element;
+#else
+ Back[jx][jy] = element;
+#endif
+ }
MovDelay[jx][jy] = 96;
case EL_EMERALD_YELLOW:
case EL_EMERALD_RED:
case EL_EMERALD_PURPLE:
- RaiseScore(level.score[SC_EDELSTEIN]);
+ RaiseScore(level.score[SC_EMERALD]);
break;
case EL_DIAMOND:
- RaiseScore(level.score[SC_DIAMANT]);
+ RaiseScore(level.score[SC_DIAMOND]);
break;
case EL_BUG:
case EL_BD_BUTTERFLY:
- RaiseScore(level.score[SC_KAEFER]);
+ RaiseScore(level.score[SC_BUG]);
break;
case EL_SPACESHIP:
case EL_BD_FIREFLY:
- RaiseScore(level.score[SC_FLIEGER]);
+ RaiseScore(level.score[SC_SPACESHIP]);
break;
case EL_YAMYAM:
case EL_DARK_YAMYAM:
- RaiseScore(level.score[SC_MAMPFER]);
+ RaiseScore(level.score[SC_YAMYAM]);
break;
case EL_ROBOT:
RaiseScore(level.score[SC_ROBOT]);
RaiseScore(level.score[SC_PACMAN]);
break;
case EL_NUT:
- RaiseScore(level.score[SC_KOKOSNUSS]);
+ RaiseScore(level.score[SC_NUT]);
break;
case EL_DYNAMITE:
- RaiseScore(level.score[SC_DYNAMIT]);
+ RaiseScore(level.score[SC_DYNAMITE]);
break;
case EL_KEY_1:
case EL_KEY_2:
case EL_KEY_3:
case EL_KEY_4:
- RaiseScore(level.score[SC_SCHLUESSEL]);
+ RaiseScore(level.score[SC_KEY]);
break;
default:
break;
else
#endif
{
- game_status = MAINMENU;
+ game_status = GAME_MODE_MAIN;
DrawMainMenu();
}
}
{
int id = gi->custom_id;
- if (game_status != PLAYING)
+ if (game_status != GAME_MODE_PLAYING)
return;
switch (id)