fixed handling of pushed objects in EM engine for old tapes
[rocksndiamonds.git] / src / game_em / logic.c
index 6270550dd6ee8c5b36c1a9fd23a1b626038d5fb5..7840734eaa75235a2d3a6b977be4b3f39c0ddf1e 100644 (file)
@@ -82,6 +82,21 @@ static const byte is_amoeba[GAME_TILE_MAX] =
   [Xamoeba_8]          = 1
 };
 
+static byte is_android_blank[GAME_TILE_MAX] =
+{
+  [Xblank]             = 1,
+  [Xsplash_e]          = 1,
+  [Xsplash_w]          = 1,
+  [Xfake_acid_1]       = 1,
+  [Xfake_acid_2]       = 1,
+  [Xfake_acid_3]       = 1,
+  [Xfake_acid_4]       = 1,
+  [Xfake_acid_5]       = 1,
+  [Xfake_acid_6]       = 1,
+  [Xfake_acid_7]       = 1,
+  [Xfake_acid_8]       = 1
+};
+
 static const byte is_android_walkable[GAME_TILE_MAX] =
 {
   [Xblank]             = 1,
@@ -214,6 +229,31 @@ static void Lboom_eater_new(int x, int y, boolean chain_explosion)
   Lboom_eater(x, y);
 }
 
+static void Lboom_cave_new(int x, int y, int element)
+{
+  if (game_em.use_old_explosions)
+    return;
+
+  cave[x][y] = element;
+}
+
+static void Lboom_next_new(int x, int y, int element)
+{
+  if (game_em.use_old_explosions)
+    return;
+
+  next[x][y] = element;
+}
+
+static void Lpush_element_old(int x, int y, int element)
+{
+  if (!game_em.use_old_push_elements)
+    return;
+
+  cave[x][y] = element;
+  next[x][y] = element;
+}
+
 static boolean player_killed(struct PLAYER *ply)
 {
   int x = ply->x;
@@ -1279,6 +1319,11 @@ static boolean player_digfield(struct PLAYER *ply, int dx, int dy)
     }
   }
 
+  /* check for wrap-around movement */
+  if (ply->x < lev.left ||
+      ply->x > lev.right - 1)
+    play_element_sound(oldx, oldy, SOUND_door, Xdoor_1);
+
   return result;
 }
 
@@ -1532,14 +1577,14 @@ static void Landroid(int x, int y)
 
   if (lev.android_clone_cnt == 0)
   {
-    if (!is_blank[cave[x-1][y-1]] &&
-       !is_blank[cave[x][y-1]]   &&
-       !is_blank[cave[x+1][y-1]] &&
-       !is_blank[cave[x-1][y]]   &&
-       !is_blank[cave[x+1][y]]   &&
-       !is_blank[cave[x-1][y+1]] &&
-       !is_blank[cave[x][y+1]]   &&
-       !is_blank[cave[x+1][y+1]])
+    if (!is_android_blank[cave[x-1][y-1]] &&
+       !is_android_blank[cave[x][y-1]]   &&
+       !is_android_blank[cave[x+1][y-1]] &&
+       !is_android_blank[cave[x-1][y]]   &&
+       !is_android_blank[cave[x+1][y]]   &&
+       !is_android_blank[cave[x-1][y+1]] &&
+       !is_android_blank[cave[x][y+1]]   &&
+       !is_android_blank[cave[x+1][y+1]])
       goto android_move;
 
     switch (RANDOM(8))
@@ -1643,91 +1688,91 @@ static void Landroid(int x, int y)
       /* randomly find a direction to move */
 
       case 0: /* S,NE,W,NW,SE,E,SW,N */
-       if (is_blank[cave[x][y+1]])   goto android_s;
-       if (is_blank[cave[x+1][y-1]]) goto android_ne;
-       if (is_blank[cave[x-1][y]])   goto android_w;
-       if (is_blank[cave[x-1][y-1]]) goto android_nw;
-       if (is_blank[cave[x+1][y+1]]) goto android_se;
-       if (is_blank[cave[x+1][y]])   goto android_e;
-       if (is_blank[cave[x-1][y+1]]) goto android_sw;
-       if (is_blank[cave[x][y-1]])   goto android_n;
+       if (is_android_blank[cave[x][y+1]])   goto android_s;
+       if (is_android_blank[cave[x+1][y-1]]) goto android_ne;
+       if (is_android_blank[cave[x-1][y]])   goto android_w;
+       if (is_android_blank[cave[x-1][y-1]]) goto android_nw;
+       if (is_android_blank[cave[x+1][y+1]]) goto android_se;
+       if (is_android_blank[cave[x+1][y]])   goto android_e;
+       if (is_android_blank[cave[x-1][y+1]]) goto android_sw;
+       if (is_android_blank[cave[x][y-1]])   goto android_n;
        goto android_move;
 
       case 1: /* NW,SE,N,S,NE,SW,E,W */
-       if (is_blank[cave[x-1][y-1]]) goto android_nw;
-       if (is_blank[cave[x+1][y+1]]) goto android_se;
-       if (is_blank[cave[x][y-1]])   goto android_n;
-       if (is_blank[cave[x][y+1]])   goto android_s;
-       if (is_blank[cave[x+1][y-1]]) goto android_ne;
-       if (is_blank[cave[x-1][y+1]]) goto android_sw;
-       if (is_blank[cave[x+1][y]])   goto android_e;
-       if (is_blank[cave[x-1][y]])   goto android_w;
+       if (is_android_blank[cave[x-1][y-1]]) goto android_nw;
+       if (is_android_blank[cave[x+1][y+1]]) goto android_se;
+       if (is_android_blank[cave[x][y-1]])   goto android_n;
+       if (is_android_blank[cave[x][y+1]])   goto android_s;
+       if (is_android_blank[cave[x+1][y-1]]) goto android_ne;
+       if (is_android_blank[cave[x-1][y+1]]) goto android_sw;
+       if (is_android_blank[cave[x+1][y]])   goto android_e;
+       if (is_android_blank[cave[x-1][y]])   goto android_w;
        goto android_move;
 
       case 2: /* SW,E,S,W,N,NW,SE,NE */
-       if (is_blank[cave[x-1][y+1]]) goto android_sw;
-       if (is_blank[cave[x+1][y]])   goto android_e;
-       if (is_blank[cave[x][y+1]])   goto android_s;
-       if (is_blank[cave[x-1][y]])   goto android_w;
-       if (is_blank[cave[x][y-1]])   goto android_n;
-       if (is_blank[cave[x-1][y-1]]) goto android_nw;
-       if (is_blank[cave[x+1][y+1]]) goto android_se;
-       if (is_blank[cave[x+1][y-1]]) goto android_ne;
+       if (is_android_blank[cave[x-1][y+1]]) goto android_sw;
+       if (is_android_blank[cave[x+1][y]])   goto android_e;
+       if (is_android_blank[cave[x][y+1]])   goto android_s;
+       if (is_android_blank[cave[x-1][y]])   goto android_w;
+       if (is_android_blank[cave[x][y-1]])   goto android_n;
+       if (is_android_blank[cave[x-1][y-1]]) goto android_nw;
+       if (is_android_blank[cave[x+1][y+1]]) goto android_se;
+       if (is_android_blank[cave[x+1][y-1]]) goto android_ne;
        goto android_move;
 
       case 3: /* N,SE,NE,E,W,S,NW,SW */
-       if (is_blank[cave[x][y-1]])   goto android_n;
-       if (is_blank[cave[x+1][y+1]]) goto android_se;
-       if (is_blank[cave[x+1][y-1]]) goto android_ne;
-       if (is_blank[cave[x+1][y]])   goto android_e;
-       if (is_blank[cave[x-1][y]])   goto android_w;
-       if (is_blank[cave[x][y+1]])   goto android_s;
-       if (is_blank[cave[x-1][y-1]]) goto android_nw;
-       if (is_blank[cave[x-1][y+1]]) goto android_sw;
+       if (is_android_blank[cave[x][y-1]])   goto android_n;
+       if (is_android_blank[cave[x+1][y+1]]) goto android_se;
+       if (is_android_blank[cave[x+1][y-1]]) goto android_ne;
+       if (is_android_blank[cave[x+1][y]])   goto android_e;
+       if (is_android_blank[cave[x-1][y]])   goto android_w;
+       if (is_android_blank[cave[x][y+1]])   goto android_s;
+       if (is_android_blank[cave[x-1][y-1]]) goto android_nw;
+       if (is_android_blank[cave[x-1][y+1]]) goto android_sw;
        goto android_move;
 
       case 4: /* SE,NW,E,NE,SW,W,N,S */
-       if (is_blank[cave[x+1][y+1]]) goto android_se;
-       if (is_blank[cave[x-1][y-1]]) goto android_nw;
-       if (is_blank[cave[x+1][y]])   goto android_e;
-       if (is_blank[cave[x+1][y-1]]) goto android_ne;
-       if (is_blank[cave[x-1][y+1]]) goto android_sw;
-       if (is_blank[cave[x-1][y]])   goto android_w;
-       if (is_blank[cave[x][y-1]])   goto android_n;
-       if (is_blank[cave[x][y+1]])   goto android_s;
+       if (is_android_blank[cave[x+1][y+1]]) goto android_se;
+       if (is_android_blank[cave[x-1][y-1]]) goto android_nw;
+       if (is_android_blank[cave[x+1][y]])   goto android_e;
+       if (is_android_blank[cave[x+1][y-1]]) goto android_ne;
+       if (is_android_blank[cave[x-1][y+1]]) goto android_sw;
+       if (is_android_blank[cave[x-1][y]])   goto android_w;
+       if (is_android_blank[cave[x][y-1]])   goto android_n;
+       if (is_android_blank[cave[x][y+1]])   goto android_s;
        goto android_move;
 
       case 5: /* NE,W,SE,SW,S,N,E,NW */
-       if (is_blank[cave[x+1][y-1]]) goto android_ne;
-       if (is_blank[cave[x-1][y]])   goto android_w;
-       if (is_blank[cave[x+1][y+1]]) goto android_se;
-       if (is_blank[cave[x-1][y+1]]) goto android_sw;
-       if (is_blank[cave[x][y+1]])   goto android_s;
-       if (is_blank[cave[x][y-1]])   goto android_n;
-       if (is_blank[cave[x+1][y]])   goto android_e;
-       if (is_blank[cave[x-1][y-1]]) goto android_nw;
+       if (is_android_blank[cave[x+1][y-1]]) goto android_ne;
+       if (is_android_blank[cave[x-1][y]])   goto android_w;
+       if (is_android_blank[cave[x+1][y+1]]) goto android_se;
+       if (is_android_blank[cave[x-1][y+1]]) goto android_sw;
+       if (is_android_blank[cave[x][y+1]])   goto android_s;
+       if (is_android_blank[cave[x][y-1]])   goto android_n;
+       if (is_android_blank[cave[x+1][y]])   goto android_e;
+       if (is_android_blank[cave[x-1][y-1]]) goto android_nw;
        goto android_move;
 
       case 6: /* E,N,SW,S,NW,NE,SE,W */
-       if (is_blank[cave[x+1][y]])   goto android_e;
-       if (is_blank[cave[x][y-1]])   goto android_n;
-       if (is_blank[cave[x-1][y+1]]) goto android_sw;
-       if (is_blank[cave[x][y+1]])   goto android_s;
-       if (is_blank[cave[x-1][y-1]]) goto android_nw;
-       if (is_blank[cave[x+1][y-1]]) goto android_ne;
-       if (is_blank[cave[x+1][y+1]]) goto android_se;
-       if (is_blank[cave[x-1][y]])   goto android_w;
+       if (is_android_blank[cave[x+1][y]])   goto android_e;
+       if (is_android_blank[cave[x][y-1]])   goto android_n;
+       if (is_android_blank[cave[x-1][y+1]]) goto android_sw;
+       if (is_android_blank[cave[x][y+1]])   goto android_s;
+       if (is_android_blank[cave[x-1][y-1]]) goto android_nw;
+       if (is_android_blank[cave[x+1][y-1]]) goto android_ne;
+       if (is_android_blank[cave[x+1][y+1]]) goto android_se;
+       if (is_android_blank[cave[x-1][y]])   goto android_w;
        goto android_move;
 
       case 7: /* W,SW,NW,N,E,SE,NE,S */
-       if (is_blank[cave[x-1][y]])   goto android_w;
-       if (is_blank[cave[x-1][y+1]]) goto android_sw;
-       if (is_blank[cave[x-1][y-1]]) goto android_nw;
-       if (is_blank[cave[x][y-1]])   goto android_n;
-       if (is_blank[cave[x+1][y]])   goto android_e;
-       if (is_blank[cave[x+1][y+1]]) goto android_se;
-       if (is_blank[cave[x+1][y-1]]) goto android_ne;
-       if (is_blank[cave[x][y+1]])   goto android_s;
+       if (is_android_blank[cave[x-1][y]])   goto android_w;
+       if (is_android_blank[cave[x-1][y+1]]) goto android_sw;
+       if (is_android_blank[cave[x-1][y-1]]) goto android_nw;
+       if (is_android_blank[cave[x][y-1]])   goto android_n;
+       if (is_android_blank[cave[x+1][y]])   goto android_e;
+       if (is_android_blank[cave[x+1][y+1]]) goto android_se;
+       if (is_android_blank[cave[x+1][y-1]]) goto android_ne;
+       if (is_android_blank[cave[x][y+1]])   goto android_s;
        goto android_move;
     }
   }
@@ -4472,7 +4517,7 @@ static void Lstone_fall(int x, int y)
     case Xeater_s:
     case Xeater_w:
       cave[x][y] = Ystone_sB;
-      next[x][y] = Xblank;
+      Lboom_next_new(x, y, Xblank);
       cave[x][y+1] = Yeater_stone;
       next[x][y+1] = Zeater;
       Lboom_eater_old(x, y+1);
@@ -4482,7 +4527,7 @@ static void Lstone_fall(int x, int y)
     case Xalien:
     case Xalien_pause:
       cave[x][y] = Ystone_sB;
-      next[x][y] = Xblank;
+      Lboom_next_new(x, y, Xblank);
       cave[x][y+1] = Yalien_stone;
       next[x][y+1] = Ztank;
       Lboom_tank_old(x, y+1);
@@ -4498,7 +4543,7 @@ 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;
+      Lboom_next_new(x, y, Xblank);
       cave[x][y+1] = Ybug_stone;
       next[x][y+1] = Zbug;
       Lboom_bug_old(x, y+1);
@@ -4514,7 +4559,7 @@ 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;
+      Lboom_next_new(x, y, Xblank);
       cave[x][y+1] = Ytank_stone;
       next[x][y+1] = Ztank;
       Lboom_tank_old(x, y+1);
@@ -4593,8 +4638,8 @@ static void Lstone_fall(int x, int y)
 
     case Xbomb:
     case Xbomb_pause:
-      cave[x][y] = Xstone;
-      next[x][y] = Xstone;
+      Lboom_cave_new(x, y, Xstone);
+      Lboom_next_new(x, y, Xstone);
       cave[x][y+1] = Ybomb_blank;
       next[x][y+1] = Ztank;
       Lboom_tank_old(x, y+1);
@@ -5673,6 +5718,9 @@ static void Lpush_emerald_e(int x, int y)
 
   switch (cave[x+1][y])
   {
+    case Zplayer:
+      if (!game_em.use_old_push_elements)
+       break;
     case Zborder:
     case Zbug:
     case Ztank:
@@ -5684,6 +5732,7 @@ static void Lpush_emerald_e(int x, int y)
     case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
+      Lpush_element_old(x, y, Xemerald);
       return;
 
 #ifdef ACID_ROLL
@@ -5715,6 +5764,9 @@ static void Lpush_emerald_w(int x, int y)
 
   switch (cave[x-1][y])
   {
+    case Zplayer:
+      if (!game_em.use_old_push_elements)
+       break;
     case Zborder:
     case Zbug:
     case Ztank:
@@ -5726,6 +5778,7 @@ static void Lpush_emerald_w(int x, int y)
     case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
+      Lpush_element_old(x, y, Xemerald);
       return;
 
 #ifdef ACID_ROLL
@@ -5757,6 +5810,9 @@ static void Lpush_diamond_e(int x, int y)
 
   switch (cave[x+1][y])
   {
+    case Zplayer:
+      if (!game_em.use_old_push_elements)
+       break;
     case Zborder:
     case Zbug:
     case Ztank:
@@ -5768,6 +5824,7 @@ static void Lpush_diamond_e(int x, int y)
     case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
+      Lpush_element_old(x, y, Xdiamond);
       return;
 
 #ifdef ACID_ROLL
@@ -5799,6 +5856,9 @@ static void Lpush_diamond_w(int x, int y)
 
   switch (cave[x-1][y])
   {
+    case Zplayer:
+      if (!game_em.use_old_push_elements)
+       break;
     case Zborder:
     case Zbug:
     case Ztank:
@@ -5810,6 +5870,7 @@ static void Lpush_diamond_w(int x, int y)
     case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
+      Lpush_element_old(x, y, Xdiamond);
       return;
 
 #ifdef ACID_ROLL
@@ -5841,6 +5902,9 @@ static void Lpush_stone_e(int x, int y)
 
   switch (cave[x+1][y])
   {
+    case Zplayer:
+      if (!game_em.use_old_push_elements)
+       break;
     case Zborder:
     case Zbug:
     case Ztank:
@@ -5852,6 +5916,7 @@ static void Lpush_stone_e(int x, int y)
     case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
+      Lpush_element_old(x, y, Xstone);
       return;
 
 #ifdef ACID_ROLL
@@ -5883,6 +5948,9 @@ static void Lpush_stone_w(int x, int y)
 
   switch (cave[x-1][y])
   {
+    case Zplayer:
+      if (!game_em.use_old_push_elements)
+       break;
     case Zborder:
     case Zbug:
     case Ztank:
@@ -5894,6 +5962,7 @@ static void Lpush_stone_w(int x, int y)
     case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
+      Lpush_element_old(x, y, Xstone);
       return;
 
 #ifdef ACID_ROLL
@@ -5925,6 +5994,9 @@ static void Lpush_bomb_e(int x, int y)
 
   switch (cave[x+1][y])
   {
+    case Zplayer:
+      if (!game_em.use_old_push_elements)
+       break;
     case Zborder:
     case Zbug:
     case Ztank:
@@ -5936,6 +6008,7 @@ static void Lpush_bomb_e(int x, int y)
     case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
+      Lpush_element_old(x, y, Xbomb);
       return;
 
 #ifdef ACID_ROLL
@@ -5967,6 +6040,9 @@ static void Lpush_bomb_w(int x, int y)
 
   switch (cave[x-1][y])
   {
+    case Zplayer:
+      if (!game_em.use_old_push_elements)
+       break;
     case Zborder:
     case Zbug:
     case Ztank:
@@ -5978,6 +6054,7 @@ static void Lpush_bomb_w(int x, int y)
     case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
+      Lpush_element_old(x, y, Xbomb);
       return;
 
 #ifdef ACID_ROLL
@@ -6009,6 +6086,9 @@ static void Lpush_nut_e(int x, int y)
 
   switch (cave[x+1][y])
   {
+    case Zplayer:
+      if (!game_em.use_old_push_elements)
+       break;
     case Zborder:
     case Zbug:
     case Ztank:
@@ -6020,6 +6100,7 @@ static void Lpush_nut_e(int x, int y)
     case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
+      Lpush_element_old(x, y, Xnut);
       return;
 
 #ifdef ACID_ROLL
@@ -6051,6 +6132,9 @@ static void Lpush_nut_w(int x, int y)
 
   switch (cave[x-1][y])
   {
+    case Zplayer:
+      if (!game_em.use_old_push_elements)
+       break;
     case Zborder:
     case Zbug:
     case Ztank:
@@ -6062,6 +6146,7 @@ static void Lpush_nut_w(int x, int y)
     case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
+      Lpush_element_old(x, y, Xnut);
       return;
 
 #ifdef ACID_ROLL
@@ -6093,6 +6178,9 @@ static void Lpush_spring_e(int x, int y)
 
   switch (cave[x+1][y])
   {
+    case Zplayer:
+      if (!game_em.use_old_push_elements)
+       break;
     case Zborder:
     case Zbug:
     case Ztank:
@@ -6104,6 +6192,7 @@ static void Lpush_spring_e(int x, int y)
     case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
+      Lpush_element_old(x, y, Xspring);
       return;
 
 #ifdef ACID_ROLL
@@ -6135,6 +6224,9 @@ static void Lpush_spring_w(int x, int y)
 
   switch (cave[x-1][y])
   {
+    case Zplayer:
+      if (!game_em.use_old_push_elements)
+       break;
     case Zborder:
     case Zbug:
     case Ztank:
@@ -6146,6 +6238,7 @@ static void Lpush_spring_w(int x, int y)
     case Xboom_tank:
     case Xboom_android:
     case Xboom_1:
+      Lpush_element_old(x, y, Xspring);
       return;
 
 #ifdef ACID_ROLL
@@ -7431,6 +7524,14 @@ static void logic_globals(void)
       next[x][y] = cave[x][y];
 }
 
+void logic_init(void)
+{
+  int splash_is_blank = !game_em.use_old_android;
+
+  is_android_blank[Xsplash_e] = splash_is_blank;
+  is_android_blank[Xsplash_w] = splash_is_blank;
+}
+
 void logic(void)
 {
   if (frame == 0)