*/
GdCave *gd_cave_new(void)
{
- int i;
GdCave *cave;
cave = checked_calloc(sizeof(GdCave));
/* hash table which stores unknown tags as strings. */
cave->tags = g_hash_table_new_full(gd_str_case_hash, gd_str_case_equal, free, free);
- /* for strings */
- for (i = 0; gd_cave_properties[i].identifier != NULL; i++)
- if (gd_cave_properties[i].type == GD_TYPE_LONGSTRING)
- G_STRUCT_MEMBER(GString *, cave, gd_cave_properties[i].offset) = g_string_new(NULL);
-
gd_cave_set_gdash_defaults(cave);
return cave;
if (cave->random) /* random generator is a GRand * */
g_rand_free(cave->random);
- /* free GStrings */
+ /* free strings */
for (i = 0; gd_cave_properties[i].identifier != NULL; i++)
- if (gd_cave_properties[i].type==GD_TYPE_LONGSTRING)
- g_string_free(G_STRUCT_MEMBER(GString *, cave, gd_cave_properties[i].offset), TRUE);
+ if (gd_cave_properties[i].type == GD_TYPE_LONGSTRING)
+ checked_free(G_STRUCT_MEMBER(char *, cave, gd_cave_properties[i].offset));
/* map */
gd_cave_map_free(cave->map);
/* for longstrings */
for (i = 0; gd_cave_properties[i].identifier != NULL; i++)
- if (gd_cave_properties[i].type==GD_TYPE_LONGSTRING)
- G_STRUCT_MEMBER(GString *, dest, gd_cave_properties[i].offset) =
- g_string_new(G_STRUCT_MEMBER(GString *, src, gd_cave_properties[i].offset)->str);
+ if (gd_cave_properties[i].type == GD_TYPE_LONGSTRING)
+ G_STRUCT_MEMBER(char *, dest, gd_cave_properties[i].offset) =
+ getStringCopy(G_STRUCT_MEMBER(char *, src, gd_cave_properties[i].offset));
/* no reason to copy this */
dest->objects_order = NULL;
case O_INBOX:
/* shrink only lines, which have only ONE player or outbox.
this is for bd4 intermission 2, for example. */
- if (empty==STEEL_OR_OTHER)
+ if (empty == STEEL_OR_OTHER)
empty = NO_SHRINK;
- if (empty==STEEL_ONLY)
+ if (empty == STEEL_ONLY)
empty = STEEL_OR_OTHER;
break;
case O_PRE_OUTBOX:
case O_PRE_INVIS_OUTBOX:
case O_INBOX:
- if (empty==STEEL_OR_OTHER)
+ if (empty == STEEL_OR_OTHER)
empty = NO_SHRINK;
- if (empty==STEEL_ONLY)
+ if (empty == STEEL_ONLY)
empty = STEEL_OR_OTHER;
break;
case O_PRE_OUTBOX:
case O_PRE_INVIS_OUTBOX:
case O_INBOX:
- if (empty==STEEL_OR_OTHER)
+ if (empty == STEEL_OR_OTHER)
empty = NO_SHRINK;
- if (empty==STEEL_ONLY)
+ if (empty == STEEL_ONLY)
empty = STEEL_OR_OTHER;
break;
rep = checked_calloc(sizeof(GdReplay));
- /* create dynamic objects */
- rep->comment = g_string_new(NULL);
rep->movements = g_byte_array_new();
return rep;
rep = g_memdup(orig, sizeof(GdReplay));
/* replicate dynamic data */
- rep->comment = g_string_new(orig->comment->str);
+ rep->comment = getStringCopy(orig->comment);
rep->movements = g_byte_array_new();
g_byte_array_append(rep->movements, orig->movements->data, orig->movements->len);
void gd_replay_free(GdReplay *replay)
{
g_byte_array_free(replay->movements, TRUE);
- g_string_free(replay->comment, TRUE);
+ checked_free(replay->comment);
free(replay);
}
g_byte_array_append(replay->movements, data, 1);
}
-/* get next available movement from a replay; store variables to player_move,
- player_fire, suicide */
-/* return true if successful */
-boolean gd_replay_get_next_movement(GdReplay *replay, GdDirection *player_move,
- boolean *player_fire, boolean *suicide)
-{
- guint8 data;
-
- /* if no more available movements */
- if (replay->current_playing_pos >= replay->movements->len)
- return FALSE;
-
- data = replay->movements->data[replay->current_playing_pos++];
- *suicide = (data & GD_REPLAY_SUICIDE_MASK) != 0;
- *player_fire = (data & GD_REPLAY_FIRE_MASK) != 0;
- *player_move = (data & GD_REPLAY_MOVE_MASK);
-
- return TRUE;
-}
-
-void gd_replay_rewind(GdReplay *replay)
-{
- replay->current_playing_pos = 0;
-}
-
-#define REPLAY_BDCFF_UP "u"
-#define REPLAY_BDCFF_UP_RIGHT "ur"
-#define REPLAY_BDCFF_RIGHT "r"
-#define REPLAY_BDCFF_DOWN_RIGHT "dr"
-#define REPLAY_BDCFF_DOWN "d"
-#define REPLAY_BDCFF_DOWN_LEFT "dl"
-#define REPLAY_BDCFF_LEFT "l"
-#define REPLAY_BDCFF_UP_LEFT "ul"
-/* when not moving */
-#define REPLAY_BDCFF_STILL "."
-/* when the fire is pressed */
-#define REPLAY_BDCFF_FIRE "F"
-#define REPLAY_BDCFF_SUICIDE "k"
-
-static char *direction_to_bdcff(GdDirection mov)
-{
- switch (mov)
- {
- /* not moving */
- case GD_MV_STILL: return REPLAY_BDCFF_STILL;
-
- /* directions */
- case GD_MV_UP: return REPLAY_BDCFF_UP;
- case GD_MV_UP_RIGHT: return REPLAY_BDCFF_UP_RIGHT;
- case GD_MV_RIGHT: return REPLAY_BDCFF_RIGHT;
- case GD_MV_DOWN_RIGHT: return REPLAY_BDCFF_DOWN_RIGHT;
- case GD_MV_DOWN: return REPLAY_BDCFF_DOWN;
- case GD_MV_DOWN_LEFT: return REPLAY_BDCFF_DOWN_LEFT;
- case GD_MV_LEFT: return REPLAY_BDCFF_LEFT;
- case GD_MV_UP_LEFT: return REPLAY_BDCFF_UP_LEFT;
-
- default:
- return REPLAY_BDCFF_STILL;
- }
-}
-
-/* same as above; pressing fire will be a capital letter. */
-static char *direction_fire_to_bdcff(GdDirection dir, boolean fire)
-{
- static char mov[10];
-
- strcpy(mov, direction_to_bdcff(dir));
-
- if (fire)
- {
- int i;
-
- for (i = 0; mov[i] != 0; i++)
- mov[i] = g_ascii_toupper(mov[i]);
- }
-
- return mov;
-}
-
-char *gd_replay_movements_to_bdcff(GdReplay *replay)
-{
- int pos;
- GString *str;
-
- str = g_string_new(NULL);
-
- for (pos = 0; pos < replay->movements->len; pos++)
- {
- int num = 1;
- guint8 data;
-
- /* if this is not the first movement, append a space. */
- if (str->len != 0)
- g_string_append_c(str, ' ');
-
- /* if same byte appears, count number of occurrences - something like an rle compression. */
- /* be sure not to cross the array boundaries */
- while (pos < replay->movements->len - 1 &&
- replay->movements->data[pos] == replay->movements->data[pos + 1])
- {
- pos++;
- num++;
- }
-
- data = replay->movements->data[pos];
-
- if (data & GD_REPLAY_SUICIDE_MASK)
- g_string_append(str, REPLAY_BDCFF_SUICIDE);
-
- g_string_append(str, direction_fire_to_bdcff(data & GD_REPLAY_MOVE_MASK,
- data & GD_REPLAY_FIRE_MASK));
-
- if (num != 1)
- g_string_append_printf(str, "%d", num);
- }
-
- return g_string_free(str, FALSE);
-}
-
/* calculate adler checksum for a rendered cave; this can be used for more caves. */
void gd_cave_adler_checksum_more(GdCave *cave, guint32 *a, guint32 *b)
{