changed handling of chain explosions in EM engine
[rocksndiamonds.git] / src / game_em / logic.c
index bfe1d8436e78a4a03b4117bdf5e26e875412e790..7774c1dba4490e04b987d51e91ac05307943a038 100644 (file)
@@ -9,6 +9,8 @@
 
 
 #define SPRING_ROLL    /* spring rolling off round things continues to roll */
+#define ACID_ROLL      /* rolling objects go into acid rather than remove it */
+
 #define USE_CHANGED_ACID_STUFF
 
 #define RANDOM_RAW     (seed = seed << 31 | seed >> 1)
@@ -111,31 +113,34 @@ static void Lboom_generic(int x, int y, int element, int element_middle)
   boom[x+1][y+1] = element;
 }
 
-static void Lboom_bug(int x, int y, int by_element)
+static void Lboom_bug(int x, int y)
 {
-  next[x][y] = Znormal;
+  if (game_em.use_old_explosions)
+    next[x][y] = Zbug;
 
   Lboom_generic(x, y, Xemerald, Xdiamond);
 
 #if PLAY_ELEMENT_SOUND
-  play_element_sound(x, y, SOUND_boom, by_element);
+  play_element_sound(x, y, SOUND_boom, Xbug_1_n);
 #endif
 }
 
-static void Lboom_tank(int x, int y, int by_element)
+static void Lboom_tank(int x, int y)
 {
-  next[x][y] = Znormal;
+  if (game_em.use_old_explosions)
+    next[x][y] = Ztank;
 
   Lboom_generic(x, y, Xblank, Xblank);
 
 #if PLAY_ELEMENT_SOUND
-  play_element_sound(x, y, SOUND_boom, by_element);
+  play_element_sound(x, y, SOUND_boom, Xtank_1_n);
 #endif
 }
 
-static void Lboom_eater(int x, int y, int by_element)
+static void Lboom_eater(int x, int y)
 {
-  next[x][y] = Znormal;
+  if (game_em.use_old_explosions)
+    next[x][y] = Zeater;
 
   boom[x-1][y-1] = lev.eater_array[lev.eater_pos][0];
   boom[x][y-1]   = lev.eater_array[lev.eater_pos][1];
@@ -150,10 +155,67 @@ static void Lboom_eater(int x, int y, int by_element)
   lev.eater_pos = (lev.eater_pos + 1) & 7;
 
 #if PLAY_ELEMENT_SOUND
-  play_element_sound(x, y, SOUND_boom, by_element);
+  play_element_sound(x, y, SOUND_boom, Xeater_n);
 #endif
 }
 
+static void Lboom_bug_old(int x, int y)
+{
+  if (!game_em.use_old_explosions)
+    return;
+
+  Lboom_bug(x, y);
+}
+
+static void Lboom_tank_old(int x, int y)
+{
+  if (!game_em.use_old_explosions)
+    return;
+
+  Lboom_tank(x, y);
+}
+
+static void Lboom_eater_old(int x, int y)
+{
+  if (!game_em.use_old_explosions)
+    return;
+
+  Lboom_eater(x, y);
+}
+
+static void Lboom_bug_new(int x, int y, boolean chain_explosion)
+{
+  if (game_em.use_old_explosions)
+    return;
+
+  if (chain_explosion)
+    cave[x][y] = Xchain;
+
+  Lboom_bug(x, y);
+}
+
+static void Lboom_tank_new(int x, int y, boolean chain_explosion)
+{
+  if (game_em.use_old_explosions)
+    return;
+
+  if (chain_explosion)
+    cave[x][y] = Xchain;
+
+  Lboom_tank(x, y);
+}
+
+static void Lboom_eater_new(int x, int y, boolean chain_explosion)
+{
+  if (game_em.use_old_explosions)
+    return;
+
+  if (chain_explosion)
+    cave[x][y] = Xchain;
+
+  Lboom_eater(x, y);
+}
+
 static boolean player_killed(struct PLAYER *ply)
 {
   int x = ply->x;
@@ -291,6 +353,7 @@ static void kill_player(struct PLAYER *ply)
     case Xbug_2_s:
     case Xbug_2_w:
       cave[x][y-1] = Xboom_bug;
+      Lboom_bug_new(x, y-1, TRUE);
       break;
 
     case Xtank_1_n:
@@ -301,7 +364,8 @@ static void kill_player(struct PLAYER *ply)
     case Xtank_2_e:
     case Xtank_2_s:
     case Xtank_2_w:
-      cave[x][y-1] = Xboom_bomb;
+      cave[x][y-1] = Xboom_tank;
+      Lboom_tank_new(x, y-1, TRUE);
       break;
   }
 
@@ -316,6 +380,7 @@ static void kill_player(struct PLAYER *ply)
     case Xbug_2_s:
     case Xbug_2_w:
       cave[x+1][y] = Xboom_bug;
+      Lboom_bug_new(x+1, y, TRUE);
       break;
 
     case Xtank_1_n:
@@ -326,7 +391,8 @@ static void kill_player(struct PLAYER *ply)
     case Xtank_2_e:
     case Xtank_2_s:
     case Xtank_2_w:
-      cave[x+1][y] = Xboom_bomb;
+      cave[x+1][y] = Xboom_tank;
+      Lboom_tank_new(x+1, y, TRUE);
       break;
   }
 
@@ -341,6 +407,7 @@ static void kill_player(struct PLAYER *ply)
     case Xbug_2_s:
     case Xbug_2_w:
       cave[x][y+1] = Xboom_bug;
+      Lboom_bug_new(x, y+1, TRUE);
       break;
 
     case Xtank_1_n:
@@ -351,7 +418,8 @@ static void kill_player(struct PLAYER *ply)
     case Xtank_2_e:
     case Xtank_2_s:
     case Xtank_2_w:
-      cave[x][y+1] = Xboom_bomb;
+      cave[x][y+1] = Xboom_tank;
+      Lboom_tank_new(x, y+1, TRUE);
       break;
   }
 
@@ -366,6 +434,7 @@ static void kill_player(struct PLAYER *ply)
     case Xbug_2_s:
     case Xbug_2_w:
       cave[x-1][y] = Xboom_bug;
+      Lboom_bug_new(x-1, y, TRUE);
       break;
 
     case Xtank_1_n:
@@ -376,7 +445,8 @@ static void kill_player(struct PLAYER *ply)
     case Xtank_2_e:
     case Xtank_2_s:
     case Xtank_2_w:
-      cave[x-1][y] = Xboom_bomb;
+      cave[x-1][y] = Xboom_tank;
+      Lboom_tank_new(x-1, y, TRUE);
       break;
   }
 
@@ -533,7 +603,7 @@ static boolean player_digfield(struct PLAYER *ply, int dx, int dy)
        next[x][y] = Zplayer;
        play_element_sound(x, y, SOUND_collect, element);
        lev.score += lev.diamond_score;
-       lev.required = lev.required < 3 ? 0 : lev.required - 3;
+       lev.gems_needed = lev.gems_needed < 3 ? 0 : lev.gems_needed - 3;
        game.snapshot.collected_item = TRUE;
        ply->anim = PLY_walk_n + anim;
        ply->x = x;
@@ -546,7 +616,7 @@ static boolean player_digfield(struct PLAYER *ply, int dx, int dy)
        next[x][y] = Zplayer;
        play_element_sound(x, y, SOUND_collect, element);
        lev.score += lev.emerald_score;
-       lev.required = lev.required < 1 ? 0 : lev.required - 1;
+       lev.gems_needed = lev.gems_needed < 1 ? 0 : lev.gems_needed - 1;
        game.snapshot.collected_item = TRUE;
        ply->anim = PLY_walk_n + anim;
        ply->x = x;
@@ -1124,7 +1194,7 @@ static boolean player_digfield(struct PLAYER *ply, int dx, int dy)
        next[x][y] = Xblank;
        play_element_sound(x, y, SOUND_collect, element);
        lev.score += lev.diamond_score;
-       lev.required = lev.required < 3 ? 0 : lev.required - 3;
+       lev.gems_needed = lev.gems_needed < 3 ? 0 : lev.gems_needed - 3;
        game.snapshot.collected_item = TRUE;
        ply->anim = PLY_walk_n + anim;
        break;
@@ -1135,7 +1205,7 @@ static boolean player_digfield(struct PLAYER *ply, int dx, int dy)
        next[x][y] = Xblank;
        play_element_sound(x, y, SOUND_collect, element);
        lev.score += lev.emerald_score;
-       lev.required = lev.required < 1 ? 0 : lev.required - 1;
+       lev.gems_needed = lev.gems_needed < 1 ? 0 : lev.gems_needed - 1;
        game.snapshot.collected_item = TRUE;
        ply->anim = PLY_walk_n + anim;
        break;
@@ -1311,7 +1381,8 @@ static void check_player(struct PLAYER *ply)
       ply->dynamite_cnt = 0;
     }
 
-    RandomEM += 7;     /* be a bit more random if the player doesn't move */
+    /* be a bit more random if the player doesn't move */
+    game_em.random += 7;
 
     return;
   }
@@ -2799,7 +2870,8 @@ static void Lbug_1_n(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_bug(x, y, Xbug_1_n);
+    next[x][y] = Zboom;
+    Lboom_bug(x, y);
 
     return;
   }
@@ -2846,7 +2918,8 @@ static void Lbug_2_n(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_bug(x, y, Xbug_2_n);
+    next[x][y] = Zboom;
+    Lboom_bug(x, y);
 
     return;
   }
@@ -2911,7 +2984,8 @@ static void Lbug_1_e(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_bug(x, y, Xbug_1_e);
+    next[x][y] = Zboom;
+    Lboom_bug(x, y);
 
     return;
   }
@@ -2958,7 +3032,8 @@ static void Lbug_2_e(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_bug(x, y, Xbug_2_e);
+    next[x][y] = Zboom;
+    Lboom_bug(x, y);
 
     return;
   }
@@ -3023,7 +3098,8 @@ static void Lbug_1_s(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_bug(x, y, Xbug_1_s);
+    next[x][y] = Zboom;
+    Lboom_bug(x, y);
 
     return;
   }
@@ -3070,7 +3146,8 @@ static void Lbug_2_s(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_bug(x, y, Xbug_2_s);
+    next[x][y] = Zboom;
+    Lboom_bug(x, y);
 
     return;
   }
@@ -3135,7 +3212,8 @@ static void Lbug_1_w(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_bug(x, y, Xbug_1_w);
+    next[x][y] = Zboom;
+    Lboom_bug(x, y);
 
     return;
   }
@@ -3182,7 +3260,8 @@ static void Lbug_2_w(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_bug(x, y, Xbug_2_w);
+    next[x][y] = Zboom;
+    Lboom_bug(x, y);
 
     return;
   }
@@ -3247,7 +3326,8 @@ static void Ltank_1_n(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_tank(x, y, Xtank_1_n);
+    next[x][y] = Zboom;
+    Lboom_tank(x, y);
 
     return;
   }
@@ -3294,7 +3374,8 @@ static void Ltank_2_n(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_tank(x, y, Xtank_2_n);
+    next[x][y] = Zboom;
+    Lboom_tank(x, y);
 
     return;
   }
@@ -3359,7 +3440,8 @@ static void Ltank_1_e(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_tank(x, y, Xtank_1_e);
+    next[x][y] = Zboom;
+    Lboom_tank(x, y);
 
     return;
   }
@@ -3406,7 +3488,8 @@ static void Ltank_2_e(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_tank(x, y, Xtank_2_e);
+    next[x][y] = Zboom;
+    Lboom_tank(x, y);
 
     return;
   }
@@ -3471,7 +3554,8 @@ static void Ltank_1_s(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_tank(x, y, Xtank_1_s);
+    next[x][y] = Zboom;
+    Lboom_tank(x, y);
 
     return;
   }
@@ -3518,7 +3602,8 @@ static void Ltank_2_s(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_tank(x, y, Xtank_2_s);
+    next[x][y] = Zboom;
+    Lboom_tank(x, y);
 
     return;
   }
@@ -3583,7 +3668,8 @@ static void Ltank_1_w(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_tank(x, y, Xtank_1_w);
+    next[x][y] = Zboom;
+    Lboom_tank(x, y);
 
     return;
   }
@@ -3630,7 +3716,8 @@ static void Ltank_2_w(int x, int y)
       is_amoeba[cave[x][y+1]] ||
       is_amoeba[cave[x-1][y]])
   {
-    Lboom_tank(x, y, Xtank_2_w);
+    next[x][y] = Zboom;
+    Lboom_tank(x, y);
 
     return;
   }
@@ -4390,16 +4477,20 @@ static void Lstone_fall(int x, int y)
     case Xeater_s:
     case Xeater_w:
       cave[x][y] = Ystone_sB;
+      next[x][y] = Xblank;
       cave[x][y+1] = Yeater_stone;
-      Lboom_eater(x, y+1, Xstone_fall);
+      next[x][y+1] = Zeater;
+      Lboom_eater_old(x, y+1);
       score += lev.eater_score;
       return;
 
     case Xalien:
     case Xalien_pause:
       cave[x][y] = Ystone_sB;
+      next[x][y] = Xblank;
       cave[x][y+1] = Yalien_stone;
-      Lboom_tank(x, y+1, Xstone_fall);
+      next[x][y+1] = Ztank;
+      Lboom_tank_old(x, y+1);
       score += lev.alien_score;
       return;
 
@@ -4412,8 +4503,10 @@ static void Lstone_fall(int x, int y)
     case Xbug_2_s:
     case Xbug_2_w:
       cave[x][y] = Ystone_sB;
+      next[x][y] = Xblank;
       cave[x][y+1] = Ybug_stone;
-      Lboom_bug(x, y+1, Xstone_fall);
+      next[x][y+1] = Zbug;
+      Lboom_bug_old(x, y+1);
       score += lev.bug_score;
       return;
 
@@ -4426,8 +4519,10 @@ static void Lstone_fall(int x, int y)
     case Xtank_2_s:
     case Xtank_2_w:
       cave[x][y] = Ystone_sB;
+      next[x][y] = Xblank;
       cave[x][y+1] = Ytank_stone;
-      Lboom_tank(x, y+1, Xstone_fall);
+      next[x][y+1] = Ztank;
+      Lboom_tank_old(x, y+1);
       score += lev.tank_score;
       return;
 
@@ -4503,8 +4598,11 @@ static void Lstone_fall(int x, int y)
 
     case Xbomb:
     case Xbomb_pause:
+      cave[x][y] = Xstone;
+      next[x][y] = Xstone;
       cave[x][y+1] = Ybomb_blank;
-      Lboom_tank(x, y+1, Xstone_fall);
+      next[x][y+1] = Ztank;
+      Lboom_tank_old(x, y+1);
       return;
 
     case Xnut:
@@ -4812,7 +4910,8 @@ static void Lbomb_fall(int x, int y)
 
     default:
       cave[x][y] = Ybomb_blank;
-      Lboom_tank(x, y, Xbomb_fall);
+      next[x][y] = Ztank;
+      Lboom_tank_old(x, y);
       return;
   }
 }
@@ -5506,16 +5605,20 @@ static void Lspring_fall(int x, int y)
     case Xeater_s:
     case Xeater_w:
       cave[x][y] = Yspring_sB;
+      next[x][y] = Xblank;
       cave[x][y+1] = Yeater_spring;
-      Lboom_eater(x, y+1, Xspring_fall);
+      next[x][y+1] = Zeater;
+      Lboom_eater_old(x, y+1);
       score += lev.eater_score;
       return;
 
     case Xalien:
     case Xalien_pause:
       cave[x][y] = Yspring_sB;
+      next[x][y] = Xblank;
       cave[x][y+1] = Yalien_spring;
-      Lboom_tank(x, y+1, Xspring_fall);
+      next[x][y+1] = Ztank;
+      Lboom_tank_old(x, y+1);
       score += lev.alien_score;
       return;
 
@@ -5528,8 +5631,10 @@ static void Lspring_fall(int x, int y)
     case Xbug_2_s:
     case Xbug_2_w:
       cave[x][y] = Yspring_sB;
+      next[x][y] = Xblank;
       cave[x][y+1] = Ybug_spring;
-      Lboom_bug(x, y+1, Xspring_fall);
+      next[x][y+1] = Zbug;
+      Lboom_bug_old(x, y+1);
       score += lev.bug_score;
       return;
 
@@ -5542,15 +5647,20 @@ static void Lspring_fall(int x, int y)
     case Xtank_2_s:
     case Xtank_2_w:
       cave[x][y] = Yspring_sB;
+      next[x][y] = Xblank;
       cave[x][y+1] = Ytank_spring;
-      Lboom_tank(x, y+1, Xspring_fall);
+      next[x][y+1] = Ztank;
+      Lboom_tank_old(x, y+1);
       score += lev.tank_score;
       return;
 
     case Xbomb:
     case Xbomb_pause:
+      cave[x][y] = Xspring;
+      next[x][y] = Xspring;
       cave[x][y+1] = Ybomb_blank;
-      Lboom_tank(x, y+1, Xspring_fall);
+      next[x][y+1] = Ztank;
+      Lboom_tank_old(x, y+1);
       return;
 
     default:
@@ -5563,302 +5673,506 @@ static void Lspring_fall(int x, int y)
 
 static void Lpush_emerald_e(int x, int y)
 {
+  cave[x][y] = Yemerald_eB;
+  next[x][y] = Xblank;
+
   switch (cave[x+1][y])
   {
-    case Zplayer:
     case Zborder:
-    case Znormal:
+    case Zbug:
+    case Ztank:
+    case Zeater:
     case Zdynamite:
+    case Zboom:
+    case Xchain:
     case Xboom_bug:
-    case Xboom_bomb:
+    case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
-      cave[x][y] = Xemerald;
-      next[x][y] = Xemerald;
       return;
 
-    default:
-      cave[x][y] = Yemerald_eB;
-      next[x][y] = Xblank;
-      cave[x+1][y] = Yemerald_e;
-      next[x+1][y] = Xemerald_pause;
+#ifdef ACID_ROLL
+    case Xacid_1:
+    case Xacid_2:
+    case Xacid_3:
+    case Xacid_4:
+    case Xacid_5:
+    case Xacid_6:
+    case Xacid_7:
+    case Xacid_8:
+      if (cave[x+2][y-1] == Xblank)
+       cave[x+2][y-1] = Xsplash_e;
+      if (cave[x][y-1] == Xblank)
+       cave[x][y-1] = Xsplash_w;
+      play_element_sound(x, y, SOUND_acid, Xacid_1);
       return;
+#endif
   }
+
+  cave[x+1][y] = Yemerald_e;
+  next[x+1][y] = Xemerald_pause;
 }
 
 static void Lpush_emerald_w(int x, int y)
 {
+  cave[x][y] = Yemerald_wB;
+  next[x][y] = Xblank;
+
   switch (cave[x-1][y])
   {
-    case Zplayer:
     case Zborder:
-    case Znormal:
+    case Zbug:
+    case Ztank:
+    case Zeater:
     case Zdynamite:
+    case Zboom:
+    case Xchain:
     case Xboom_bug:
-    case Xboom_bomb:
+    case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
-      cave[x][y] = Xemerald;
-      next[x][y] = Xemerald;
       return;
 
-    default:
-      cave[x][y] = Yemerald_wB;
-      next[x][y] = Xblank;
-      cave[x-1][y] = Yemerald_w;
-      next[x-1][y] = Xemerald_pause;
+#ifdef ACID_ROLL
+    case Xacid_1:
+    case Xacid_2:
+    case Xacid_3:
+    case Xacid_4:
+    case Xacid_5:
+    case Xacid_6:
+    case Xacid_7:
+    case Xacid_8:
+      if (cave[x][y-1] == Xblank)
+       cave[x][y-1] = Xsplash_e;
+      if (cave[x-2][y-1] == Xblank)
+       cave[x-2][y-1] = Xsplash_w;
+      play_element_sound(x, y, SOUND_acid, Xacid_1);
       return;
+#endif
   }
+
+  cave[x-1][y] = Yemerald_w;
+  next[x-1][y] = Xemerald_pause;
 }
 
 static void Lpush_diamond_e(int x, int y)
 {
+  cave[x][y] = Ydiamond_eB;
+  next[x][y] = Xblank;
+
   switch (cave[x+1][y])
   {
-    case Zplayer:
     case Zborder:
-    case Znormal:
+    case Zbug:
+    case Ztank:
+    case Zeater:
     case Zdynamite:
+    case Zboom:
+    case Xchain:
     case Xboom_bug:
-    case Xboom_bomb:
+    case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
-      cave[x][y] = Xdiamond;
-      next[x][y] = Xdiamond;
       return;
 
-    default:
-      cave[x][y] = Ydiamond_eB;
-      next[x][y] = Xblank;
-      cave[x+1][y] = Ydiamond_e;
-      next[x+1][y] = Xdiamond_pause;
+#ifdef ACID_ROLL
+    case Xacid_1:
+    case Xacid_2:
+    case Xacid_3:
+    case Xacid_4:
+    case Xacid_5:
+    case Xacid_6:
+    case Xacid_7:
+    case Xacid_8:
+      if (cave[x+2][y-1] == Xblank)
+       cave[x+2][y-1] = Xsplash_e;
+      if (cave[x][y-1] == Xblank)
+       cave[x][y-1] = Xsplash_w;
+      play_element_sound(x, y, SOUND_acid, Xacid_1);
       return;
+#endif
   }
+
+  cave[x+1][y] = Ydiamond_e;
+  next[x+1][y] = Xdiamond_pause;
 }
 
 static void Lpush_diamond_w(int x, int y)
 {
+  cave[x][y] = Ydiamond_wB;
+  next[x][y] = Xblank;
+
   switch (cave[x-1][y])
   {
-    case Zplayer:
     case Zborder:
-    case Znormal:
+    case Zbug:
+    case Ztank:
+    case Zeater:
     case Zdynamite:
+    case Zboom:
+    case Xchain:
     case Xboom_bug:
-    case Xboom_bomb:
+    case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
-      cave[x][y] = Xdiamond;
-      next[x][y] = Xdiamond;
       return;
 
-    default:
-      cave[x][y] = Ydiamond_wB;
-      next[x][y] = Xblank;
-      cave[x-1][y] = Ydiamond_w;
-      next[x-1][y] = Xdiamond_pause;
+#ifdef ACID_ROLL
+    case Xacid_1:
+    case Xacid_2:
+    case Xacid_3:
+    case Xacid_4:
+    case Xacid_5:
+    case Xacid_6:
+    case Xacid_7:
+    case Xacid_8:
+      if (cave[x][y-1] == Xblank)
+       cave[x][y-1] = Xsplash_e;
+      if (cave[x-2][y-1] == Xblank)
+       cave[x-2][y-1] = Xsplash_w;
+      play_element_sound(x, y, SOUND_acid, Xacid_1);
       return;
+#endif
   }
+
+  cave[x-1][y] = Ydiamond_w;
+  next[x-1][y] = Xdiamond_pause;
 }
 
 static void Lpush_stone_e(int x, int y)
 {
+  cave[x][y] = Ystone_eB;
+  next[x][y] = Xblank;
+
   switch (cave[x+1][y])
   {
-    case Zplayer:
     case Zborder:
-    case Znormal:
+    case Zbug:
+    case Ztank:
+    case Zeater:
     case Zdynamite:
+    case Zboom:
+    case Xchain:
     case Xboom_bug:
-    case Xboom_bomb:
+    case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
-      cave[x][y] = Xstone;
-      next[x][y] = Xstone;
       return;
 
-    default:
-      cave[x][y] = Ystone_eB;
-      next[x][y] = Xblank;
-      cave[x+1][y] = Ystone_e;
-      next[x+1][y] = Xstone_pause;
+#ifdef ACID_ROLL
+    case Xacid_1:
+    case Xacid_2:
+    case Xacid_3:
+    case Xacid_4:
+    case Xacid_5:
+    case Xacid_6:
+    case Xacid_7:
+    case Xacid_8:
+      if (cave[x+2][y-1] == Xblank)
+       cave[x+2][y-1] = Xsplash_e;
+      if (cave[x][y-1] == Xblank)
+       cave[x][y-1] = Xsplash_w;
+      play_element_sound(x, y, SOUND_acid, Xacid_1);
       return;
+#endif
   }
+
+  cave[x+1][y] = Ystone_e;
+  next[x+1][y] = Xstone_pause;
 }
 
 static void Lpush_stone_w(int x, int y)
 {
+  cave[x][y] = Ystone_wB;
+  next[x][y] = Xblank;
+
   switch (cave[x-1][y])
   {
-    case Zplayer:
     case Zborder:
-    case Znormal:
+    case Zbug:
+    case Ztank:
+    case Zeater:
     case Zdynamite:
+    case Zboom:
+    case Xchain:
     case Xboom_bug:
-    case Xboom_bomb:
+    case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
-      cave[x][y] = Xstone;
-      next[x][y] = Xstone;
       return;
 
-    default:
-      cave[x][y] = Ystone_wB;
-      next[x][y] = Xblank;
-      cave[x-1][y] = Ystone_w;
-      next[x-1][y] = Xstone_pause;
+#ifdef ACID_ROLL
+    case Xacid_1:
+    case Xacid_2:
+    case Xacid_3:
+    case Xacid_4:
+    case Xacid_5:
+    case Xacid_6:
+    case Xacid_7:
+    case Xacid_8:
+      if (cave[x][y-1] == Xblank)
+       cave[x][y-1] = Xsplash_e;
+      if (cave[x-2][y-1] == Xblank)
+       cave[x-2][y-1] = Xsplash_w;
+      play_element_sound(x, y, SOUND_acid, Xacid_1);
       return;
+#endif
   }
+
+  cave[x-1][y] = Ystone_w;
+  next[x-1][y] = Xstone_pause;
 }
 
 static void Lpush_bomb_e(int x, int y)
 {
+  cave[x][y] = Ybomb_eB;
+  next[x][y] = Xblank;
+
   switch (cave[x+1][y])
   {
-    case Zplayer:
     case Zborder:
-    case Znormal:
+    case Zbug:
+    case Ztank:
+    case Zeater:
     case Zdynamite:
+    case Zboom:
+    case Xchain:
     case Xboom_bug:
-    case Xboom_bomb:
+    case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
-      cave[x][y] = Xbomb;
-      next[x][y] = Xbomb;
       return;
 
-    default:
-      cave[x][y] = Ybomb_eB;
-      next[x][y] = Xblank;
-      cave[x+1][y] = Ybomb_e;
-      next[x+1][y] = Xbomb_pause;
+#ifdef ACID_ROLL
+    case Xacid_1:
+    case Xacid_2:
+    case Xacid_3:
+    case Xacid_4:
+    case Xacid_5:
+    case Xacid_6:
+    case Xacid_7:
+    case Xacid_8:
+      if (cave[x+2][y-1] == Xblank)
+       cave[x+2][y-1] = Xsplash_e;
+      if (cave[x][y-1] == Xblank)
+       cave[x][y-1] = Xsplash_w;
+      play_element_sound(x, y, SOUND_acid, Xacid_1);
       return;
+#endif
   }
+
+  cave[x+1][y] = Ybomb_e;
+  next[x+1][y] = Xbomb_pause;
 }
 
 static void Lpush_bomb_w(int x, int y)
 {
+  cave[x][y] = Ybomb_wB;
+  next[x][y] = Xblank;
+
   switch (cave[x-1][y])
   {
-    case Zplayer:
     case Zborder:
-    case Znormal:
+    case Zbug:
+    case Ztank:
+    case Zeater:
     case Zdynamite:
+    case Zboom:
+    case Xchain:
     case Xboom_bug:
-    case Xboom_bomb:
+    case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
-      cave[x][y] = Xbomb;
-      next[x][y] = Xbomb;
       return;
 
-    default:
-      cave[x][y] = Ybomb_wB;
-      next[x][y] = Xblank;
-      cave[x-1][y] = Ybomb_w;
-      next[x-1][y] = Xbomb_pause;
+#ifdef ACID_ROLL
+    case Xacid_1:
+    case Xacid_2:
+    case Xacid_3:
+    case Xacid_4:
+    case Xacid_5:
+    case Xacid_6:
+    case Xacid_7:
+    case Xacid_8:
+      if (cave[x][y-1] == Xblank)
+       cave[x][y-1] = Xsplash_e;
+      if (cave[x-2][y-1] == Xblank)
+       cave[x-2][y-1] = Xsplash_w;
+      play_element_sound(x, y, SOUND_acid, Xacid_1);
       return;
+#endif
   }
+
+  cave[x-1][y] = Ybomb_w;
+  next[x-1][y] = Xbomb_pause;
 }
 
 static void Lpush_nut_e(int x, int y)
 {
+  cave[x][y] = Ynut_eB;
+  next[x][y] = Xblank;
+
   switch (cave[x+1][y])
   {
-    case Zplayer:
     case Zborder:
-    case Znormal:
+    case Zbug:
+    case Ztank:
+    case Zeater:
     case Zdynamite:
+    case Zboom:
+    case Xchain:
     case Xboom_bug:
-    case Xboom_bomb:
+    case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
-      cave[x][y] = Xnut;
-      next[x][y] = Xnut;
       return;
 
-    default:
-      cave[x][y] = Ynut_eB;
-      next[x][y] = Xblank;
-      cave[x+1][y] = Ynut_e;
-      next[x+1][y] = Xnut_pause;
+#ifdef ACID_ROLL
+    case Xacid_1:
+    case Xacid_2:
+    case Xacid_3:
+    case Xacid_4:
+    case Xacid_5:
+    case Xacid_6:
+    case Xacid_7:
+    case Xacid_8:
+      if (cave[x+2][y-1] == Xblank)
+       cave[x+2][y-1] = Xsplash_e;
+      if (cave[x][y-1] == Xblank)
+       cave[x][y-1] = Xsplash_w;
+      play_element_sound(x, y, SOUND_acid, Xacid_1);
       return;
+#endif
   }
+
+  cave[x+1][y] = Ynut_e;
+  next[x+1][y] = Xnut_pause;
 }
 
 static void Lpush_nut_w(int x, int y)
 {
+  cave[x][y] = Ynut_wB;
+  next[x][y] = Xblank;
+
   switch (cave[x-1][y])
   {
-    case Zplayer:
     case Zborder:
-    case Znormal:
+    case Zbug:
+    case Ztank:
+    case Zeater:
     case Zdynamite:
+    case Zboom:
+    case Xchain:
     case Xboom_bug:
-    case Xboom_bomb:
+    case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
-      cave[x][y] = Xnut;
-      next[x][y] = Xnut;
       return;
 
-    default:
-      cave[x][y] = Ynut_wB;
-      next[x][y] = Xblank;
-      cave[x-1][y] = Ynut_w;
-      next[x-1][y] = Xnut_pause;
+#ifdef ACID_ROLL
+    case Xacid_1:
+    case Xacid_2:
+    case Xacid_3:
+    case Xacid_4:
+    case Xacid_5:
+    case Xacid_6:
+    case Xacid_7:
+    case Xacid_8:
+      if (cave[x][y-1] == Xblank)
+       cave[x][y-1] = Xsplash_e;
+      if (cave[x-2][y-1] == Xblank)
+       cave[x-2][y-1] = Xsplash_w;
+      play_element_sound(x, y, SOUND_acid, Xacid_1);
       return;
+#endif
   }
+
+  cave[x-1][y] = Ynut_w;
+  next[x-1][y] = Xnut_pause;
 }
 
 static void Lpush_spring_e(int x, int y)
 {
+  cave[x][y] = Yspring_eB;
+  next[x][y] = Xblank;
+
   switch (cave[x+1][y])
   {
-    case Zplayer:
     case Zborder:
-    case Znormal:
+    case Zbug:
+    case Ztank:
+    case Zeater:
     case Zdynamite:
+    case Zboom:
+    case Xchain:
     case Xboom_bug:
-    case Xboom_bomb:
+    case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
-      cave[x][y] = Xspring;
-      next[x][y] = Xspring;
       return;
 
-    default:
-      cave[x][y] = Yspring_eB;
-      next[x][y] = Xblank;
-      cave[x+1][y] = Yspring_e;
-      next[x+1][y] = Xspring_e;
+#ifdef ACID_ROLL
+    case Xacid_1:
+    case Xacid_2:
+    case Xacid_3:
+    case Xacid_4:
+    case Xacid_5:
+    case Xacid_6:
+    case Xacid_7:
+    case Xacid_8:
+      if (cave[x+2][y-1] == Xblank)
+       cave[x+2][y-1] = Xsplash_e;
+      if (cave[x][y-1] == Xblank)
+       cave[x][y-1] = Xsplash_w;
+      play_element_sound(x, y, SOUND_acid, Xacid_1);
       return;
+#endif
   }
+
+  cave[x+1][y] = Yspring_e;
+  next[x+1][y] = Xspring_e;
 }
 
 static void Lpush_spring_w(int x, int y)
 {
+  cave[x][y] = Yspring_wB;
+  next[x][y] = Xblank;
+
   switch (cave[x-1][y])
   {
-    case Zplayer:
     case Zborder:
-    case Znormal:
+    case Zbug:
+    case Ztank:
+    case Zeater:
     case Zdynamite:
+    case Zboom:
+    case Xchain:
     case Xboom_bug:
-    case Xboom_bomb:
+    case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
-      cave[x][y] = Xspring;
-      next[x][y] = Xspring;
       return;
 
-    default:
-      cave[x][y] = Yspring_wB;
-      next[x][y] = Xblank;
-      cave[x-1][y] = Yspring_w;
-      next[x-1][y] = Xspring_w;
+#ifdef ACID_ROLL
+    case Xacid_1:
+    case Xacid_2:
+    case Xacid_3:
+    case Xacid_4:
+    case Xacid_5:
+    case Xacid_6:
+    case Xacid_7:
+    case Xacid_8:
+      if (cave[x][y-1] == Xblank)
+       cave[x][y-1] = Xsplash_e;
+      if (cave[x-2][y-1] == Xblank)
+       cave[x-2][y-1] = Xsplash_w;
+      play_element_sound(x, y, SOUND_acid, Xacid_1);
       return;
+#endif
   }
+
+  cave[x-1][y] = Yspring_w;
+  next[x-1][y] = Xspring_w;
 }
 
 static void Ldynamite_1(int x, int y)
@@ -6551,7 +6865,7 @@ static void Lslide_ew(int x, int y)
 
 static void Lexit(int x, int y)
 {
-  if (lev.required > 0)
+  if (lev.gems_needed > 0)
     return;
 
   switch (RANDOM(64) / 21)
@@ -6628,10 +6942,14 @@ static void Lboom_one(int x, int y, boolean by_dynamite)
   switch (cave[x][y])
   {
     case Zborder:
-    case Znormal:
+    case Zbug:
+    case Ztank:
+    case Zeater:
     case Zdynamite:
+    case Zboom:
+    case Xchain:
     case Xboom_bug:
-    case Xboom_bomb:
+    case Xboom_tank:
     case Xboom_android:
     case Xacid_1:
     case Xacid_2:
@@ -6692,12 +7010,14 @@ static void Lboom_one(int x, int y, boolean by_dynamite)
     case Xbug_2_s:
     case Xbug_2_w:
       cave[x][y] = Xboom_bug;
+      Lboom_bug_new(x, y, TRUE);
       return;
 
     case Xbomb:
     case Xbomb_pause:
     case Xbomb_fall:
-      cave[x][y] = Xboom_bomb;
+      cave[x][y] = Xboom_tank;
+      Lboom_tank_new(x, y, TRUE);
       return;
 
     default:
@@ -6724,13 +7044,28 @@ static void Lexplode(int x, int y)
 {
   switch (cave[x][y])
   {
-    case Znormal:
+    case Zbug:
+      Lboom_bug_new(x, y, FALSE);
+      Lboom_nine(x, y, FALSE);
+      break;
+
+    case Ztank:
+      Lboom_tank_new(x, y, FALSE);
+      Lboom_nine(x, y, FALSE);
+      break;
+
+    case Zeater:
+      Lboom_eater_new(x, y, FALSE);
       Lboom_nine(x, y, FALSE);
       break;
 
     case Zdynamite:
       Lboom_nine(x, y, TRUE);
       break;
+
+    case Zboom:
+      Lboom_nine(x, y, FALSE);
+      break;
   }
 }
 
@@ -6759,6 +7094,11 @@ static void Lboom_android(int x, int y)
   Lboom_1(x, y);
 }
 
+static void Lchain(int x, int y)
+{
+  next[x][y] = Zboom;
+}
+
 static void handle_tile(int x, int y)
 {
   switch (cave[x][y])
@@ -6918,8 +7258,9 @@ static void handle_tile(int x, int y)
 
     case Xpause:               Lpause(x, y);                   break;
 
-    case Xboom_bug:            Lboom_bug(x, y, Xboom_bug);     break;
-    case Xboom_bomb:           Lboom_tank(x, y, Xboom_bomb);   break;
+    case Xchain:               Lchain(x, y);                   break;
+    case Xboom_bug:            Lboom_bug(x, y);                break;
+    case Xboom_tank:           Lboom_tank(x, y);               break;
     case Xboom_android:                Lboom_android(x, y);            break;
     case Xboom_1:              Lboom_1(x, y);                  break;
     case Xboom_2:              Lboom_2(x, y);                  break;
@@ -6965,7 +7306,8 @@ void logic_players(void)
     ply[i].anim = PLY_still;
   }
 
-  start_check_nr = (RandomEM & 128 ? 0 : 1) * 2 + (RandomEM & 256 ? 0 : 1);
+  start_check_nr = ((game_em.random & 128 ? 0 : 1) * 2 +
+                   (game_em.random & 256 ? 0 : 1));
 
   for (i = 0; i < MAX_PLAYERS; i++)
   {
@@ -7002,7 +7344,7 @@ void logic_objects(void)
   next = lev.next;
   boom = lev.boom;
 
-  seed = RandomEM;
+  seed = game_em.random;
   score = 0;
 
   for (y = lev.top; y < lev.bottom; y++)
@@ -7014,7 +7356,7 @@ void logic_objects(void)
   else
     game_em.game_over = TRUE;
 
-  RandomEM = seed;
+  game_em.random = seed;
 
   /* triple buffering */
   void *temp = lev.cave;
@@ -7062,7 +7404,7 @@ void logic_globals(void)
 
   /* grow amoeba */
 
-  random = RandomEM;
+  random = game_em.random;
 
   for (count = lev.amoeba_time; count--;)
   {
@@ -7076,7 +7418,7 @@ void logic_globals(void)
     random = random * 129 + 1;
   }
 
-  RandomEM = random;
+  game_em.random = random;
 
   /* handle explosions */