From: Holger Schemel Date: Mon, 2 Sep 2024 23:54:30 +0000 (+0200) Subject: changed how the native BD game engine handles scanned game elements X-Git-Tag: 4.4.0.0-test-4~277 X-Git-Url: https://git.artsoft.org/?a=commitdiff_plain;h=e8dee4b8a19f55672f0ff5c27146dd9793269479;p=rocksndiamonds.git changed how the native BD game engine handles scanned game elements After scanning (processing) game elements on the playfield using the native BD game engine, game elements are marked as "scanned" to prevent processing them again (for example, newly created elements in the next row that are just about to be scanned). Previously, elements were marked by setting a "scanned" bit. Now, elements are marked by using special "scanned" variants for the already processed element. There is another change that breaks old cave replays (BD style tapes): When checking game element properties, the old engine always checked the non-scanned elements, while the new engine checks the element just as it is (that is, either scanned or non-scanned), which causes some game elements (like the amoeba) to behave slightly differently. This is handled by a special flag to choose the old or new behaviour, which is currently still set to use the old behaviour. --- diff --git a/src/game_bd/bd_cave.c b/src/game_bd/bd_cave.c index d062b304..b56e2ac7 100644 --- a/src/game_bd/bd_cave.c +++ b/src/game_bd/bd_cave.c @@ -1186,7 +1186,7 @@ static void cave_set_ckdelay_extra_for_animation(GdCave *cave) { for (x = 0; x < cave->w; x++) { - switch (cave->map[y][x] & ~SCANNED) + switch (non_scanned_pair(cave->map[y][x])) { case O_FIREFLY_1: case O_FIREFLY_2: diff --git a/src/game_bd/bd_caveengine.c b/src/game_bd/bd_caveengine.c index f73da218..ab9b3d61 100644 --- a/src/game_bd/bd_caveengine.c +++ b/src/game_bd/bd_caveengine.c @@ -33,6 +33,9 @@ #include "main_bd.h" +// for compatibility with old game engine +static boolean use_old_game_engine = TRUE; + // for gravity static const GdDirection ccw_eighth[] = { @@ -127,8 +130,11 @@ void gd_cave_set_seconds_sound(GdCave *cave) } // returns true if the element has a certain property -static inline boolean has_property(const int element, const int property) +static inline boolean has_property(int element, const int property) { + if (use_old_game_engine) + element = non_scanned_pair(element); + return (gd_element_properties[element & O_MASK].properties & property) != 0; } @@ -546,10 +552,15 @@ GdElement non_scanned_pair(GdElement of_what) return gd_element_properties[of_what].pair; } +static inline boolean is_scanned(const GdCave *cave, const int x, const int y) +{ + return is_scanned_element(get(cave, x, y)); +} + static inline boolean is_scanned_dir(const GdCave *cave, const int x, const int y, const GdDirection dir) { - return (get_dir(cave, x, y, dir) & SCANNED) != 0; + return is_scanned_element(get_dir(cave, x, y, dir)); } // returns true if neighbouring element is "e" @@ -623,13 +634,13 @@ static inline void store(GdCave *cave, const int x, const int y, const GdElement return; } - *e = element; + *e = scanned_pair(element); } // store an element with SCANNED flag turned on static inline void store_sc(GdCave *cave, const int x, const int y, const GdElement element) { - store(cave, x, y, element | SCANNED); + store(cave, x, y, scanned_pair(element)); } // store an element to a neighbouring cell @@ -637,7 +648,7 @@ static inline void store_dir(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 | SCANNED); + store(cave, x + gd_dx[dir], y + gd_dy[dir], scanned_pair(element)); } // store an element to a neighbouring cell @@ -676,6 +687,16 @@ static inline void next(GdCave *cave, const int x, const int y) (*getp(cave, x, y))++; } +// Remove the scanned "bit" from an element. +// To be called only for scanned elements!!! +static inline void unscan(GdCave *cave, const int x, const int y) +{ + GdElement *e = getp(cave, x, y); + + if (is_scanned_element(*e)) + *e = gd_element_properties[*e].pair; +} + static void cell_explode(GdCave *cave, int x, int y, GdElement explode_to) { if (non_explodable (cave, x, y)) @@ -1760,9 +1781,9 @@ 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 (is_scanned(cave, x, y)) { - store(cave, x, y, get(cave, x, y) & ~SCANNED); + unscan(cave, x, y); continue; } @@ -3625,6 +3646,12 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, // other inanimate elements that do nothing break; } + + // after processing, check the current coordinate, if it became scanned. + // the scanned bit can be cleared, as it will not be processed again. + // and, it must be cleared, as it should not be scanned; for example, + // if it is, a replicator will not replicate it! + unscan(cave, x, y); } } @@ -3640,8 +3667,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, { for (x = 0; x < cave->w; x++) { - if (get(cave, x, y) & SCANNED) - store(cave, x, y, get(cave, x, y) & ~SCANNED); + unscan(cave, x, y); if (get(cave, x, y) == O_TIME_PENALTY) { @@ -3668,7 +3694,7 @@ void gd_cave_iterate(GdCave *cave, GdDirection player_move, boolean player_fire, next(cave, x, y); // forget scanned flag immediately - store(cave, x, y, get(cave, x, y) & ~SCANNED); + unscan(cave, x, y); } } } diff --git a/src/game_bd/bd_gameplay.c b/src/game_bd/bd_gameplay.c index 1fb424d9..629e0362 100644 --- a/src/game_bd/bd_gameplay.c +++ b/src/game_bd/bd_gameplay.c @@ -140,9 +140,6 @@ static void load_cave(GdGame *game) game->cave = gd_get_prepared_cave(game->original_cave, game->level_num); - // temporary workaround: set all elements in a cave to their non-scanned counterparts - unscan_cave(game->cave); - // if requested, recolor cave (cave is a copy only, so no worries) if (setup.bd_random_colors) gd_cave_set_random_colors(game->cave, setup.bd_default_color_type);