Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package black-hole-solver for openSUSE:Factory checked in at 2025-09-12 21:10:25 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/black-hole-solver (Old) and /work/SRC/openSUSE:Factory/.black-hole-solver.new.1977 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "black-hole-solver" Fri Sep 12 21:10:25 2025 rev:4 rq:1304218 version:1.14.0 Changes: -------- --- /work/SRC/openSUSE:Factory/black-hole-solver/black-hole-solver.changes 2022-12-13 18:55:48.927314744 +0100 +++ /work/SRC/openSUSE:Factory/.black-hole-solver.new.1977/black-hole-solver.changes 2025-09-12 21:11:24.879995219 +0200 @@ -1,0 +2,11 @@ +Fri Sep 12 07:04:29 UTC 2025 - Dirk Müller <dmuel...@suse.com> + +- update to 1.4.0: + * Fixed running black_hole_solver_run with the same + (or a smaller) iterations limit. It ran indefinetely + then (Possible Denial-of-service?) + * Fix some hypothetical rresource leaks (e.g.: with "fopen()"). + * Cleanups: add "const"s , convert "int" to "bool", etc. + * Add tests. + +------------------------------------------------------------------- Old: ---- black-hole-solver-1.12.0.tar.xz New: ---- black-hole-solver-1.14.0.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ black-hole-solver.spec ++++++ --- /var/tmp/diff_new_pack.QcXA8L/_old 2025-09-12 21:11:25.476020350 +0200 +++ /var/tmp/diff_new_pack.QcXA8L/_new 2025-09-12 21:11:25.476020350 +0200 @@ -1,7 +1,7 @@ # # spec file for package black-hole-solver # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2025 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -20,7 +20,7 @@ # Missing perl(Env::Path), should also skip some tests like build-process %global run_tests 0 Name: black-hole-solver -Version: 1.12.0 +Version: 1.14.0 Release: 0 Summary: The Black Hole Solver Executable License: MIT ++++++ black-hole-solver-1.12.0.tar.xz -> black-hole-solver-1.14.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/CMakeLists.txt new/black-hole-solver-1.14.0/CMakeLists.txt --- old/black-hole-solver-1.12.0/CMakeLists.txt 2021-12-11 06:47:47.000000000 +0100 +++ new/black-hole-solver-1.14.0/CMakeLists.txt 2025-03-03 08:21:09.000000000 +0100 @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.5) +CMAKE_MINIMUM_REQUIRED(VERSION 3.15) PROJECT(black-hole-solver) INCLUDE ("${CMAKE_SOURCE_DIR}/cmake/shlomif_common_bootstrap.cmake") @@ -13,6 +13,8 @@ option (LINK_TO_STATIC "Link the executables to the static library") option (DISABLE_APPLYING_RPATH "Disable applying rpath") option (ENABLE_DISPLAYING_MAX_NUM_PLAYED_CARDS "Allow recording and displaying the maximal number of played/\"moved\" cards. Enabling it may make the non-related run time somewhat slower.") +option (USE_SIGNED_CHARS "-fsigned-char") +option (USE_UNSIGNED_CHARS "-funsigned-char") INCLUDE(FindPkgConfig) @@ -33,7 +35,7 @@ SET (BHS_STATE_STORAGE "BHS_STATE_STORAGE_INTERNAL_HASH" CACHE STRING "The State Storage Type") SET (FCS_IA_PACK_SIZE 64 CACHE STRING "Size of a single pack in kilo-bytes.") -SET (IA_STATE_PACKS_GROW_BY 32 CACHE STRING "Amount to Grow State Packs By") +SET (IA_STATE_PACKS_GROW_BY 32 CACHE STRING "Amount to Grow State Packs By ( UNUSED! Kept for backward compatibility. )") SET (base_with_ver "black_hole_solver-[0-9]+\\\\.[0-9]+\\\\.[0-9]+") SET(CPACK_SOURCE_GENERATOR "TXZ") SET(CPACK_SOURCE_IGNORE_FILES @@ -133,6 +135,7 @@ IF ("$ENV{FCS_CLANG}") ADD_DEFINITIONS("-Weverything -Wno-language-extension-token -Wno-gnu-statement-expression -Wno-used-but-marked-unused -Wno-padded -Wno-cast-align -Wno-extra-semi-stmt") + ADD_DEFINITIONS("-Wno-declaration-after-statement") ENDIF () IF ("$ENV{FCS_GCC}") @@ -146,6 +149,15 @@ ENDIF () ADD_DEFINITIONS("-Wno-unknown-pragmas") +IF (USE_UNSIGNED_CHARS) + ADD_DEFINITIONS("-funsigned-char") + IF (USE_SIGNED_CHARS) + MESSAGE(FATAL_ERROR "Cannot have both USE_SIGNED_CHARS and USE_UNSIGNED_CHARS !") + ENDIF () +ELSEIF (USE_SIGNED_CHARS) + ADD_DEFINITIONS("-fsigned-char") +ENDIF () + # So it can find config.h INCLUDE_DIRECTORIES(BEFORE "${CMAKE_CURRENT_SOURCE_DIR}") INCLUDE_DIRECTORIES(BEFORE "${CMAKE_CURRENT_BINARY_DIR}") @@ -207,7 +219,7 @@ ) SET_TARGET_PROPERTIES( - "${LIB_BASE}" PROPERTIES VERSION 1.0.1 SOVERSION 1 + "${LIB_BASE}" PROPERTIES VERSION 1.0.2 SOVERSION 1 ) SET (LIBS "${LIB_BASE}") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/NEWS.asciidoc new/black-hole-solver-1.14.0/NEWS.asciidoc --- old/black-hole-solver-1.12.0/NEWS.asciidoc 2022-03-28 12:28:47.000000000 +0200 +++ new/black-hole-solver-1.14.0/NEWS.asciidoc 2025-03-03 07:56:03.000000000 +0100 @@ -1,9 +1,21 @@ Black Hole Solver's News File ============================= Shlomi Fish <shlo...@cpan.org> -:Date: 2020-06-28 +:Date: 2025-03-03 :Revision: $Id$ +1.14.0 ( 03 March 2025 ): +------------------------------- + +* Fixed running black_hole_solver_run with the same (or a smaller) iterations +limit. It ran indefinetely then (Possible Denial-of-service?) + +* Fix some hypothetical rresource leaks (e.g.: with "fopen()"). + +* Cleanups: add "const"s , convert "int" to "bool", etc. + +* Add tests. + 1.12.0 ( 28 March 2022 ): ------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/black-hole-solver.spec new/black-hole-solver-1.14.0/black-hole-solver.spec --- old/black-hole-solver-1.12.0/black-hole-solver.spec 2022-03-28 12:29:16.000000000 +0200 +++ new/black-hole-solver-1.14.0/black-hole-solver.spec 2025-03-03 07:57:04.000000000 +0100 @@ -1,5 +1,5 @@ Name: black-hole-solver -Version: 1.12.0 +Version: 1.14.0 Release: 1 License: MIT Group: Amusement/Games @@ -41,22 +41,20 @@ Group: Amusement/Games %description -n libblack_hole_solver1 -Contains the Blach Hole Solitaire libraries. +Contains the Black Hole Solitaire libraries. This package is mandatory for the Black Hole Solitaire executable too. %package -n libblack_hole_solver1-devel -Summary: The Freecell Solver development tools for solving Freecell games +Summary: The Black Hole Solitaire development tools Group: Amusement/Games Requires: libblack_hole_solver1 = %{version} %description -n libblack_hole_solver1-devel -Freecell Solver is a library for automatically solving boards of Freecell and -similar variants of card Solitaire. This package contains the header files and -static libraries necessary for developing programs using Freecell Solver. +Contains the Black Hole Solitaire development libraries. You should install it if you are a game developer who would like to use -Freecell Solver from within your programs. +Black Hole Solitaire Solver from within your programs. %prep %setup @@ -92,81 +90,5 @@ rm -rf $RPM_BUILD_ROOT %changelog -* Tue Mar 31 2009 Shlomi Fish <shlo...@cpan.org> 2.21.2-1 -- Adapted to the CMake build system. -- Changed the license from "Public Domain" to "MIT". - -* Mon Oct 24 2005 Shlomi Fish <shlo...@cpan.org> 2.8.11-1 -- Changed "Copyright" to "License" - -* Fri Jul 30 2004 Shlomi Fish <shlo...@cpan.org> 2.8.7-1 -- Added some unpackaged files -- deleted make-microsoft-freecell-board so it won't be reported as - unpacked -- removed some old cd's that are now useless -- removed the serial tags - they are just trouble. - -* Mon Sep 02 2002 Shlomi Fish <shlo...@cpan.org> 2.7.15-1 -- Used strip on the range solver -- Added the presets' related files - -* Sat Feb 16 2002 Shlomi Fish <shlo...@cpan.org> 2.1.10-1 -- updated to version 2.1.10 -- removed the man pages symlinks (they were superceded by the ".so" links). - -* Fri Jan 04 2002 Shlomi Fish <shlo...@cpan.org> 2.0.1-1 -- updated to version 2.0.1 -- added freecell-solver-range-parallel-solve to the /usr/bin programs - -* Tue Dec 18 2001 Shlomi Fish <shlo...@cpan.org> 2.0.0-1 -- updated to version 2.0.0 - -* Fri Nov 23 2001 Shlomi Fish <shlo...@cpan.org> 1.10.3-1 -- updated to version 1.10.3 - -* Thu Nov 22 2001 Shlomi Fish <shlo...@cpan.org> 1.10.2-1 -- updated to version 1.10.2 - -* Tue Oct 02 2001 Shlomi Fish <shlo...@cpan.org> 1.10.0-1 -- updated to version 1.10.0 - -* Sat Sep 22 2001 Shlomi Fish <shlo...@cpan.org> 1.8.2-1 -- updated to version 1.8.2 - -* Sat Sep 01 2001 Shlomi Fish <shlo...@cpan.org> 1.8.0-1 -- Changed the version to 1.8.0 -- Removed the -autconf suffix from the archive. - -* Sat Jul 07 2001 Shlomi Fish <shlo...@cpan.org> 1.6.7-2 -- Fixed the man pages. -- Included a paragraph about the board_gen programs in the description of - the executable package. - -* Sat Jun 09 2001 Shlomi Fish <shlo...@cpan.org> 1.6.7-1 -- Changed the version to 1.6.7. -- Added support for the man pages. -- Added the symlinked man pages. -- Added the board_gen sub-dir in the documentation directory. (using a rather -crude hack) -- Known Bugs: - 1 - The man pages need a little rework, there are some typos and they - don't look very standard. - - -* Thu May 24 2001 Shlomi Fish <shlo...@cpan.org> 1.6.4-3 -- Added the board generation programs into the RPM. -- Changed the package to my name and E-mail. Done through the home-dir conf -file, not by editting the SPEC, but what the heck. - -* Sat May 19 2001 Shlomi Fish <shlo...@cpan.org> 1.6.4-2 -- Changed the descriptions and summaries to something more meaningful -- Removed the dependency on "Serial" in "Requires". - -* Fri May 18 2001 Shlomi Fish <shlo...@cpan.org> 1.6.4-1 -- First working version with libs and executable support. -- Known Bugs: - 1 - No "devel" package. - 2 - No options passed to "configure". -- Added calls to strip. -- "configure" is now OK with all the options set. -- Added Headers and a working freecell-solver-devel +* Mon Feb 10 2025 Shlomi Fish <shlo...@cpan.org> 1.12.0-1 +- Trim the old, freecell-solver, changelog. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/black-hole-solver.spec.in new/black-hole-solver-1.14.0/black-hole-solver.spec.in --- old/black-hole-solver-1.12.0/black-hole-solver.spec.in 2020-11-27 09:09:50.000000000 +0100 +++ new/black-hole-solver-1.14.0/black-hole-solver.spec.in 2025-02-10 11:00:17.000000000 +0100 @@ -41,22 +41,20 @@ Group: Amusement/Games %description -n libblack_hole_solver1 -Contains the Blach Hole Solitaire libraries. +Contains the Black Hole Solitaire libraries. This package is mandatory for the Black Hole Solitaire executable too. %package -n libblack_hole_solver1-devel -Summary: The Freecell Solver development tools for solving Freecell games +Summary: The Black Hole Solitaire development tools Group: Amusement/Games Requires: libblack_hole_solver1 = %{version} %description -n libblack_hole_solver1-devel -Freecell Solver is a library for automatically solving boards of Freecell and -similar variants of card Solitaire. This package contains the header files and -static libraries necessary for developing programs using Freecell Solver. +Contains the Black Hole Solitaire development libraries. You should install it if you are a game developer who would like to use -Freecell Solver from within your programs. +Black Hole Solitaire Solver from within your programs. %prep %setup @@ -92,81 +90,5 @@ rm -rf $RPM_BUILD_ROOT %changelog -* Tue Mar 31 2009 Shlomi Fish <shlo...@cpan.org> 2.21.2-1 -- Adapted to the CMake build system. -- Changed the license from "Public Domain" to "MIT". - -* Mon Oct 24 2005 Shlomi Fish <shlo...@cpan.org> 2.8.11-1 -- Changed "Copyright" to "License" - -* Fri Jul 30 2004 Shlomi Fish <shlo...@cpan.org> 2.8.7-1 -- Added some unpackaged files -- deleted make-microsoft-freecell-board so it won't be reported as - unpacked -- removed some old cd's that are now useless -- removed the serial tags - they are just trouble. - -* Mon Sep 02 2002 Shlomi Fish <shlo...@cpan.org> 2.7.15-1 -- Used strip on the range solver -- Added the presets' related files - -* Sat Feb 16 2002 Shlomi Fish <shlo...@cpan.org> 2.1.10-1 -- updated to version 2.1.10 -- removed the man pages symlinks (they were superceded by the ".so" links). - -* Fri Jan 04 2002 Shlomi Fish <shlo...@cpan.org> 2.0.1-1 -- updated to version 2.0.1 -- added freecell-solver-range-parallel-solve to the /usr/bin programs - -* Tue Dec 18 2001 Shlomi Fish <shlo...@cpan.org> 2.0.0-1 -- updated to version 2.0.0 - -* Fri Nov 23 2001 Shlomi Fish <shlo...@cpan.org> 1.10.3-1 -- updated to version 1.10.3 - -* Thu Nov 22 2001 Shlomi Fish <shlo...@cpan.org> 1.10.2-1 -- updated to version 1.10.2 - -* Tue Oct 02 2001 Shlomi Fish <shlo...@cpan.org> 1.10.0-1 -- updated to version 1.10.0 - -* Sat Sep 22 2001 Shlomi Fish <shlo...@cpan.org> 1.8.2-1 -- updated to version 1.8.2 - -* Sat Sep 01 2001 Shlomi Fish <shlo...@cpan.org> 1.8.0-1 -- Changed the version to 1.8.0 -- Removed the -autconf suffix from the archive. - -* Sat Jul 07 2001 Shlomi Fish <shlo...@cpan.org> 1.6.7-2 -- Fixed the man pages. -- Included a paragraph about the board_gen programs in the description of - the executable package. - -* Sat Jun 09 2001 Shlomi Fish <shlo...@cpan.org> 1.6.7-1 -- Changed the version to 1.6.7. -- Added support for the man pages. -- Added the symlinked man pages. -- Added the board_gen sub-dir in the documentation directory. (using a rather -crude hack) -- Known Bugs: - 1 - The man pages need a little rework, there are some typos and they - don't look very standard. - - -* Thu May 24 2001 Shlomi Fish <shlo...@cpan.org> 1.6.4-3 -- Added the board generation programs into the RPM. -- Changed the package to my name and E-mail. Done through the home-dir conf -file, not by editting the SPEC, but what the heck. - -* Sat May 19 2001 Shlomi Fish <shlo...@cpan.org> 1.6.4-2 -- Changed the descriptions and summaries to something more meaningful -- Removed the dependency on "Serial" in "Requires". - -* Fri May 18 2001 Shlomi Fish <shlo...@cpan.org> 1.6.4-1 -- First working version with libs and executable support. -- Known Bugs: - 1 - No "devel" package. - 2 - No options passed to "configure". -- Added calls to strip. -- "configure" is now OK with all the options set. -- Added Headers and a working freecell-solver-devel +* Mon Feb 10 2025 Shlomi Fish <shlo...@cpan.org> 1.12.0-1 +- Trim the old, freecell-solver, changelog. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/cmake/Shlomif_Common.cmake new/black-hole-solver-1.14.0/cmake/Shlomif_Common.cmake --- old/black-hole-solver-1.12.0/cmake/Shlomif_Common.cmake 2021-09-23 10:42:02.000000000 +0200 +++ new/black-hole-solver-1.14.0/cmake/Shlomif_Common.cmake 2025-02-23 18:26:45.000000000 +0100 @@ -224,11 +224,14 @@ FILE (WRITE "${TO}" "${contents}") ENDMACRO() +# See: https://github.com/shlomif/shlomif-cmake-modules/issues/1 +SET (SHLOMIF_SYSTEM_INSTALL_DIR "/usr/share/cmake/Modules" CACHE STRING "cmake sys installation dir") + MACRO(SHLOMIF_COMMON_SETUP private_mod_path) SET (private_mod "Shlomif_Common.cmake") SET (_dest "${private_mod_path}/${private_mod}") IF (NOT EXISTS "${_dest}") - SHLOMIF_PHYS_COPY_FILE( "/usr/share/cmake/Modules/${private_mod}" "${_dest}") + SHLOMIF_PHYS_COPY_FILE( "${SHLOMIF_SYSTEM_INSTALL_DIR}/${private_mod}" "${_dest}") ENDIF () ENDMACRO() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/cmake/pod2man-wrapper.pl new/black-hole-solver-1.14.0/cmake/pod2man-wrapper.pl --- old/black-hole-solver-1.12.0/cmake/pod2man-wrapper.pl 2019-01-14 01:59:57.000000000 +0100 +++ new/black-hole-solver-1.14.0/cmake/pod2man-wrapper.pl 2025-02-10 11:02:19.000000000 +0100 @@ -4,8 +4,8 @@ use warnings; use Getopt::Long; -use File::Temp qw/tempdir/; -use File::Copy; +use File::Temp qw/ tempdir /; +use File::Copy qw/ copy /; my ( $src, $dest, $sect, $center, $release ); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/config.h.in new/black-hole-solver-1.14.0/config.h.in --- old/black-hole-solver-1.12.0/config.h.in 2020-10-25 10:56:51.000000000 +0100 +++ new/black-hole-solver-1.14.0/config.h.in 2025-02-10 11:05:23.000000000 +0100 @@ -14,8 +14,8 @@ * ${AUTOGENERATED_CONFIG_H} */ -#ifndef FC_SOLVE__CONFIG_H -#define FC_SOLVE__CONFIG_H +#ifndef BLACK_HOLE_SOLVE__CONFIG_H +#define BLACK_HOLE_SOLVE__CONFIG_H #ifdef __cplusplus extern "C" { @@ -23,17 +23,6 @@ #cmakedefine CARD_DEBUG_PRES -/* - The sort margin size for the previous states array. -*/ -#define PREV_STATES_SORT_MARGIN 32 - -/* - The amount the pack pointers array grows by. Shouldn't be too high - because it doesn't happen too often. -*/ -#cmakedefine IA_STATE_PACKS_GROW_BY 32 - /* The size of a single pack in alloc.c/alloc.h measured in 1024 chars. */ #cmakedefine FCS_IA_PACK_SIZE ${FCS_IA_PACK_SIZE} @@ -53,5 +42,4 @@ } #endif -#endif /* #ifndef FC_SOLVE__CONFIG_H */ - +#endif /* #ifndef BLACK_HOLE_SOLVE__CONFIG_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/fcs_hash.c new/black-hole-solver-1.14.0/fcs_hash.c --- old/black-hole-solver-1.12.0/fcs_hash.c 2019-12-28 20:43:33.000000000 +0100 +++ new/black-hole-solver-1.14.0/fcs_hash.c 2025-02-10 12:32:15.000000000 +0100 @@ -27,21 +27,20 @@ // hash table, allowing for smaller chains, and faster lookup. static inline bool bh_solve_hash_rehash(bh_solve_hash_t *hash) { - bh_solve_hash_symlink_t *new_entries; - const_AUTO(old_size, hash->size); const_AUTO(new_size, old_size << 1); const_AUTO(new_size_bitmask, new_size - 1); - if (unlikely(!(new_entries = calloc( - (size_t)new_size, sizeof(bh_solve_hash_symlink_t))))) + bh_solve_hash_symlink_t *new_entries; + if (unlikely( + !(new_entries = calloc((size_t)new_size, sizeof(new_entries[0]))))) { return true; } /* Copy the items to the new hash while not allocating them again */ - for (bh_solve_hash_value_t i = 0; i < old_size; i++) + for (bh_solve_hash_value_t i = 0; i < old_size; ++i) { var_AUTO(item, hash->entries[i].first_item); /* traverse the chain item by item */ @@ -76,7 +75,7 @@ return false; } -int bh_solve_hash_init(bh_solve_hash_t *hash, meta_allocator *const meta_alloc) +bool bh_solve_hash_init(bh_solve_hash_t *hash, meta_allocator *const meta_alloc) { const bh_solve_hash_value_t size = 256; @@ -90,7 +89,7 @@ if (!(hash->entries = calloc((size_t)size, sizeof(bh_solve_hash_symlink_t)))) { - return 1; + return true; } #ifdef BHS_WITH_HASH_VACANT_ITEMS hash->list_of_vacant_items = NULL; @@ -101,10 +100,10 @@ { free(hash->entries); hash->entries = NULL; - return 1; + return true; } - return 0; + return false; } int bh_solve_hash_insert( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/fcs_hash.h new/black-hole-solver-1.14.0/fcs_hash.h --- old/black-hole-solver-1.12.0/fcs_hash.h 2019-06-30 19:39:36.000000000 +0200 +++ new/black-hole-solver-1.14.0/fcs_hash.h 2025-02-10 12:32:52.000000000 +0100 @@ -90,7 +90,7 @@ } bh_solve_hash_t; -extern int bh_solve_hash_init(bh_solve_hash_t *hash, meta_allocator *); +extern bool bh_solve_hash_init(bh_solve_hash_t *hash, meta_allocator *); // Returns false if the key is new and the key/val pair was inserted. // Returns true if the key is not new and *existing_key / *existing_val @@ -111,6 +111,7 @@ memset(hash->entries, '\0', sizeof(hash->entries[0]) * hash->size); hash->num_elems = 0; } + static inline void bh_solve_hash_get( bh_solve_hash_t *hash, bhs_state_key_t *key_ptr, bhs_state_value_t *result) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/include/black-hole-solver/fcs_dllexport.h new/black-hole-solver-1.14.0/include/black-hole-solver/fcs_dllexport.h --- old/black-hole-solver-1.12.0/include/black-hole-solver/fcs_dllexport.h 2019-04-16 21:17:00.000000000 +0200 +++ new/black-hole-solver-1.14.0/include/black-hole-solver/fcs_dllexport.h 2024-04-04 09:36:25.000000000 +0200 @@ -1,5 +1,4 @@ -#ifndef FC_SOLVE__FCS_DLLEXPORT_H -#define FC_SOLVE__FCS_DLLEXPORT_H +#pragma once #ifdef _MSC_VER #ifdef BUILDING_DLL @@ -15,5 +14,3 @@ #define DLLEXPORT #define DLLLOCAL #endif - -#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/lib.c new/black-hole-solver-1.14.0/lib.c --- old/black-hole-solver-1.12.0/lib.c 2020-11-27 09:09:50.000000000 +0100 +++ new/black-hole-solver-1.14.0/lib.c 2025-02-20 16:54:58.000000000 +0100 @@ -49,7 +49,7 @@ INVALID_SUIT = -1 }; -static int suit_char_to_index(char suit) +static int suit_char_to_index(const char suit) { switch (suit) { @@ -173,7 +173,7 @@ fc_solve_meta_compact_allocator_init(&(ret->meta_alloc)); if (unlikely(bh_solve_hash_init(&(ret->positions), &(ret->meta_alloc)))) { - fc_solve_meta_compact_allocator_finish(&(ret->meta_alloc)); + bh_solve_meta_compact_allocator_finish(&(ret->meta_alloc)); free(ret); *ret_instance = NULL; return BLACK_HOLE_SOLVER__OUT_OF_MEMORY; @@ -549,7 +549,7 @@ next_queue_item.s.packed.value.prev_foundation = prev_foundation; next_queue_item.rank_counts = queue_item_copy_ptr->rank_counts; - next_queue_item.rank_counts.c[(ssize_t)card]--; + --next_queue_item.rank_counts.c[(ssize_t)card]; const int ret = bh_solve_hash_insert(&(solver->positions), &(next_queue_item.s.packed)); @@ -629,7 +629,7 @@ } extern int DLLEXPORT black_hole_solver_config_setup( - black_hole_solver_instance_t *instance_proto) + black_hole_solver_instance_t *const instance_proto) { bhs_solver_t *const solver = (bhs_solver_t *)instance_proto; setup_config(solver); @@ -637,14 +637,14 @@ } extern int DLLEXPORT black_hole_solver_setup( - black_hole_solver_instance_t *instance_proto) + black_hole_solver_instance_t *const instance_proto) { bhs_solver_t *const solver = (bhs_solver_t *)instance_proto; return setup_init_state(solver); } extern int DLLEXPORT black_hole_solver_run( - black_hole_solver_instance_t *instance_proto) + black_hole_solver_instance_t *const instance_proto) { bhs_solver_t *const solver = (bhs_solver_t *)instance_proto; @@ -661,6 +661,11 @@ max_reached_depths_stack_len, solver->max_reached_depths_stack_len); var_AUTO(current_depths_stack_len, solver->current_depths_stack_len); + if (iterations_num >= max_iters_limit) + { + return BLACK_HOLE_SOLVER__OUT_OF_ITERS; + } + while (solver->queue_len > 0) { const_AUTO(prev_len, solver->queue_len); @@ -754,8 +759,9 @@ return BLACK_HOLE_SOLVER__SUCCESS; } - else if (iterations_num == max_iters_limit) + else if (iterations_num >= max_iters_limit) { + assert(iterations_num == max_iters_limit); solver->max_reached_depths_stack_len = max_reached_depths_stack_len; solver->iterations_num = iterations_num; solver->current_depths_stack_len = current_depths_stack_len; @@ -772,7 +778,7 @@ } extern int DLLEXPORT black_hole_solver_recycle( - black_hole_solver_instance_t *instance_proto) + black_hole_solver_instance_t *const instance_proto) { bhs_solver_t *const solver = (bhs_solver_t *)instance_proto; @@ -788,7 +794,7 @@ } DLLEXPORT void black_hole_solver_init_solution_moves( - black_hole_solver_instance_t *instance_proto) + black_hole_solver_instance_t *const instance_proto) { bhs_solver_t *const solver = (bhs_solver_t *)instance_proto; const_SLOT(num_columns, solver); @@ -824,7 +830,7 @@ states[num_states + 1].packed.value.prev_foundation; unsigned char *data = states[num_states + 1].packed.key.data; for (size_t i = 0; i < TALON_PTR_BITS; - ++i, new_moved_card_height >>= 1) + ++i, new_moved_card_height >>= 1) { data[0] &= (~(1 << (i))); data[0] |= ((new_moved_card_height & 0x1) << (i)); @@ -841,7 +847,7 @@ var_AUTO(offset, TALON_PTR_BITS + bits_per_column * col_idx); unsigned char *data = states[num_states + 1].packed.key.data; for (size_t i = 0; i < bits_per_column; - ++i, ++offset, new_moved_card_height >>= 1) + ++i, ++offset, new_moved_card_height >>= 1) { data[offset >> 3] &= (~(1 << (offset & 0x7))); data[offset >> 3] |= @@ -905,14 +911,14 @@ DLLEXPORT extern unsigned long __attribute__((pure)) black_hole_solver_get_iterations_num( - black_hole_solver_instance_t *instance_proto) + black_hole_solver_instance_t *const instance_proto) { return ((bhs_solver_t *)instance_proto)->iterations_num; } DLLEXPORT extern unsigned long __attribute__((pure)) black_hole_solver_get_max_num_played_cards( - black_hole_solver_instance_t *instance_proto) + black_hole_solver_instance_t *const instance_proto) { const_AUTO( ret, ((bhs_solver_t *)instance_proto)->max_reached_depths_stack_len); @@ -920,7 +926,7 @@ } DLLEXPORT extern int black_hole_solver_get_current_solution_board( - black_hole_solver_instance_t *instance_proto, char *const output) + black_hole_solver_instance_t *const instance_proto, char *const output) { bhs_solver_t *const solver = (bhs_solver_t *)instance_proto; @@ -982,12 +988,12 @@ } extern int DLLEXPORT black_hole_solver_free( - black_hole_solver_instance_t *instance_proto) + black_hole_solver_instance_t *const instance_proto) { bhs_solver_t *const solver = (bhs_solver_t *)instance_proto; bh_solve_hash_free(&(solver->positions)); - fc_solve_meta_compact_allocator_finish(&(solver->meta_alloc)); + bh_solve_meta_compact_allocator_finish(&(solver->meta_alloc)); free(solver); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/meta_alloc.c new/black-hole-solver-1.14.0/meta_alloc.c --- old/black-hole-solver-1.12.0/meta_alloc.c 2019-08-16 10:35:02.000000000 +0200 +++ new/black-hole-solver-1.14.0/meta_alloc.c 2025-02-10 12:04:05.000000000 +0100 @@ -30,12 +30,12 @@ } } -int fc_solve_compact_allocator_extend(compact_allocator *const allocator) +bool bh_solve_compact_allocator_extend(compact_allocator *const allocator) { char *const new_data = meta_request_new_buffer(allocator->meta); if (unlikely(!new_data)) { - return 1; + return true; } FCS__COMPACT_ALLOC__OLD_LIST_NEXT(new_data) = allocator->old_list; @@ -43,15 +43,15 @@ allocator->ptr = allocator->rollback_ptr = OLD_LIST_DATA(new_data); allocator->max_ptr = new_data + ALLOCED_SIZE; - return 0; + return false; } -void fc_solve_meta_compact_allocator_finish(meta_allocator *const meta_alloc) +void bh_solve_meta_compact_allocator_finish(meta_allocator *const meta_alloc) { char *iter = meta_alloc->recycle_bin; char *iter_next = iter ? FCS__COMPACT_ALLOC__OLD_LIST_NEXT(iter) : NULL; for (; iter_next; - iter = iter_next, iter_next = FCS__COMPACT_ALLOC__OLD_LIST_NEXT(iter)) + iter = iter_next, iter_next = FCS__COMPACT_ALLOC__OLD_LIST_NEXT(iter)) { free(iter); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/meta_alloc.h new/black-hole-solver-1.14.0/meta_alloc.h --- old/black-hole-solver-1.12.0/meta_alloc.h 2019-08-16 10:35:02.000000000 +0200 +++ new/black-hole-solver-1.14.0/meta_alloc.h 2025-02-10 12:09:37.000000000 +0100 @@ -16,6 +16,7 @@ extern "C" { #endif +#include <stdbool.h> #include <stddef.h> #include "rinutils/likely.h" #include "rinutils/typeof_wrap.h" @@ -39,14 +40,14 @@ meta_allocator *meta; } compact_allocator; -extern int fc_solve_compact_allocator_extend(compact_allocator *); +extern bool bh_solve_compact_allocator_extend(compact_allocator *); /* To be called after the meta_alloc was set. */ -static inline int fc_solve_compact_allocator_init_helper( +static inline bool fc_solve_compact_allocator_init_helper( compact_allocator *const allocator) { allocator->old_list = NULL; - return fc_solve_compact_allocator_extend(allocator); + return bh_solve_compact_allocator_extend(allocator); } static inline void fc_solve_meta_compact_allocator_init( @@ -55,7 +56,7 @@ meta->recycle_bin = NULL; } -extern void fc_solve_meta_compact_allocator_finish(meta_allocator *); +extern void bh_solve_meta_compact_allocator_finish(meta_allocator *); static inline void *fcs_compact_alloc_ptr( compact_allocator *const allocator, const size_t how_much_proto) @@ -68,7 +69,7 @@ if ((size_t)(allocator->max_ptr - allocator->ptr) < how_much) { - if (unlikely(fc_solve_compact_allocator_extend(allocator))) + if (unlikely(bh_solve_compact_allocator_extend(allocator))) { return NULL; } @@ -97,8 +98,8 @@ // Enqueue all the allocated buffers in the meta allocator for re-use. for (iter = allocator->old_list, iter_next = FCS__COMPACT_ALLOC__OLD_LIST_NEXT(iter); - iter_next; - iter = iter_next, iter_next = FCS__COMPACT_ALLOC__OLD_LIST_NEXT(iter)) + iter_next; + iter = iter_next, iter_next = FCS__COMPACT_ALLOC__OLD_LIST_NEXT(iter)) { FCS__COMPACT_ALLOC__OLD_LIST_NEXT(iter) = bin; bin = iter; @@ -115,7 +116,7 @@ fc_solve_compact_allocator_init_helper(allocator); } -static inline int fc_solve_compact_allocator_init( +static inline bool fc_solve_compact_allocator_init( compact_allocator *const allocator, meta_allocator *const meta_alloc) { allocator->meta = meta_alloc; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/multi_solver.c new/black-hole-solver-1.14.0/multi_solver.c --- old/black-hole-solver-1.12.0/multi_solver.c 2020-11-27 09:09:50.000000000 +0100 +++ new/black-hole-solver-1.14.0/multi_solver.c 2025-02-10 12:39:44.000000000 +0100 @@ -12,7 +12,14 @@ { char *const filename = argv[arg_idx]; fprintf(settings.out_fh, "[= Starting file %s =]\n", filename); - solve_filename(filename, &settings); + bool should_abort; + const int ret = solve_filename(filename, &settings, &should_abort); + if (ret && should_abort) + { + fflush(settings.out_fh); + solve_free(&settings); + return ret; + } fprintf(settings.out_fh, "[= END of file %s =]\n", filename); } fflush(settings.out_fh); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/multi_solver_stats.c new/black-hole-solver-1.14.0/multi_solver_stats.c --- old/black-hole-solver-1.12.0/multi_solver_stats.c 2021-11-24 07:59:54.000000000 +0100 +++ new/black-hole-solver-1.14.0/multi_solver_stats.c 2025-03-02 12:28:49.000000000 +0100 @@ -3,7 +3,7 @@ // Distributed under terms of the Expat license. #include <solver_common.h> -static inline void output_stats__solve_file( +static inline int output_stats__solve_file( const char *const filename, bhs_settings *const settings_ptr) { #define settings (*settings_ptr) @@ -14,7 +14,7 @@ if (!fh) { fprintf(stderr, "Cannot open '%s' for reading!\n", filename); - return; + return -1; } } char board[MAX_LEN_BOARD_STRING]; @@ -59,6 +59,7 @@ if (!solver_ret_code) { + fputs("Solved!\n", out_fh); } else if (solver_ret_code == BLACK_HOLE_SOLVER__OUT_OF_MEMORY) { @@ -72,12 +73,19 @@ else { fputs("Unsolved!\n", out_fh); - fprintf(out_fh, "At most %lu cards could be played.\n", - black_hole_solver_get_max_num_played_cards(solver)); } + fprintf(out_fh, "At most %lu cards could be played.\n", + black_hole_solver_get_max_num_played_cards(solver)); + fprintf(out_fh, + "Total number of states checked is %lu.\n" + "This scan generated %lu states.\n", + black_hole_solver_get_iterations_num(solver), + black_hole_solver_get_num_states_in_collection(solver)); + black_hole_solver_recycle(solver); #undef settings + return 0; } int main(int argc, char *argv[]) @@ -89,7 +97,12 @@ { char *const filename = argv[arg_idx]; fprintf(settings.out_fh, "[= Starting file %s =]\n", filename); - output_stats__solve_file(filename, &settings); + const int ret = output_stats__solve_file(filename, &settings); + if (unlikely(ret)) + { + solve_free(&settings); + return -1; + } fprintf(settings.out_fh, "[= END of file %s =]\n", filename); } fflush(settings.out_fh); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/rank_reach_prune.h new/black-hole-solver-1.14.0/rank_reach_prune.h --- old/black-hole-solver-1.12.0/rank_reach_prune.h 2019-04-16 21:17:00.000000000 +0200 +++ new/black-hole-solver-1.14.0/rank_reach_prune.h 2024-09-29 16:29:30.000000000 +0200 @@ -74,7 +74,7 @@ static const int LINKS[2] = {-1, 1}; for (size_t link_idx = 0; link_idx < (sizeof(LINKS) / sizeof(LINKS[0])); - link_idx++) + ++link_idx) { signed char offset_rank = (signed char)(rank + LINKS[link_idx]); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/run-tests.pl new/black-hole-solver-1.14.0/run-tests.pl --- old/black-hole-solver-1.12.0/run-tests.pl 2021-04-25 07:09:31.000000000 +0200 +++ new/black-hole-solver-1.14.0/run-tests.pl 2024-04-04 09:36:25.000000000 +0200 @@ -6,8 +6,8 @@ use autodie; use Getopt::Long qw/ GetOptions /; -use Env::Path (); -use Path::Tiny qw/ path /; +use Env::Path (); +use Path::Tiny qw/ path /; my $src_dir = path(__FILE__)->parent->absolute; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/scripts/gen-c-lookup-files.pl new/black-hole-solver-1.14.0/scripts/gen-c-lookup-files.pl --- old/black-hole-solver-1.12.0/scripts/gen-c-lookup-files.pl 2019-06-30 20:26:54.000000000 +0200 +++ new/black-hole-solver-1.14.0/scripts/gen-c-lookup-files.pl 2025-02-10 12:48:08.000000000 +0100 @@ -6,37 +6,32 @@ use autodie; use Path::Tiny qw/ path /; -my $FALSE = 0; -my $TRUE = 1; +sub emit +{ + my ( $DECL, $bn, $header_headers, $contents, $types ) = @_; + $types //= ''; -my $MAX_RANK = $ENV{FCS_MAX_RANK} || 13; -my $NUM_SUITS = 4; -my @SUITS = ( 0 .. $NUM_SUITS - 1 ); -my @RANKS = ( 1 .. $MAX_RANK ); -my @PARENT_RANKS = ( 2 .. $MAX_RANK ); -my $MAX_NUM_DECKS = 1; -my $FCS_POS_BY_RANK_WIDTH = ( $MAX_NUM_DECKS << 3 ); + my $header_fn = "$bn.h"; -sub make_card -{ - my ( $rank, $suit ) = @_; - return ( ( $rank << 2 ) | $suit ); -} + path($header_fn) + ->spew_utf8( "#pragma once\n" + . join( '', map { qq{#include $_\n} } @$header_headers ) + . $types + . "extern $DECL;\n" ); + path("$bn.c") + ->spew_utf8( qq/#include "$header_fn"\n\n$DECL = {/ + . join( ',', @$contents ) + . "};\n" ); -sub key -{ - my ( $parent, $child ) = @_; - return "${parent}\t${child}"; + return; } -my $NUM_CHILD_CARDS = 64; -my $NUM_PARENT_CARDS = make_card( $MAX_RANK, $SUITS[-1] ) + 1; -my @is_king = ( ($FALSE) x $NUM_PARENT_CARDS ); -my %lookup; -my @state_pos = ( map { [ (0) x $NUM_SUITS ] } 0 .. $MAX_RANK ); -my @card_pos; -my @positions_by_rank__lookup; -my @pos_by_rank; +my $FALSE = 0; +my $TRUE = 1; + +my $MAX_RANK = $ENV{FCS_MAX_RANK} || 13; +my @RANKS = ( 1 .. $MAX_RANK ); + my @can_move; foreach my $wrap_ranks ( 0, 1 ) @@ -58,41 +53,6 @@ } } -path('board_gen_lookup1.h')->spew_utf8( - "#pragma once\n", - 'static const size_t offset_by_i[52] = {', - join( - ',', - map { - my $i = $_; - my $col = ( $i & ( 8 - 1 ) ); - 3 * - ( $col * 7 - ( ( $col > 4 ) ? ( $col - 4 ) : 0 ) + ( $i >> 3 ) ) - } 0 .. ( 52 - 1 ) - ), - "};\n" -); - -sub emit -{ - my ( $DECL, $bn, $header_headers, $contents, $types ) = @_; - $types //= ''; - - my $header_fn = "$bn.h"; - - path($header_fn) - ->spew_utf8( "#pragma once\n" - . join( '', map { qq{#include $_\n} } @$header_headers ) - . $types - . "extern $DECL;\n" ); - path("$bn.c") - ->spew_utf8( qq/#include "$header_fn"\n\n$DECL = {/ - . join( ',', @$contents ) - . "};\n" ); - - return; -} - emit( qq#const bool black_hole_solver__can_move[2][@{[$MAX_RANK+1]}][@{[$MAX_RANK]}]#, 'can_move', @@ -104,8 +64,7 @@ ',', map { my $row = $_; - '{' - . join( ',', map { $_ ? 'true' : 'false' } @$row ) . '}' + '{' . join( ',', map { $_ ? 'true' : 'false' } @$row ) . '}' } @{$table} ) . '}' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/single_board_main.c new/black-hole-solver-1.14.0/single_board_main.c --- old/black-hole-solver-1.12.0/single_board_main.c 2020-11-27 09:09:50.000000000 +0100 +++ new/black-hole-solver-1.14.0/single_board_main.c 2025-02-10 13:15:49.000000000 +0100 @@ -12,13 +12,41 @@ char *filename = NULL; if (argc > arg_idx) { - if (strcmp(argv[arg_idx], "-")) + bool dashdash = false; + if (argv[arg_idx][0] == '-') { + if (strcmp(argv[arg_idx], "--")) + { + dashdash = true; + ++arg_idx; + } + } + if (arg_idx < argc - 1) + { + fprintf(stderr, + "Too many filenames given; only one is accepted.\nStarting " + "from %s .\n", + argv[arg_idx]); + solve_free(&settings); + return -1; + } + if (dashdash || strcmp(argv[arg_idx], "-")) + { + if (argv[arg_idx][0] == '-') + { + if (!dashdash) + { + fprintf(stderr, "Unknown flag '%s' .\n", argv[arg_idx]); + solve_free(&settings); + return -1; + } + } filename = argv[arg_idx]; } } - const int ret = solve_filename(filename, &settings); + bool should_abort; + const int ret = solve_filename(filename, &settings, &should_abort); solve_free(&settings); return ret; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/solver_common.h new/black-hole-solver-1.14.0/solver_common.h --- old/black-hole-solver-1.12.0/solver_common.h 2020-11-27 09:09:50.000000000 +0100 +++ new/black-hole-solver-1.14.0/solver_common.h 2025-02-27 15:56:27.000000000 +0100 @@ -27,7 +27,7 @@ GAME__GOLF }; -static inline void out_board(FILE *out_fh, +static inline void out_board(FILE *const out_fh, black_hole_solver_instance_t *const solver, const bool display_boards) { if (!display_boards) @@ -74,11 +74,12 @@ bool quiet_output; bool wrap_ranks; bool show_max_num_played_cards; + bool was_output_filepath_set; } bhs_settings; #pragma clang diagnostic pop static inline bhs_settings parse_cmd_line( - int argc, char *argv[], int *out_arg_idx) + const int argc, char *argv[], int *const out_arg_idx) { bhs_settings settings; settings.out_fh = stdout; @@ -91,6 +92,7 @@ settings.wrap_ranks = true; settings.max_iters_limit = ULONG_MAX; settings.show_max_num_played_cards = false; + settings.was_output_filepath_set = false; int arg_idx = 1; while (argc > arg_idx) @@ -113,7 +115,15 @@ fputs("Error! --output requires an argument.\n", stderr); exit(-1); } + if (settings.was_output_filepath_set) + { + fputs("Error! --output can only be used once in order to avoid " + "filehandles leaks.\n", + stderr); + exit(-1); + } settings.out_fh = fopen(argv[arg_idx++], "wt"); + settings.was_output_filepath_set = true; } else if (!strcmp(argv[arg_idx], "--max-iters")) { @@ -234,11 +244,12 @@ return settings; } -static inline int solve_filename( - const char *const filename, bhs_settings *const settings_ptr) +static inline int solve_filename(const char *const filename, + bhs_settings *const settings_ptr, bool *const should_abort) { #define settings (*settings_ptr) int ret = 0; + *should_abort = false; FILE *fh = stdin; if (filename) @@ -247,6 +258,7 @@ if (!fh) { fprintf(stderr, "Cannot open '%s' for reading!\n", filename); + *should_abort = true; return -1; } } @@ -329,6 +341,7 @@ fprintf(stderr, "%s - %d\n", "Get next move routine returned the wrong error code.", next_move_ret_code); + *should_abort = true; ret = -1; } } @@ -336,6 +349,7 @@ else if (solver_ret_code == BLACK_HOLE_SOLVER__OUT_OF_MEMORY) { fputs("Out of memory!\n", stderr); + *should_abort = true; exit(-1); } else if (solver_ret_code == BLACK_HOLE_SOLVER__OUT_OF_ITERS) @@ -367,7 +381,7 @@ static inline void solve_free(bhs_settings *const settings_ptr) { - if (settings_ptr->out_fh != stdout) + if (settings_ptr->was_output_filepath_set) { fclose(settings_ptr->out_fh); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/solver_run.h new/black-hole-solver-1.14.0/solver_run.h --- old/black-hole-solver-1.12.0/solver_run.h 2019-04-16 21:17:00.000000000 +0200 +++ new/black-hole-solver-1.14.0/solver_run.h 2025-02-20 16:58:51.000000000 +0100 @@ -3,10 +3,17 @@ // // Distributed under terms of the Expat license. #pragma once +#include <assert.h> static inline int solver_run(black_hole_solver_instance_t *const solver, const unsigned long max_iters_limit, const unsigned long iters_display_step) { + if (iters_display_step == 0) + { + // fprintf(stderr, "iters_display_step is 0.\n"); + black_hole_solver_set_max_iters_limit(solver, max_iters_limit); + return black_hole_solver_run(solver); + } unsigned long iters_limit = min(iters_display_step, max_iters_limit); black_hole_solver_set_max_iters_limit(solver, iters_limit); unsigned long iters_num; @@ -16,15 +23,15 @@ { solver_ret_code = black_hole_solver_run(solver); iters_num = black_hole_solver_get_iterations_num(solver); - if (iters_limit == iters_num) + if (iters_limit <= iters_num) { - printf("Iteration: %lu\n", iters_limit); + printf("Iteration: %lu\n", iters_num); fflush(stdout); } iters_limit += iters_display_step; iters_limit = min(iters_limit, max_iters_limit); black_hole_solver_set_max_iters_limit(solver, iters_limit); } while ((solver_ret_code == BLACK_HOLE_SOLVER__OUT_OF_ITERS) && - (iters_num < max_iters_limit)); + (iters_num <= max_iters_limit)); return solver_ret_code; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/t/all-in-a-row-output.t new/black-hole-solver-1.14.0/t/all-in-a-row-output.t --- old/black-hole-solver-1.12.0/t/all-in-a-row-output.t 2020-10-26 08:47:35.000000000 +0100 +++ new/black-hole-solver-1.14.0/t/all-in-a-row-output.t 2024-04-04 09:36:25.000000000 +0200 @@ -19,7 +19,7 @@ return $exit_code = system(@_); } -use Dir::Manifest (); +use Dir::Manifest (); use Dir::Manifest::Slurp qw/ as_lf /; my $mani = Dir::Manifest->new( { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/t/black-hole-output.t new/black-hole-solver-1.14.0/t/black-hole-output.t --- old/black-hole-solver-1.12.0/t/black-hole-output.t 2020-11-27 09:09:50.000000000 +0100 +++ new/black-hole-solver-1.14.0/t/black-hole-output.t 2025-03-02 13:24:18.000000000 +0100 @@ -3,7 +3,7 @@ use strict; use warnings; -use Test::More tests => 24; +use Test::More tests => 25; use Test::Differences qw/ eq_or_diff /; use Test::Some; @@ -11,7 +11,9 @@ trap $trap :flow:stderr(systemsafe):stdout(systemsafe):warn ); -use Path::Tiny qw/ path /; +use Path::Tiny qw/ path tempdir /; + +use Games::Solitaire::BlackHole::Test qw/ _test_multiple_verdict_lines /; my $bin_dir = path(__FILE__)->parent->absolute; my $data_dir = $bin_dir->child('data'); @@ -33,7 +35,7 @@ # TEST ok( !($exit_code), "Running the program successfully." ); -use Dir::Manifest (); +use Dir::Manifest (); use Dir::Manifest::Slurp qw/ as_lf /; my $mani = Dir::Manifest->new( { @@ -255,35 +257,71 @@ ); } +my $master_tmp = tempdir(); { - my $out_fn = "golf1to20out.txt"; - trap + my $count = 0; { - mysys( - './multi-bhs-solver', - '--output', - $out_fn, - '--game', - 'golf', - '--display-boards', - '--wrap-ranks', - ( map { $mani->fh("golf$_.board") } 1 .. 20 ) - ); - }; + my $tmp = $master_tmp->child( "multibhs-" . ++$count ); + $tmp->mkdir(); - # TEST - ok( !($exit_code), "Exit code for --display-boards for golf board #906." ); - - my $stdout = as_lf( path($out_fn)->slurp_raw ); - $stdout =~ - s#^(\[= (?:Starting|END of) file )(\S+)#$1 . path($2)->basename#egms; + my $out_fn = $tmp->child("golf1to20out.txt"); + trap + { + mysys( + './multi-bhs-solver', + '--output', + $out_fn, + '--game', + 'golf', + '--display-boards', + '--wrap-ranks', + ( map { $mani->fh("golf$_.board") } 1 .. 20 ) + ); + }; + + # TEST + ok( !($exit_code), + "Exit code for --display-boards for golf board #906." ); + + my $stdout = as_lf( path($out_fn)->slurp_raw ); + $stdout =~ +s#^(\[= (?:Starting|END of) file )(\S+)#$1 . path($2)->basename#egms; + + # TEST + is( + $stdout, + $mani->text( "golf-1to20.sol.txt", { lf => 1 } ), + "recycling works", + ); + } - # TEST - is( - $stdout, - $mani->text( "golf-1to20.sol.txt", { lf => 1 } ), - "recycling works", - ); + { + my $tmp = $master_tmp->child( "multibhs-" . ++$count ); + $tmp->mkdir(); + my $out_fn = $tmp->child("golf1to20out.txt"); + trap + { + mysys( + './multi-bhs-solver', + '--output', + $out_fn, + '--game', + 'golf', + '--display-boards', + '--wrap-ranks', + ( map { $mani->fh("golf$_.board") } 1 .. 2 ), + $tmp->child("not--------exist.c"), + ( map { $mani->fh("golf$_.board") } 3 .. 4 ), + ); + }; + + # TEST + ok( $exit_code, "Exit code for --display-boards for golf board #906." ); + + my $stdout = as_lf( path($out_fn)->slurp_raw ); + $stdout =~ +s#^(\[= (?:Starting|END of) file )(\S+)#$1 . path($2)->basename#egms; + } } my $MAX_NUM_PLAYED_CARDS_RE = @@ -327,7 +365,7 @@ # TEST subtest 'max_num_played' => sub { - plan tests => 10; + plan tests => 12; trap { mysys( './black-hole-solve', '--game', 'black_hole', @@ -422,5 +460,53 @@ input_text => scalar( $trap->stdout() ), }, ); + + { + my $count = 0; + my $tmp = $master_tmp->child( "statsmultibhs-" . ++$count ); + $tmp->mkdir(); + + my @deals_indexes = ( 1 .. 20 ); + my $out_fn = $tmp->child("golf1to20out.txt"); + trap + { + mysys( + './stats-multi-bhs-solver', + '--output', + $out_fn, + '--game', + 'golf', + '--display-boards', + '--wrap-ranks', + ( map { $mani->fh("golf$_.board") } 1 .. 20 ) + ); + }; + + ok( !($exit_code), + "Exit code for --display-boards for golf board #906." ); + + _test_multiple_verdict_lines( + { + name => "test multiple verdict lines", + expected_results => [ + "Solved!", "Solved!", "Solved!", "Solved!", + "Solved!", "Solved!", "Solved!", "Solved!", + "Solved!", "Solved!", "Unsolved!", "Solved!", + "Solved!", "Solved!", "Solved!", "Solved!", + "Solved!", "Solved!", "Solved!", "Solved!", + ], + expected_files_checks => sub { + my $i = shift; + my $dealidx = $deals_indexes[$i]; + my $fn = path(shift); + my $bn = $fn->basename(); + + return ( $bn =~ m#golf\Q$dealidx\E\.board#ms ); + }, + input_lines => [ path($out_fn)->lines_utf8() ], + } + ); + + } }, '!no_max_num_played'; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/t/lib/Games/Solitaire/BlackHole/RankReachPrune/PP.pm new/black-hole-solver-1.14.0/t/lib/Games/Solitaire/BlackHole/RankReachPrune/PP.pm --- old/black-hole-solver-1.12.0/t/lib/Games/Solitaire/BlackHole/RankReachPrune/PP.pm 2019-01-14 01:59:57.000000000 +0100 +++ new/black-hole-solver-1.14.0/t/lib/Games/Solitaire/BlackHole/RankReachPrune/PP.pm 2024-09-29 16:34:40.000000000 +0200 @@ -27,7 +27,7 @@ # Count the foundation - the starting point - in. if ( $rank_counts->[$foundation] == 0 ) { - $full_max++; + ++$full_max; } my $full_count = 0; @@ -45,7 +45,7 @@ } $reached[$rank] = $TRUE; - $full_count++; + ++$full_count; for my $link ( -1, 1 ) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/t/lib/Games/Solitaire/BlackHole/RankReachPrune/XS.pm new/black-hole-solver-1.14.0/t/lib/Games/Solitaire/BlackHole/RankReachPrune/XS.pm --- old/black-hole-solver-1.12.0/t/lib/Games/Solitaire/BlackHole/RankReachPrune/XS.pm 2020-10-07 12:53:32.000000000 +0200 +++ new/black-hole-solver-1.14.0/t/lib/Games/Solitaire/BlackHole/RankReachPrune/XS.pm 2024-09-29 16:34:35.000000000 +0200 @@ -12,7 +12,7 @@ int call_prune(int foundation, AV * rank_counts_av) { bhs_rank_counts rank_counts; - for (int i = 0; i < NUM_RANKS; i++) + for (int i = 0; i < NUM_RANKS; ++i) { SV * * item = av_fetch(rank_counts_av, i, false); assert(item); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/t/lib/Games/Solitaire/BlackHole/Test.pm new/black-hole-solver-1.14.0/t/lib/Games/Solitaire/BlackHole/Test.pm --- old/black-hole-solver-1.12.0/t/lib/Games/Solitaire/BlackHole/Test.pm 1970-01-01 01:00:00.000000000 +0100 +++ new/black-hole-solver-1.14.0/t/lib/Games/Solitaire/BlackHole/Test.pm 2025-03-02 13:17:56.000000000 +0100 @@ -0,0 +1,115 @@ +package Games::Solitaire::BlackHole::Test; + +use strict; +use warnings; + +use Test::More; + +use Dir::Manifest::Slurp qw/ as_lf /; +use Test::Differences qw/ eq_or_diff /; + +our @ISA = qw(Exporter); +our %EXPORT_TAGS = ( 'all' => [qw( _test_multiple_verdict_lines )] ); +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); +require Exporter; + +# We intend this test subroutine to be used by more than one +# subproject. +sub _test_multiple_verdict_lines +{ + my %is_verdict_line = map { $_ => 1, } + ( "Solved!", "Unsolved!", "Exceeded max_iters_limit !" ); + my ($args) = @_; + my ( $name, $expected_files_checks, $want, $input_lines ) = + @{$args}{qw/ name expected_files_checks expected_results input_lines/}; + local $Test::Builder::Level = $Test::Builder::Level + 1; + return subtest $name => sub { + plan tests => 2; + $input_lines = + [ map { my $l = as_lf($_); chomp $l; $l } @$input_lines ]; + my @matches; + my $deal_idx = 0; + while (@$input_lines) + { + my $dealstart = shift @$input_lines; + my ($fn) = $dealstart =~ /^\[\= Starting file (\S+) \=\]$/ms + or die "cannot match"; + if ( not $expected_files_checks->( $deal_idx, $fn ) ) + { + die "filename check"; + } + my $dealverdict = shift @$input_lines; + if ( $is_verdict_line{$dealverdict} ) + { + push @matches, $dealverdict; + } + else + { + die "mismatch"; + } + my $at_most_num_cards__line = 0; + if ( @$input_lines + and $input_lines->[0] =~ + /^At most (?:(?:0)|(?:[1-9][0-9]*)) cards could be played\.\z/ms + ) + { + $at_most_num_cards__line = 1; + shift @$input_lines; + } + my $traversed_states_count__line = 0; + if ( @$input_lines + and $input_lines->[0] =~ +/^Total number of states checked is (?:(?:0)|(?:[1-9][0-9]*))\.\z/ms, + ) + { + $traversed_states_count__line = 1; + shift @$input_lines; + } + my $generated_states_count__line = 0; + if ( @$input_lines + and $input_lines->[0] =~ + /^This scan generated (?:(?:0)|(?:[1-9][0-9]*)) states\.\z/ms ) + { + $generated_states_count__line = 1; + shift @$input_lines; + } + if (0) + { + while ( @$input_lines and $input_lines->[0] !~ /^\[\= /ms ) + { + diag( "unrecognised: '" . $input_lines->[0] . "'" ); + shift @$input_lines; + } + } + my $dealend = shift @$input_lines; + if ( $dealend ne "[= END of file $fn =]" ) + { + die "dealend mismatch"; + } + if ( not $at_most_num_cards__line ) + { + die "At most cards played line is absent"; + } + if ( not $traversed_states_count__line ) + { + die "'checked states' line is absent"; + } + if ( not $generated_states_count__line ) + { + die "'This scan generated' line is absent"; + } + } + continue + { + ++$deal_idx; + } + + is( scalar(@matches), scalar(@$want), "lines count." ); + + eq_or_diff( [@matches], [@$want], "expected results.", ); + }; +} + +1; + +__END__ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/t/perltidy.t new/black-hole-solver-1.14.0/t/perltidy.t --- old/black-hole-solver-1.12.0/t/perltidy.t 2019-01-14 01:59:57.000000000 +0100 +++ new/black-hole-solver-1.14.0/t/perltidy.t 2024-04-04 09:36:25.000000000 +0200 @@ -9,6 +9,17 @@ Test::More::plan( 'skip_all' => "Skipping perltidy test because FCS_TEST_SKIP_PERLTIDY was set" ); } + +{ + my $key = "AUTHOR_TESTING"; + if ( not $ENV{$key} ) + { + require Test::More; + Test::More::plan( + 'skip_all' => "Skipping perltidy test because $key was not set" ); + } +} + require Test::Code::TidyAll; Test::Code::TidyAll::tidyall_ok( conf_file => "$ENV{FCS_SRC_PATH}/.tidyallrc", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/t/valgrind.t new/black-hole-solver-1.14.0/t/valgrind.t --- old/black-hole-solver-1.12.0/t/valgrind.t 2020-07-04 17:23:27.000000000 +0200 +++ new/black-hole-solver-1.14.0/t/valgrind.t 2024-04-04 09:36:25.000000000 +0200 @@ -5,7 +5,7 @@ use Test::More; use Test::RunValgrind (); -use Path::Tiny qw/ path /; +use Path::Tiny qw/ path /; my $bin_dir = path($0)->parent->absolute; my $data_dir = $bin_dir->child('data'); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/black-hole-solver-1.12.0/ver.txt new/black-hole-solver-1.14.0/ver.txt --- old/black-hole-solver-1.12.0/ver.txt 2022-03-28 12:22:05.000000000 +0200 +++ new/black-hole-solver-1.14.0/ver.txt 2025-03-03 07:56:29.000000000 +0100 @@ -1 +1 @@ -1.12.0 +1.14.0