fixed some element class names
[rocksndiamonds.git] / src / game_bd / bd_caveengine.c
index 1fe5b2b017c8dee40e53d71d888736ed05e6f954..bfe796f7f3aa77428239e43a3b48dde036014096 100644 (file)
@@ -30,8 +30,6 @@
  * The player_get function will also behave for lava as it does for space.
  */
 
-#include <glib.h>
-
 #include "main_bd.h"
 
 
@@ -303,6 +301,38 @@ static void play_sound_of_element_pushing(GdCave *cave, GdElement element, int x
   }
 }
 
+static inline int getx(const GdCave *cave, const int x, const int y)
+{
+  return cave->getx(cave, x, y);
+}
+
+static inline int gety(const GdCave *cave, const int x, const int y)
+{
+  return cave->gety(cave, x, y);
+}
+
+/* perfect (non-lineshifting) GET x/y functions; returns range corrected x/y position */
+static inline int getx_perfect(const GdCave *cave, const int x, const int y)
+{
+  return (x + cave->w) % cave->w;
+}
+
+static inline int gety_perfect(const GdCave *cave, const int x, const int y)
+{
+  return (y + cave->h) % cave->h;
+}
+
+/* line shifting GET x/y function; returns range corrected x/y position */
+static inline int getx_shift(const GdCave *cave, int x, int y)
+{
+  return (x + cave->w) % cave->w;
+}
+
+static inline int gety_shift(const GdCave *cave, int x, int y)
+{
+  return ((x < 0 ? y - 1 : x >= cave->w ? y + 1 : y) + cave->h) % cave->h;
+}
+
 static inline GdElement *getp(const GdCave *cave, const int x, const int y)
 {
   return cave->getp(cave, x, y);
@@ -489,11 +519,24 @@ static inline boolean is_element_dir(const GdCave *cave, const int x, const int
 static inline boolean is_space_dir(const GdCave *cave, const int x, const int y,
                                   const GdDirection dir)
 {
-  GdElement e = get_dir(cave, x, y, dir)&O_MASK;
+  GdElement e = get_dir(cave, x, y, dir) & O_MASK;
 
   return (e == O_SPACE || e == O_LAVA);
 }
 
+static inline void store_dir_buffer(GdCave *cave, const int x, const int y, const GdDirection dir)
+{
+  /* raw values without range correction */
+  int raw_x = x + gd_dx[dir];
+  int raw_y = y + gd_dy[dir];
+  /* final values with range correction */
+  int new_x = getx(cave, raw_x, raw_y);
+  int new_y = gety(cave, raw_x, raw_y);
+  int new_dir = (dir > GD_MV_TWICE ? dir - GD_MV_TWICE : dir);
+
+  game_bd.game->dir_buffer[new_y][new_x] = new_dir;
+}
+
 /* store an element at the given position */
 static inline void store(GdCave *cave, const int x, const int y, const GdElement element)
 {
@@ -519,13 +562,15 @@ static inline void store_sc(GdCave *cave, const int x, const int y, const GdElem
 static inline void store_dir(GdCave *cave, const int x, const int y,
                             const GdDirection dir, const GdElement element)
 {
-  store(cave, x + gd_dx[dir], y + gd_dy[dir], element|SCANNED);
+  store_dir_buffer(cave, x, y, dir);
+  store(cave, x + gd_dx[dir], y + gd_dy[dir], element | SCANNED);
 }
 
 /* store an element to a neighbouring cell */
 static inline void store_dir_no_scanned(GdCave *cave, const int x, const int y,
                                        const GdDirection dir, const GdElement element)
 {
+  store_dir_buffer(cave, x, y, dir);
   store(cave, x + gd_dx[dir], y + gd_dy[dir], element);
 }
 
@@ -1053,7 +1098,7 @@ static boolean do_push(GdCave *cave, int x, int y, GdDirection player_move, bool
        }
 
        if (is_space_dir(cave, x, y, GD_MV_TWICE + player_move) &&
-           g_rand_int_range(cave->random, 0, 1000000) < prob)
+           gd_rand_int_range(cave->random, 0, 1000000) < prob)
        {
          /* if decided that he will be able to push, */
          store_dir(cave, x, y, GD_MV_TWICE + player_move, what);
@@ -1300,10 +1345,10 @@ static boolean do_fall_try_magic(GdCave *cave, int x, int y,
   {
     play_sound_of_element(cave, O_DIAMOND, x, y);    /* always play diamond sound */
 
-    if (cave->magic_wall_state==GD_MW_DORMANT)
+    if (cave->magic_wall_state == GD_MW_DORMANT)
       cave->magic_wall_state = GD_MW_ACTIVE;
 
-    if (cave->magic_wall_state==GD_MW_ACTIVE &&
+    if (cave->magic_wall_state == GD_MW_ACTIVE &&
        is_space_dir(cave, x, y, GD_MV_TWICE+fall_dir))
     {
       /* if magic wall active and place underneath, it turns element
@@ -1517,9 +1562,17 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
 
   /* set cave get function; to implement perfect or lineshifting borders */
   if (cave->lineshift)
+  {
     cave->getp = getp_shift;
+    cave->getx = getx_shift;
+    cave->gety = gety_shift;
+  }
   else
+  {
     cave->getp = getp_perfect;
+    cave->getx = getx_perfect;
+    cave->gety = gety_perfect;
+  }
 
   /* increment this. if the scan routine comes across player, clears it (sets to zero). */
   if (cave->player_seen_ago < 100)
@@ -1554,7 +1607,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
       for (x = 0; x < cave->w; x++)
       {
        /* timer for the cell > 0? */
-       if (cave->hammered_reappear[y][x]>0)
+       if (cave->hammered_reappear[y][x] > 0)
        {
          /* decrease timer */
          cave->hammered_reappear[y][x]--;
@@ -1600,7 +1653,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
     {
       /* if we find a scanned element, change it to the normal one, and that's all. */
       /* this is required, for example for chasing stones, which have moved, always passing slime! */
-      if (get(cave, x, y)&SCANNED)
+      if (get(cave, x, y) & SCANNED)
       {
        store(cave, x, y, get(cave, x, y) & ~SCANNED);
 
@@ -1625,7 +1678,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
          cave->player_seen_ago = 0;
          /* bd4 intermission caves have many players. so if one of them has exited,
           * do not change the flag anymore. so this if () is needed */
-         if (cave->player_state!=GD_PL_EXITED)
+         if (cave->player_state != GD_PL_EXITED)
            cave->player_state = GD_PL_LIVING;
 
          /* check for pneumatic hammer things */
@@ -1669,8 +1722,11 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
            /* try to push element; if successful, break  */
            push = do_push(cave, x, y, player_move, player_fire);
            if (push)
+           {
              remains = O_SPACE;
+           }
            else
+           {
              switch (what)
              {
                case O_BOMB:
@@ -1718,9 +1774,10 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
                default:
                  /* get element - process others.
                     if cannot get, player_get_element will return the same */
-                 remains = player_get_element (cave, what, x, y);
+                 remains = player_get_element(cave, what, x, y);
                  break;
              }
+           }
 
            if (remains != what || remains == O_SPACE)
            {
@@ -1785,7 +1842,9 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
 
            /* player fire is false... */
            if (do_push(cave, x, y, player_move, FALSE))
+           {
              remains = O_SPACE;
+           }
            else
            {
              switch (what)
@@ -1795,10 +1854,10 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
                     player_move parameter) */
                  /* only allow changing direction if the new dir is not diagonal */
                  if (cave->gravity_switch_active &&
-                     (player_move==GD_MV_LEFT ||
-                      player_move==GD_MV_RIGHT ||
-                      player_move==GD_MV_UP ||
-                      player_move==GD_MV_DOWN))
+                     (player_move == GD_MV_LEFT ||
+                      player_move == GD_MV_RIGHT ||
+                      player_move == GD_MV_UP ||
+                      player_move == GD_MV_DOWN))
                  {
                    gd_sound_play(cave, GD_S_SWITCH_GRAVITY, what, x, y);
                    cave->gravity_will_change =
@@ -1837,7 +1896,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
          cave->player_seen_ago = 0;
          /* bd4 intermission caves have many players. so if one of them has exited,
           * do not change the flag anymore. so this if () is needed */
-         if (cave->player_state!=GD_PL_EXITED)
+         if (cave->player_state != GD_PL_EXITED)
            cave->player_state = GD_PL_LIVING;
 
          if (player_fire)
@@ -1860,7 +1919,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
          }
 
          cave->player_seen_ago = 0;
-         if (cave->player_state!=GD_PL_EXITED)
+         if (cave->player_state != GD_PL_EXITED)
            cave->player_state = GD_PL_LIVING;
 
          /* if hammering time is up, becomes a normal player again. */
@@ -2199,7 +2258,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
          {
            const GdDirection *creature_move;
            boolean ccw = rotates_ccw(cave, x, y);    /* check if default is counterclockwise */
-           GdElement base;    /* base element number (which is like O_***_1) */
+           GdElement base = -1;    /* base element number (which is like O_***_1) */
            int dir, dirn, dirp;    /* direction */
 
            if (get(cave, x, y) >= O_FIREFLY_1 &&
@@ -2218,7 +2277,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
                     get(cave, x, y) <= O_ALT_BUTTER_4)
              base = O_ALT_BUTTER_1;
 
-           dir = get(cave, x, y)-base;    /* facing where */
+           dir = get(cave, x, y) - base;    /* facing where */
            creature_move = cave->creatures_backwards ? creature_chdir : creature_dir;
 
            /* now change direction if backwards */
@@ -2276,7 +2335,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
          {
            int px = cave->px[0];
            int py = cave->py[0];
-           boolean horizontal = g_rand_boolean(cave->random);
+           boolean horizontal = gd_rand_boolean(cave->random);
            boolean dont_move = FALSE;
            int i = 3;
 
@@ -2460,7 +2519,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
            int i;
            GdElement made_sound_of = O_NONE;
 
-           for (i = 0; i < G_N_ELEMENTS (biter_try); i++)
+           for (i = 0; i < ARRAY_SIZE (biter_try); i++)
            {
              if (is_element_dir(cave, x, y, biter_move[dir], biter_try[i]))
              {
@@ -2485,7 +2544,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
              }
            }
 
-           if (i == G_N_ELEMENTS(biter_try))
+           if (i == ARRAY_SIZE(biter_try))
              /* i = number of elements in array: could not move, so just turn */
              store(cave, x, y, O_BITER_1 + dirp);
            else if (biter_try[i] == O_STONE)
@@ -2575,7 +2634,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
            /* is space over the bladder? */
            if (is_space_dir(cave, x, y, opposite[grav_compat]))
            {
-             if (get(cave, x, y)==O_BLADDER_8)
+             if (get(cave, x, y) == O_BLADDER_8)
              {
                /* if it is a bladder 8, really move up */
                move(cave, x, y, opposite[grav_compat], O_BLADDER_1);
@@ -2650,7 +2709,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
              };
              GdDirection random_dir;
 
-             random_dir = dirs[g_rand_int_range(cave->random, 0, G_N_ELEMENTS(dirs))];
+             random_dir = dirs[gd_rand_int_range(cave->random, 0, ARRAY_SIZE(dirs))];
              if (is_space_dir(cave, x, y, random_dir))
              {
                move(cave, x, y, random_dir, O_GHOST);
@@ -2693,11 +2752,11 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
                }
 
              /* if alive, check in which dir to grow (or not) */
-             if (cave->amoeba_state==GD_AM_AWAKE)
+             if (cave->amoeba_state == GD_AM_AWAKE)
              {
-               if (g_rand_int_range(cave->random, 0, 1000000) < cave->amoeba_growth_prob)
+               if (gd_rand_int_range(cave->random, 0, 1000000) < cave->amoeba_growth_prob)
                {
-                 switch (g_rand_int_range(cave->random, 0, 4))
+                 switch (gd_rand_int_range(cave->random, 0, 4))
                  {
                    /* decided to grow, choose a random direction. */
                    case 0:    /* let this be up. numbers indifferent. */
@@ -2763,9 +2822,9 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
 
                /* if it is alive, decide if it attempts to grow */
                if (cave->amoeba_2_state == GD_AM_AWAKE)
-                 if (g_rand_int_range(cave->random, 0, 1000000) < cave->amoeba_2_growth_prob)
+                 if (gd_rand_int_range(cave->random, 0, 1000000) < cave->amoeba_2_growth_prob)
                  {
-                   switch (g_rand_int_range(cave->random, 0, 4))
+                   switch (gd_rand_int_range(cave->random, 0, 4))
                    {
                      /* decided to grow, choose a random direction. */
                      case 0:    /* let this be up. numbers indifferent. */
@@ -2796,7 +2855,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
 
        case O_ACID:
          /* choose randomly, if it spreads */
-         if (g_rand_int_range(cave->random, 0, 1000000) <= cave->acid_spread_ratio)
+         if (gd_rand_int_range(cave->random, 0, 1000000) <= cave->acid_spread_ratio)
          {
            /* the current one explodes */
            store(cave, x, y, cave->acid_turns_to);
@@ -2857,8 +2916,8 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
          if (((get(cave, x, y) == O_H_EXPANDING_WALL ||
                get(cave, x, y) == O_H_EXPANDING_STEEL_WALL) &&
               !cave->expanding_wall_changed) ||
-             ((get(cave, x, y)==O_V_EXPANDING_WALL ||
-               get(cave, x, y)==O_V_EXPANDING_STEEL_WALL) &&
+             ((get(cave, x, y) == O_V_EXPANDING_WALL ||
+               get(cave, x, y) == O_V_EXPANDING_STEEL_WALL) &&
               cave->expanding_wall_changed))
          {
            if (is_space_dir(cave, x, y, GD_MV_LEFT))
@@ -2915,21 +2974,21 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
 #if 1
          ; // to make compilers happy ...
 #else
-         g_print("Step[%03d]", cave->frame); /* XXX */
+         Info("Step[%03d]", cave->frame); /* XXX */
 #endif
          int rrr = gd_cave_c64_random(cave);
 #if 1
 #else
-         g_print(".Rand[%03d].Perm[%03d].Result[%d]\n", rrr, cave->slime_permeability_c64,
-                 (rrr & cave->slime_permeability_c64) == 0);
+         Info(".Rand[%03d].Perm[%03d].Result[%d]\n", rrr, cave->slime_permeability_c64,
+              (rrr & cave->slime_permeability_c64) == 0);
 #endif
          /*
-          * unpredictable: g_rand_int
+          * unpredictable: gd_rand_int
           * predictable: c64 predictable random generator.
           *    for predictable, a random number is generated,
           *    whether or not it is even possible that the stone will be able to pass.
           */
-         if (cave->slime_predictable ? ((rrr /* XXX */ & cave->slime_permeability_c64) == 0) : g_rand_int_range(cave->random, 0, 1000000) < cave->slime_permeability)
+         if (cave->slime_predictable ? ((rrr /* XXX */ & cave->slime_permeability_c64) == 0) : gd_rand_int_range(cave->random, 0, 1000000) < cave->slime_permeability)
          {
            GdDirection grav = cave->gravity;
            GdDirection oppos = opposite[cave->gravity];
@@ -2983,13 +3042,13 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
                  store_dir(cave, x, y, oppos, O_BLADDER_1);
                  play_sound_of_element(cave, O_SLIME, x, y);
                }
-               else if (get_dir(cave, x, y, grav)==O_FLYING_STONE)
+               else if (get_dir(cave, x, y, grav) == O_FLYING_STONE)
                {
                  store_dir(cave, x, y, grav, O_SPACE);
                  store_dir(cave, x, y, oppos, O_FLYING_STONE_F);
                  play_sound_of_element(cave, O_SLIME, x, y);
                }
-               else if (get_dir(cave, x, y, grav)==O_FLYING_DIAMOND)
+               else if (get_dir(cave, x, y, grav) == O_FLYING_DIAMOND)
                {
                  store_dir(cave, x, y, grav, O_SPACE);
                  store_dir(cave, x, y, oppos, O_FLYING_DIAMOND_F);
@@ -3140,7 +3199,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
              O_WAITING_STONE, O_BITER_1
            };
 
-           store(cave, x, y, ghost_explode[g_rand_int_range(cave->random, 0, G_N_ELEMENTS(ghost_explode))]);
+           store(cave, x, y, ghost_explode[gd_rand_int_range(cave->random, 0, ARRAY_SIZE(ghost_explode))]);
          }
          break;
 
@@ -3306,7 +3365,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
   /* this loop finds the coordinates of the player. needed for scrolling and chasing stone.*/
   /* but we only do this, if a living player was found. if not yet, the setup
      routine coordinates are used */
-  if (cave->player_state==GD_PL_LIVING)
+  if (cave->player_state == GD_PL_LIVING)
   {
     if (cave->active_is_first_found)
     {
@@ -3343,14 +3402,14 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire,
   }
 
   /* record coordinates of player for chasing stone */
-  for (i = 0; i < G_N_ELEMENTS(cave->px) - 1; i++)
+  for (i = 0; i < ARRAY_SIZE(cave->px) - 1; i++)
   {
     cave->px[i] = cave->px[i + 1];
     cave->py[i] = cave->py[i + 1];
   }
 
-  cave->px[G_N_ELEMENTS(cave->px) - 1] = cave->player_x;
-  cave->py[G_N_ELEMENTS(cave->py) - 1] = cave->player_y;
+  cave->px[ARRAY_SIZE(cave->px) - 1] = cave->player_x;
+  cave->py[ARRAY_SIZE(cave->py) - 1] = cave->player_y;
 
   /* SCHEDULING */