Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package rocksndiamonds for openSUSE:Factory checked in at 2026-07-01 17:11:11 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rocksndiamonds (Old) and /work/SRC/openSUSE:Factory/.rocksndiamonds.new.11887 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rocksndiamonds" Wed Jul 1 17:11:11 2026 rev:49 rq:1362989 version:4.4.2.3 Changes: -------- --- /work/SRC/openSUSE:Factory/rocksndiamonds/rocksndiamonds.changes 2026-06-25 10:59:47.794717848 +0200 +++ /work/SRC/openSUSE:Factory/.rocksndiamonds.new.11887/rocksndiamonds.changes 2026-07-01 17:11:21.921083355 +0200 @@ -1,0 +2,9 @@ +Sun Jun 28 09:13:27 UTC 2026 - Carsten Ziepke <[email protected]> + +- Update to version 4.4.2.3 + * added checkbox to use optional EM/DC style player explosions + * changed killing player not before, but after digging land mine + * fixed highlighting player name after editing on names screen + * fixed a few potential string buffer overflow problems + +------------------------------------------------------------------- Old: ---- rocksndiamonds-4.4.2.2-linux.tar.gz New: ---- rocksndiamonds-4.4.2.3-linux.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rocksndiamonds.spec ++++++ --- /var/tmp/diff_new_pack.TzHmD3/_old 2026-07-01 17:11:22.953118923 +0200 +++ /var/tmp/diff_new_pack.TzHmD3/_new 2026-07-01 17:11:22.957119061 +0200 @@ -17,7 +17,7 @@ Name: rocksndiamonds -Version: 4.4.2.2 +Version: 4.4.2.3 Release: 0 Summary: Colorful Boulderdash'n'Emerald Mine'n'Sokoban'n'Stuff License: GPL-2.0-or-later ++++++ rocksndiamonds-4.4.2.2-linux.tar.gz -> rocksndiamonds-4.4.2.3-linux.tar.gz ++++++ Binary files old/rocksndiamonds-4.4.2.2/rocksndiamonds and new/rocksndiamonds-4.4.2.3/rocksndiamonds differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/confhash.h new/rocksndiamonds-4.4.2.3/src/confhash.h --- old/rocksndiamonds-4.4.2.2/src/confhash.h 2026-06-20 23:19:06.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/confhash.h 2026-06-27 18:14:06.000000000 +0200 @@ -1 +1 @@ -#define SOURCE_HASH_STRING "43413116" +#define SOURCE_HASH_STRING "54a2717d" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/config.c new/rocksndiamonds-4.4.2.3/src/config.c --- old/rocksndiamonds-4.4.2.2/src/config.c 2026-06-20 23:18:45.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/config.c 2026-06-27 18:13:46.000000000 +0200 @@ -34,7 +34,7 @@ char *getVersionString(VersionType version) { // this function can be called up to ten times before version string gets overwritten - static char version_string_array[10][32]; + static char version_string_array[10][MAX_LINE_LEN]; static int version_string_nr = 0; char *version_string = version_string_array[version_string_nr]; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/conftime.h new/rocksndiamonds-4.4.2.3/src/conftime.h --- old/rocksndiamonds-4.4.2.2/src/conftime.h 2026-06-20 23:19:06.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/conftime.h 2026-06-27 18:14:06.000000000 +0200 @@ -1 +1 @@ -#define SOURCE_DATE_STRING "2026-06-20 21:15" +#define SOURCE_DATE_STRING "2026-06-27 16:08" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/editor.c new/rocksndiamonds-4.4.2.3/src/editor.c --- old/rocksndiamonds-4.4.2.2/src/editor.c 2026-06-20 23:18:45.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/editor.c 2026-06-27 18:13:46.000000000 +0200 @@ -887,6 +887,7 @@ GADGET_ID_USE_START_ELEMENT, GADGET_ID_USE_ARTWORK_ELEMENT, GADGET_ID_USE_EXPLOSION_ELEMENT, + GADGET_ID_USE_EM_STYLE_EXPLOSION, GADGET_ID_INITIAL_GRAVITY, GADGET_ID_USE_INITIAL_INVENTORY, GADGET_ID_CAN_PASS_TO_WALKABLE, @@ -1360,6 +1361,7 @@ ED_CHECKBUTTON_ID_USE_START_ELEMENT, ED_CHECKBUTTON_ID_USE_ARTWORK_ELEMENT, ED_CHECKBUTTON_ID_USE_EXPLOSION_ELEMENT, + ED_CHECKBUTTON_ID_USE_EM_STYLE_EXPLOSION, ED_CHECKBUTTON_ID_INITIAL_GRAVITY, ED_CHECKBUTTON_ID_USE_INITIAL_INVENTORY, ED_CHECKBUTTON_ID_CAN_PASS_TO_WALKABLE, @@ -4781,8 +4783,16 @@ "Use explosion from element:", "Use explosion properties from element" }, { - ED_CHECKBUTTON_ID_INITIAL_GRAVITY, + ED_CHECKBUTTON_ID_USE_EM_STYLE_EXPLOSION, ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(13), + GADGET_ID_USE_EM_STYLE_EXPLOSION, GADGET_ID_NONE, + &level.use_em_style_explosion[0], + NULL, NULL, + "Use EM style explosion", "Use explosion like in Emerald Mine" + }, + { + ED_CHECKBUTTON_ID_INITIAL_GRAVITY, + ED_ELEMENT_SETTINGS_XPOS(0), ED_ELEMENT_SETTINGS_YPOS(5), GADGET_ID_INITIAL_GRAVITY, GADGET_ID_NONE, &level.initial_player_gravity[0], NULL, NULL, @@ -8476,13 +8486,13 @@ char *filename; // 1st try: look for element description file for exactly this element - sprintf(basename, "%s.txt", element_info[element].token_name); + snprintf(basename, sizeof(basename), "%s.txt", element_info[element].token_name); filename = getElementDescriptionFilenameExt(basename); if (filename != NULL) return filename; // 2nd try: look for element description file for this element's class - sprintf(basename, "%s.txt", element_info[element].class_name); + snprintf(basename, sizeof(basename), "%s.txt", element_info[element].class_name); filename = getElementDescriptionFilenameExt(basename); if (filename != NULL) return filename; @@ -9382,6 +9392,7 @@ static void CreateCounterButtons(void) { int max_infotext_len = getMaxInfoTextLength(); + char infotext[max_infotext_len + 1]; int i; for (i = 0; i < ED_NUM_COUNTERBUTTONS; i++) @@ -9412,7 +9423,6 @@ struct GraphicInfo *gd; int gd_x1, gd_x2, gd_y1, gd_y2; unsigned int event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED; - char infotext[max_infotext_len + 1]; if (i == ED_COUNTER_ID_SELECT_LEVEL) { @@ -9447,7 +9457,7 @@ gd_x2 = gd->src_x + gd->pressed_xoffset; gd_y2 = gd->src_y + gd->pressed_yoffset; - sprintf(infotext, "%s counter value by 1, 5 or 10", (j == 0 ? "Decrease" : "Increase")); + snprintf(infotext, sizeof(infotext), "%s counter value by 1, 5 or 10", (j == 0 ? "Decrease" : "Increase")); gi = CreateGadget(GDI_CUSTOM_ID, id, GDI_CUSTOM_TYPE_ID, type_id, @@ -9599,6 +9609,7 @@ { struct GraphicInfo *gd = &graphic_info[IMG_EDITOR_INPUT_TEXT]; int max_infotext_len = getMaxInfoTextLength(); + char infotext[max_infotext_len + 1]; int i; for (i = 0; i < ED_NUM_TEXTINPUT; i++) @@ -9609,7 +9620,6 @@ int gd_y2 = gd->src_y + gd->active_yoffset; struct GadgetInfo *gi; unsigned int event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING; - char infotext[MAX_OUTPUT_LINESIZE + 1]; int id = textinput_info[i].gadget_id; int type_id = textinput_info[i].gadget_type_id; int x, y; @@ -9643,8 +9653,7 @@ if (textinput_info[i].text_left != NULL) x += getTextWidthForGadget(textinput_info[i].text_left); - sprintf(infotext, "%s", textinput_info[i].infotext); - infotext[max_infotext_len] = '\0'; + snprintf(infotext, sizeof(infotext), "%s", textinput_info[i].infotext); gi = CreateGadget(GDI_CUSTOM_ID, id, GDI_CUSTOM_TYPE_ID, type_id, @@ -9676,6 +9685,7 @@ static void CreateTextAreaGadgets(void) { int max_infotext_len = getMaxInfoTextLength(); + char infotext[max_infotext_len + 1]; int i; for (i = 0; i < ED_NUM_TEXTAREAS; i++) @@ -9687,7 +9697,6 @@ int gd_y2 = gd->src_y + gd->active_yoffset; struct GadgetInfo *gi; unsigned int event_mask = GD_EVENT_TEXT_LEAVING; - char infotext[MAX_OUTPUT_LINESIZE + 1]; int id = textarea_info[i].gadget_id; int type_id = textarea_info[i].gadget_type_id; int area_xsize = textarea_info[i].xsize; @@ -9696,8 +9705,7 @@ if (type_id != i) Fail("'textarea_info' structure corrupted at index %d -- please fix", i); - sprintf(infotext, "Enter %s", textarea_info[i].infotext); - infotext[max_infotext_len] = '\0'; + snprintf(infotext, sizeof(infotext), "Enter %s", textarea_info[i].infotext); gi = CreateGadget(GDI_CUSTOM_ID, id, GDI_CUSTOM_TYPE_ID, type_id, @@ -9727,7 +9735,7 @@ static void CreateSelectboxGadgets(void) { int max_infotext_len = getMaxInfoTextLength(); - + char infotext[max_infotext_len + 1]; int i, j; for (i = 0; i < ED_NUM_SELECTBOX; i++) @@ -9740,7 +9748,6 @@ int gd_y2 = gd->src_y + gd->active_yoffset; int selectbox_button_xsize = gd2->width; struct GadgetInfo *gi; - char infotext[MAX_OUTPUT_LINESIZE + 1]; int id = selectbox_info[i].gadget_id; int type_id = selectbox_info[i].gadget_type_id; int x = SX + ED_SETTINGS_X(selectbox_info[i].x); @@ -9772,8 +9779,7 @@ if (selectbox_info[i].text_left != NULL) x += getTextWidthForGadget(selectbox_info[i].text_left); - sprintf(infotext, "%s", selectbox_info[i].infotext); - infotext[max_infotext_len] = '\0'; + snprintf(infotext, sizeof(infotext), "%s", selectbox_info[i].infotext); gi = CreateGadget(GDI_CUSTOM_ID, id, GDI_CUSTOM_TYPE_ID, type_id, @@ -9808,6 +9814,7 @@ static void CreateTextbuttonGadgets(void) { int max_infotext_len = getMaxInfoTextLength(); + char infotext[max_infotext_len + 1]; int i; for (i = 0; i < ED_NUM_TEXTBUTTONS; i++) @@ -9831,7 +9838,6 @@ int border_ysize = gd->border_size; struct GadgetInfo *gi; unsigned int event_mask = GD_EVENT_RELEASED; - char infotext[MAX_OUTPUT_LINESIZE + 1]; int x = SX + ED_SETTINGS_X(textbutton_info[i].x); int y = SY + ED_SETTINGS_Y(textbutton_info[i].y); @@ -9841,8 +9847,7 @@ if (textbutton_info[i].size == -1) // dynamically determine size textbutton_info[i].size = strlen(textbutton_info[i].text); - sprintf(infotext, "%s", textbutton_info[i].infotext); - infotext[max_infotext_len] = '\0'; + snprintf(infotext, sizeof(infotext), "%s", textbutton_info[i].infotext); // determine horizontal position to the right of specified gadget if (textbutton_info[i].gadget_id_align != GADGET_ID_NONE) @@ -11385,7 +11390,7 @@ // dynamically (re)build selectbox for selecting change page for (i = 0; i < element_info[element].num_change_pages; i++) { - sprintf(options_change_page_strings[i], "%d", i + 1); + snprintf(options_change_page_strings[i], sizeof(options_change_page_strings[i]), "%d", i + 1); options_change_page[i].value = i; options_change_page[i].text = options_change_page_strings[i]; @@ -14059,8 +14064,8 @@ &level.use_artwork_element[player_nr]; checkbutton_info[ED_CHECKBUTTON_ID_USE_EXPLOSION_ELEMENT].value = &level.use_explosion_element[player_nr]; - checkbutton_info[ED_CHECKBUTTON_ID_INITIAL_GRAVITY].value = - &level.initial_player_gravity[player_nr]; + checkbutton_info[ED_CHECKBUTTON_ID_USE_EM_STYLE_EXPLOSION].value = + &level.use_em_style_explosion[player_nr]; selectbox_info[ED_SELECTBOX_ID_PLAYER_SPEED].value = &level.initial_player_stepsize[player_nr]; @@ -14077,7 +14082,7 @@ MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_START_ELEMENT); MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_ARTWORK_ELEMENT); MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_EXPLOSION_ELEMENT); - MapCheckbuttonGadget(ED_CHECKBUTTON_ID_INITIAL_GRAVITY); + MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_EM_STYLE_EXPLOSION); MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_PASS_TO_WALKABLE); MapCheckbuttonGadget(ED_CHECKBUTTON_ID_SOLVED_BY_ONE_PLAYER); @@ -14097,11 +14102,14 @@ checkbutton_info[ED_CHECKBUTTON_ID_USE_INITIAL_INVENTORY].value = &level.use_initial_inventory[player_nr]; + checkbutton_info[ED_CHECKBUTTON_ID_INITIAL_GRAVITY].value = + &level.initial_player_gravity[player_nr]; // draw checkbutton gadgets MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_INITIAL_INVENTORY); MapCheckbuttonGadget(ED_CHECKBUTTON_ID_FINISH_DIG_COLLECT); MapCheckbuttonGadget(ED_CHECKBUTTON_ID_KEEP_WALKABLE_CE); + MapCheckbuttonGadget(ED_CHECKBUTTON_ID_INITIAL_GRAVITY); // draw counter gadgets MapCounterButtons(ED_COUNTER_ID_INVENTORY_SIZE); @@ -16064,10 +16072,9 @@ if (old_element != new_element) { int max_infotext_len = getMaxInfoTextLength(); - char infotext[MAX_OUTPUT_LINESIZE + 1]; + char infotext[max_infotext_len + 1]; - strncpy(infotext, getElementInfoText(new_element), max_infotext_len); - infotext[max_infotext_len] = '\0'; + snprintf(infotext, sizeof(infotext), "%s", getElementInfoText(new_element)); ClearEditorGadgetInfoText(); @@ -16846,8 +16853,8 @@ { char request[100]; - sprintf(request, "Replace level with %dx%d level sketch from clipboard?", - brush_width, brush_height); + snprintf(request, sizeof(request), "Replace level with %dx%d level sketch from clipboard?", + brush_width, brush_height); if (!Request(request, REQ_ASK)) return; @@ -18034,7 +18041,8 @@ { int type_id = gi->custom_type_id; - strcpy(textinput_info[type_id].value, gi->textinput.value); + strncpy(textinput_info[type_id].value, gi->textinput.value, textinput_info[type_id].size); + textarea_info[type_id].value[textinput_info[type_id].size] = '\0'; if (type_id == ED_TEXTINPUT_ID_ELEMENT_NAME) { @@ -18068,7 +18076,8 @@ { int type_id = gi->custom_type_id; - strncpy(textarea_info[type_id].value, gi->textarea.value, MAX_ENVELOPE_TEXT_LEN); + // (using memcpy() instead of strncpy() here to prevent idiotic GCC warning) + memcpy(textarea_info[type_id].value, gi->textarea.value, MAX_ENVELOPE_TEXT_LEN); textarea_info[type_id].value[MAX_ENVELOPE_TEXT_LEN] = '\0'; level.changed = TRUE; @@ -18965,9 +18974,9 @@ char level_saved_msg[64]; if (leveldir_former->readonly) - sprintf(level_saved_msg, "Level saved as level %d into personal level set!", level_nr); + snprintf(level_saved_msg, sizeof(level_saved_msg), "Level saved as level %d into personal level set!", level_nr); else - strcpy(level_saved_msg, "Level saved!"); + snprintf(level_saved_msg, sizeof(level_saved_msg), "Level saved!"); Request(level_saved_msg, REQ_CONFIRM); } @@ -19396,14 +19405,13 @@ void PrintEditorGadgetInfoText(struct GadgetInfo *gi) { - char infotext[MAX_OUTPUT_LINESIZE + 1]; int max_infotext_len = getMaxInfoTextLength(); + char infotext[max_infotext_len + 1]; if (gi == NULL || strlen(gi->info_text) == 0) return; - strncpy(infotext, gi->info_text, max_infotext_len); - infotext[max_infotext_len] = '\0'; + snprintf(infotext, sizeof(infotext), "%s", gi->info_text); if (gi->custom_id < ED_NUM_CTRL_BUTTONS) { @@ -19414,17 +19422,17 @@ char shortcut[MAX_OUTPUT_LINESIZE + 1]; if (gi->custom_id == GADGET_ID_SINGLE_ITEMS) - sprintf(shortcut, " ('.' or '%c')", key); + snprintf(shortcut, sizeof(shortcut), " ('.' or '%c')", key); else if (gi->custom_id == GADGET_ID_PICK_ELEMENT) - sprintf(shortcut, " ('%c' or 'Ctrl')", key); + snprintf(shortcut, sizeof(shortcut), " ('%c' or 'Ctrl')", key); else if (gi->custom_id == GADGET_ID_TEST) - sprintf(shortcut, " ('Enter' or 'Shift-%c')", key); + snprintf(shortcut, sizeof(shortcut), " ('Enter' or 'Shift-%c')", key); else if (gi->custom_id == GADGET_ID_UNDO) - sprintf(shortcut, " ('%c/Shift-U')", key); + snprintf(shortcut, sizeof(shortcut), " ('%c/Shift-U')", key); else if (gi->custom_id == GADGET_ID_ZOOM) - sprintf(shortcut, " ('%c', '0', '-')", key); + snprintf(shortcut, sizeof(shortcut), " ('%c', '0', '-')", key); else - sprintf(shortcut, " ('%s%c')", (key >= 'A' && key <= 'Z' ? "Shift-" : ""), key); + snprintf(shortcut, sizeof(shortcut), " ('%s%c')", (key >= 'A' && key <= 'Z' ? "Shift-" : ""), key); if (strlen(infotext) + strlen(shortcut) <= max_infotext_len) strcat(infotext, shortcut); @@ -19466,7 +19474,7 @@ int max_sy = gi->drawing.area_ysize - 1; int actual_drawing_function = drawing_function; int max_infotext_len = getMaxInfoTextLength(); - char infotext[MAX_OUTPUT_LINESIZE + 1]; + char infotext[max_infotext_len + 1]; infotext[0] = '\0'; // start with empty info text @@ -19556,14 +19564,14 @@ } if (actual_drawing_function == GADGET_ID_PICK_ELEMENT) - sprintf(infotext, "%s: %d, %d", text, lx, ly); + snprintf(infotext, sizeof(infotext), "%s: %d, %d", text, lx, ly); else - sprintf(infotext, "%s: %d, %d", text, ABS(lx - start_lx) + 1, ABS(ly - start_ly) + 1); + snprintf(infotext, sizeof(infotext), "%s: %d, %d", text, ABS(lx - start_lx) + 1, ABS(ly - start_ly) + 1); } else if (actual_drawing_function == GADGET_ID_PICK_ELEMENT) - strncpy(infotext, getElementInfoText(Tile[lx][ly]), max_infotext_len); + snprintf(infotext, sizeof(infotext), "%s", getElementInfoText(Tile[lx][ly])); else - sprintf(infotext, "Level position: %d, %d", lx, ly); + snprintf(infotext, sizeof(infotext), "Level position: %d, %d", lx, ly); } // misuse this function to draw brush cursor, if needed @@ -19590,30 +19598,28 @@ int pos = sx * drawingarea_info[type_id].area_ysize + sy; int element = drawingarea_info[type_id].value[pos]; - strncpy(infotext, getElementInfoText(element), max_infotext_len); + snprintf(infotext, sizeof(infotext), "%s", getElementInfoText(element)); } else { if (id == GADGET_ID_CUSTOM_CONTENT) - sprintf(infotext, "custom element content position: %d, %d", sx, sy); + snprintf(infotext, sizeof(infotext), "custom element content position: %d, %d", sx, sy); else if (id == GADGET_ID_GROUP_CONTENT) - sprintf(infotext, "group element position: %d", sx + 1); + snprintf(infotext, sizeof(infotext), "group element position: %d", sx + 1); else if (id >= GADGET_ID_YAMYAM_CONTENT_0 && id <= GADGET_ID_YAMYAM_CONTENT_7) - sprintf(infotext, "content area %d position: %d, %d", + snprintf(infotext, sizeof(infotext), "content area %d position: %d, %d", id - GADGET_ID_YAMYAM_CONTENT_0 + 1, sx, sy); else if (id >= GADGET_ID_MAGIC_BALL_CONTENT_0 && id <= GADGET_ID_MAGIC_BALL_CONTENT_7) - sprintf(infotext, "content area %d position: %d, %d", + snprintf(infotext, sizeof(infotext), "content area %d position: %d, %d", id - GADGET_ID_MAGIC_BALL_CONTENT_0 + 1, sx, sy); else if (id == GADGET_ID_ANDROID_CONTENT) - sprintf(infotext, "android element position: %d", sx + 1); + snprintf(infotext, sizeof(infotext), "android element position: %d", sx + 1); else if (drawingarea_info[type_id].infotext != NULL) - strcpy(infotext, drawingarea_info[type_id].infotext); + snprintf(infotext, sizeof(infotext), "%s", drawingarea_info[type_id].infotext); } - infotext[max_infotext_len] = '\0'; - if (strlen(infotext) > 0) DrawTextS(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, INFOTEXT_FONT, infotext); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/events.c new/rocksndiamonds-4.4.2.3/src/events.c --- old/rocksndiamonds-4.4.2.2/src/events.c 2026-06-20 23:18:45.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/events.c 2026-06-27 18:13:46.000000000 +0200 @@ -1554,7 +1554,7 @@ { char message[100]; - sprintf(message, "%s set already exists! Replace with new set?", + snprintf(message, sizeof(message), "%s set already exists! Replace with new set?", (tree_type == TREE_TYPE_LEVELSET_DIR ? "Level" : "Artwork")); // ask if level or artwork set directory should be replaced (and fail if not) @@ -1565,7 +1565,7 @@ struct tm *now = localtime(&epoch_seconds); char suffix[100]; - sprintf(suffix, ".REPLACED-%04d%02d%02d-%02d%02d%02d", + snprintf(suffix, sizeof(suffix), ".REPLACED-%04d%02d%02d-%02d%02d%02d", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, @@ -1653,20 +1653,20 @@ { char message_part1[50]; - sprintf(message_part1, "New %s set%s added", + snprintf(message_part1, sizeof(message_part1), "New %s set%s added", (num_artwork_sets_succeeded == 0 ? "level" : num_level_sets_succeeded == 0 ? "artwork" : "level and artwork"), (num_level_sets_succeeded + num_artwork_sets_succeeded > 1 ? "s" : "")); if (num_files_failed > 0) - sprintf(message, "%s, but %d dropped file%s failed!", + snprintf(message, sizeof(message), "%s, but %d dropped file%s failed!", message_part1, num_files_failed, num_files_failed > 1 ? "s" : ""); else - sprintf(message, "%s!", message_part1); + snprintf(message, sizeof(message), "%s!", message_part1); } else if (num_files_failed > 0) { - sprintf(message, "Failed to process dropped file%s!", num_files_failed > 1 ? "s" : ""); + snprintf(message, sizeof(message), "Failed to process dropped file%s!", num_files_failed > 1 ? "s" : ""); } Request(message, REQ_CONFIRM); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/files.c new/rocksndiamonds-4.4.2.3/src/files.c --- old/rocksndiamonds-4.4.2.2/src/files.c 2026-06-20 23:18:45.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/files.c 2026-06-27 18:13:46.000000000 +0200 @@ -564,6 +564,11 @@ &li.initial_inventory_content[0][0], EL_EMPTY, NULL, &li.initial_inventory_size[0], 1, MAX_INITIAL_INVENTORY_SIZE }, + { + EL_PLAYER_1, -1, + TYPE_BOOLEAN, CONF_VALUE_8_BIT(18), + &li.use_em_style_explosion[0], FALSE + }, { EL_PLAYER_2, -1, @@ -621,6 +626,11 @@ &li.initial_inventory_content[1][0], EL_EMPTY, NULL, &li.initial_inventory_size[1], 1, MAX_INITIAL_INVENTORY_SIZE }, + { + EL_PLAYER_2, -1, + TYPE_BOOLEAN, CONF_VALUE_8_BIT(18), + &li.use_em_style_explosion[1], FALSE + }, { EL_PLAYER_3, -1, @@ -678,6 +688,11 @@ &li.initial_inventory_content[2][0], EL_EMPTY, NULL, &li.initial_inventory_size[2], 1, MAX_INITIAL_INVENTORY_SIZE }, + { + EL_PLAYER_3, -1, + TYPE_BOOLEAN, CONF_VALUE_8_BIT(18), + &li.use_em_style_explosion[2], FALSE + }, { EL_PLAYER_4, -1, @@ -735,6 +750,11 @@ &li.initial_inventory_content[3][0], EL_EMPTY, NULL, &li.initial_inventory_size[3], 1, MAX_INITIAL_INVENTORY_SIZE }, + { + EL_PLAYER_4, -1, + TYPE_BOOLEAN, CONF_VALUE_8_BIT(18), + &li.use_em_style_explosion[3], FALSE + }, // (these values are only valid for BD style levels) // (some values for BD style amoeba following below) @@ -2954,9 +2974,9 @@ static char basename[MAX_FILENAME_LEN]; if (nr < 0) - sprintf(basename, "%s", LEVELTEMPLATE_FILENAME); + snprintf(basename, sizeof(basename), "%s", LEVELTEMPLATE_FILENAME); else - sprintf(basename, "%03d.%s", nr, extension); + snprintf(basename, sizeof(basename), "%03d.%s", nr, extension); return basename; } @@ -5084,7 +5104,7 @@ level->time = cav->time_seconds; level->gems_needed = cav->gems_needed; - sprintf(level->name, "Level %d", level->file_info.nr); + snprintf(level->name, sizeof(level->name), "Level %d", level->file_info.nr); level->score[SC_EMERALD] = cav->emerald_score; level->score[SC_DIAMOND] = cav->diamond_score; @@ -8038,6 +8058,10 @@ // Diamond Caves uses classic (BD/EM style) behavior for magic walls level->em_magic_wall_behavior = TRUE; + // Diamond Caves uses classic (EM style) player explosions + level->use_em_style_explosion[0] = TRUE; + level->use_em_style_explosion[1] = TRUE; + // Diamond Caves uses special (EM style) behavior (and different speed) for amoeba level->dc_amoeba_behavior = TRUE; @@ -8244,7 +8268,7 @@ // set level title, if not properly defined if (strEqualCase(level->name, NAMELESS_LEVEL_NAME) || strEqualCase(level->name, "no title")) - sprintf(level->name, "Level %d", level_file_info->nr); + snprintf(level->name, sizeof(level->name), "Level %d", level_file_info->nr); } @@ -8516,7 +8540,7 @@ } else { - sprintf(level->name, "--> Level %d <--", level_file_info->nr); + snprintf(level->name, sizeof(level->name), "--> Level %d <--", level_file_info->nr); } // set all empty fields beyond the border walls to invisible steel wall @@ -11425,8 +11449,7 @@ { if (*line_ptr != ' ' && *line_ptr != '\t' && *line_ptr != '\0') { - strncpy(scores.entry[i].name, line_ptr, MAX_PLAYER_NAME_LEN); - scores.entry[i].name[MAX_PLAYER_NAME_LEN] = '\0'; + snprintf(scores.entry[i].name, sizeof(scores.entry[i].name), "%s", line_ptr); break; } @@ -11908,7 +11931,7 @@ { char token[MAX_NUMBER_LEN + 1]; - sprintf(token, "%02d.%d", i, j); + snprintf(token, sizeof(token), "%02d.%d", i, j); char *value = getHashEntry(score_hash, token); @@ -12840,7 +12863,7 @@ { char token_string[MAX_LINE_LEN]; - sprintf(token_string, "touch.virtual_buttons.%d.%02d", i, y); + snprintf(token_string, sizeof(token_string), "touch.virtual_buttons.%d.%02d", i, y); char *value_string = getHashEntry(setup_file_hash, token_string); @@ -12866,14 +12889,14 @@ { char prefix[30]; - sprintf(prefix, "%s%d", TOKEN_STR_PLAYER_PREFIX, pnr + 1); + snprintf(prefix, sizeof(prefix), "%s%d", TOKEN_STR_PLAYER_PREFIX, pnr + 1); setup_input = setup.input[pnr]; for (i = 0; i < ARRAY_SIZE(player_setup_tokens); i++) { char full_token[100]; - sprintf(full_token, "%s%s", prefix, player_setup_tokens[i].text); + snprintf(full_token, sizeof(full_token), "%s%s", prefix, player_setup_tokens[i].text); setSetupInfoFromTokenText(setup_file_hash, player_setup_tokens, i, full_token); } setup.input[pnr] = setup_input; @@ -13208,7 +13231,7 @@ char token_string[MAX_LINE_LEN]; char value_string[MAX_LINE_LEN]; - sprintf(token_string, "touch.virtual_buttons.%d.%02d", i, y); + snprintf(token_string, sizeof(token_string), "touch.virtual_buttons.%d.%02d", i, y); for (x = 0; x < grid_xsize; x++) { @@ -13235,7 +13258,7 @@ { char prefix[30]; - sprintf(prefix, "%s%d", TOKEN_STR_PLAYER_PREFIX, pnr + 1); + snprintf(prefix, sizeof(prefix), "%s%d", TOKEN_STR_PLAYER_PREFIX, pnr + 1); fprintf(file, "\n"); setup_input = setup.input[pnr]; @@ -15705,8 +15728,8 @@ char *filename1; char *filename2; - sprintf(basename1, "%04d.bmp", i); - sprintf(basename2, "%04ds.bmp", i); + snprintf(basename1, sizeof(basename1), "%04d.bmp", i); + snprintf(basename2, sizeof(basename2), "%04ds.bmp", i); filename1 = getPath2(global.create_sketch_images_dir, basename1); filename2 = getPath2(global.create_sketch_images_dir, basename2); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/game.c new/rocksndiamonds-4.4.2.3/src/game.c --- old/rocksndiamonds-4.4.2.2/src/game.c 2026-06-20 23:18:45.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/game.c 2026-06-27 18:13:46.000000000 +0200 @@ -4387,6 +4387,8 @@ player->inventory_infinite_element = EL_UNDEFINED; player->inventory_size = 0; + player->kill_after_moving = FALSE; + if (level.use_initial_inventory[i]) { for (j = 0; j < level.initial_inventory_size[i]; j++) @@ -5897,8 +5899,8 @@ struct ScoreEntry new_entry = {{ 0 }}; // (prevent warning from GCC bug 53119) boolean one_per_name = FALSE; - strncpy(new_entry.tape_basename, tape.score_tape_basename, MAX_FILENAME_LEN); - strncpy(new_entry.name, setup.player_name, MAX_PLAYER_NAME_LEN); + snprintf(new_entry.tape_basename, sizeof(new_entry.tape_basename), "%s", tape.score_tape_basename); + snprintf(new_entry.name, sizeof(new_entry.name), "%s", setup.player_name); new_entry.score = game.score_final; new_entry.time = game.score_time_final; @@ -6840,6 +6842,8 @@ if (level.use_explosion_element[player_nr]) explosion_element = level.explosion_element[player_nr]; + else if (level.use_em_style_explosion[player_nr]) + explosion_element = EL_EMPTY; Tile[x][y] = (stored_player[player_nr].active ? EL_EMPTY : element_info[explosion_element].content.e[xx][yy]); @@ -6963,6 +6967,10 @@ else if (element_info[explosion_element].explosion_type == EXPLODES_1X1) explosion_type = EX_TYPE_CENTER; } + else if (level.use_em_style_explosion[player->index_nr]) + { + explosion_type = EX_TYPE_CENTER; + } } switch (element) @@ -14173,6 +14181,9 @@ } } + if (player->kill_after_moving) + KillPlayer(player); + if (Tile[jx][jy] == EL_EXIT_OPEN || Tile[jx][jy] == EL_EM_EXIT_OPEN || Tile[jx][jy] == EL_EM_EXIT_OPENING || @@ -15179,13 +15190,19 @@ return MP_DONT_RUN_INTO; } - // when using a deadly shield, player can dig traps and (DC) landmines like sand - if (player_can_move && player->shield_deadly_time_left > 0 && level.use_diggable_landmines && + // when configured as diggable, player can dig traps and (DC) landmines like sand + if (player_can_move && level.use_diggable_landmines && (element == EL_LANDMINE || element == EL_DC_LANDMINE || element == EL_TRAP_ACTIVE)) + { element = EL_SAND; + // when not using a deadly shield, player is killed after digging traps and (DC) landmines + if (player->shield_deadly_time_left == 0) + player->kill_after_moving = TRUE; + } + if (player_can_move && DONT_RUN_INTO(element)) { TestIfPlayerRunsIntoBadThing(jx, jy, player->MovDir); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/game.h new/rocksndiamonds-4.4.2.3/src/game.h --- old/rocksndiamonds-4.4.2.2/src/game.h 2026-06-20 23:18:45.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/game.h 2026-06-27 18:13:46.000000000 +0200 @@ -463,6 +463,9 @@ int inventory_element[MAX_INVENTORY_SIZE]; int inventory_infinite_element; int inventory_size; + + // flag to set when running into land mine + boolean kill_after_moving; }; extern struct GameInfo game; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/game_bd/bd_cave.h new/rocksndiamonds-4.4.2.3/src/game_bd/bd_cave.h --- old/rocksndiamonds-4.4.2.2/src/game_bd/bd_cave.h 2026-06-20 23:18:45.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/game_bd/bd_cave.h 2026-06-27 18:13:46.000000000 +0200 @@ -758,7 +758,12 @@ // function to copy a GdString static inline char *gd_strcpy(GdString dest, const char *src) { - return strncpy(dest, src, sizeof(GdString)); + int max_size = sizeof(GdString) - 1; + char *result = strncpy(dest, src, max_size); + + dest[max_size] = '\0'; + + return result; } int gd_cave_time_show(const GdCave *cave, int internal_time); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/game_bd/bd_colors.c new/rocksndiamonds-4.4.2.3/src/game_bd/bd_colors.c --- old/rocksndiamonds-4.4.2.2/src/game_bd/bd_colors.c 2026-06-20 23:18:45.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/game_bd/bd_colors.c 2026-06-27 18:13:46.000000000 +0200 @@ -736,17 +736,17 @@ if (gd_color_is_atari(color)) { - sprintf(text, "Atari%02x", color & 0xff); + snprintf(text, sizeof(text), "Atari%02x", color & 0xff); return text; } if (gd_color_is_dtv(color)) { - sprintf(text, "C64DTV%02x", color & 0xff); + snprintf(text, sizeof(text), "C64DTV%02x", color & 0xff); return text; } - sprintf(text, "#%02x%02x%02x", (color >> 16) & 255, (color >> 8) & 255, color & 255); + snprintf(text, sizeof(text), "#%02x%02x%02x", (color >> 16) & 255, (color >> 8) & 255, color & 255); return text; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/init.c new/rocksndiamonds-4.4.2.3/src/init.c --- old/rocksndiamonds-4.4.2.2/src/init.c 2026-06-20 23:18:45.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/init.c 2026-06-27 18:13:46.000000000 +0200 @@ -5914,7 +5914,7 @@ char font_token[128]; int len_font_token; - sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1); + snprintf(font_token, sizeof(font_token), "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1); len_font_token = strlen(font_token); if (strEqual(image_config[i].token, font_token)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/libgame/gadgets.c new/rocksndiamonds-4.4.2.3/src/libgame/gadgets.c --- old/rocksndiamonds-4.4.2.2/src/libgame/gadgets.c 2026-06-20 23:18:45.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/libgame/gadgets.c 2026-06-27 18:13:46.000000000 +0200 @@ -452,10 +452,10 @@ RGBColor color_rgb = get_rgb_from_hsv(gi->colorpicker.color_hsv); char text[128]; - sprintf(text, "#%02x%02x%02x", - (int) (color_rgb.r * 255), - (int) (color_rgb.g * 255), - (int) (color_rgb.b * 255)); + snprintf(text, sizeof(text), "#%02x%02x%02x", + (int) (color_rgb.r * 255), + (int) (color_rgb.g * 255), + (int) (color_rgb.b * 255)); DrawText(x_text, y_text, text, font_nr); } @@ -1639,7 +1639,7 @@ case GDI_NUMBER_VALUE: gi->textinput.number_value = va_arg(ap, int); - sprintf(gi->textinput.value, "%d", gi->textinput.number_value); + snprintf(gi->textinput.value, MAX_GADGET_TEXTSIZE, "%d", gi->textinput.number_value); strcpy(gi->textinput.last_value, gi->textinput.value); gi->textinput.cursor_position = strlen(gi->textinput.value); break; @@ -1649,7 +1649,7 @@ if (gi->textinput.number_value < gi->textinput.number_min) { gi->textinput.number_value = gi->textinput.number_min; - sprintf(gi->textinput.value, "%d", gi->textinput.number_value); + snprintf(gi->textinput.value, MAX_GADGET_TEXTSIZE, "%d", gi->textinput.number_value); strcpy(gi->textinput.last_value, gi->textinput.value); } break; @@ -1659,7 +1659,7 @@ if (gi->textinput.number_value > gi->textinput.number_max) { gi->textinput.number_value = gi->textinput.number_max; - sprintf(gi->textinput.value, "%d", gi->textinput.number_value); + snprintf(gi->textinput.value, MAX_GADGET_TEXTSIZE, "%d", gi->textinput.number_value); strcpy(gi->textinput.last_value, gi->textinput.value); } break; @@ -2017,7 +2017,7 @@ value > text->number_max ? text->number_max : value); - sprintf(text->value, "%d", text->number_value); + snprintf(text->value, MAX_GADGET_TEXTSIZE, "%d", text->number_value); } if (gi->type & GD_TYPE_TEXT_BUTTON) @@ -2222,7 +2222,7 @@ if (gi->textinput.number_value > gi->textinput.number_max) gi->textinput.number_value = gi->textinput.number_max; - sprintf(gi->textinput.value, "%d", gi->textinput.number_value); + snprintf(gi->textinput.value, MAX_GADGET_TEXTSIZE, "%d", gi->textinput.number_value); if (gi->textinput.cursor_position < 0) gi->textinput.cursor_position = 0; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/libgame/setup.c new/rocksndiamonds-4.4.2.3/src/libgame/setup.c --- old/rocksndiamonds-4.4.2.2/src/libgame/setup.c 2026-06-20 23:18:45.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/libgame/setup.c 2026-06-27 18:13:46.000000000 +0200 @@ -1164,10 +1164,10 @@ static char *getLevelSetTitleMessageBasename(int nr, boolean initial) { - static char basename[32]; + static char basename[MAX_FILENAME_LEN]; - sprintf(basename, "%s_%d.txt", - (initial ? "titlemessage_initial" : "titlemessage"), nr + 1); + snprintf(basename, sizeof(basename), "%s_%d.txt", + (initial ? "titlemessage_initial" : "titlemessage"), nr + 1); return basename; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/main.h new/rocksndiamonds-4.4.2.3/src/main.h --- old/rocksndiamonds-4.4.2.2/src/main.h 2026-06-20 23:18:45.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/main.h 2026-06-27 18:13:46.000000000 +0200 @@ -3222,7 +3222,7 @@ #define PROGRAM_VERSION_SUPER 4 #define PROGRAM_VERSION_MAJOR 4 #define PROGRAM_VERSION_MINOR 2 -#define PROGRAM_VERSION_PATCH 2 +#define PROGRAM_VERSION_PATCH 3 #define PROGRAM_VERSION_STABLE 1 #define PROGRAM_VERSION_EXTRA 0 @@ -3923,6 +3923,8 @@ int explosion_element[MAX_PLAYERS]; boolean use_explosion_element[MAX_PLAYERS]; + boolean use_em_style_explosion[MAX_PLAYERS]; + // values for the new EMC elements int android_move_time; int android_clone_time; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/rocksndiamonds-4.4.2.2/src/screens.c new/rocksndiamonds-4.4.2.3/src/screens.c --- old/rocksndiamonds-4.4.2.2/src/screens.c 2026-06-20 23:18:45.000000000 +0200 +++ new/rocksndiamonds-4.4.2.3/src/screens.c 2026-06-27 18:13:46.000000000 +0200 @@ -418,6 +418,8 @@ static int getInfoScreenBackgroundSound_Generic(void); static int getInfoScreenBackgroundMusic_Generic(void); +static void drawChooseTreeScreen(TreeInfo *, boolean); + static struct TokenInfo *getSetupInfoFinal(struct TokenInfo *); static struct GadgetInfo *screen_gadget[NUM_SCREEN_GADGETS]; @@ -5614,6 +5616,8 @@ if (game_status == GAME_MODE_MAIN) InitializeMainControls(FALSE); + else + drawChooseTreeScreen(player_name_current, FALSE); } }
