added saving native BDCFF file with cheat code ":save-native-level"
[rocksndiamonds.git] / src / game_bd / bd_caveobject.c
index c02023976b1d6de13e15680aaa2b074dfc1648f1..b9c094251e33952afbf5a4bb4de3b2dcf5f31b3a 100644 (file)
@@ -14,9 +14,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <glib.h>
-#include <glib/gi18n.h>
-
 #include "main_bd.h"
 
 
@@ -32,125 +29,82 @@ GdObjectLevels gd_levels_mask[] =
 /* bdcff text description of object. caller should free string. */
 char *gd_object_get_bdcff(const GdObject *object)
 {
-  GString *str;
+  char *str = NULL;
   int j;
   const char *type;
 
   switch (object->type)
   {
     case GD_POINT:
-      return g_strdup_printf("Point=%d %d %s",
-                            object->x1, object->y1,
-                            gd_elements[object->element].filename);
+      return getStringPrint("Point=%d %d %s", object->x1, object->y1, gd_elements[object->element].filename);
 
     case GD_LINE:
-      return g_strdup_printf("Line=%d %d %d %d %s",
-                            object->x1, object->y1, object->x2, object->y2,
-                            gd_elements[object->element].filename);
+      return getStringPrint("Line=%d %d %d %d %s", object->x1, object->y1, object->x2, object->y2, gd_elements[object->element].filename);
 
     case GD_RECTANGLE:
-      return g_strdup_printf("Rectangle=%d %d %d %d %s",
-                            object->x1, object->y1, object->x2, object->y2,
-                            gd_elements[object->element].filename);
+      return getStringPrint("Rectangle=%d %d %d %d %s", object->x1, object->y1, object->x2, object->y2, gd_elements[object->element].filename);
 
     case GD_FILLED_RECTANGLE:
       /* if elements are not the same */
-      if (object->fill_element != object->element)
-       return g_strdup_printf("FillRect=%d %d %d %d %s %s",
-                              object->x1, object->y1, object->x2, object->y2,
-                              gd_elements[object->element].filename,
-                              gd_elements[object->fill_element].filename);
-
+      if (object->fill_element!=object->element)
+       return getStringPrint("FillRect=%d %d %d %d %s %s", object->x1, object->y1, object->x2, object->y2, gd_elements[object->element].filename, gd_elements[object->fill_element].filename);
       /* they are the same */
-      return g_strdup_printf("FillRect=%d %d %d %d %s",
-                            object->x1, object->y1, object->x2, object->y2,
-                            gd_elements[object->element].filename);
+      return getStringPrint("FillRect=%d %d %d %d %s", object->x1, object->y1, object->x2, object->y2, gd_elements[object->element].filename);
 
     case GD_RASTER:
-      return g_strdup_printf("Raster=%d %d %d %d %d %d %s",
-                            object->x1, object->y1,
-                            (object->x2 - object->x1) / object->dx + 1,
-                            (object->y2 - object->y1) / object->dy + 1,
-                            object->dx, object->dy,
-                            gd_elements[object->element].filename);
+      return getStringPrint("Raster=%d %d %d %d %d %d %s", object->x1, object->y1, (object->x2-object->x1)/object->dx+1, (object->y2-object->y1)/object->dy+1, object->dx, object->dy, gd_elements[object->element].filename);
 
     case GD_JOIN:
-      return g_strdup_printf("Add=%d %d %s %s",
-                            object->dx, object->dy,
-                            gd_elements[object->element].filename,
-                            gd_elements[object->fill_element].filename);
+      return getStringPrint("Add=%d %d %s %s", object->dx, object->dy, gd_elements[object->element].filename, gd_elements[object->fill_element].filename);
 
     case GD_FLOODFILL_BORDER:
-      return g_strdup_printf("BoundaryFill=%d %d %s %s",
-                            object->x1, object->y1,
-                            gd_elements[object->fill_element].filename,
-                            gd_elements[object->element].filename);
+      return getStringPrint("BoundaryFill=%d %d %s %s", object->x1, object->y1, gd_elements[object->fill_element].filename, gd_elements[object->element].filename);
 
     case GD_FLOODFILL_REPLACE:
-      return g_strdup_printf("FloodFill=%d %d %s %s",
-                            object->x1, object->y1,
-                            gd_elements[object->fill_element].filename,
-                            gd_elements[object->element].filename);
+      return getStringPrint("FloodFill=%d %d %s %s", object->x1, object->y1, gd_elements[object->fill_element].filename, gd_elements[object->element].filename);
 
     case GD_MAZE:
     case GD_MAZE_UNICURSAL:
     case GD_MAZE_BRAID:
-      switch (object->type)
+      switch(object->type)
       {
-       case GD_MAZE: type = "perfect"; break;
-       case GD_MAZE_UNICURSAL: type = "unicursal"; break;
-       case GD_MAZE_BRAID: type = "braid"; break;
-       default: break;
+       case GD_MAZE:
+         type = "perfect";
+         break;
+
+       case GD_MAZE_UNICURSAL:
+         type = "unicursal";
+         break;
+
+       case GD_MAZE_BRAID:
+         type = "braid";
+         break;
+
+       default:
+         /* never reached */
+         break;
       }
 
-      return g_strdup_printf("Maze=%d %d %d %d %d %d %d %d %d %d %d %d %s %s %s",
-                            object->x1, object->y1, object->x2, object->y2,
-                            object->dx, object->dy,
-                            object->horiz,
-                            object->seed[0],
-                            object->seed[1],
-                            object->seed[2],
-                            object->seed[3],
-                            object->seed[4],
-                            gd_elements[object->element].filename,
-                            gd_elements[object->fill_element].filename, type);
+      return getStringPrint("Maze=%d %d %d %d %d %d %d %d %d %d %d %d %s %s %s", object->x1, object->y1, object->x2, object->y2, object->dx, object->dy, object->horiz, object->seed[0], object->seed[1], object->seed[2], object->seed[3], object->seed[4], gd_elements[object->element].filename, gd_elements[object->fill_element].filename, type);
 
     case GD_RANDOM_FILL:
-      str = g_string_new(NULL);
-      /* seed and initial fill */
-      g_string_append_printf(str, "%s=%d %d %d %d %d %d %d %d %d %s",
-                            object->c64_random ? "RandomFillC64" : "RandomFill",
-                            object->x1, object->y1, object->x2, object->y2,
-                            object->seed[0],
-                            object->seed[1],
-                            object->seed[2],
-                            object->seed[3],
-                            object->seed[4],
-                            gd_elements[object->fill_element].filename);
+      appendStringPrint(&str, "%s=%d %d %d %d %d %d %d %d %d %s", object->c64_random?"RandomFillC64":"RandomFill", object->x1, object->y1, object->x2, object->y2, object->seed[0], object->seed[1], object->seed[2], object->seed[3], object->seed[4], gd_elements[object->fill_element].filename);
 
+      /* seed and initial fill */
       for (j = 0; j < 4; j++)
-      {
        if (object->random_fill_probability[j] != 0)
-         g_string_append_printf(str, " %s %d",
-                                gd_elements[object->random_fill[j]].filename,
-                                object->random_fill_probability[j]);
-      }
+         appendStringPrint(&str, " %s %d", gd_elements[object->random_fill[j]].filename, object->random_fill_probability[j]);
 
-      if (object->element!=O_NONE)
-       g_string_append_printf(str, " %s",
-                              gd_elements[object->element].filename);
+      if (object->element != O_NONE)
+       appendStringPrint(&str, " %s", gd_elements[object->element].filename);
 
-      /* free string but do not free char *; return char *. */
-      return g_string_free(str, FALSE);
+      return str;
 
     case GD_COPY_PASTE:
-      return g_strdup_printf("CopyPaste=%d %d %d %d %d %d %s %s",
-                            object->x1, object->y1, object->x2, object->y2,
-                            object->dx, object->dy,
-                            object->mirror ? "mirror" : "nomirror",
-                            object->flip?"flip":"noflip");
+      return getStringPrint("CopyPaste=%d %d %d %d %d %d %s %s", object->x1, object->y1, object->x2, object->y2, object->dx, object->dy, object->mirror?"mirror":"nomirror", object->flip?"flip":"noflip");
 
     case NONE:
+      /* never reached */
       break;
   }
 
@@ -291,7 +245,7 @@ GdObject *gd_object_new_floodfill_replace(GdObjectLevels levels, int x1, int y1,
 
 GdObject *gd_object_new_maze(GdObjectLevels levels, int x1, int y1, int x2, int y2,
                             int wall_w, int path_w, GdElement wall_e, GdElement path_e,
-                            int horiz_percent, const gint32 seed[5])
+                            int horiz_percent, const int seed[5])
 {
   int i;
   GdObject *newobj = checked_calloc(sizeof(GdObject));
@@ -316,7 +270,7 @@ GdObject *gd_object_new_maze(GdObjectLevels levels, int x1, int y1, int x2, int
 
 GdObject *gd_object_new_maze_unicursal(GdObjectLevels levels, int x1, int y1, int x2, int y2,
                                       int wall_w, int path_w, GdElement wall_e, GdElement path_e,
-                                      int horiz_percent, const gint32 seed[5])
+                                      int horiz_percent, const int seed[5])
 {
   int i;
   GdObject *newobj = checked_calloc(sizeof(GdObject));
@@ -341,7 +295,7 @@ GdObject *gd_object_new_maze_unicursal(GdObjectLevels levels, int x1, int y1, in
 
 GdObject *gd_object_new_maze_braid(GdObjectLevels levels, int x1, int y1, int x2, int y2,
                                   int wall_w, int path_w, GdElement wall_e, GdElement path_e,
-                                  int horiz_percent, const gint32 seed[5])
+                                  int horiz_percent, const int seed[5])
 {
   int i;
   GdObject *newobj = checked_calloc(sizeof(GdObject));
@@ -365,8 +319,8 @@ GdObject *gd_object_new_maze_braid(GdObjectLevels levels, int x1, int y1, int x2
 }
 
 GdObject *gd_object_new_random_fill(GdObjectLevels levels, int x1, int y1, int x2, int y2,
-                                   const gint32 seed[5], GdElement initial,
-                                   const GdElement random[4], const gint32 prob[4],
+                                   const int seed[5], GdElement initial,
+                                   const GdElement random[4], const int prob[4],
                                    GdElement replace_only, boolean c64)
 {
   int i;
@@ -441,7 +395,7 @@ GdObject *gd_object_new_from_string(char *str)
     {
       object.element = gd_get_element_from_string(elem0);
 
-      return g_memdup(&object, sizeof (GdObject));
+      return get_memcpy(&object, sizeof (GdObject));
     }
 
     return NULL;
@@ -455,7 +409,7 @@ GdObject *gd_object_new_from_string(char *str)
     {
       object.element = gd_get_element_from_string(elem0);
 
-      return g_memdup(&object, sizeof (GdObject));
+      return get_memcpy(&object, sizeof (GdObject));
     }
 
     return NULL;
@@ -469,7 +423,7 @@ GdObject *gd_object_new_from_string(char *str)
       object.type = GD_RECTANGLE;
       object.element = gd_get_element_from_string (elem0);
 
-      return g_memdup(&object, sizeof (GdObject));
+      return get_memcpy(&object, sizeof (GdObject));
     }
 
     return NULL;
@@ -488,14 +442,14 @@ GdObject *gd_object_new_from_string(char *str)
       object.element = gd_get_element_from_string (elem0);
       object.fill_element = gd_get_element_from_string (elem1);
 
-      return g_memdup(&object, sizeof (GdObject));
+      return get_memcpy(&object, sizeof (GdObject));
     }
 
     if (paramcount == 5)
     {
       object.element = object.fill_element = gd_get_element_from_string (elem0);
 
-      return g_memdup(&object, sizeof (GdObject));
+      return get_memcpy(&object, sizeof (GdObject));
     }
 
     return NULL;
@@ -515,7 +469,7 @@ GdObject *gd_object_new_from_string(char *str)
       object.type = GD_RASTER;
       object.element = gd_get_element_from_string (elem0);
 
-      return g_memdup(&object, sizeof (GdObject));
+      return get_memcpy(&object, sizeof (GdObject));
     }
 
     return NULL;
@@ -531,7 +485,7 @@ GdObject *gd_object_new_from_string(char *str)
       object.element = gd_get_element_from_string (elem0);
       object.fill_element = gd_get_element_from_string (elem1);
 
-      return g_memdup(&object, sizeof (GdObject));
+      return get_memcpy(&object, sizeof (GdObject));
     }
 
     return NULL;
@@ -546,7 +500,7 @@ GdObject *gd_object_new_from_string(char *str)
       object.fill_element = gd_get_element_from_string (elem0);
       object.element = gd_get_element_from_string (elem1);
 
-      return g_memdup(&object, sizeof (GdObject));
+      return get_memcpy(&object, sizeof (GdObject));
     }
 
     return NULL;
@@ -561,7 +515,7 @@ GdObject *gd_object_new_from_string(char *str)
       object.fill_element = gd_get_element_from_string (elem0);
       object.element = gd_get_element_from_string (elem1);
 
-      return g_memdup(&object, sizeof (GdObject));
+      return get_memcpy(&object, sizeof (GdObject));
     }
 
     return NULL;
@@ -591,7 +545,7 @@ GdObject *gd_object_new_from_string(char *str)
       object.element = gd_get_element_from_string (elem0);
       object.fill_element = gd_get_element_from_string (elem1);
 
-      return g_memdup(&object, sizeof (GdObject));
+      return get_memcpy(&object, sizeof (GdObject));
     }
 
     return NULL;
@@ -615,10 +569,10 @@ GdObject *gd_object_new_from_string(char *str)
       return NULL;
 
     if (words)
-      g_strfreev(words);
+      freeStringArray(words);
 
     words = getSplitStringArray(param, " ", -1);
-    l = g_strv_length(words);
+    l = getStringArrayLength(words);
 
     if (l < 10 || l > 19)
       return NULL;
@@ -647,7 +601,7 @@ GdObject *gd_object_new_from_string(char *str)
     if (l > 10 && l % 2 == 1)
       object.element = gd_get_element_from_string(words[l - 1]);
 
-    return g_memdup(&object, sizeof (GdObject));
+    return get_memcpy(&object, sizeof (GdObject));
   }
 
   /* COPY PASTE OBJECT */
@@ -678,7 +632,7 @@ GdObject *gd_object_new_from_string(char *str)
     else
       Warn("invalid setting for copypaste flip property: %s", flip);
 
-    return g_memdup(&object, sizeof(GdObject));
+    return get_memcpy(&object, sizeof(GdObject));
   }
 
   return NULL;
@@ -951,7 +905,7 @@ static void draw_join(GdCave *cave, const GdObject *object)
 
 /* create a maze in a boolean **maze. */
 /* recursive algorithm. */
-static void mazegen(GRand *rand, boolean **maze, int width, int height, int x, int y, int horiz)
+static void mazegen(GdRand *rand, boolean **maze, int width, int height, int x, int y, int horiz)
 {
   int dirmask = 15;
 
@@ -961,15 +915,15 @@ static void mazegen(GRand *rand, boolean **maze, int width, int height, int x, i
     int dir;
 
     /* horiz or vert */
-    dir = g_rand_int_range(rand, 0, 100) <horiz ? 2 : 0;
+    dir = gd_rand_int_range(rand, 0, 100) < horiz ? 2 : 0;
 
     /* if no horizontal movement possible, choose vertical */
     if (dir == 2 && (dirmask & 12) == 0)
       dir = 0;
-    else if (dir == 0 && (dirmask&3) == 0)    /* and vice versa */
+    else if (dir == 0 && (dirmask & 3) == 0)    /* and vice versa */
       dir = 2;
 
-    dir += g_rand_int_range(rand, 0, 2);                /* dir */
+    dir += gd_rand_int_range(rand, 0, 2);                /* dir */
     if (dirmask & (1 << dir))
     {
       dirmask &= ~(1 << dir);
@@ -1012,7 +966,7 @@ static void mazegen(GRand *rand, boolean **maze, int width, int height, int x, i
   }
 }
 
-static void braidmaze(GRand *rand, boolean **maze, int w, int h)
+static void braidmaze(GdRand *rand, boolean **maze, int w, int h)
 {
   int x, y;
 
@@ -1060,7 +1014,7 @@ static void braidmaze(GRand *rand, boolean **maze, int w, int h)
       if (closed == 3 && dirs != 0)
       {
        /* make up a random direction, and open in that direction, so dead end is removed */
-       int dir = closed_dirs[g_rand_int_range(rand, 0, dirs)];
+       int dir = closed_dirs[gd_rand_int_range(rand, 0, dirs)];
 
        switch (dir)
        {
@@ -1088,7 +1042,7 @@ static void draw_maze(GdCave *cave, const GdObject *object, int level)
   int y2 = object->y2;
   int w, h, path, wall;
   int xk, yk;
-  GRand *rand;
+  GdRand *rand;
   int i,j;
 
   /* change coordinates if not in correct order */
@@ -1151,8 +1105,8 @@ static void draw_maze(GdCave *cave, const GdObject *object, int level)
   /* start generation, if map is big enough.
      otherwise the application would crash, as the editor places maze objects
      during mouse click & drag that have no sense */
-  rand = g_rand_new_with_seed(object->seed[level] == -1 ?
-                             g_rand_int(cave->random) : object->seed[level]);
+  rand = gd_rand_new_with_seed(object->seed[level] == -1 ?
+                              gd_rand_int(cave->random) : object->seed[level]);
 
   if (w >= 1 && h >= 1)
     mazegen(rand, map, w, h, 0, 0, object->horiz);
@@ -1160,7 +1114,7 @@ static void draw_maze(GdCave *cave, const GdObject *object, int level)
   if (object->type == GD_MAZE_BRAID)
     braidmaze(rand, map, w, h);
 
-  g_rand_free(rand);
+  gd_rand_free(rand);
 
   if (w >= 1 && h >= 1 && object->type == GD_MAZE_UNICURSAL)
   {
@@ -1265,17 +1219,17 @@ static void draw_random_fill(GdCave *cave, const GdObject *object, int level)
   int y1 = object->y1;
   int x2 = object->x2;
   int y2 = object->y2;
-  GRand *rand;
+  GdRand *rand;
   GdC64RandomGenerator c64_rand;
-  guint32 seed;
+  unsigned int seed;
 
   /* -1 means that it should be different every time played. */
   if (object->seed[level] == -1)
-    seed = g_rand_int(cave->random);
+    seed = gd_rand_int(cave->random);
   else
     seed = object->seed[level];
 
-  rand = g_rand_new_with_seed(seed);
+  rand = gd_rand_new_with_seed(seed);
   /* for c64 random, use the 2*8 lsb. */
   gd_c64_random_set_seed(&c64_rand, seed / 256 % 256, seed % 256);
 
@@ -1306,7 +1260,7 @@ static void draw_random_fill(GdCave *cave, const GdObject *object, int level)
        randm = gd_c64_random(&c64_rand);
       else
        /* use the much better glib random generator */
-       randm = g_rand_int_range(rand, 0, 256);
+       randm = gd_rand_int_range(rand, 0, 256);
 
       element = object->fill_element;
       if (randm < object->random_fill_probability[0])
@@ -1318,13 +1272,13 @@ static void draw_random_fill(GdCave *cave, const GdObject *object, int level)
       if (randm < object->random_fill_probability[3])
        element = object->random_fill[3];
 
-      if (object->element==O_NONE ||
+      if (object->element == O_NONE ||
          gd_cave_get_rc(cave, x, y) == object->element)
        gd_cave_store_rc(cave, x, y, element, object);
     }
   }
 
-  g_rand_free(rand);
+  gd_rand_free(rand);
 }
 
 
@@ -1444,22 +1398,22 @@ void gd_cave_draw_object(GdCave *cave, const GdObject *object, int level)
 }
 
 /* load cave to play... also can be called rendering the cave elements */
-GdCave *gd_cave_new_rendered(const GdCave *data, const int level, const guint32 seed)
+GdCave *gd_cave_new_rendered(const GdCave *data, const int level, const unsigned int seed)
 {
   GdCave *cave;
   GdElement element;
   int x, y;
-  GList *iter;
+  List *iter;
 
   /* make a copy */
   cave = gd_cave_new_from_cave(data);
   cave->rendered = level + 1;
 
   cave->render_seed = seed;
-  cave->random = g_rand_new_with_seed(cave->render_seed);
+  cave->random = gd_rand_new_with_seed(cave->render_seed);
 
   /* maps needed during drawing and gameplay */
-  cave->objects_order = gd_cave_map_new(cave, gpointer);
+  cave->objects_order = gd_cave_map_new(cave, void *);
 
   cave->time                   = data->level_time[level];
   cave->timevalue              = data->level_timevalue[level];
@@ -1484,8 +1438,8 @@ GdCave *gd_cave_new_rendered(const GdCave *data, const int level, const guint32
     /* IF CAVE HAS NO MAP, USE THE RANDOM NUMBER GENERATOR */
     /* init c64 randomgenerator */
     if (data->level_rand[level] < 0)
-      gd_cave_c64_random_set_seed(cave, g_rand_int_range(cave->random, 0, 256),
-                                 g_rand_int_range(cave->random, 0, 256));
+      gd_cave_c64_random_set_seed(cave, gd_rand_int_range(cave->random, 0, 256),
+                                 gd_rand_int_range(cave->random, 0, 256));
     else
       gd_cave_c64_random_set_seed(cave, 0, data->level_rand[level]);
 
@@ -1502,7 +1456,7 @@ GdCave *gd_cave_new_rendered(const GdCave *data, const int level, const guint32
 
        if (data->level_rand[level] < 0)
          /* use the much better glib random generator */
-         randm = g_rand_int_range(cave->random, 0, 256);
+         randm = gd_rand_int_range(cave->random, 0, 256);
        else
          /* use c64 */
          randm = gd_cave_c64_random(cave);
@@ -1553,7 +1507,7 @@ GdCave *gd_cave_new_rendered(const GdCave *data, const int level, const guint32
   }
 
   /* render cave objects above random data or map */
-  for (iter = data->objects; iter; iter = g_list_next(iter))
+  for (iter = data->objects; iter; iter = list_next(iter))
   {
     GdObject *object = (GdObject *)iter->data;
 
@@ -1603,6 +1557,6 @@ void gd_flatten_cave(GdCave *cave, const int level)
   gd_cave_free(rendered);
 
   /* forget objects */
-  g_list_foreach(cave->objects, (GFunc) free, NULL);
+  list_foreach(cave->objects, (list_fn) free, NULL);
   cave->objects = NULL;
 }