From 10406b9d6cad2b0ec7c30c71520abe2c702bccbc Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Mon, 29 Oct 2018 20:32:07 +0100 Subject: [PATCH] added editor settings if Sokoban fields and objects need to be solved --- src/editor.c | 30 ++++++++++++++++++++++++++++++ src/files.c | 12 ++++++++++++ src/game.c | 38 ++++++++++++++++++++++++++++++++------ src/main.h | 2 ++ 4 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/editor.c b/src/editor.c index 55e8104b..57c79132 100644 --- a/src/editor.c +++ b/src/editor.c @@ -642,6 +642,8 @@ enum GADGET_ID_RANDOM_BALL_CONTENT, GADGET_ID_INITIAL_BALL_STATE, GADGET_ID_GROW_INTO_DIGGABLE, + GADGET_ID_SB_FIELDS_NEEDED, + GADGET_ID_SB_OBJECTS_NEEDED, GADGET_ID_AUTO_EXIT_SOKOBAN, GADGET_ID_SOLVED_BY_ONE_PLAYER, GADGET_ID_CONTINUOUS_SNAPPING, @@ -945,6 +947,8 @@ enum ED_CHECKBUTTON_ID_RANDOM_BALL_CONTENT, ED_CHECKBUTTON_ID_INITIAL_BALL_STATE, ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE, + ED_CHECKBUTTON_ID_SB_FIELDS_NEEDED, + ED_CHECKBUTTON_ID_SB_OBJECTS_NEEDED, ED_CHECKBUTTON_ID_AUTO_EXIT_SOKOBAN, ED_CHECKBUTTON_ID_SOLVED_BY_ONE_PLAYER, ED_CHECKBUTTON_ID_CONTINUOUS_SNAPPING, @@ -3068,6 +3072,20 @@ static struct }, { ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(0), + GADGET_ID_SB_FIELDS_NEEDED, GADGET_ID_NONE, + &level.sb_fields_needed, + NULL, NULL, + "all fields need to be filled", "require all SB fields to be solved" + }, + { + ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(0), + GADGET_ID_SB_OBJECTS_NEEDED, GADGET_ID_NONE, + &level.sb_objects_needed, + NULL, NULL, + "all objects need to be placed", "require all SB objects to be solved" + }, + { + ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(1), GADGET_ID_AUTO_EXIT_SOKOBAN, GADGET_ID_NONE, &level.auto_exit_sokoban, NULL, NULL, @@ -9931,10 +9949,22 @@ static void DrawPropertiesConfig(void) MapCheckbuttonGadget(ED_CHECKBUTTON_ID_GROW_INTO_DIGGABLE); } + if (properties_element == EL_SOKOBAN_FIELD_EMPTY) + MapCheckbuttonGadget(ED_CHECKBUTTON_ID_SB_FIELDS_NEEDED); + + if (properties_element == EL_SOKOBAN_OBJECT) + MapCheckbuttonGadget(ED_CHECKBUTTON_ID_SB_OBJECTS_NEEDED); + if (properties_element == EL_SOKOBAN_OBJECT || properties_element == EL_SOKOBAN_FIELD_EMPTY || properties_element == EL_SOKOBAN_FIELD_FULL) + { + checkbutton_info[ED_CHECKBUTTON_ID_AUTO_EXIT_SOKOBAN].y = + ED_ELEMENT_SETTINGS_XPOS(properties_element == EL_SOKOBAN_FIELD_FULL ? + 0 : 1); + MapCheckbuttonGadget(ED_CHECKBUTTON_ID_AUTO_EXIT_SOKOBAN); + } if (IS_BALLOON_ELEMENT(properties_element)) MapSelectboxGadget(ED_SELECTBOX_ID_WIND_DIRECTION); diff --git a/src/files.c b/src/files.c index 0b0c37d3..58af0597 100644 --- a/src/files.c +++ b/src/files.c @@ -818,6 +818,18 @@ static struct LevelFileConfigInfo chunk_config_ELEM[] = &li.num_ball_contents, 4, MAX_ELEMENT_CONTENTS }, + { + EL_SOKOBAN_FIELD_EMPTY, -1, + TYPE_BOOLEAN, CONF_VALUE_8_BIT(1), + &li.sb_fields_needed, TRUE + }, + + { + EL_SOKOBAN_OBJECT, -1, + TYPE_BOOLEAN, CONF_VALUE_8_BIT(1), + &li.sb_objects_needed, TRUE + }, + { EL_MM_MCDUFFIN, -1, TYPE_BOOLEAN, CONF_VALUE_8_BIT(1), diff --git a/src/game.c b/src/game.c index 4a3d1eef..2fb1b686 100644 --- a/src/game.c +++ b/src/game.c @@ -1683,6 +1683,30 @@ int GetElementFromGroupElement(int element) return element; } +static void IncrementPlayerSokobanFieldsNeeded(struct PlayerInfo *player) +{ + if (level.sb_fields_needed) + player->sokoban_fields_still_needed++; +} + +static void IncrementPlayerSokobanObjectsNeeded(struct PlayerInfo *player) +{ + if (level.sb_objects_needed) + player->sokoban_objects_still_needed++; +} + +static void DecrementPlayerSokobanFieldsNeeded(struct PlayerInfo *player) +{ + if (player->sokoban_fields_still_needed > 0) + player->sokoban_fields_still_needed--; +} + +static void DecrementPlayerSokobanObjectsNeeded(struct PlayerInfo *player) +{ + if (player->sokoban_objects_still_needed > 0) + player->sokoban_objects_still_needed--; +} + static void InitPlayerField(int x, int y, int element, boolean init_game) { if (element == EL_SP_MURPHY) @@ -1792,11 +1816,11 @@ static void InitField(int x, int y, boolean init_game) break; case EL_SOKOBAN_FIELD_EMPTY: - local_player->sokoban_fields_still_needed++; + IncrementPlayerSokobanFieldsNeeded(local_player); break; case EL_SOKOBAN_OBJECT: - local_player->sokoban_objects_still_needed++; + IncrementPlayerSokobanObjectsNeeded(local_player); break; case EL_STONEBLOCK: @@ -13948,15 +13972,17 @@ static int DigField(struct PlayerInfo *player, if (element == EL_SOKOBAN_FIELD_FULL) { Back[x][y] = EL_SOKOBAN_FIELD_EMPTY; - local_player->sokoban_fields_still_needed++; - local_player->sokoban_objects_still_needed++; + + IncrementPlayerSokobanFieldsNeeded(local_player); + IncrementPlayerSokobanObjectsNeeded(local_player); } if (Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY) { Back[nextx][nexty] = EL_SOKOBAN_FIELD_EMPTY; - local_player->sokoban_fields_still_needed--; - local_player->sokoban_objects_still_needed--; + + DecrementPlayerSokobanFieldsNeeded(local_player); + DecrementPlayerSokobanObjectsNeeded(local_player); // sokoban object was pushed from empty field to sokoban field if (Back[x][y] == EL_EMPTY) diff --git a/src/main.h b/src/main.h index 8cf8642a..b645a73c 100644 --- a/src/main.h +++ b/src/main.h @@ -3097,6 +3097,8 @@ struct LevelInfo boolean lazy_relocation; // only redraw off-screen player relocation boolean can_pass_to_walkable; // player can pass to empty or walkable tile boolean grow_into_diggable; // amoeba can grow into anything diggable + boolean sb_fields_needed; // all Sokoban fields must be solved + boolean sb_objects_needed; // all Sokoban objects must be solved boolean auto_exit_sokoban; // automatically finish solved Sokoban levels boolean solved_by_one_player; // level is solved if one player enters exit -- 2.34.1