X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame_bd%2Fbd_cave.c;h=197bec5e4a10282276fc36bf05ac747774f8f562;hb=ade923d10dfedc818718fbdc144db6dfc63a1681;hp=2ffb071e365097f3b117888785b61a8c606bd91d;hpb=7fb08abe58b2c84e36a5ed247d2103e08ae98aa4;p=rocksndiamonds.git diff --git a/src/game_bd/bd_cave.c b/src/game_bd/bd_cave.c index 2ffb071e..197bec5e 100644 --- a/src/game_bd/bd_cave.c +++ b/src/game_bd/bd_cave.c @@ -81,7 +81,7 @@ static const char* scheduling_filename[] = "bd2ckatari" }; -static GHashTable *name_to_element; +static HashTable *name_to_element; GdElement gd_char_to_element[256]; /* color of flashing the screen, gate opening to exit */ @@ -247,7 +247,7 @@ void gd_create_char_to_element_table(void) if (c) { - if (gd_char_to_element[c]!=O_UNKNOWN) + if (gd_char_to_element[c] != O_UNKNOWN) Warn("Character %c already used for element %x", c, gd_char_to_element[c]); gd_char_to_element[c] = i; @@ -275,9 +275,8 @@ void gd_cave_init(void) /* put names to a hash table */ /* this is a helper for file read operations */ - /* maps g_strdupped strings to elemenets (integers) */ - name_to_element = g_hash_table_new_full(gd_str_case_hash, gd_str_case_equal, - free, NULL); + /* maps copied strings to elements (integers) */ + name_to_element = create_hashtable(gd_str_case_hash, gd_str_case_equal, NULL, NULL); for (i = 0; i < O_MAX; i++) { @@ -285,36 +284,36 @@ void gd_cave_init(void) key = g_ascii_strup(gd_elements[i].filename, -1); - if (g_hash_table_lookup_extended(name_to_element, key, NULL, NULL)) + if (hashtable_exists(name_to_element, key)) /* hash value may be 0 */ Warn("Name %s already used for element %x", key, i); - g_hash_table_insert(name_to_element, key, GINT_TO_POINTER(i)); + hashtable_insert(name_to_element, key, INT_TO_PTR(i)); /* ^^^ do not free "key", as hash table needs it during the whole time! */ - key = g_strdup_printf("SCANNED_%s", key); /* new string */ + key = getStringCat2("SCANNED_", key); /* new string */ - g_hash_table_insert(name_to_element, key, GINT_TO_POINTER(i)); + hashtable_insert(name_to_element, key, INT_TO_PTR(i)); /* once again, do not free "key" ^^^ */ } /* for compatibility with tim stridmann's memorydump->bdcff converter... .... ... */ - g_hash_table_insert(name_to_element, "HEXPANDING_WALL", GINT_TO_POINTER(O_H_EXPANDING_WALL)); - g_hash_table_insert(name_to_element, "FALLING_DIAMOND", GINT_TO_POINTER(O_DIAMOND_F)); - g_hash_table_insert(name_to_element, "FALLING_BOULDER", GINT_TO_POINTER(O_STONE_F)); - g_hash_table_insert(name_to_element, "EXPLOSION1S", GINT_TO_POINTER(O_EXPLODE_1)); - g_hash_table_insert(name_to_element, "EXPLOSION2S", GINT_TO_POINTER(O_EXPLODE_2)); - g_hash_table_insert(name_to_element, "EXPLOSION3S", GINT_TO_POINTER(O_EXPLODE_3)); - g_hash_table_insert(name_to_element, "EXPLOSION4S", GINT_TO_POINTER(O_EXPLODE_4)); - g_hash_table_insert(name_to_element, "EXPLOSION5S", GINT_TO_POINTER(O_EXPLODE_5)); - g_hash_table_insert(name_to_element, "EXPLOSION1D", GINT_TO_POINTER(O_PRE_DIA_1)); - g_hash_table_insert(name_to_element, "EXPLOSION2D", GINT_TO_POINTER(O_PRE_DIA_2)); - g_hash_table_insert(name_to_element, "EXPLOSION3D", GINT_TO_POINTER(O_PRE_DIA_3)); - g_hash_table_insert(name_to_element, "EXPLOSION4D", GINT_TO_POINTER(O_PRE_DIA_4)); - g_hash_table_insert(name_to_element, "EXPLOSION5D", GINT_TO_POINTER(O_PRE_DIA_5)); - g_hash_table_insert(name_to_element, "WALL2", GINT_TO_POINTER(O_STEEL_EXPLODABLE)); + hashtable_insert(name_to_element, "HEXPANDING_WALL", INT_TO_PTR(O_H_EXPANDING_WALL)); + hashtable_insert(name_to_element, "FALLING_DIAMOND", INT_TO_PTR(O_DIAMOND_F)); + hashtable_insert(name_to_element, "FALLING_BOULDER", INT_TO_PTR(O_STONE_F)); + hashtable_insert(name_to_element, "EXPLOSION1S", INT_TO_PTR(O_EXPLODE_1)); + hashtable_insert(name_to_element, "EXPLOSION2S", INT_TO_PTR(O_EXPLODE_2)); + hashtable_insert(name_to_element, "EXPLOSION3S", INT_TO_PTR(O_EXPLODE_3)); + hashtable_insert(name_to_element, "EXPLOSION4S", INT_TO_PTR(O_EXPLODE_4)); + hashtable_insert(name_to_element, "EXPLOSION5S", INT_TO_PTR(O_EXPLODE_5)); + hashtable_insert(name_to_element, "EXPLOSION1D", INT_TO_PTR(O_PRE_DIA_1)); + hashtable_insert(name_to_element, "EXPLOSION2D", INT_TO_PTR(O_PRE_DIA_2)); + hashtable_insert(name_to_element, "EXPLOSION3D", INT_TO_PTR(O_PRE_DIA_3)); + hashtable_insert(name_to_element, "EXPLOSION4D", INT_TO_PTR(O_PRE_DIA_4)); + hashtable_insert(name_to_element, "EXPLOSION5D", INT_TO_PTR(O_PRE_DIA_5)); + hashtable_insert(name_to_element, "WALL2", INT_TO_PTR(O_STEEL_EXPLODABLE)); /* compatibility with old bd-faq (pre disassembly of bladder) */ - g_hash_table_insert(name_to_element, "BLADDERd9", GINT_TO_POINTER(O_BLADDER_8)); + hashtable_insert(name_to_element, "BLADDERd9", INT_TO_PTR(O_BLADDER_8)); /* create table to show errors at the start of the application */ gd_create_char_to_element_table(); @@ -324,7 +323,7 @@ void gd_cave_init(void) GdElement gd_get_element_from_string (const char *string) { char *upper = g_ascii_strup(string, -1); - gpointer value; + void *value; boolean found; if (!string) @@ -333,12 +332,15 @@ GdElement gd_get_element_from_string (const char *string) return O_UNKNOWN; } - found = g_hash_table_lookup_extended(name_to_element, upper, NULL, &value); + found = hashtable_exists(name_to_element, upper); /* hash value may be 0 */ + if (found) + value = hashtable_search(name_to_element, upper); free(upper); if (found) - return (GdElement) (GPOINTER_TO_INT(value)); + return (GdElement) (PTR_TO_INT(value)); + + Warn("Invalid string representing element: '%s'", string); - Warn("Invalid string representing element: %s", string); return O_UNKNOWN; } @@ -421,19 +423,18 @@ int gd_add_highscore(GdHighScore *highscores, const char *name, int score) } /* for the case-insensitive hash keys */ -boolean gd_str_case_equal(gconstpointer s1, gconstpointer s2) +int gd_str_case_equal(void *s1, void *s2) { return strcasecmp(s1, s2) == 0; } -guint gd_str_case_hash(gconstpointer v) +unsigned int gd_str_case_hash(void *v) { - char *upper; - guint hash; + char *upper = getStringToUpper(v); + unsigned int hash = get_hash_from_string(upper); - upper = g_ascii_strup(v, -1); - hash = g_str_hash(v); free(upper); + return hash; } @@ -443,18 +444,12 @@ guint gd_str_case_hash(gconstpointer v) */ 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); + cave->tags = create_hashtable(gd_str_case_hash, gd_str_case_equal, free, free); gd_cave_set_gdash_defaults(cave); @@ -511,7 +506,7 @@ gpointer gd_cave_map_dup_size(const GdCave *cave, const gpointer map, const int return NULL; rows = checked_malloc((cave->h) * sizeof(gpointer)); - rows[0] = g_memdup (maplines[0], cell_size * cave->w * cave->h); + rows[0] = getMemCopy (maplines[0], cell_size * cave->w * cave->h); for (y = 1; y < cave->h; y++) rows[y] = (char *)rows[0] + cell_size * cave->w * y; @@ -541,15 +536,15 @@ void gd_cave_free(GdCave *cave) return; if (cave->tags) - g_hash_table_destroy(cave->tags); + hashtable_destroy(cave->tags); 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); @@ -572,9 +567,9 @@ void gd_cave_free(GdCave *cave) free (cave); } -static void hash_copy_foreach(const char *key, const char *value, GHashTable *dest) +static void hash_copy_foreach(const char *key, const char *value, HashTable *dest) { - g_hash_table_insert(dest, g_strdup(key), g_strdup(value)); + hashtable_insert(dest, getStringCopy(key), getStringCopy(value)); } /* copy cave from src to destination, with duplicating dynamically allocated data */ @@ -586,19 +581,19 @@ void gd_cave_copy(GdCave *dest, const GdCave *src) g_memmove(dest, src, sizeof(GdCave)); /* but duplicate dynamic data */ - dest->tags = g_hash_table_new_full(gd_str_case_hash, gd_str_case_equal, - free, free); + dest->tags = create_hashtable(gd_str_case_hash, gd_str_case_equal, free, free); + if (src->tags) - g_hash_table_foreach(src->tags, (GHFunc) hash_copy_foreach, dest->tags); + hashtable_foreach(src->tags, (hashtable_fn)hash_copy_foreach, dest->tags); dest->map = gd_cave_map_dup(src, map); dest->hammered_reappear = gd_cave_map_dup(src, hammered_reappear); /* 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; @@ -610,7 +605,7 @@ void gd_cave_copy(GdCave *dest, const GdCave *src) dest->objects = NULL; /* new empty list */ for (iter = src->objects; iter != NULL; iter = iter->next) /* do a deep copy */ - dest->objects = g_list_append(dest->objects, g_memdup (iter->data, sizeof (GdObject))); + dest->objects = g_list_append(dest->objects, getMemCopy (iter->data, sizeof (GdObject))); } /* copy replays */ @@ -879,9 +874,9 @@ void gd_cave_auto_shrink(GdCave *cave) 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; @@ -914,9 +909,9 @@ void gd_cave_auto_shrink(GdCave *cave) 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; @@ -951,9 +946,9 @@ void gd_cave_auto_shrink(GdCave *cave) 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; @@ -1299,7 +1294,7 @@ void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer /* player with bomb does not blink or tap - no graphics drawn for that. running is drawn using w/o bomb cells */ - if (cave->last_direction!=GD_MV_STILL) + if (cave->last_direction != GD_MV_STILL) { elemmapping[O_PLAYER_BOMB] = map; elemdrawing[O_PLAYER_BOMB] = draw; @@ -1396,8 +1391,6 @@ GdReplay *gd_replay_new(void) rep = checked_calloc(sizeof(GdReplay)); - /* create dynamic objects */ - rep->comment = g_string_new(NULL); rep->movements = g_byte_array_new(); return rep; @@ -1407,10 +1400,10 @@ GdReplay *gd_replay_new_from_replay(GdReplay *orig) { GdReplay *rep; - rep = g_memdup(orig, sizeof(GdReplay)); + rep = getMemCopy(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); @@ -1420,7 +1413,7 @@ GdReplay *gd_replay_new_from_replay(GdReplay *orig) 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); } @@ -1437,125 +1430,6 @@ void gd_replay_store_movement(GdReplay *replay, GdDirection player_move, 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) {