move bits functions to separate file + fix missing defaults with disabled program_options on windows
This commit is contained in:
@ -18,6 +18,7 @@ option(DISABLE_BENCH "Disable building benchmarks" OFF)
|
|||||||
# Headers + Sources (excluding main.cpp)
|
# Headers + Sources (excluding main.cpp)
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
src/backward.cpp
|
src/backward.cpp
|
||||||
|
src/bits.cpp
|
||||||
src/graph_distances.cpp
|
src/graph_distances.cpp
|
||||||
src/input_handler.cpp
|
src/input_handler.cpp
|
||||||
src/load_save.cpp
|
src/load_save.cpp
|
||||||
@ -133,4 +134,4 @@ if(supported)
|
|||||||
set_property(TARGET masssprings PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
set_property(TARGET masssprings PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||||
else()
|
else()
|
||||||
message(STATUS "IPO / LTO not supported")
|
message(STATUS "IPO / LTO not supported")
|
||||||
endif()
|
endif()
|
||||||
69
include/bits.hpp
Normal file
69
include/bits.hpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#ifndef BITS_HPP_
|
||||||
|
#define BITS_HPP_
|
||||||
|
|
||||||
|
#include "util.hpp"
|
||||||
|
|
||||||
|
#include <concepts>
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
requires std::unsigned_integral<T>
|
||||||
|
// ReSharper disable once CppRedundantInlineSpecifier
|
||||||
|
INLINE inline auto create_mask(const uint8_t first, const uint8_t last) -> T
|
||||||
|
{
|
||||||
|
// If the mask width is equal the type width return all 1s instead of shifting
|
||||||
|
// as shifting by type-width is undefined behavior.
|
||||||
|
if (static_cast<size_t>(last - first + 1) >= sizeof(T) * 8) {
|
||||||
|
return ~T{0};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example: first=4, last=7, 7-4+1=4
|
||||||
|
// 1 << 4 = 0b00010000
|
||||||
|
// 32 - 1 = 0b00001111
|
||||||
|
// 31 << 4 = 0b11110000
|
||||||
|
// Subtracting 1 generates a consecutive mask.
|
||||||
|
return ((T{1} << (last - first + 1)) - 1) << first;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
requires std::unsigned_integral<T>
|
||||||
|
// ReSharper disable once CppRedundantInlineSpecifier
|
||||||
|
INLINE inline auto clear_bits(T& bits, const uint8_t first, const uint8_t last) -> void
|
||||||
|
{
|
||||||
|
const T mask = create_mask<T>(first, last);
|
||||||
|
|
||||||
|
bits = bits & ~mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class U>
|
||||||
|
requires std::unsigned_integral<T> && std::unsigned_integral<U>
|
||||||
|
// ReSharper disable once CppRedundantInlineSpecifier
|
||||||
|
INLINE inline auto set_bits(T& bits, const uint8_t first, const uint8_t last, const U value) -> void
|
||||||
|
{
|
||||||
|
const T mask = create_mask<T>(first, last);
|
||||||
|
|
||||||
|
// Example: first=4, last=6, value=0b1110, bits = 0b 01111110
|
||||||
|
// mask = 0b 01110000
|
||||||
|
// bits & ~mask = 0b 00001110
|
||||||
|
// value << 4 = 0b 11100000
|
||||||
|
// (value << 4) & mask = 0b 01100000
|
||||||
|
// (bits & ~mask) | (value << 4) & mask = 0b 01101110
|
||||||
|
// Insert position: ^^^
|
||||||
|
// First clear the bits, then | with the value positioned at the insertion point.
|
||||||
|
// The value may be larger than [first, last], extra bits are ignored.
|
||||||
|
bits = (bits & ~mask) | ((static_cast<T>(value) << first) & mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
requires std::unsigned_integral<T>
|
||||||
|
// ReSharper disable once CppRedundantInlineSpecifier
|
||||||
|
INLINE inline auto get_bits(const T bits, const uint8_t first, const uint8_t last) -> T
|
||||||
|
{
|
||||||
|
const T mask = create_mask<T>(first, last);
|
||||||
|
|
||||||
|
// We can >> without sign extension because T is unsigned_integral
|
||||||
|
return (bits & mask) >> first;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto print_bitmap(uint64_t bitmap, uint8_t w, uint8_t h, const std::string& title) -> void;
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
|
#include "bits.hpp"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@ -418,12 +419,12 @@ public:
|
|||||||
[[nodiscard]] auto try_toggle_wall(uint8_t x, uint8_t y) const -> std::optional<puzzle>;
|
[[nodiscard]] auto try_toggle_wall(uint8_t x, uint8_t y) const -> std::optional<puzzle>;
|
||||||
|
|
||||||
// Playing
|
// Playing
|
||||||
[[nodiscard]] auto try_move_block_at(uint8_t x, uint8_t y, direction dir) const -> std::optional<puzzle>;
|
[[nodiscard]] auto try_move_block_at(uint8_t x, uint8_t y, dir dir) const -> std::optional<puzzle>;
|
||||||
|
|
||||||
// Statespace
|
// Statespace
|
||||||
[[nodiscard]] INLINE inline auto try_move_block_at_fast(uint64_t bitmap,
|
[[nodiscard]] INLINE inline auto try_move_block_at_fast(uint64_t bitmap,
|
||||||
uint8_t block_idx,
|
uint8_t block_idx,
|
||||||
direction dir,
|
dir dir,
|
||||||
bool check_collision = true) const -> std::optional<puzzle>;
|
bool check_collision = true) const -> std::optional<puzzle>;
|
||||||
[[nodiscard]] static auto sorted_replace(std::array<uint16_t, MAX_BLOCKS> blocks,
|
[[nodiscard]] static auto sorted_replace(std::array<uint16_t, MAX_BLOCKS> blocks,
|
||||||
uint8_t idx,
|
uint8_t idx,
|
||||||
@ -456,7 +457,7 @@ public:
|
|||||||
* @param dir Direction in which the block should be moved
|
* @param dir Direction in which the block should be moved
|
||||||
* @return True if b would collide with any other block on the board after moving in direction dir
|
* @return True if b would collide with any other block on the board after moving in direction dir
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] INLINE inline auto bitmap_check_collision(uint64_t bitmap, block b, direction dir) const -> bool;
|
[[nodiscard]] INLINE inline auto bitmap_check_collision(uint64_t bitmap, block b, dir dir) const -> bool;
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
// ReSharper disable once CppRedundantInlineSpecifier
|
// ReSharper disable once CppRedundantInlineSpecifier
|
||||||
@ -473,7 +474,7 @@ public:
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const int dirs = r ? b.principal_dirs() : nor | eas | sou | wes;
|
const int dirs = r ? b.principal_dirs() : nor | eas | sou | wes;
|
||||||
for (const direction d : {nor, eas, sou, wes}) {
|
for (const dir d : {nor, eas, sou, wes}) {
|
||||||
if (dirs & d) {
|
if (dirs & d) {
|
||||||
if (auto moved = try_move_block_at_fast(bitmap, idx, d)) {
|
if (auto moved = try_move_block_at_fast(bitmap, idx, d)) {
|
||||||
callback(*moved);
|
callback(*moved);
|
||||||
@ -717,7 +718,7 @@ inline auto puzzle::get_goal_y() const -> uint8_t
|
|||||||
|
|
||||||
INLINE inline auto puzzle::try_move_block_at_fast(uint64_t bitmap,
|
INLINE inline auto puzzle::try_move_block_at_fast(uint64_t bitmap,
|
||||||
const uint8_t block_idx,
|
const uint8_t block_idx,
|
||||||
const direction dir,
|
const dir dir,
|
||||||
const bool check_collision) const -> std::optional<puzzle>
|
const bool check_collision) const -> std::optional<puzzle>
|
||||||
{
|
{
|
||||||
const block b = block(repr.cooked.blocks[block_idx]);
|
const block b = block(repr.cooked.blocks[block_idx]);
|
||||||
@ -853,7 +854,7 @@ INLINE inline auto puzzle::bitmap_check_collision(const uint64_t bitmap, const b
|
|||||||
|
|
||||||
INLINE inline auto puzzle::bitmap_check_collision(const uint64_t bitmap,
|
INLINE inline auto puzzle::bitmap_check_collision(const uint64_t bitmap,
|
||||||
const block b,
|
const block b,
|
||||||
const direction dir) const -> bool
|
const dir dir) const -> bool
|
||||||
{
|
{
|
||||||
const auto [x, y, w, h, t, i] = b.unpack_repr();
|
const auto [x, y, w, h, t, i] = b.unpack_repr();
|
||||||
const uint8_t width = get_width();
|
const uint8_t width = get_width();
|
||||||
|
|||||||
178
include/util.hpp
178
include/util.hpp
@ -7,112 +7,6 @@
|
|||||||
#define INLINE __attribute__((always_inline))
|
#define INLINE __attribute__((always_inline))
|
||||||
#define PACKED __attribute__((packed))
|
#define PACKED __attribute__((packed))
|
||||||
|
|
||||||
enum ctrl
|
|
||||||
{
|
|
||||||
reset = 0,
|
|
||||||
bold_bright = 1,
|
|
||||||
underline = 4,
|
|
||||||
inverse = 7,
|
|
||||||
bold_bright_off = 21,
|
|
||||||
underline_off = 24,
|
|
||||||
inverse_off = 27
|
|
||||||
};
|
|
||||||
|
|
||||||
enum fg
|
|
||||||
{
|
|
||||||
fg_black = 30,
|
|
||||||
fg_red = 31,
|
|
||||||
fg_green = 32,
|
|
||||||
fg_yellow = 33,
|
|
||||||
fg_blue = 34,
|
|
||||||
fg_magenta = 35,
|
|
||||||
fg_cyan = 36,
|
|
||||||
fg_white = 37
|
|
||||||
};
|
|
||||||
|
|
||||||
enum bg
|
|
||||||
{
|
|
||||||
bg_black = 40,
|
|
||||||
bg_red = 41,
|
|
||||||
bg_green = 42,
|
|
||||||
bg_yellow = 43,
|
|
||||||
bg_blue = 44,
|
|
||||||
bg_magenta = 45,
|
|
||||||
bg_cyan = 46,
|
|
||||||
bg_white = 47
|
|
||||||
};
|
|
||||||
|
|
||||||
inline auto ansi_bold_fg(const fg color) -> std::string
|
|
||||||
{
|
|
||||||
return std::format("\033[{};{}m", static_cast<int>(bold_bright), static_cast<int>(color));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline auto ansi_reset() -> std::string
|
|
||||||
{
|
|
||||||
return std::format("\033[{}m", static_cast<int>(reset));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bit shifting + masking
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
requires std::unsigned_integral<T>
|
|
||||||
// ReSharper disable once CppRedundantInlineSpecifier
|
|
||||||
INLINE inline auto create_mask(const uint8_t first, const uint8_t last) -> T
|
|
||||||
{
|
|
||||||
// If the mask width is equal the type width return all 1s instead of shifting
|
|
||||||
// as shifting by type-width is undefined behavior.
|
|
||||||
if (static_cast<size_t>(last - first + 1) >= sizeof(T) * 8) {
|
|
||||||
return ~T{0};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Example: first=4, last=7, 7-4+1=4
|
|
||||||
// 1 << 4 = 0b00010000
|
|
||||||
// 32 - 1 = 0b00001111
|
|
||||||
// 31 << 4 = 0b11110000
|
|
||||||
// Subtracting 1 generates a consecutive mask.
|
|
||||||
return ((T{1} << (last - first + 1)) - 1) << first;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
requires std::unsigned_integral<T>
|
|
||||||
// ReSharper disable once CppRedundantInlineSpecifier
|
|
||||||
INLINE inline auto clear_bits(T& bits, const uint8_t first, const uint8_t last) -> void
|
|
||||||
{
|
|
||||||
const T mask = create_mask<T>(first, last);
|
|
||||||
|
|
||||||
bits = bits & ~mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T, class U>
|
|
||||||
requires std::unsigned_integral<T> && std::unsigned_integral<U>
|
|
||||||
// ReSharper disable once CppRedundantInlineSpecifier
|
|
||||||
INLINE inline auto set_bits(T& bits, const uint8_t first, const uint8_t last, const U value) -> void
|
|
||||||
{
|
|
||||||
const T mask = create_mask<T>(first, last);
|
|
||||||
|
|
||||||
// Example: first=4, last=6, value=0b1110, bits = 0b 01111110
|
|
||||||
// mask = 0b 01110000
|
|
||||||
// bits & ~mask = 0b 00001110
|
|
||||||
// value << 4 = 0b 11100000
|
|
||||||
// (value << 4) & mask = 0b 01100000
|
|
||||||
// (bits & ~mask) | (value << 4) & mask = 0b 01101110
|
|
||||||
// Insert position: ^^^
|
|
||||||
// First clear the bits, then | with the value positioned at the insertion point.
|
|
||||||
// The value may be larger than [first, last], extra bits are ignored.
|
|
||||||
bits = (bits & ~mask) | ((static_cast<T>(value) << first) & mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
requires std::unsigned_integral<T>
|
|
||||||
// ReSharper disable once CppRedundantInlineSpecifier
|
|
||||||
INLINE inline auto get_bits(const T bits, const uint8_t first, const uint8_t last) -> T
|
|
||||||
{
|
|
||||||
const T mask = create_mask<T>(first, last);
|
|
||||||
|
|
||||||
// We can >> without sign extension because T is unsigned_integral
|
|
||||||
return (bits & mask) >> first;
|
|
||||||
}
|
|
||||||
|
|
||||||
// std::variant visitor
|
// std::variant visitor
|
||||||
|
|
||||||
// https://en.cppreference.com/w/cpp/utility/variant/visit
|
// https://en.cppreference.com/w/cpp/utility/variant/visit
|
||||||
@ -124,7 +18,7 @@ struct overloads : Ts...
|
|||||||
|
|
||||||
// Enums
|
// Enums
|
||||||
|
|
||||||
enum direction
|
enum dir : uint8_t
|
||||||
{
|
{
|
||||||
nor = 1 << 0,
|
nor = 1 << 0,
|
||||||
eas = 1 << 1,
|
eas = 1 << 1,
|
||||||
@ -132,6 +26,53 @@ enum direction
|
|||||||
wes = 1 << 3,
|
wes = 1 << 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Ansi
|
||||||
|
|
||||||
|
enum class ctrl : uint8_t
|
||||||
|
{
|
||||||
|
reset = 0,
|
||||||
|
bold_bright = 1,
|
||||||
|
underline = 4,
|
||||||
|
inverse = 7,
|
||||||
|
bold_bright_off = 21,
|
||||||
|
underline_off = 24,
|
||||||
|
inverse_off = 27
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class fg : uint8_t
|
||||||
|
{
|
||||||
|
black = 30,
|
||||||
|
red = 31,
|
||||||
|
green = 32,
|
||||||
|
yellow = 33,
|
||||||
|
blue = 34,
|
||||||
|
magenta = 35,
|
||||||
|
cyan = 36,
|
||||||
|
white = 37
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class bg : uint8_t
|
||||||
|
{
|
||||||
|
black = 40,
|
||||||
|
red = 41,
|
||||||
|
green = 42,
|
||||||
|
yellow = 43,
|
||||||
|
blue = 44,
|
||||||
|
magenta = 45,
|
||||||
|
cyan = 46,
|
||||||
|
white = 47
|
||||||
|
};
|
||||||
|
|
||||||
|
inline auto ansi_bold_fg(const fg color) -> std::string
|
||||||
|
{
|
||||||
|
return std::format("\033[{};{}m", static_cast<int>(ctrl::bold_bright), static_cast<int>(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline auto ansi_reset() -> std::string
|
||||||
|
{
|
||||||
|
return std::format("\033[{}m", static_cast<int>(ctrl::reset));
|
||||||
|
}
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
|
|
||||||
inline auto operator<<(std::ostream& os, const Vector2& v) -> std::ostream&
|
inline auto operator<<(std::ostream& os, const Vector2& v) -> std::ostream&
|
||||||
@ -150,44 +91,29 @@ inline auto operator<<(std::ostream& os, const Vector3& v) -> std::ostream&
|
|||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
auto traceln(std::format_string<Args...> fmt, Args&&... args) -> void
|
auto traceln(std::format_string<Args...> fmt, Args&&... args) -> void
|
||||||
{
|
{
|
||||||
std::cout << std::format("[{}TRACE{}]: ", ansi_bold_fg(fg_cyan), ansi_reset()) << std::format(
|
std::cout << std::format("[{}TRACE{}]: ", ansi_bold_fg(fg::cyan), ansi_reset()) << std::format(
|
||||||
fmt, std::forward<Args>(args)...) << std::endl;
|
fmt, std::forward<Args>(args)...) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
auto infoln(std::format_string<Args...> fmt, Args&&... args) -> void
|
auto infoln(std::format_string<Args...> fmt, Args&&... args) -> void
|
||||||
{
|
{
|
||||||
std::cout << std::format("[{}INFO{}]: ", ansi_bold_fg(fg_blue), ansi_reset()) << std::format(
|
std::cout << std::format("[{}INFO{}]: ", ansi_bold_fg(fg::blue), ansi_reset()) << std::format(
|
||||||
fmt, std::forward<Args>(args)...) << std::endl;
|
fmt, std::forward<Args>(args)...) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
auto warnln(std::format_string<Args...> fmt, Args&&... args) -> void
|
auto warnln(std::format_string<Args...> fmt, Args&&... args) -> void
|
||||||
{
|
{
|
||||||
std::cout << std::format("[{}WARNING{}]: ", ansi_bold_fg(fg_yellow), ansi_reset()) << std::format(
|
std::cout << std::format("[{}WARNING{}]: ", ansi_bold_fg(fg::yellow), ansi_reset()) << std::format(
|
||||||
fmt, std::forward<Args>(args)...) << std::endl;
|
fmt, std::forward<Args>(args)...) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
auto errln(std::format_string<Args...> fmt, Args&&... args) -> void
|
auto errln(std::format_string<Args...> fmt, Args&&... args) -> void
|
||||||
{
|
{
|
||||||
std::cout << std::format("[{}ERROR{}]: ", ansi_bold_fg(fg_red), ansi_reset()) << std::format(
|
std::cout << std::format("[{}ERROR{}]: ", ansi_bold_fg(fg::red), ansi_reset()) << std::format(
|
||||||
fmt, std::forward<Args>(args)...) << std::endl;
|
fmt, std::forward<Args>(args)...) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline auto print_bitmap(const uint64_t bitmap, const uint8_t w, const uint8_t h, const std::string& title) -> void
|
|
||||||
{
|
|
||||||
traceln("{}:", title);
|
|
||||||
traceln("{}", std::string(2 * w - 1, '='));
|
|
||||||
for (size_t y = 0; y < w; ++y) {
|
|
||||||
std::cout << " ";
|
|
||||||
for (size_t x = 0; x < h; ++x) {
|
|
||||||
std::cout << static_cast<int>(get_bits(bitmap, y * w + x, y * h + x)) << " ";
|
|
||||||
}
|
|
||||||
std::cout << "\n";
|
|
||||||
}
|
|
||||||
std::cout << std::flush;
|
|
||||||
traceln("{}", std::string(2 * w - 1, '='));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
15
src/bits.cpp
Normal file
15
src/bits.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "bits.hpp"
|
||||||
|
|
||||||
|
auto print_bitmap(const uint64_t bitmap, const uint8_t w, const uint8_t h, const std::string& title) -> void {
|
||||||
|
traceln("{}:", title);
|
||||||
|
traceln("{}", std::string(2 * w - 1, '='));
|
||||||
|
for (size_t y = 0; y < w; ++y) {
|
||||||
|
std::cout << " ";
|
||||||
|
for (size_t x = 0; x < h; ++x) {
|
||||||
|
std::cout << static_cast<int>(get_bits(bitmap, y * w + x, y * h + x)) << " ";
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
std::cout << std::flush;
|
||||||
|
traceln("{}", std::string(2 * w - 1, '='));
|
||||||
|
}
|
||||||
37
src/main.cpp
37
src/main.cpp
@ -16,7 +16,6 @@
|
|||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// TODO: Implement state discovery/enumeration
|
// TODO: Implement state discovery/enumeration
|
||||||
// - Find all possible initial board states (single one for each possible statespace).
|
// - Find all possible initial board states (single one for each possible statespace).
|
||||||
// Currently wer're just finding all states given the initial state
|
// Currently wer're just finding all states given the initial state
|
||||||
@ -47,8 +46,8 @@ constexpr std::optional<BS::thread_pool<>* const> thread_pool = &threads;
|
|||||||
constexpr std::optional<BS::thread_pool<>* const> thread_pool = std::nullopt;
|
constexpr std::optional<BS::thread_pool<>* const> thread_pool = std::nullopt;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string preset_file;
|
std::string preset_file = "default.puzzle";
|
||||||
std::string output_file;
|
std::string output_file = "clusters.puzzle";
|
||||||
int max_blocks = 5;
|
int max_blocks = 5;
|
||||||
int board_width = 6;
|
int board_width = 6;
|
||||||
int board_height = 6;
|
int board_height = 6;
|
||||||
@ -231,21 +230,21 @@ enum class runmode
|
|||||||
|
|
||||||
auto argparse(const int argc, char* argv[]) -> runmode
|
auto argparse(const int argc, char* argv[]) -> runmode
|
||||||
{
|
{
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
po::options_description desc("Allowed options");
|
po::options_description desc("Allowed options");
|
||||||
desc.add_options() //
|
desc.add_options() //
|
||||||
("help", "produce help message") //
|
("help", "produce help message") //
|
||||||
|
("presets", po::value<std::string>()->default_value(preset_file), "load presets from file") //
|
||||||
("presets", po::value<std::string>()->default_value("default.puzzle"), "load presets from file") //
|
("output", po::value<std::string>()->default_value(output_file), "output file for generated clusters") //
|
||||||
|
("space", po::value<std::string>()->value_name("rh|klotski"), "generate puzzle space with ruleset") //
|
||||||
("output", po::value<std::string>()->default_value("clusters.puzzle"), "output file for generated clusters") //
|
("w", po::value<int>()->default_value(board_width)->value_name("[3, 8]"), "board width") //
|
||||||
("space", po::value<std::string>()->value_name("rh|klotski"), "generate puzzle space with ruleset") //
|
("h", po::value<int>()->default_value(board_height)->value_name("[3, 8"), "board height") //
|
||||||
("w", po::value<int>()->default_value(6), "board width") //
|
("gx", po::value<int>()->default_value(goal_x)->value_name("[0, w-1]"), "board goal horizontal position") //
|
||||||
("h", po::value<int>()->default_value(6), "board height") //
|
("gy", po::value<int>()->default_value(goal_y)->value_name("[0, h-1]"), "board goal vertical position") //
|
||||||
("gx", po::value<int>()->default_value(4), "board goal horizontal position") //
|
("free", "allow free block movement") //
|
||||||
("gy", po::value<int>()->default_value(2), "board goal vertical position") //
|
("blocks",
|
||||||
("free", "allow free block movement") //
|
po::value<int>()->default_value(max_blocks)->value_name("[1, 15]"),
|
||||||
("blocks", po::value<int>()->default_value(5), "block limit for puzzle space generation") //
|
"block limit for puzzle space generation") //
|
||||||
;
|
;
|
||||||
|
|
||||||
po::positional_options_description positional;
|
po::positional_options_description positional;
|
||||||
@ -308,7 +307,7 @@ auto argparse(const int argc, char* argv[]) -> runmode
|
|||||||
if (vm.contains("presets")) {
|
if (vm.contains("presets")) {
|
||||||
preset_file = vm["presets"].as<std::string>();
|
preset_file = vm["presets"].as<std::string>();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return runmode::USER_INTERFACE;
|
return runmode::USER_INTERFACE;
|
||||||
}
|
}
|
||||||
@ -346,4 +345,4 @@ auto main(const int argc, char* argv[]) -> int
|
|||||||
};
|
};
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -682,7 +682,7 @@ auto puzzle::try_toggle_wall(const uint8_t x, const uint8_t y) const -> std::opt
|
|||||||
return puzzle(w, h, gx, gy, r, g, blocks);
|
return puzzle(w, h, gx, gy, r, g, blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto puzzle::try_move_block_at(const uint8_t x, const uint8_t y, const direction dir) const -> std::optional<puzzle>
|
auto puzzle::try_move_block_at(const uint8_t x, const uint8_t y, const dir dir) const -> std::optional<puzzle>
|
||||||
{
|
{
|
||||||
const std::optional<block> b = try_get_block(x, y);
|
const std::optional<block> b = try_get_block(x, y);
|
||||||
const auto [bx, by, bw, bh, bt, bi] = b->unpack_repr();
|
const auto [bx, by, bw, bh, bt, bi] = b->unpack_repr();
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
#include <catch2/catch_template_test_macros.hpp>
|
#include <catch2/catch_template_test_macros.hpp>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "util.hpp"
|
#include "bits.hpp"
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Catch2
|
// Catch2
|
||||||
|
|||||||
@ -668,7 +668,7 @@ TEST_CASE("try_move_block_at_fast matches try_move_block_at", "[move]")
|
|||||||
|
|
||||||
uint64_t bm = p3->blocks_bitmap();
|
uint64_t bm = p3->blocks_bitmap();
|
||||||
|
|
||||||
for (const direction d : {nor, eas, sou, wes}) {
|
for (const dir d : {nor, eas, sou, wes}) {
|
||||||
// Block 0 is the first in sorted order
|
// Block 0 is the first in sorted order
|
||||||
auto slow = p3->try_move_block_at(1, 1, d);
|
auto slow = p3->try_move_block_at(1, 1, d);
|
||||||
auto fast = p3->try_move_block_at_fast(bm, 0, d);
|
auto fast = p3->try_move_block_at_fast(bm, 0, d);
|
||||||
|
|||||||
Reference in New Issue
Block a user