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 (CAN_MOVE(element) || COULD_MOVE(element))
InitMovDir(x, y);
DrawLevelField(x, y);
+
+ if (IS_PLAYER(x, y) && !PLAYERINFO(x,y)->present)
+ StorePlayer[x][y] = 0;
}
else if (!(phase % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
{
if (phase == delay)
ErdreichAnbroeckeln(SCREENX(x), SCREENY(y));
- DrawGraphic(SCREENX(x), SCREENY(y), graphic + (phase / delay - 1));
+ graphic += (phase / delay - 1);
+
+ if (IS_PFORTE(Store[x][y]))
+ {
+ DrawLevelElement(x, y, Store[x][y]);
+ DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic);
+ }
+ else
+ DrawGraphic(SCREENX(x), SCREENY(y), graphic);
}
}
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 (element == EL_KAEFER || element == EL_BUTTERFLY)
{
- TestIfBadThingHitsOtherBadThing(x, y);
+ TestIfBadThingTouchesOtherBadThing(x, y);
if (IN_LEV_FIELD(right_x, right_y) &&
IS_FREE(right_x, right_y))
else if (element == EL_FLIEGER || element == EL_FIREFLY ||
element == EL_SP_SNIKSNAK || element == EL_SP_ELECTRON)
{
- TestIfBadThingHitsOtherBadThing(x, y);
+ TestIfBadThingTouchesOtherBadThing(x, y);
if (IN_LEV_FIELD(left_x, left_y) &&
IS_FREE(left_x, left_y))
{
#if 1
- TestIfBadThingHitsHero(x, y);
+ TestIfBadThingRunsIntoHero(x, y, MovDir[x][y]);
return;
#else
/* enemy got the player */
DrawGraphicAnimation(x, y, GFX2_SP_ELECTRON, 8, 2, ANIM_NORMAL);
if (DONT_TOUCH(element))
- TestIfBadThingHitsHero(x, y);
+ TestIfBadThingTouchesHero(x, y);
return;
}
if (DONT_TOUCH(element)) /* object may be nasty to player or others */
{
- TestIfBadThingHitsHero(newx, newy);
- TestIfBadThingHitsFriend(newx, newy);
- TestIfBadThingHitsOtherBadThing(newx, newy);
+ TestIfBadThingTouchesHero(newx, newy);
+ TestIfBadThingTouchesFriend(newx, newy);
+ TestIfBadThingTouchesOtherBadThing(newx, newy);
}
else if (element == EL_PINGUIN)
- TestIfFriendHitsBadThing(newx, newy);
+ TestIfFriendTouchesBadThing(newx, newy);
if (CAN_SMASH(element) && direction == MV_DOWN &&
(newy == lev_fieldy-1 || !IS_FREE(x, newy+1)))
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);
+ InitMovingField(ax, ay, MV_DOWN); /* drop dripping out of amoeba */
Feld[ax][ay] = EL_AMOEBA_DRIPPING;
Store[ax][ay] = EL_TROPFEN;
ContinueMoving(ax, ay);
SnapField(player, 0, 0);
CheckGravityMovement(player);
+ if (player->MovPos == 0) /* needed for tape.playing */
+ player->last_move_dir = MV_NO_MOVING;
+
if (++player->frame_reset_delay > player->move_delay_value)
player->Frame = 0;
}
}
}
+static void sleep_milliseconds_x(unsigned long milliseconds_delay)
+{
+ boolean do_busy_waiting = (milliseconds_delay < 5 ? TRUE : FALSE);
+
+#if defined(PLATFORM_MSDOS)
+ /* don't use select() to perform waiting operations under DOS/Windows
+ environment; always use a busy loop for waiting instead */
+ do_busy_waiting = TRUE;
+#endif
+
+
+
+ do_busy_waiting = TRUE;
+
+
+
+ if (do_busy_waiting)
+ {
+ /* we want to wait only a few ms -- if we assume that we have a
+ kernel timer resolution of 10 ms, we would wait far to long;
+ therefore it's better to do a short interval of busy waiting
+ to get our sleeping time more accurate */
+
+ unsigned long base_counter = Counter(), actual_counter = Counter();
+
+ while (actual_counter < base_counter + milliseconds_delay &&
+ actual_counter >= base_counter)
+ actual_counter = Counter();
+ }
+ else
+ {
+#if defined(TARGET_SDL)
+ SDL_Delay(milliseconds_delay);
+#else
+ struct timeval delay;
+
+ delay.tv_sec = milliseconds_delay / 1000;
+ delay.tv_usec = 1000 * (milliseconds_delay % 1000);
+
+ if (select(0, NULL, NULL, NULL, &delay) != 0)
+ Error(ERR_WARN, "sleep_milliseconds(): select() failed");
+#endif
+ }
+}
+
void GameActions()
{
static unsigned long action_delay = 0;
/* ---------- main game synchronization point ---------- */
- WaitUntilDelayReached(&action_delay, action_delay_value);
+
+
+#if 1
+ WaitUntilDelayReached(&action_delay, action_delay_value);
+#else
+ {
+ unsigned long count1 = SDL_GetTicks(), count2, current_ms, test;
+
+ /*
+ WaitUntilDelayReached(&action_delay, action_delay_value);
+ */
+
+ /*
+ SDL_Delay(20);
+ */
+
+ /*
+ sleep_milliseconds_x(20);
+ */
+
+ current_ms = SDL_GetTicks();
+ test = -1;
+ while (current_ms < count1 + 20)
+ {
+ current_ms = SDL_GetTicks(); /* busy wait! */
+
+ if (test != current_ms)
+ {
+ Error(ERR_RETURN, "current_ms == %ld", current_ms);
+ test = current_ms;
+ }
+ }
+
+ count2 = SDL_GetTicks();
+ Error(ERR_RETURN, "delay == %ld", count2 - count1);
+ }
+#endif
+
+
if (network_playing && !network_player_action_received)
{
AmoebeWaechst(x, y);
else if (element == EL_DEAMOEBING)
AmoebeSchrumpft(x, y);
+#if 0
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)
}
}
+#if 1
+ /* new experimental amoeba growth stuff*/
+#if 1
+ if (!(FrameCounter % 8))
+#endif
+ {
+ static unsigned long random = 1684108901;
+
+ for (i = 0; i < level.amoeba_speed * 28 / 8; i++)
+ {
+#if 0
+ 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
BuryHero(player);
}
else
- TestIfBadThingHitsHero(new_jx, new_jy);
+ TestIfHeroRunsIntoBadThing(jx, jy, player->MovDir);
return MF_MOVING;
}
player->last_move_dir = MV_NO_MOVING;
}
- TestIfHeroHitsBadThing(jx, jy);
+ TestIfHeroTouchesBadThing(jx, jy);
if (!player->active)
RemoveHero(player);
ScreenMovDir = MV_NO_MOVING;
}
-void TestIfGoodThingHitsBadThing(int goodx, int goody)
+void TestIfGoodThingHitsBadThing(int goodx, int goody, int move_dir)
{
int i, killx = goodx, killy = goody;
static int xy[4][2] =
{ +1, 0 },
{ 0, +1 }
};
- static int harmless[4] =
+ static int xy_dir[4] =
{
MV_UP,
MV_LEFT,
element = MovingOrBlocked2ElementIfNotLeaving(x, y);
#endif
- if (DONT_TOUCH(element))
+ /* 1st case: good thing is moving towards DONT_GO_TO style bad thing;
+ 2nd case: DONT_TOUCH style bad thing does not move away from good thing
+ */
+ if ((DONT_GO_TO(element) && move_dir == xy_dir[i]) ||
+ (DONT_TOUCH(element) && MovDir[x][y] != xy_dir[i]))
{
- if (MovDir[x][y] == harmless[i])
- continue;
-
killx = x;
killy = y;
break;
}
}
-void TestIfBadThingHitsGoodThing(int badx, int bady)
+void TestIfBadThingHitsGoodThing(int badx, int bady, int move_dir)
{
int i, killx = badx, killy = bady;
+ int bad_element = Feld[badx][bady];
static int xy[4][2] =
{
{ 0, -1 },
{ +1, 0 },
{ 0, +1 }
};
- static int harmless[4] =
+ static int xy_dir[4] =
{
MV_UP,
MV_LEFT,
MV_DOWN
};
- if (Feld[badx][bady] == EL_EXPLODING) /* skip just exploding bad things */
+ if (bad_element == EL_EXPLODING) /* skip just exploding bad things */
return;
for (i=0; i<4; i++)
element = Feld[x][y];
- if (IS_PLAYER(x, y))
- {
- killx = x;
- killy = y;
- break;
- }
- else if (element == EL_PINGUIN)
+ /* 1st case: good thing is moving towards DONT_GO_TO style bad thing;
+ 2nd case: DONT_TOUCH style bad thing does not move away from good thing
+ */
+ if ((DONT_GO_TO(bad_element) && move_dir == xy_dir[i]) ||
+ (DONT_TOUCH(bad_element) && MovDir[x][y] != xy_dir[i]))
{
- if (MovDir[x][y] == harmless[i] && IS_MOVING(x, y))
- continue;
+ /* good thing is player or penguin that does not move away */
+ if (IS_PLAYER(x, y))
+ {
+ struct PlayerInfo *player = PLAYERINFO(x, y);
- killx = x;
- killy = y;
- break;
+ if (bad_element == EL_ROBOT && player->last_move_dir)
+ continue; /* robot does not kill player if he moves */
+
+ killx = x;
+ killy = y;
+ break;
+ }
+ else if (element == EL_PINGUIN &&
+ (MovDir[x][y] != xy_dir[i] || !IS_MOVING(x, y)))
+ {
+ killx = x;
+ killy = y;
+ break;
+ }
}
}
{
struct PlayerInfo *player = PLAYERINFO(killx, killy);
+#if 0
+ int dir = player->MovDir;
+ int newx = player->jx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
+ int newy = player->jy + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
+
+ if (Feld[badx][bady] == EL_ROBOT && player->last_move_dir &&
+ newx != badx && newy != bady)
+ ; /* robot does not kill player if he moves */
+ else
+ printf("-> %d\n", player->MovDir);
+
+ if (Feld[badx][bady] == EL_ROBOT && player->last_move_dir &&
+ newx != badx && newy != bady)
+ ; /* robot does not kill player if he moves */
+ else
+ ;
+#endif
+
if (player->shield_active_time_left > 0)
Bang(badx, bady);
else if (!PLAYER_PROTECTED(killx, killy))
}
}
-void TestIfHeroHitsBadThing(int x, int y)
+void TestIfHeroTouchesBadThing(int x, int y)
{
- TestIfGoodThingHitsBadThing(x, y);
+ TestIfGoodThingHitsBadThing(x, y, MV_NO_MOVING);
}
-void TestIfBadThingHitsHero(int x, int y)
+void TestIfHeroRunsIntoBadThing(int x, int y, int move_dir)
{
- TestIfBadThingHitsGoodThing(x, y);
+ TestIfGoodThingHitsBadThing(x, y, move_dir);
}
-void TestIfFriendHitsBadThing(int x, int y)
+void TestIfBadThingTouchesHero(int x, int y)
{
- TestIfGoodThingHitsBadThing(x, y);
+ TestIfBadThingHitsGoodThing(x, y, MV_NO_MOVING);
}
-void TestIfBadThingHitsFriend(int x, int y)
+void TestIfBadThingRunsIntoHero(int x, int y, int move_dir)
{
- TestIfBadThingHitsGoodThing(x, y);
+ TestIfBadThingHitsGoodThing(x, y, move_dir);
}
-void TestIfBadThingHitsOtherBadThing(int badx, int bady)
+void TestIfFriendTouchesBadThing(int x, int y)
+{
+ TestIfGoodThingHitsBadThing(x, y, MV_NO_MOVING);
+}
+
+void TestIfBadThingTouchesFriend(int x, int y)
+{
+ TestIfBadThingHitsGoodThing(x, y, MV_NO_MOVING);
+}
+
+void TestIfBadThingTouchesOtherBadThing(int badx, int bady)
{
int i, killx = badx, killy = bady;
static int xy[4][2] =
player->present = FALSE;
player->active = FALSE;
- StorePlayer[jx][jy] = 0;
+ if (!ExplodeField[jx][jy])
+ StorePlayer[jx][jy] = 0;
for (i=0; i<MAX_PLAYERS; i++)
if (stored_player[i].active)