/***********************************************************
* Rocks'n'Diamonds -- McDuffin Strikes Back! *
*----------------------------------------------------------*
-* (c) 1995-2001 Artsoft Entertainment *
+* (c) 1995-2002 Artsoft Entertainment *
* Holger Schemel *
* Detmolder Strasse 189 *
* 33604 Bielefeld *
#define DX_TIME (DX + XX_TIME)
#define DY_TIME (DY + YY_TIME)
+/* values for initial player move delay (initial delay counter value) */
+#define INITIAL_MOVE_DELAY_OFF -1
+#define INITIAL_MOVE_DELAY_ON 0
+
/* values for player movement speed (which is in fact a delay value) */
#define MOVE_DELAY_NORMAL_SPEED 8
#define MOVE_DELAY_HIGH_SPEED 4
static void CheckGravityMovement(struct PlayerInfo *);
static void KillHeroUnlessProtected(int, int);
+void PlaySoundLevel(int, int, int);
+void PlaySoundLevelAction(int, int, int);
+void PlaySoundLevelElementAction(int, int, int, int);
+
static void MapGameButtons();
static void HandleGameButtons(struct GadgetInfo *);
static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS];
-static boolean is_loop_sound[NUM_SOUND_EFFECTS];
-static boolean is_loop_sound_initialized = FALSE;
-static int loop_sounds[] =
+#define SND_ACTION_UNKNOWN 0
+#define SND_ACTION_WAITING 1
+#define SND_ACTION_MOVING 2
+#define SND_ACTION_DIGGING 3
+#define SND_ACTION_COLLECTING 4
+#define SND_ACTION_PASSING 5
+#define SND_ACTION_IMPACT 6
+#define SND_ACTION_PUSHING 7
+#define SND_ACTION_ACTIVATING 8
+#define SND_ACTION_BURNING 9
+
+#define NUM_SND_ACTIONS 10
+
+static struct
+{
+ char *text;
+ int value;
+ boolean is_loop;
+} sound_action_properties[] =
{
- SND_BD_MAGIC_WALL_RUNNING,
- SND_BD_BUTTERFLY_MOVING,
- SND_BD_FIREFLY_MOVING,
- SND_SP_SNIKSNAK_MOVING,
- SND_SP_ELECTRON_MOVING,
- SND_DYNAMITE_BURNING,
- SND_BUG_MOVING,
- SND_SPACESHIP_MOVING,
- SND_YAMYAM_MOVING,
- SND_YAMYAM_WAITING,
- SND_ROBOT_WHEEL_RUNNING,
- SND_MAGIC_WALL_RUNNING,
- SND_BALLOON_MOVING,
- SND_MOLE_MOVING,
- SND_TIMEGATE_WHEEL_RUNNING,
- SND_CONVEYOR_BELT_RUNNING,
- SND_DYNABOMB_BURNING,
- SND_PACMAN_MOVING,
- SND_PENGUIN_MOVING,
- SND_PIG_MOVING,
- SND_DRAGON_MOVING,
- SND_DRAGON_BREATHING_FIRE
+ /* insert _all_ loop sound actions here */
+ { ".waiting", SND_ACTION_WAITING, TRUE },
+ { ".moving", SND_ACTION_MOVING, TRUE }, /* continuos moving */
+ { ".running", SND_ACTION_UNKNOWN, TRUE },
+ { ".burning", SND_ACTION_BURNING, TRUE },
+ { ".growing", SND_ACTION_UNKNOWN, TRUE },
+ { ".attacking", SND_ACTION_UNKNOWN, TRUE },
+ { ".activated", SND_ACTION_UNKNOWN, TRUE },
+
+ /* other (non-loop) sound actions are optional */
+ { ".stepping", SND_ACTION_MOVING, FALSE }, /* discrete moving */
+ { ".digging", SND_ACTION_DIGGING, FALSE },
+ { ".collecting", SND_ACTION_COLLECTING, FALSE },
+ { ".passing", SND_ACTION_PASSING, FALSE },
+ { ".impact", SND_ACTION_IMPACT, FALSE },
+ { ".pushing", SND_ACTION_PUSHING, FALSE },
+ { ".activating", SND_ACTION_ACTIVATING, FALSE },
+ { NULL, 0, 0 },
};
+static int element_action_sound[NUM_LEVEL_ELEMENTS][NUM_SND_ACTIONS];
+static boolean is_loop_sound[NUM_SOUND_FILES];
#define IS_LOOP_SOUND(x) (is_loop_sound[x])
-
#ifdef DEBUG
#if 0
static unsigned int getStateCheckSum(int counter)
int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
}
+
+/*
+ =============================================================================
+ InitGameSound()
+ -----------------------------------------------------------------------------
+ initialize sound effect lookup table for element actions
+ =============================================================================
+*/
+
+void InitGameSound()
+{
+ int sound_effect_properties[NUM_SOUND_FILES];
+ int i, j;
+
+#if 0
+ debug_print_timestamp(0, NULL);
+#endif
+
+ for (i=0; i<NUM_SND_ACTIONS; i++)
+ for (j=0; j<NUM_LEVEL_ELEMENTS; j++)
+ element_action_sound[j][i] = -1;
+
+ for (i=0; i<NUM_SOUND_FILES; i++)
+ {
+ int len_effect_text = strlen(sound_files[i].token);
+
+ sound_effect_properties[i] = SND_ACTION_UNKNOWN;
+ is_loop_sound[i] = FALSE;
+
+ /* determine all loop sounds and identify certain sound classes */
+
+ for (j=0; sound_action_properties[j].text; j++)
+ {
+ int len_action_text = strlen(sound_action_properties[j].text);
+
+ if (len_action_text < len_effect_text &&
+ strcmp(&sound_files[i].token[len_effect_text - len_action_text],
+ sound_action_properties[j].text) == 0)
+ {
+ sound_effect_properties[i] = sound_action_properties[j].value;
+
+ if (sound_action_properties[j].is_loop)
+ is_loop_sound[i] = TRUE;
+ }
+ }
+
+ /* associate elements and some selected sound actions */
+
+ for (j=0; j<NUM_LEVEL_ELEMENTS; j++)
+ {
+ if (element_info[j].sound_class_name)
+ {
+ int len_class_text = strlen(element_info[j].sound_class_name);
+
+ if (len_class_text + 1 < len_effect_text &&
+ strncmp(sound_files[i].token,
+ element_info[j].sound_class_name, len_class_text) == 0 &&
+ sound_files[i].token[len_class_text] == '.')
+ {
+ int sound_action_value = sound_effect_properties[i];
+
+ element_action_sound[j][sound_action_value] = i;
+ }
+ }
+ }
+ }
+
+#if 0
+ debug_print_timestamp(0, "InitGameEngine");
+#endif
+
+#if 0
+ /* TEST ONLY */
+ {
+ int element = EL_ERDREICH;
+ int sound_action = SND_ACTION_DIGGING;
+ int j = 0;
+
+ while (sound_action_properties[j].text)
+ {
+ if (sound_action_properties[j].value == sound_action)
+ printf("element %d, sound action '%s' == %d\n",
+ element, sound_action_properties[j].text,
+ element_action_sound[element][sound_action]);
+ j++;
+ }
+ }
+#endif
+}
+
+
+/*
+ =============================================================================
+ InitGameEngine()
+ -----------------------------------------------------------------------------
+ initialize game engine due to level / tape version number
+ =============================================================================
+*/
+
+static void InitGameEngine()
+{
+ int i;
+
+ game.engine_version = (tape.playing ? tape.engine_version :
+ level.game_version);
+
+#if 0
+ printf("level %d: level version == %06d\n", level_nr, level.game_version);
+ printf(" tape version == %06d [%s] [file: %06d]\n",
+ tape.engine_version, (tape.playing ? "PLAYING" : "RECORDING"),
+ tape.file_version);
+ printf(" => game.engine_version == %06d\n", game.engine_version);
+#endif
+
+ /* dynamically adjust player properties according to game engine version */
+ game.initial_move_delay =
+ (game.engine_version <= VERSION_IDENT(2,0,1) ? INITIAL_MOVE_DELAY_ON :
+ INITIAL_MOVE_DELAY_OFF);
+
+ /* dynamically adjust player properties according to level information */
+ game.initial_move_delay_value =
+ (level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED);
+
+ /* dynamically adjust element properties according to game engine version */
+ {
+ static int ep_em_slippery_wall[] =
+ {
+ EL_BETON,
+ EL_MAUERWERK,
+ EL_MAUER_LEBT,
+ EL_MAUER_X,
+ EL_MAUER_Y,
+ EL_MAUER_XY
+ };
+ static int ep_em_slippery_wall_num = SIZEOF_ARRAY_INT(ep_em_slippery_wall);
+
+ for (i=0; i<ep_em_slippery_wall_num; i++)
+ {
+ if (level.em_slippery_gems) /* special EM style gems behaviour */
+ Elementeigenschaften2[ep_em_slippery_wall[i]] |=
+ EP_BIT_EM_SLIPPERY_WALL;
+ else
+ Elementeigenschaften2[ep_em_slippery_wall[i]] &=
+ ~EP_BIT_EM_SLIPPERY_WALL;
+ }
+
+ /* "EL_MAUERND" was not slippery for EM gems in version 2.0.1 */
+ if (level.em_slippery_gems && game.engine_version > VERSION_IDENT(2,0,1))
+ Elementeigenschaften2[EL_MAUERND] |= EP_BIT_EM_SLIPPERY_WALL;
+ else
+ Elementeigenschaften2[EL_MAUERND] &= ~EP_BIT_EM_SLIPPERY_WALL;
+ }
+}
+
+
+/*
+ =============================================================================
+ InitGame()
+ -----------------------------------------------------------------------------
+ initialize and start new game
+ =============================================================================
+*/
+
void InitGame()
{
- int i, j, x, y;
boolean emulate_bd = TRUE; /* unless non-BOULDERDASH elements found */
boolean emulate_sb = TRUE; /* unless non-SOKOBAN elements found */
boolean emulate_sp = TRUE; /* unless non-SUPAPLEX elements found */
+ int i, j, x, y;
+
+ InitGameEngine();
#if DEBUG
#if USE_NEW_AMOEBA_CODE
player->last_move_dir = MV_NO_MOVING;
player->is_moving = FALSE;
- player->move_delay = -1; /* no initial move delay */
- player->move_delay_value =
- (level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED);
+ player->move_delay = game.initial_move_delay;
+ player->move_delay_value = game.initial_move_delay_value;
player->push_delay = 0;
player->push_delay_value = 5;
}
}
+ game.emulation = (emulate_bd ? EMU_BOULDERDASH :
+ emulate_sb ? EMU_SOKOBAN :
+ emulate_sp ? EMU_SUPAPLEX : EMU_NONE);
+
/* correct non-moving belts to start moving left */
for (i=0; i<4; i++)
if (game.belt_dir[i] == MV_NO_MOVING)
}
}
- /* initialize sound effect properties */
- if (!is_loop_sound_initialized)
- {
- int i;
-
- for (i=0; i<NUM_SOUND_EFFECTS; i++)
- is_loop_sound[i] = FALSE;
-
- for (i=0; i<SIZEOF_ARRAY_INT(loop_sounds); i++)
- is_loop_sound[loop_sounds[i]] = TRUE;
-
- is_loop_sound_initialized = TRUE;
- }
-
- game.version = (tape.playing ? tape.game_version : level.game_version);
- game.emulation = (emulate_bd ? EMU_BOULDERDASH :
- emulate_sb ? EMU_SOKOBAN :
- emulate_sp ? EMU_SUPAPLEX : EMU_NONE);
-
- /* dynamically adjust element properties according to game engine version */
- {
- static int ep_em_slippery_wall[] =
- {
- EL_BETON,
- EL_MAUERWERK,
- EL_MAUER_LEBT,
- EL_MAUER_X,
- EL_MAUER_Y,
- EL_MAUER_XY
- };
-#if 1
- static int ep_em_slippery_wall_num = SIZEOF_ARRAY_INT(ep_em_slippery_wall);
-#else
- static int ep_em_slippery_wall_num =
- sizeof(ep_em_slippery_wall) / sizeof(int);
-#endif
-
- /*
- printf("level %d: game.version == %06d\n", level_nr, level.game_version);
- printf(" file_version == %06d\n", level.file_version);
- */
-
- for (i=0; i<ep_em_slippery_wall_num; i++)
- {
-#if 1
- if (level.em_slippery_gems) /* special EM style gems behaviour */
-#else
- if (game.version >= GAME_VERSION_2_0)
-#endif
- Elementeigenschaften2[ep_em_slippery_wall[i]] |=
- EP_BIT_EM_SLIPPERY_WALL;
- else
- Elementeigenschaften2[ep_em_slippery_wall[i]] &=
- ~EP_BIT_EM_SLIPPERY_WALL;
- }
- }
-
if (BorderElement == EL_LEERRAUM)
{
SBX_Left = 0;
OpenDoor(DOOR_OPEN_ALL);
- PlaySoundStereo(SND_GAME_STARTING, PSND_MAX_RIGHT);
+ PlaySoundStereo(SND_GAME_STARTING, SOUND_MAX_RIGHT);
if (setup.sound_music)
PlayMusic(level_nr);
local_player->LevelSolved = FALSE;
- PlaySoundStereo(SND_GAME_WINNING, PSND_MAX_RIGHT);
+ PlaySoundStereo(SND_GAME_WINNING, SOUND_MAX_RIGHT);
if (TimeLeft)
{
if (!tape.playing && setup.sound_loops)
- PlaySoundExt(SND_GAME_LEVELTIME_BONUS, PSND_MAX_VOLUME, PSND_MAX_RIGHT,
+ PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MAX_RIGHT,
SND_CTRL_PLAY_LOOP);
while (TimeLeft > 0)
{
if (!tape.playing && !setup.sound_loops)
- PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, PSND_MAX_RIGHT);
+ PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_RIGHT);
if (TimeLeft > 0 && !(TimeLeft % 10))
RaiseScore(level.score[SC_ZEITBONUS]);
if (TimeLeft > 100 && !(TimeLeft % 10))
else if (level.time == 0) /* level without time limit */
{
if (!tape.playing && setup.sound_loops)
- PlaySoundExt(SND_GAME_LEVELTIME_BONUS, PSND_MAX_VOLUME, PSND_MAX_RIGHT,
+ PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MAX_RIGHT,
SND_CTRL_PLAY_LOOP);
while (TimePlayed < 999)
{
if (!tape.playing && !setup.sound_loops)
- PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, PSND_MAX_RIGHT);
+ PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_RIGHT);
if (TimePlayed < 999 && !(TimePlayed % 10))
RaiseScore(level.score[SC_ZEITBONUS]);
if (TimePlayed < 900 && !(TimePlayed % 10))
MovDelay[x][y]--;
if (MovDelay[x][y])
{
- if (!(MovDelay[x][y] % 12))
- {
- if (Feld[x][y] == EL_DYNAMITE_ACTIVE)
- PlaySoundLevel(x, y, SND_DYNAMITE_BURNING);
- else
- PlaySoundLevel(x, y, SND_DYNABOMB_BURNING);
- }
+ if (!(MovDelay[x][y] % 6))
+ PlaySoundLevelAction(x, y, SND_ACTION_BURNING);
if (IS_ACTIVE_BOMB(Feld[x][y]))
{
/* play sound of object that hits the ground */
if (lastline || object_hit)
- {
- int sound;
-
- switch (element)
- {
- case EL_EDELSTEIN_BD:
- sound = SND_BD_DIAMOND_IMPACT;
- break;
- case EL_EDELSTEIN:
- case EL_EDELSTEIN_GELB:
- case EL_EDELSTEIN_ROT:
- case EL_EDELSTEIN_LILA:
- sound = SND_EMERALD_IMPACT;
- break;
- case EL_DIAMANT:
- sound = SND_DIAMOND_IMPACT;
- break;
- case EL_PEARL:
- sound = SND_PEARL_IMPACT;
- break;
- case EL_CRYSTAL:
- sound = SND_CRYSTAL_IMPACT;
- break;
- case EL_SP_INFOTRON:
- sound = SND_SP_INFOTRON_IMPACT;
- break;
- case EL_KOKOSNUSS:
- sound = SND_NUT_IMPACT;
- break;
- case EL_BD_ROCK:
- sound = SND_BD_ROCK_IMPACT;
- break;
- case EL_FELSBROCKEN:
- sound = SND_ROCK_IMPACT;
- break;
- case EL_SP_ZONK:
- sound = SND_SP_ZONK_IMPACT;
- break;
- case EL_ZEIT_VOLL:
- sound = SND_TIME_ORB_FULL_IMPACT;
- break;
- case EL_ZEIT_LEER:
- sound = SND_TIME_ORB_EMPTY_IMPACT;
- break;
- case EL_SPRING:
- sound = SND_SPRING_IMPACT;
- break;
- default:
- sound = -1;
- break;
- }
-
- if (sound >= 0)
- PlaySoundLevel(x, y, sound);
- }
+ PlaySoundLevelElementAction(x, y, element, SND_ACTION_IMPACT);
}
void TurnRound(int x, int y)
if (element!=EL_MAMPFER && element!=EL_MAMPFER2 && element!=EL_PACMAN)
{
TurnRound(x, y);
+
if (MovDelay[x][y] && (element == EL_KAEFER ||
element == EL_FLIEGER ||
element == EL_SP_SNIKSNAK ||
}
}
- if (MovDelay[x][y])
+ if (MovDelay[x][y]) /* element still has to wait some time */
+ {
+ PlaySoundLevelAction(x, y, SND_ACTION_WAITING);
+
return;
+ }
}
- if (element == EL_KAEFER)
- PlaySoundLevel(x, y, SND_BUG_MOVING);
- else if (element == EL_FLIEGER)
- PlaySoundLevel(x, y, SND_SPACESHIP_MOVING);
- else if (element == EL_BUTTERFLY)
- PlaySoundLevel(x, y, SND_BD_BUTTERFLY_MOVING);
- else if (element == EL_FIREFLY)
- PlaySoundLevel(x, y, SND_BD_FIREFLY_MOVING);
- else if (element == EL_SP_SNIKSNAK)
- PlaySoundLevel(x, y, SND_SP_SNIKSNAK_MOVING);
- else if (element == EL_SP_ELECTRON)
- PlaySoundLevel(x, y, SND_SP_ELECTRON_MOVING);
- else if (element == EL_MAMPFER)
- PlaySoundLevel(x, y, SND_YAMYAM_MOVING);
- else if (element == EL_MAMPFER2)
- PlaySoundLevel(x, y, SND_DARK_YAMYAM_MOVING);
- else if (element == EL_BALLOON)
- PlaySoundLevel(x, y, SND_BALLOON_MOVING);
- else if (element == EL_SPRING_MOVING)
- PlaySoundLevel(x, y, SND_SPRING_MOVING);
- else if (element == EL_MOLE)
- PlaySoundLevel(x, y, SND_MOLE_MOVING);
- else if (element == EL_SONDE)
- PlaySoundLevel(x, y, SND_SATELLITE_MOVING);
- else if (element == EL_PACMAN)
- PlaySoundLevel(x, y, SND_PACMAN_MOVING);
- else if (element == EL_PINGUIN)
- PlaySoundLevel(x, y, SND_PENGUIN_MOVING);
- else if (element == EL_SCHWEIN)
- PlaySoundLevel(x, y, SND_PIG_MOVING);
- else if (element == EL_DRACHE)
- PlaySoundLevel(x, y, SND_DRAGON_MOVING);
-
/* now make next step */
Moving2Blocked(x, y, &newx, &newy); /* get next screen position */
else
DrawLevelField(x, y);
- PlaySoundLevel(x, y, SND_DRAGON_BREATHING_FIRE);
+ PlaySoundLevel(x, y, SND_DRAGON_ATTACKING);
MovDelay[x][y] = 50;
Feld[newx][newy] = EL_BURNING;
if (DONT_TOUCH(element))
TestIfBadThingTouchesHero(x, y);
+ PlaySoundLevelAction(x, y, SND_ACTION_WAITING);
+
return;
}
- if (element == EL_ROBOT && IN_SCR_FIELD(x, y))
- PlaySoundLevel(x, y, SND_ROBOT_MOVING);
-
InitMovingField(x, y, MovDir[x][y]);
+
+ PlaySoundLevelAction(x, y, SND_ACTION_MOVING);
}
if (MovDir[x][y])
MovPos[x][y] += step;
- if (ABS(MovPos[x][y])>=TILEX) /* object reached its destination */
+ if (ABS(MovPos[x][y]) >= TILEX) /* object reached its destination */
{
Feld[x][y] = EL_LEERRAUM;
Feld[newx][newy] = element;
if (DelayReached(&sound_delay, sound_delay_value))
{
if (Store[x][y] == EL_AMOEBE_BD)
- PlaySoundLevel(x, y, SND_BD_AMOEBA_GROWING);
+ PlaySoundLevel(x, y, SND_BD_AMOEBA_CREATING);
else
- PlaySoundLevel(x, y, SND_AMOEBA_GROWING);
+ PlaySoundLevel(x, y, SND_AMOEBA_CREATING);
sound_delay_value = 30;
}
}
}
if (changed)
- PlaySoundLevel(ax, ay, element == EL_LIFE ? SND_GAMEOFLIFE_GROWING :
- SND_BIOMAZE_GROWING);
+ PlaySoundLevel(ax, ay, element == EL_LIFE ? SND_GAMEOFLIFE_CREATING :
+ SND_BIOMAZE_CREATING);
}
void RobotWheel(int x, int y)
DrawGraphic(SCREENX(ax-1), SCREENY(ay), GFX_MAUER_LEFT);
new_wall = TRUE;
}
+
if (rechts_frei)
{
Feld[ax+1][ay] = EL_MAUERND;
else if (element == EL_SHIELD_PASSIVE)
{
DrawGraphicAnimation(x, y, GFX_SHIELD_PASSIVE, 6, 4, ANIM_NORMAL);
+#if 0
if (!(FrameCounter % 4))
PlaySoundLevel(x, y, SND_SHIELD_PASSIVE_ACTIVATED);
+#endif
}
else if (element == EL_SHIELD_ACTIVE)
{
DrawGraphicAnimation(x, y, GFX_SHIELD_ACTIVE, 6, 4, ANIM_NORMAL);
+#if 0
if (!(FrameCounter % 4))
PlaySoundLevel(x, y, SND_SHIELD_ACTIVE_ACTIVATED);
+#endif
}
if (game.magic_wall_active)
CloseAllOpenTimegates();
}
+ for (i=0; i<MAX_PLAYERS; i++)
+ {
+ struct PlayerInfo *player = &stored_player[i];
+
+ if (SHIELD_ON(player))
+ {
+ if (player->shield_active_time_left)
+ PlaySoundLevel(player->jx, player->jy, SND_SHIELD_ACTIVE_ACTIVATED);
+ else if (player->shield_passive_time_left)
+ PlaySoundLevel(player->jx, player->jy, SND_SHIELD_PASSIVE_ACTIVATED);
+ }
+ }
+
if (TimeFrames >= (1000 / GameFrameDelay))
{
TimeFrames = 0;
for (i=0; i<MAX_PLAYERS; i++)
{
- if (SHIELD_ON(&stored_player[i]))
+ struct PlayerInfo *player = &stored_player[i];
+
+ if (SHIELD_ON(player))
{
- stored_player[i].shield_passive_time_left--;
+ player->shield_passive_time_left--;
- if (stored_player[i].shield_active_time_left > 0)
- stored_player[i].shield_active_time_left--;
+ if (player->shield_active_time_left > 0)
+ player->shield_active_time_left--;
}
}
TimeLeft--;
if (TimeLeft <= 10 && setup.time_limit)
- PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, PSND_MAX_RIGHT);
+ PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MAX_RIGHT);
DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
(Feld[new_jx][new_jy] == EL_SP_BASE ||
Feld[new_jx][new_jy] == EL_ERDREICH));
- if (field_under_player_is_free && !player_is_moving_to_valid_field)
+ if (field_under_player_is_free &&
+ !player_is_moving_to_valid_field &&
+ !IS_TUBE(Feld[jx][jy]))
player->programmed_action = MV_DOWN;
}
}
return FALSE;
#else
if (!FrameReached(&player->move_delay, player->move_delay_value) &&
- !(tape.playing && tape.game_version < GAME_VERSION_2_0))
+ !(tape.playing && tape.file_version < FILE_VERSION_2_0))
return FALSE;
#endif
dy == +1 ? MV_DOWN : MV_NO_MOVING);
int element;
- if (!player->MovPos)
+ if (player->MovPos == 0)
player->Pushing = FALSE;
if (mode == DF_NO_PUSH)
case EL_SP_BASE:
case EL_SP_BUG:
RemoveField(x, y);
-
- if (element == EL_LEERRAUM)
- PlaySoundLevel(x, y, SND_EMPTY_SPACE_DIGGING);
- else if (element == EL_ERDREICH)
- PlaySoundLevel(x, y, SND_SAND_DIGGING);
- else if (element == EL_SAND_INVISIBLE)
- PlaySoundLevel(x, y, SND_SAND_INVISIBLE_DIGGING);
- else if (element == EL_TRAP_INACTIVE)
- PlaySoundLevel(x, y, SND_TRAP_INACTIVE_DIGGING);
- else if (element == EL_SP_BASE)
- PlaySoundLevel(x, y, SND_SP_BASE_DIGGING);
- else if (element == EL_SP_BUG)
- PlaySoundLevel(x, y, SND_SP_BUGGY_BASE_DIGGING);
+ PlaySoundLevelElementAction(x, y, element, SND_ACTION_DIGGING);
break;
case EL_EDELSTEIN:
DrawText(DX_EMERALDS, DY_EMERALDS,
int2str(local_player->gems_still_needed, 3),
FS_SMALL, FC_YELLOW);
-
- if (element == EL_EDELSTEIN_BD)
- PlaySoundLevel(x, y, SND_BD_DIAMOND_COLLECTING);
- else if (element == EL_DIAMANT)
- PlaySoundLevel(x, y, SND_DIAMOND_COLLECTING);
- else if (element == EL_SP_INFOTRON)
- PlaySoundLevel(x, y, SND_SP_INFOTRON_COLLECTING);
- else if (element == EL_PEARL)
- PlaySoundLevel(x, y, SND_PEARL_COLLECTING);
- else if (element == EL_CRYSTAL)
- PlaySoundLevel(x, y, SND_CRYSTAL_COLLECTING);
- else /* EL_EDELSTEIN style element */
- PlaySoundLevel(x, y, SND_EMERALD_COLLECTING);
+ PlaySoundLevelElementAction(x, y, element, SND_ACTION_COLLECTING);
break;
case EL_SPEED_PILL:
TimeLeft += 10;
DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
}
- PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, PSND_MAX_RIGHT);
+ PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, SOUND_MAX_RIGHT);
break;
case EL_SHIELD_PASSIVE:
DrawText(DX_DYNAMITE, DY_DYNAMITE,
int2str(local_player->dynamite, 3),
FS_SMALL, FC_YELLOW);
- if (element == EL_SP_DISK_RED)
- PlaySoundLevel(x, y, SND_SP_DISK_RED_COLLECTING);
- else
- PlaySoundLevel(x, y, SND_DYNAMITE_COLLECTING);
+ PlaySoundLevelElementAction(x, y, element, SND_ACTION_COLLECTING);
break;
case EL_DYNABOMB_NR:
element == EL_BALLOON_SEND_UP ? MV_UP :
element == EL_BALLOON_SEND_DOWN ? MV_DOWN :
MV_NO_MOVING);
+ PlaySoundLevel(x, y, SND_BALLOON_SWITCH_ACTIVATING);
return MF_ACTION;
break;
return MF_NO_ACTION;
player->LevelSolved = player->GameOver = TRUE;
- PlaySoundStereo(SND_SP_EXIT_ENTERING, PSND_MAX_RIGHT);
+ PlaySoundStereo(SND_SP_EXIT_ENTERING, SOUND_MAX_RIGHT);
break;
+ /* the following elements cannot be pushed by "snapping" */
case EL_FELSBROCKEN:
- case EL_BD_ROCK:
case EL_BOMBE:
case EL_DX_SUPABOMB:
case EL_KOKOSNUSS:
case EL_SP_ZONK:
case EL_SP_DISK_ORANGE:
case EL_SPRING:
- if (dy || mode == DF_SNAP)
+ if (mode == DF_SNAP)
+ return MF_NO_ACTION;
+ /* no "break" -- fall through to next case */
+ /* the following elements can be pushed by "snapping" */
+ case EL_BD_ROCK:
+ if (dy)
return MF_NO_ACTION;
player->Pushing = TRUE;
return MF_NO_ACTION;
#else
if (!FrameReached(&player->push_delay, player->push_delay_value) &&
- !(tape.playing && tape.game_version < GAME_VERSION_2_0) &&
+ !(tape.playing && tape.file_version < FILE_VERSION_2_0) &&
element != EL_SPRING)
return MF_NO_ACTION;
#endif
- RemoveField(x, y);
- Feld[x+dx][y+dy] = element;
+ if (mode == DF_SNAP)
+ {
+ InitMovingField(x, y, move_direction);
+ ContinueMoving(x, y);
+ }
+ else
+ {
+ RemoveField(x, y);
+ Feld[x+dx][y+dy] = element;
+ }
if (element == EL_SPRING)
{
player->push_delay_value = (element == EL_SPRING ? 0 : 2 + RND(8));
DrawLevelField(x+dx, y+dy);
- if (element == EL_FELSBROCKEN)
- PlaySoundLevel(x+dx, y+dy, SND_ROCK_PUSHING);
- else if (element == EL_BD_ROCK)
- PlaySoundLevel(x+dx, y+dy, SND_BD_ROCK_PUSHING);
- else if (element == EL_BOMBE)
- PlaySoundLevel(x+dx, y+dy, SND_BOMB_PUSHING);
- else if (element == EL_DX_SUPABOMB)
- PlaySoundLevel(x+dx, y+dy, SND_DX_BOMB_PUSHING);
- else if (element == EL_KOKOSNUSS)
- PlaySoundLevel(x+dx, y+dy, SND_NUT_PUSHING);
- else if (element == EL_ZEIT_LEER)
- PlaySoundLevel(x+dx, y+dy, SND_TIME_ORB_EMPTY_PUSHING);
- else if (element == EL_SP_ZONK)
- PlaySoundLevel(x+dx, y+dy, SND_SP_ZONK_PUSHING);
- else if (element == EL_SP_DISK_ORANGE)
- PlaySoundLevel(x+dx, y+dy, SND_SP_DISK_ORANGE_PUSHING);
- else if (element == EL_SPRING)
- PlaySoundLevel(x+dx, y+dy, SND_SPRING_PUSHING);
+ PlaySoundLevelElementAction(x, y, element, SND_ACTION_PUSHING);
break;
case EL_PFORTE1:
DOUBLE_PLAYER_SPEED(player);
PlaySoundLevel(x, y, SND_GATE_PASSING);
-
break;
case EL_EM_GATE_1X:
DOUBLE_PLAYER_SPEED(player);
PlaySoundLevel(x, y, SND_GATE_PASSING);
-
break;
case EL_SWITCHGATE_OPEN:
player->programmed_action = move_direction;
DOUBLE_PLAYER_SPEED(player);
- if (element == EL_SWITCHGATE_OPEN)
- PlaySoundLevel(x, y, SND_SWITCHGATE_PASSING);
- else
- PlaySoundLevel(x, y, SND_TIMEGATE_PASSING);
-
+ PlaySoundLevelElementAction(x, y, element, SND_ACTION_PASSING);
break;
case EL_SP_PORT1_LEFT:
if (!(tube_enter_directions[i][1] & move_direction))
return MF_NO_ACTION; /* tube has no opening in this direction */
+
+ PlaySoundLevel(x, y, SND_TUBE_PASSING);
}
break;
TimeLeft += 10;
DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
DrawLevelField(x, y);
- PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, PSND_MAX_RIGHT);
+ PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MAX_RIGHT);
return MF_ACTION;
break;
return MF_NO_ACTION;
#else
if (!FrameReached(&player->push_delay, player->push_delay_value) &&
- !(tape.playing && tape.game_version < GAME_VERSION_2_0) &&
+ !(tape.playing && tape.file_version < FILE_VERSION_2_0) &&
element != EL_BALLOON)
return MF_NO_ACTION;
#endif
{
RemoveField(x, y);
Feld[x+dx][y+dy] = element;
+ PlaySoundLevelElementAction(x, y, element, SND_ACTION_PUSHING);
}
player->push_delay_value = (element == EL_BALLOON ? 0 : 2);
DrawLevelField(x, y);
DrawLevelField(x+dx, y+dy);
- if (element == EL_SONDE)
- PlaySoundLevel(x+dx, y+dy, SND_SATELLITE_PUSHING);
- else if (element == EL_SP_DISK_YELLOW)
- PlaySoundLevel(x+dx, y+dy, SND_SP_DISK_YELLOW_PUSHING);
- else if (element == EL_BALLOON)
- PlaySoundLevel(x+dx, y+dy, SND_BALLOON_PUSHING);
if (IS_SB_ELEMENT(element) &&
local_player->sokobanfields_still_needed == 0 &&
if (!dx && !dy)
{
+ if (player->MovPos == 0)
+ player->Pushing = FALSE;
+
player->snapped = FALSE;
return FALSE;
}
void PlaySoundLevel(int x, int y, int nr)
{
+ static int loop_sound_frame[NUM_SOUND_FILES];
+ static int loop_sound_volume[NUM_SOUND_FILES];
int sx = SCREENX(x), sy = SCREENY(y);
int volume, stereo_position;
- int silence_distance = 8;
+ int max_distance = 8;
int type = (IS_LOOP_SOUND(nr) ? SND_CTRL_PLAY_LOOP : SND_CTRL_PLAY_SOUND);
if ((!setup.sound_simple && !IS_LOOP_SOUND(nr)) ||
return;
if (!IN_LEV_FIELD(x, y) ||
- sx < -silence_distance || sx >= SCR_FIELDX + silence_distance ||
- sy < -silence_distance || sy >= SCR_FIELDY + silence_distance)
+ sx < -max_distance || sx >= SCR_FIELDX + max_distance ||
+ sy < -max_distance || sy >= SCR_FIELDY + max_distance)
return;
- volume = PSND_MAX_VOLUME;
-
-#if !defined(PLATFORM_MSDOS)
- stereo_position = (sx - SCR_FIELDX / 2) * 12;
-#else
- stereo_position = PSND_MIDDLE + (2 * sx - (SCR_FIELDX - 1)) * 5;
- if (stereo_position > PSND_MAX_RIGHT)
- stereo_position = PSND_MAX_RIGHT;
- if (stereo_position < PSND_MAX_LEFT)
- stereo_position = PSND_MAX_LEFT;
-#endif
+ volume = SOUND_MAX_VOLUME;
if (!IN_SCR_FIELD(sx, sy))
{
- int dx = ABS(sx - SCR_FIELDX/2) - SCR_FIELDX/2;
- int dy = ABS(sy - SCR_FIELDY/2) - SCR_FIELDY/2;
+ int dx = ABS(sx - SCR_FIELDX / 2) - SCR_FIELDX / 2;
+ int dy = ABS(sy - SCR_FIELDY / 2) - SCR_FIELDY / 2;
- volume -= volume * (dx > dy ? dx : dy) / silence_distance;
+ volume -= volume * (dx > dy ? dx : dy) / max_distance;
+ }
+
+ stereo_position = (SOUND_MAX_LEFT +
+ (sx + max_distance) * SOUND_MAX_LEFT2RIGHT /
+ (SCR_FIELDX + 2 * max_distance));
+
+ if (IS_LOOP_SOUND(nr))
+ {
+ /* This assures that quieter loop sounds do not overwrite louder ones,
+ while restarting sound volume comparison with each new game frame. */
+
+ if (loop_sound_volume[nr] > volume && loop_sound_frame[nr] == FrameCounter)
+ return;
+
+ loop_sound_volume[nr] = volume;
+ loop_sound_frame[nr] = FrameCounter;
}
PlaySoundExt(nr, volume, stereo_position, type);
}
+void PlaySoundLevelAction(int x, int y, int sound_action)
+{
+ PlaySoundLevelElementAction(x, y, Feld[x][y], sound_action);
+}
+
+void PlaySoundLevelElementAction(int x, int y, int element, int sound_action)
+{
+ int sound_effect = element_action_sound[element][sound_action];
+
+ if (sound_effect != -1)
+ PlaySoundLevel(x, y, sound_effect);
+}
+
void RaiseScore(int value)
{
local_player->score += value;