/***********************************************************
-* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
*----------------------------------------------------------*
-* (c) 1995-98 Artsoft Entertainment *
-* Holger Schemel *
-* Oststrasse 11a *
-* 33604 Bielefeld *
-* phone: ++49 +521 290471 *
-* email: aeglos@valinor.owl.de *
+* (c) 1995-2001 Artsoft Entertainment *
+* Holger Schemel *
+* Detmolder Strasse 189 *
+* 33604 Bielefeld *
+* Germany *
+* e-mail: info@artsoft.org *
*----------------------------------------------------------*
-* game.c *
+* game.c *
***********************************************************/
#include "libgame/libgame.h"
/* for Explode() */
#define EX_PHASE_START 0
-#define EX_NORMAL 0
-#define EX_CENTER 1
-#define EX_BORDER 2
+#define EX_NO_EXPLOSION 0
+#define EX_NORMAL 1
+#define EX_CENTER 2
+#define EX_BORDER 3
/* special positions in the game control window (relative to control window) */
#define XX_LEVEL 37
game.timegate_time_left = 0;
game.switchgate_pos = 0;
game.balloon_dir = MV_NO_MOVING;
+ game.explosions_delayed = TRUE;
for (i=0; i<4; i++)
{
AmoebaNr[x][y] = 0;
JustStopped[x][y] = 0;
Stop[x][y] = FALSE;
+ ExplodeField[x][y] = EX_NO_EXPLOSION;
}
}
}
}
+ 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_slippery[] =
+ {
+ EL_BETON,
+ EL_MAUERWERK,
+ EL_MAUER_LEBT,
+ EL_MAUER_X,
+ EL_MAUER_Y,
+ EL_MAUER_XY
+ };
+ static int ep_slippery_num = sizeof(ep_slippery)/sizeof(int);
+
+ for (i=0; i<ep_slippery_num; i++)
+ {
+ if (game.version >= GAME_VERSION_2_0)
+ Elementeigenschaften2[ep_slippery[i]] |= EP_BIT_SLIPPERY_GEMS;
+ else
+ Elementeigenschaften2[ep_slippery[i]] &= ~EP_BIT_SLIPPERY_GEMS;
+ }
+ }
+
if (BorderElement == EL_LEERRAUM)
{
SBX_Left = 0;
OpenDoor(DOOR_OPEN_ALL);
- if (setup.sound_music)
- PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
+ if (setup.sound_music && num_bg_loops)
+ PlayMusic(level_nr % num_bg_loops);
KeyboardAutoRepeatOff();
StopSound(SND_SIRR);
}
+#if 0
FadeSounds();
+#endif
/* Hero disappears */
DrawLevelField(ExitX, ExitY);
{
leveldir_current->handicap_level++;
SaveLevelSetup_SeriesInfo();
-
- if (level_nr < leveldir_current->last_level)
- raise_level = TRUE;
}
+ if (level_editor_test_game)
+ local_player->score = -1; /* no highscore when playing from editor */
+ else if (level_nr < leveldir_current->last_level)
+ raise_level = TRUE; /* advance to next level */
+
if ((hi_pos = NewHiScore()) >= 0)
{
game_status = HALLOFFAME;
}
if (Feld[x][y] == EL_BLOCKED &&
- (Store[oldx][oldy] == EL_MORAST_LEER ||
- Store[oldx][oldy] == EL_MAGIC_WALL_EMPTY ||
- Store[oldx][oldy] == EL_MAGIC_WALL_BD_EMPTY ||
- Store[oldx][oldy] == EL_AMOEBE_NASS))
- {
- Feld[oldx][oldy] = Store[oldx][oldy];
- Store[oldx][oldy] = Store2[oldx][oldy] = 0;
- }
+ (Feld[oldx][oldy] == EL_QUICKSAND_EMPTYING ||
+ Feld[oldx][oldy] == EL_MAGIC_WALL_EMPTYING ||
+ Feld[oldx][oldy] == EL_MAGIC_WALL_BD_EMPTYING ||
+ Feld[oldx][oldy] == EL_AMOEBA_DRIPPING))
+ Feld[oldx][oldy] = get_next_element(Feld[oldx][oldy]);
else
Feld[oldx][oldy] = EL_LEERRAUM;
+ Store[oldx][oldy] = Store2[oldx][oldy] = 0;
+
Feld[newx][newy] = EL_LEERRAUM;
MovPos[oldx][oldy] = MovDir[oldx][oldy] = MovDelay[oldx][oldy] = 0;
MovPos[newx][newy] = MovDir[newx][newy] = MovDelay[newx][newy] = 0;
void Explode(int ex, int ey, int phase, int mode)
{
int x, y;
- int num_phase = 9, delay = 2;
+ int num_phase = 9, delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
int last_phase = num_phase * delay;
int half_phase = (num_phase / 2) * delay;
int first_phase_after_start = EX_PHASE_START + 1;
+ if (game.explosions_delayed)
+ {
+ ExplodeField[ex][ey] = mode;
+ return;
+ }
+
if (phase == EX_PHASE_START) /* initialize 'Store[][]' field */
{
int center_element = Feld[ex][ey];
return;
}
}
+ else if ((element == EL_SP_INFOTRON || element == EL_SP_ZONK) &&
+ (smashed == EL_SP_SNIKSNAK || smashed == EL_SP_ELECTRON ||
+ smashed == EL_SP_DISK_ORANGE))
+ {
+ Bang(x, y+1);
+ return;
+ }
else if (element == EL_FELSBROCKEN ||
element == EL_SP_ZONK ||
element == EL_BD_ROCK)
if (IS_FREE(x, y+1))
{
InitMovingField(x, y, MV_DOWN);
- Feld[x][y] = EL_FELSBROCKEN;
- Store[x][y] = EL_MORAST_LEER;
+ Feld[x][y] = EL_QUICKSAND_EMPTYING;
+ Store[x][y] = EL_FELSBROCKEN;
}
else if (Feld[x][y+1] == EL_MORAST_LEER)
{
Feld[x][y] = EL_MORAST_LEER;
Feld[x][y+1] = EL_MORAST_VOLL;
+ Store[x][y+1] = Store[x][y];
+ Store[x][y] = 0;
}
}
else if ((element == EL_FELSBROCKEN || element == EL_BD_ROCK) &&
Feld[x][y+1] == EL_MORAST_LEER)
{
InitMovingField(x, y, MV_DOWN);
- Store[x][y] = EL_MORAST_VOLL;
+ Feld[x][y] = EL_QUICKSAND_FILLING;
+ Store[x][y] = element;
}
else if (element == EL_MAGIC_WALL_FULL)
{
if (IS_FREE(x, y+1))
{
InitMovingField(x, y, MV_DOWN);
- Feld[x][y] = EL_CHANGED(Store2[x][y]);
- Store[x][y] = EL_MAGIC_WALL_EMPTY;
+ Feld[x][y] = EL_MAGIC_WALL_EMPTYING;
+ Store[x][y] = EL_CHANGED(Store[x][y]);
}
else if (Feld[x][y+1] == EL_MAGIC_WALL_EMPTY)
{
Feld[x][y] = EL_MAGIC_WALL_EMPTY;
Feld[x][y+1] = EL_MAGIC_WALL_FULL;
- Store2[x][y+1] = EL_CHANGED(Store2[x][y]);
- Store2[x][y] = 0;
+ Store[x][y+1] = EL_CHANGED(Store[x][y]);
+ Store[x][y] = 0;
}
}
else if (element == EL_MAGIC_WALL_BD_FULL)
if (IS_FREE(x, y+1))
{
InitMovingField(x, y, MV_DOWN);
- Feld[x][y] = EL_CHANGED2(Store2[x][y]);
- Store[x][y] = EL_MAGIC_WALL_BD_EMPTY;
+ Feld[x][y] = EL_MAGIC_WALL_BD_EMPTYING;
+ Store[x][y] = EL_CHANGED2(Store[x][y]);
}
else if (Feld[x][y+1] == EL_MAGIC_WALL_BD_EMPTY)
{
Feld[x][y] = EL_MAGIC_WALL_BD_EMPTY;
Feld[x][y+1] = EL_MAGIC_WALL_BD_FULL;
- Store2[x][y+1] = EL_CHANGED2(Store2[x][y]);
- Store2[x][y] = 0;
+ Store[x][y+1] = EL_CHANGED2(Store[x][y]);
+ Store[x][y] = 0;
}
}
else if (CAN_CHANGE(element) &&
Feld[x][y+1] == EL_MAGIC_WALL_BD_EMPTY))
{
InitMovingField(x, y, MV_DOWN);
- Store[x][y] =
- (Feld[x][y+1] == EL_MAGIC_WALL_EMPTY ? EL_MAGIC_WALL_FULL :
- EL_MAGIC_WALL_BD_FULL);
- Store2[x][y+1] = element;
+ Feld[x][y] =
+ (Feld[x][y+1] == EL_MAGIC_WALL_EMPTY ? EL_MAGIC_WALL_FILLING :
+ EL_MAGIC_WALL_BD_FILLING);
+ Store[x][y] = element;
}
else if (CAN_SMASH(element) && Feld[x][y+1] == EL_SALZSAEURE)
{
Feld[x][y] = EL_AMOEBING;
Store[x][y] = EL_AMOEBE_NASS;
}
+ /* Store[x][y+1] must be zero, because:
+ (EL_MORAST_VOLL -> EL_FELSBROCKEN): Store[x][y+1] == EL_MORAST_LEER
+ */
+#if 0
#if OLD_GAME_BEHAVIOUR
else if (IS_SLIPPERY(Feld[x][y+1]) && !Store[x][y+1])
#else
else if (IS_SLIPPERY(Feld[x][y+1]) && !Store[x][y+1] &&
!IS_FALLING(x, y+1) && !JustStopped[x][y+1] &&
element != EL_DX_SUPABOMB)
+#endif
+#else
+ else if ((IS_SLIPPERY(Feld[x][y+1]) ||
+ (IS_SLIPPERY_GEMS(Feld[x][y+1]) && IS_GEM(element))) &&
+ !IS_FALLING(x, y+1) && !JustStopped[x][y+1] &&
+ element != EL_DX_SUPABOMB && element != EL_SP_DISK_ORANGE)
#endif
{
boolean left = (x>0 && IS_FREE(x-1, y) &&
int newx = x + dx, newy = y + dy;
int step = (horiz_move ? dx : dy) * TILEX / 8;
- if (element == EL_TROPFEN)
+ if (element == EL_TROPFEN || element == EL_AMOEBA_DRIPPING)
step /= 2;
- else if (Store[x][y] == EL_MORAST_VOLL || Store[x][y] == EL_MORAST_LEER)
+ else if (element == EL_QUICKSAND_FILLING ||
+ element == EL_QUICKSAND_EMPTYING)
step /= 4;
+ else if (element == EL_MAGIC_WALL_FILLING ||
+ element == EL_MAGIC_WALL_BD_FILLING ||
+ element == EL_MAGIC_WALL_EMPTYING ||
+ element == EL_MAGIC_WALL_BD_EMPTYING)
+ step /= 2;
else if (CAN_FALL(element) && horiz_move &&
y < lev_fieldy-1 && IS_BELT(Feld[x][y+1]))
step /= 2;
}
}
- if (Store[x][y] == EL_MORAST_VOLL)
+ if (element == EL_QUICKSAND_FILLING)
{
- Store[x][y] = 0;
- Feld[newx][newy] = EL_MORAST_VOLL;
- element = EL_MORAST_VOLL;
+ element = Feld[newx][newy] = get_next_element(element);
+ Store[newx][newy] = Store[x][y];
}
- else if (Store[x][y] == EL_MORAST_LEER)
+ else if (element == EL_QUICKSAND_EMPTYING)
{
- Store[x][y] = 0;
- Feld[x][y] = EL_MORAST_LEER;
+ Feld[x][y] = get_next_element(element);
+ element = Feld[newx][newy] = Store[x][y];
}
- else if (Store[x][y] == EL_MAGIC_WALL_FULL)
+ else if (element == EL_MAGIC_WALL_FILLING)
{
- Store[x][y] = 0;
- element = Feld[newx][newy] =
- (game.magic_wall_active ? EL_MAGIC_WALL_FULL : EL_MAGIC_WALL_DEAD);
+ element = Feld[newx][newy] = get_next_element(element);
+ if (!game.magic_wall_active)
+ element = Feld[newx][newy] = EL_MAGIC_WALL_DEAD;
+ Store[newx][newy] = Store[x][y];
}
- else if (Store[x][y] == EL_MAGIC_WALL_EMPTY)
+ else if (element == EL_MAGIC_WALL_EMPTYING)
{
- Store[x][y] = Store2[x][y] = 0;
- Feld[x][y] = (game.magic_wall_active ? EL_MAGIC_WALL_EMPTY :
- EL_MAGIC_WALL_DEAD);
+ Feld[x][y] = get_next_element(element);
+ if (!game.magic_wall_active)
+ Feld[x][y] = EL_MAGIC_WALL_DEAD;
+ element = Feld[newx][newy] = Store[x][y];
}
- else if (Store[x][y] == EL_MAGIC_WALL_BD_FULL)
+ else if (element == EL_MAGIC_WALL_BD_FILLING)
{
- Store[x][y] = 0;
- element = Feld[newx][newy] =
- (game.magic_wall_active ? EL_MAGIC_WALL_BD_FULL :
- EL_MAGIC_WALL_BD_DEAD);
+ element = Feld[newx][newy] = get_next_element(element);
+ if (!game.magic_wall_active)
+ element = Feld[newx][newy] = EL_MAGIC_WALL_BD_DEAD;
+ Store[newx][newy] = Store[x][y];
}
- else if (Store[x][y] == EL_MAGIC_WALL_BD_EMPTY)
+ else if (element == EL_MAGIC_WALL_BD_EMPTYING)
{
- Store[x][y] = Store2[x][y] = 0;
- Feld[x][y] = (game.magic_wall_active ? EL_MAGIC_WALL_BD_EMPTY :
- EL_MAGIC_WALL_BD_DEAD);
+ Feld[x][y] = get_next_element(element);
+ if (!game.magic_wall_active)
+ Feld[x][y] = EL_MAGIC_WALL_BD_DEAD;
+ element = Feld[newx][newy] = Store[x][y];
}
- else if (Store[x][y] == EL_SALZSAEURE)
+ else if (element == EL_AMOEBA_DRIPPING)
{
- Store[x][y] = 0;
- Feld[newx][newy] = EL_SALZSAEURE;
- element = EL_SALZSAEURE;
+ Feld[x][y] = get_next_element(element);
+ element = Feld[newx][newy] = Store[x][y];
}
- else if (Store[x][y] == EL_AMOEBE_NASS)
+ else if (Store[x][y] == EL_SALZSAEURE)
{
- Store[x][y] = 0;
- Feld[x][y] = EL_AMOEBE_NASS;
+ element = Feld[newx][newy] = EL_SALZSAEURE;
}
+ Store[x][y] = 0;
MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
MovDelay[newx][newy] = 0;
if (element != EL_AMOEBE_NASS || neway < ay || !IS_FREE(newax, neway) ||
(neway == lev_fieldy - 1 && newax != ax))
{
- Feld[newax][neway] = EL_AMOEBING;
+ Feld[newax][neway] = EL_AMOEBING; /* simple growth of new amoeba tile */
Store[newax][neway] = element;
}
else if (neway == ay)
- Feld[newax][neway] = EL_TROPFEN;
+ Feld[newax][neway] = EL_TROPFEN; /* drop left or right from amoeba */
else
{
- InitMovingField(ax, ay, MV_DOWN);
- Feld[ax][ay] = EL_TROPFEN;
- Store[ax][ay] = EL_AMOEBE_NASS;
+ InitMovingField(ax, ay, MV_DOWN); /* drop dripping out of amoeba */
+ Feld[ax][ay] = EL_AMOEBA_DRIPPING;
+ Store[ax][ay] = EL_TROPFEN;
ContinueMoving(ax, ay);
return;
}
{
StartMoving(x, y);
- if (IS_GEM(element))
+ if (IS_GEM(element) || element == EL_SP_INFOTRON)
EdelsteinFunkeln(x, y);
}
else if (IS_MOVING(x, y))
ContinueMoving(x, y);
else if (IS_ACTIVE_BOMB(element))
CheckDynamite(x, y);
- else if (element == EL_EXPLODING)
+#if 0
+ else if (element == EL_EXPLODING && !game.explosions_delayed)
Explode(x, y, Frame[x][y], EX_NORMAL);
+#endif
else if (element == EL_AMOEBING)
AmoebeWaechst(x, y);
else if (element == EL_DEAMOEBING)
AmoebeSchrumpft(x, y);
+#if 1
else if (IS_AMOEBALIVE(element))
AmoebeAbleger(x, y);
+#endif
else if (element == EL_LIFE || element == EL_LIFE_ASYNC)
Life(x, y);
else if (element == EL_ABLENK_EIN)
boolean sieb = FALSE;
int jx = local_player->jx, jy = local_player->jy;
- if (element == EL_MAGIC_WALL_EMPTY || element == EL_MAGIC_WALL_FULL ||
- Store[x][y] == EL_MAGIC_WALL_EMPTY)
+ if (element == EL_MAGIC_WALL_FULL ||
+ element == EL_MAGIC_WALL_EMPTY ||
+ element == EL_MAGIC_WALL_EMPTYING)
{
SiebAktivieren(x, y, 1);
sieb = TRUE;
}
- else if (element == EL_MAGIC_WALL_BD_EMPTY ||
- element == EL_MAGIC_WALL_BD_FULL ||
- Store[x][y] == EL_MAGIC_WALL_BD_EMPTY)
+ else if (element == EL_MAGIC_WALL_BD_FULL ||
+ element == EL_MAGIC_WALL_BD_EMPTY ||
+ element == EL_MAGIC_WALL_BD_EMPTYING)
{
SiebAktivieren(x, y, 2);
sieb = TRUE;
}
}
+#if 0
+ /* new experimental amoeba growth stuff*/
+#if 1
+ if (!(FrameCounter % 8))
+#endif
+ {
+ static unsigned long random = 1684108901;
+
+ for (i = 0; i < level.amoeba_speed * 4; i++)
+ {
+#if 1
+ x = (random >> 10) % lev_fieldx;
+ y = (random >> 20) % lev_fieldy;
+#else
+ x = RND(lev_fieldx);
+ y = RND(lev_fieldy);
+#endif
+ element = Feld[x][y];
+
+ if (!IS_PLAYER(x,y) &&
+ (element == EL_LEERRAUM ||
+ element == EL_ERDREICH ||
+ element == EL_MORAST_LEER ||
+ element == EL_BLURB_LEFT ||
+ element == EL_BLURB_RIGHT))
+ {
+ if ((IN_LEV_FIELD(x, y-1) && Feld[x][y-1] == EL_AMOEBE_NASS) ||
+ (IN_LEV_FIELD(x-1, y) && Feld[x-1][y] == EL_AMOEBE_NASS) ||
+ (IN_LEV_FIELD(x+1, y) && Feld[x+1][y] == EL_AMOEBE_NASS) ||
+ (IN_LEV_FIELD(x, y+1) && Feld[x][y+1] == EL_AMOEBE_NASS))
+ Feld[x][y] = EL_TROPFEN;
+ }
+
+ random = random * 129 + 1;
+ }
+ }
+#endif
+
+#if 0
+ if (game.explosions_delayed)
+#endif
+ {
+ game.explosions_delayed = FALSE;
+
+ for (y=0; y<lev_fieldy; y++) for (x=0; x<lev_fieldx; x++)
+ {
+ element = Feld[x][y];
+
+ if (ExplodeField[x][y])
+ Explode(x, y, EX_PHASE_START, ExplodeField[x][y]);
+ else if (element == EL_EXPLODING)
+ Explode(x, y, Frame[x][y], EX_NORMAL);
+
+ ExplodeField[x][y] = EX_NO_EXPLOSION;
+ }
+
+ game.explosions_delayed = TRUE;
+ }
+
if (game.magic_wall_active)
{
if (!(game.magic_wall_time_left % 4))
{
element = Feld[x][y];
- if (element == EL_MAGIC_WALL_EMPTY || element == EL_MAGIC_WALL_FULL)
+ if (element == EL_MAGIC_WALL_EMPTY ||
+ element == EL_MAGIC_WALL_FULL)
{
Feld[x][y] = EL_MAGIC_WALL_DEAD;
DrawLevelField(x, y);
for (i=0; i<NUM_GAME_BUTTONS; i++)
{
- Bitmap gd_bitmap = pix[PIX_DOOR];
+ Bitmap *gd_bitmap = pix[PIX_DOOR];
struct GadgetInfo *gi;
int button_type;
boolean checked;
if (setup.sound_music)
{
setup.sound_music = FALSE;
- FadeSound(background_loop[level_nr % num_bg_loops]);
+ FadeMusic();
}
else if (audio.loops_available)
{
setup.sound = setup.sound_music = TRUE;
- PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
+ if (num_bg_loops)
+ PlayMusic(level_nr % num_bg_loops);
}
break;