diff --git a/docs/changelog.txt b/docs/changelog.txt index 15798ee67..a4f309059 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -275,8 +275,10 @@ USERS FWRITE_APPEND) is now stored in save files. This fixes a bug where the output file would be reopened in the wrong mode (ab) when reloading a saved game. -+ Fixed dragon random movement behavior. A compatibility check - has been added for 2.80 to 2.92 non-random dragon movement. ++ Fixed dragon 1/8th chance of random movement, which has been + broken since 2.80. The original DOS behavior (random movement) + or the 2.80 behavior (no random movement) can be selected via + the new board setting "Dragons randomly move". + save_slots is now enabled by default for consoles. (Spectere) + editor_show_thing_toggles is now enabled by default. - board_editor_hide_help and robot_editor_hide_help are no diff --git a/src/board.c b/src/board.c index 4d7bb43c2..fca6a5897 100644 --- a/src/board.c +++ b/src/board.c @@ -251,7 +251,7 @@ int save_board(struct world *mzx_world, struct board *cur_board, return -1; } -static void default_board(struct board *cur_board) +void default_board_settings(struct world *mzx_world, struct board *cur_board) { cur_board->mod_playing[0] = 0; cur_board->viewport_x = 0; @@ -269,12 +269,15 @@ static void default_board(struct board *cur_board) cur_board->forest_becomes = 0; cur_board->collect_bombs = 0; cur_board->fire_burns = 0; - cur_board->board_dir[0] = 0; - cur_board->board_dir[1] = 0; - cur_board->board_dir[2] = 0; - cur_board->board_dir[3] = 0; + cur_board->dragons_can_randomly_move = + (mzx_world->version < VERSION_PORT || mzx_world->version >= V293) ? true : false; + cur_board->board_dir[0] = NO_BOARD; + cur_board->board_dir[1] = NO_BOARD; + cur_board->board_dir[2] = NO_BOARD; + cur_board->board_dir[3] = NO_BOARD; cur_board->restart_if_zapped = 0; cur_board->reset_on_entry = 0; + cur_board->reset_on_entry_same_board = (mzx_world->version >= V293); cur_board->time_limit = 0; cur_board->charset_path = NULL; cur_board->palette_path = NULL; @@ -316,7 +319,7 @@ static void default_board(struct board *cur_board) #endif } -void dummy_board(struct board *cur_board) +void dummy_board(struct world *mzx_world, struct board *cur_board) { // Allocate placeholder data for broken boards so they will run int size = 2000; @@ -324,7 +327,7 @@ void dummy_board(struct board *cur_board) cur_board->board_width = 80; cur_board->board_height = 25; - default_board(cur_board); + default_board_settings(mzx_world, cur_board); cur_board->level_id = ccalloc(1, size); cur_board->level_color = ccalloc(1, size); @@ -410,8 +413,8 @@ __editor_maybe_static void board_set_palette_path(struct board *cur_board, #define err_if_missing(expected) if(last_ident < expected) { goto err_free; } -static int load_board_info(struct board *cur_board, struct zip_archive *zp, - int savegame, int *file_version) +static int load_board_info(struct world *mzx_world, struct board *cur_board, + struct zip_archive *zp, int savegame, int *file_version) { char *buffer; size_t actual_size; @@ -622,6 +625,16 @@ static int load_board_info(struct board *cur_board, struct zip_archive *zp, board_set_palette_path(cur_board, (const char *)prop.start, size); break; + case BPROP_RESET_ON_ENTRY_SAME_BOARD: + if(*file_version >= V293 && mzx_world->version >= V293) + cur_board->reset_on_entry_same_board = load_prop_boolean(&prop); + break; + + case BPROP_DRAGONS_CAN_RANDOMLY_MOVE: + if(*file_version >= V293 && mzx_world->version >= V293) + cur_board->dragons_can_randomly_move = load_prop_boolean(&prop); + break; + // Savegame only case BPROP_SCROLL_X: @@ -791,7 +804,7 @@ int load_board_direct(struct world *mzx_world, struct board *cur_board, int has_och = 0; int has_oco = 0; - default_board(cur_board); + default_board_settings(mzx_world, cur_board); while(ZIP_SUCCESS == zip_get_next_mzx_file_id(zp, &file_id, &board_id_read, &robot_id_read)) { @@ -802,7 +815,7 @@ int load_board_direct(struct world *mzx_world, struct board *cur_board, { case FILE_ID_BOARD_INFO: { - if(load_board_info(cur_board, zp, savegame, &file_version)) + if(load_board_info(mzx_world, cur_board, zp, savegame, &file_version)) goto err_invalid; has_base = 1; @@ -1217,7 +1230,7 @@ int load_board_direct(struct world *mzx_world, struct board *cur_board, err_invalid: error_message(E_ZIP_BOARD_CORRUPT, (int)board_id, NULL); - dummy_board(cur_board); + dummy_board(mzx_world, cur_board); return VAL_INVALID; } diff --git a/src/board.h b/src/board.h index 81e0c2564..b7a3bd110 100644 --- a/src/board.h +++ b/src/board.h @@ -41,7 +41,8 @@ CORE_LIBSPEC void clear_board(struct board *cur_board); struct board *duplicate_board(struct world *mzx_world, struct board *src_board); -void dummy_board(struct board *cur_board); +void default_board_settings(struct world *mzx_world, struct board *cur_board); +void dummy_board(struct world *mzx_world, struct board *cur_board); int find_board(struct world *mzx_world, char *name); diff --git a/src/board_struct.h b/src/board_struct.h index ee70811a6..4f7974b45 100644 --- a/src/board_struct.h +++ b/src/board_struct.h @@ -59,9 +59,11 @@ struct board int forest_becomes; int collect_bombs; int fire_burns; + int dragons_can_randomly_move; int board_dir[4]; int restart_if_zapped; int reset_on_entry; + int reset_on_entry_same_board; int time_limit; int last_key; int num_input; diff --git a/src/configure.c b/src/configure.c index 0068f52b6..2956c29f3 100644 --- a/src/configure.c +++ b/src/configure.c @@ -337,7 +337,7 @@ typedef void (*config_function)(struct config_info *conf, char *name, struct config_entry { - char option_name[OPTION_NAME_LEN]; + const char *option_name; config_function change_option; boolean allow_in_game_config; }; diff --git a/src/configure.h b/src/configure.h index 49f691828..f4ba60e81 100644 --- a/src/configure.h +++ b/src/configure.h @@ -24,8 +24,6 @@ __M_BEGIN_DECLS -#define OPTION_NAME_LEN 33 - enum config_type { SYSTEM_CNF, diff --git a/src/editor/board.c b/src/editor/board.c index 4673a0e59..7dc789db3 100644 --- a/src/editor/board.c +++ b/src/editor/board.c @@ -308,6 +308,7 @@ struct board *create_blank_board(struct editor_config_info *conf) cur_board->forest_becomes = conf->forest_to_floor; cur_board->collect_bombs = conf->collect_bombs; cur_board->fire_burns = conf->fire_burns_forever; + cur_board->dragons_can_randomly_move = conf->dragons_can_randomly_move; for(i = 0; i < 4; i++) { @@ -315,6 +316,7 @@ struct board *create_blank_board(struct editor_config_info *conf) } cur_board->reset_on_entry = conf->reset_on_entry; + cur_board->reset_on_entry_same_board = conf->reset_on_entry_same_board; cur_board->restart_if_zapped = conf->restart_if_hurt; cur_board->time_limit = conf->time_limit; cur_board->last_key = '?'; diff --git a/src/editor/configure.c b/src/editor/configure.c index ef0769bfd..3dc54579b 100644 --- a/src/editor/configure.c +++ b/src/editor/configure.c @@ -62,8 +62,10 @@ static const struct editor_config_info editor_conf_default = 0, // fire_burns_forever 1, // forest_to_floor 1, // collect_bombs + true, // dragons_can_randomly_move 0, // restart_if_hurt 0, // reset_on_entry + true, // reset_on_entry_same_board 0, // player_locked_ns 0, // player_locked_ew 0, // player_locked_att @@ -109,7 +111,7 @@ typedef void (* editor_config_function)(struct editor_config_info *conf, struct editor_config_entry { - char option_name[OPTION_NAME_LEN]; + const char *option_name; editor_config_function change_option; }; @@ -623,6 +625,12 @@ static void config_board_collect_bombs(struct editor_config_info *conf, config_boolean(&conf->collect_bombs, value); } +static void config_board_dragons_random_move(struct editor_config_info *conf, + char *name, char *value, char *extended_data) +{ + config_boolean(&conf->dragons_can_randomly_move, value); +} + static void config_board_restart(struct editor_config_info *conf, char *name, char *value, char *extended_data) { @@ -635,6 +643,12 @@ static void config_board_reset_on_entry(struct editor_config_info *conf, config_boolean(&conf->reset_on_entry, value); } +static void config_board_reset_on_entry_same(struct editor_config_info *conf, + char *name, char *value, char *extended_data) +{ + config_boolean(&conf->reset_on_entry_same_board, value); +} + static void config_board_locked_ns(struct editor_config_info *conf, char *name, char *value, char *extended_data) { @@ -714,6 +728,7 @@ static const struct editor_config_entry editor_config_options[] = { "board_default_can_shoot", config_board_can_shoot }, { "board_default_charset_path", config_board_charset }, { "board_default_collect_bombs", config_board_collect_bombs }, + { "board_default_dragons_can_randomly_move", config_board_dragons_random_move }, { "board_default_explosions_leave", config_board_explosions }, { "board_default_fire_burns_brown", config_board_fire_brown }, { "board_default_fire_burns_fakes", config_board_fire_fakes }, @@ -728,6 +743,7 @@ static const struct editor_config_entry editor_config_options[] = { "board_default_player_locked_ew", config_board_locked_ew }, { "board_default_player_locked_ns", config_board_locked_ns }, { "board_default_reset_on_entry", config_board_reset_on_entry }, + { "board_default_reset_on_entry_same_board", config_board_reset_on_entry_same }, { "board_default_restart_if_hurt", config_board_restart }, { "board_default_saving", config_board_saving }, { "board_default_time_limit", config_board_time_limit }, @@ -965,8 +981,12 @@ void save_local_editor_config(struct editor_config_info *conf, vf_printf(vf, "board_default_fire_burns_forever = %d\n", conf->fire_burns_forever); vf_printf(vf, "board_default_forest_to_floor = %d\n", conf->forest_to_floor); vf_printf(vf, "board_default_collect_bombs = %d\n", conf->collect_bombs); + vf_printf(vf, "board_default_dragons_can_randomly_move = %d\n", + conf->dragons_can_randomly_move); vf_printf(vf, "board_default_restart_if_hurt = %d\n", conf->restart_if_hurt); vf_printf(vf, "board_default_reset_on_entry = %d\n", conf->reset_on_entry); + vf_printf(vf, "board_default_reset_on_entry_same_board = %d\n", + conf->reset_on_entry_same_board); vf_printf(vf, "board_default_player_locked_ns = %d\n", conf->player_locked_ns); vf_printf(vf, "board_default_player_locked_ew = %d\n", conf->player_locked_ew); vf_printf(vf, "board_default_player_locked_att = %d\n", conf->player_locked_att); diff --git a/src/editor/configure.h b/src/editor/configure.h index ee24b1ae0..19e2f86a8 100644 --- a/src/editor/configure.h +++ b/src/editor/configure.h @@ -89,8 +89,10 @@ struct editor_config_info boolean fire_burns_forever; boolean forest_to_floor; boolean collect_bombs; + boolean dragons_can_randomly_move; boolean restart_if_hurt; boolean reset_on_entry; + boolean reset_on_entry_same_board; boolean player_locked_ns; boolean player_locked_ew; boolean player_locked_att; diff --git a/src/editor/edit_di.c b/src/editor/edit_di.c index a4bcf49a2..7892afaec 100644 --- a/src/editor/edit_di.c +++ b/src/editor/edit_di.c @@ -857,7 +857,8 @@ int size_pos_vlayer(struct world *mzx_world) // [ ] Fire burns brown ( ) Can't save // [ ] Forest to floor ( ) Can save on sensors // [ ] Collect bombs -// [ ] Fire burns forever ( ) No overlay +// [ ] Fire burns forever +// [ ] Dragons randomly move ( ) No overlay // [ ] Restart if hurt ( ) Normal overlay // [ ] Reset board on entry ( ) Static overlay // [ ] Player locked N/S ( ) Transparent overlay @@ -866,6 +867,7 @@ int size_pos_vlayer(struct world *mzx_world) // // Charset to load- Palette to load- // _______________________[v] _______________________[v] // +// [ ] Reset/load when entering from the same board // // _OK_ _Cancel_ _Set as defaults_ // // @@ -876,26 +878,37 @@ void board_info(struct world *mzx_world) { struct board *src_board = mzx_world->current_board; int dialog_result; - struct element *elements[11]; + struct element *elements[12]; struct dialog di; - int check_box_results[14] = + int check_box_results[15] = { src_board->can_shoot, src_board->can_bomb, src_board->fire_burn_space, src_board->fire_burn_fakes, src_board->fire_burn_trees, src_board->fire_burn_brown, src_board->forest_becomes, src_board->collect_bombs, - src_board->fire_burns, src_board->restart_if_zapped, + src_board->fire_burns, + src_board->dragons_can_randomly_move, + src_board->restart_if_zapped, src_board->reset_on_entry, src_board->player_ns_locked, src_board->player_ew_locked, src_board->player_attack_locked }; + int check_box_results_2[] = + { + src_board->reset_on_entry_same_board, + }; const char *check_box_strings[] = { "Can shoot", "Can bomb", "Fire burns space", "Fire burns fakes", "Fire burns trees", "Fire burns brown", "Forest to floor", "Collect bombs", "Fire burns forever", + "Dragons move randomly", "Restart if hurt", "Reset board on entry", "Player locked N/S", "Player locked E/W", "Player attack locked" }; + const char *check_box_strings_2[] = + { + "Reset/load when entering from the same board" + }; const char *radio_strings_1[] = { "Explosions to space", "Explosions to ash", @@ -950,15 +963,15 @@ void board_info(struct world *mzx_world) do { - elements[0] = construct_button(13, 21, "OK", 0); - elements[1] = construct_button(19, 21, "Cancel", -1); - elements[2] = construct_button(29, 21, "Set as defaults", 1); + elements[0] = construct_button(13, 22, "OK", 0); + elements[1] = construct_button(19, 22, "Cancel", -1); + elements[2] = construct_button(29, 22, "Set as defaults", 1); elements[3] = construct_input_box(7, 1, "Board name- ", BOARD_NAME_SIZE - 1, title_string); - elements[4] = construct_check_box(3, 3, check_box_strings, - 14, 20, check_box_results); + elements[4] = construct_check_box(3, 2, check_box_strings, + 15, 21, check_box_results); elements[5] = construct_radio_button(31, 3, radio_strings_1, 3, 19, &radio_result_1); @@ -978,8 +991,11 @@ void board_info(struct world *mzx_world) "Select a palette...", palette_exts, "(none)", 23, 1, "", palette_string, 2); + elements[11] = construct_check_box(6, 20, check_box_strings_2, + 1, 46, check_box_results_2); + construct_dialog(&di, "Board Settings", 10, 0, 60, 24, - elements, 11, pos); + elements, ARRAY_SIZE(elements), pos); dialog_result = run_dialog(mzx_world, &di); pos = di.current_element; @@ -1001,11 +1017,13 @@ void board_info(struct world *mzx_world) conf->forest_to_floor = check_box_results[6]; conf->collect_bombs = check_box_results[7]; conf->fire_burns_forever = check_box_results[8]; - conf->restart_if_hurt = check_box_results[9]; - conf->reset_on_entry = check_box_results[10]; - conf->player_locked_ns = check_box_results[11]; - conf->player_locked_ew = check_box_results[12]; - conf->player_locked_att = check_box_results[13]; + conf->dragons_can_randomly_move = check_box_results[9]; + conf->restart_if_hurt = check_box_results[10]; + conf->reset_on_entry = check_box_results[11]; + conf->player_locked_ns = check_box_results[12]; + conf->player_locked_ew = check_box_results[13]; + conf->player_locked_att = check_box_results[14]; + conf->reset_on_entry_same_board = check_box_results_2[0]; conf->explosions_leave = radio_result_1; conf->saving_enabled = radio_result_2; conf->overlay_enabled = radio_result_3; @@ -1030,11 +1048,13 @@ void board_info(struct world *mzx_world) src_board->forest_becomes = check_box_results[6]; src_board->collect_bombs = check_box_results[7]; src_board->fire_burns = check_box_results[8]; - src_board->restart_if_zapped = check_box_results[9]; - src_board->reset_on_entry = check_box_results[10]; - src_board->player_ns_locked = check_box_results[11]; - src_board->player_ew_locked = check_box_results[12]; - src_board->player_attack_locked = check_box_results[13]; + src_board->dragons_can_randomly_move = check_box_results[9]; + src_board->restart_if_zapped = check_box_results[10]; + src_board->reset_on_entry = check_box_results[11]; + src_board->player_ns_locked = check_box_results[12]; + src_board->player_ew_locked = check_box_results[13]; + src_board->player_attack_locked = check_box_results[14]; + src_board->reset_on_entry_same_board = check_box_results_2[0]; src_board->explosions_leave = radio_result_1; src_board->save_mode = radio_result_2; diff --git a/src/game_update_board.c b/src/game_update_board.c index 75eb1a2dc..5b9af72e4 100644 --- a/src/game_update_board.c +++ b/src/game_update_board.c @@ -956,8 +956,7 @@ void update_board(context *ctx) level_param[level_offset] = current_param & 0xE7; // One out of 8 moves is random - // This was broken in the port for a long time. - if(mzx_world->version < VERSION_PORT || mzx_world->version >= V293) + if(src_board->dragons_can_randomly_move) rval = Random(8); if(!(rval & 0x07)) diff --git a/src/legacy_board.c b/src/legacy_board.c index a53103d43..7a2f1b15e 100644 --- a/src/legacy_board.c +++ b/src/legacy_board.c @@ -175,41 +175,7 @@ int legacy_load_board_direct(struct world *mzx_world, struct board *cur_board, cur_board->sensor_list = NULL; cur_board->scroll_list = NULL; - // Initialize some fields that may no longer be loaded - // from the board file itself.. - - cur_board->last_key = '?'; - cur_board->num_input = 0; - cur_board->input_size = 0; - cur_board->input_allocated = 0; - cur_board->input_string = NULL; - cur_board->player_last_dir = 0x10; - cur_board->bottom_mesg[0] = 0; - cur_board->b_mesg_timer = 0; - cur_board->lazwall_start = 7; - cur_board->b_mesg_row = 24; - cur_board->b_mesg_col = -1; - cur_board->scroll_x = 0; - cur_board->scroll_y = 0; - cur_board->locked_x = -1; - cur_board->locked_y = -1; - cur_board->volume = 255; - cur_board->volume_inc = 0; - cur_board->volume_target = 255; - cur_board->reset_on_entry = 0; - cur_board->charset_path = NULL; - cur_board->palette_path = NULL; - cur_board->charset_path_allocated = 0; - cur_board->palette_path_allocated = 0; - cur_board->blind_dur_v1 = 0; - cur_board->firewalker_dur_v1 = 0; - cur_board->freeze_time_dur_v1 = 0; - cur_board->slow_time_dur_v1 = 0; - cur_board->wind_dur_v1 = 0; - -#if defined(DEBUG) || defined(CONFIG_EXTRAM) - cur_board->is_extram = false; -#endif + default_board_settings(mzx_world, cur_board); if(file_version >= V200) { @@ -818,7 +784,7 @@ struct board *legacy_load_board_allocate(struct world *mzx_world, vfile *vf, savegame, file_version); if(result != VAL_SUCCESS) - dummy_board(cur_board); + dummy_board(mzx_world, cur_board); return cur_board; } diff --git a/src/world.c b/src/world.c index 8c7ded66f..6eee4efb3 100644 --- a/src/world.c +++ b/src/world.c @@ -2487,7 +2487,7 @@ static int load_world_zip(struct world *mzx_world, struct zip_archive *zp, if(!mzx_world->board_list[0]) { struct board *dummy = cmalloc(sizeof(struct board)); - dummy_board(dummy); + dummy_board(mzx_world, dummy); dummy->board_name[0] = 0; dummy->robot_list[0] = &mzx_world->global_robot; diff --git a/src/world_format.h b/src/world_format.h index 0ea5cf08f..155a92f7d 100644 --- a/src/world_format.h +++ b/src/world_format.h @@ -274,8 +274,8 @@ enum sprite_prop }; -#define COUNT_BOARD_PROPS ( 1 + 7 + 3 + 25) -#define BOUND_BOARD_PROPS (BOARD_NAME_SIZE + 10 + 3*MAX_PATH + 26) +#define COUNT_BOARD_PROPS ( 1 + 7 + 3 + 27) +#define BOUND_BOARD_PROPS (BOARD_NAME_SIZE + 10 + 3*MAX_PATH + 28) #define COUNT_BOARD_SAVE_PROPS ( 2 + 20) #define BOUND_BOARD_SAVE_PROPS (2*ROBOT_MAX_TR + 30) @@ -310,7 +310,7 @@ enum board_prop BPROP_NUM_SENSORS = 0x0007, // 1 BPROP_FILE_VERSION = 0x0008, // 2 - // Non-essential 25 26 + 3 MAX_PATH + // Non-essential 27 28 + 3 MAX_PATH BPROP_MOD_PLAYING = 0x0010, // MAX_PATH BPROP_VIEWPORT_X = 0x0011, // 1 BPROP_VIEWPORT_Y = 0x0012, // 1 @@ -339,6 +339,8 @@ enum board_prop BPROP_RESET_ON_ENTRY = 0x0029, // 1 BPROP_CHARSET_PATH = 0x002A, // MAX_PATH BPROP_PALETTE_PATH = 0x002B, // MAX_PATH + BPROP_RESET_ON_ENTRY_SAME_BOARD = 0x002C, // 1 + BPROP_DRAGONS_CAN_RANDOMLY_MOVE = 0x002D, // 1 // Save 17 25 + 2 ROBOT_MAX_TR BPROP_SCROLL_X = 0x0100, // 2 diff --git a/unit/configure.cpp b/unit/configure.cpp index 1928d15c6..a2aeb276f 100644 --- a/unit/configure.cpp +++ b/unit/configure.cpp @@ -1052,6 +1052,12 @@ UNITTEST(Settings) TEST_ENUM("board_default_collect_bombs", econf->collect_bombs, boolean_data); } + SECTION(dragons_can_randomly_move) + { + TEST_ENUM("board_default_dragons_can_randomly_move", + econf->dragons_can_randomly_move, boolean_data); + } + SECTION(restart_if_hurt) { TEST_ENUM("board_default_restart_if_hurt", econf->restart_if_hurt, boolean_data); @@ -1062,6 +1068,12 @@ UNITTEST(Settings) TEST_ENUM("board_default_reset_on_entry", econf->reset_on_entry, boolean_data); } + SECTION(reset_on_entry_same_board) + { + TEST_ENUM("board_default_reset_on_entry_same_board", + econf->reset_on_entry_same_board, boolean_data); + } + SECTION(player_locked_ns) { TEST_ENUM("board_default_player_locked_ns", econf->player_locked_ns, boolean_data);