mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-28 20:32:18 -05:00
Add manual seed input for rando generation (#2057)
* add manual seed input for rando generation * add tooltip for seed input * switch to calloc * add seed testing count generator * add console command for rando gen * add boost and custom hash_32 functions * use hash_32 funcs for rando generation * limit seed input field to uint32 * rename custom boost header imports to boost_custom
This commit is contained in:
parent
170a9103f9
commit
589e25948e
@ -1935,6 +1935,32 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES MSVC_RUNTIME_LIBRARY ${MSVC_RUNTIME_LIBRARY_STR})
|
||||
endif()
|
||||
################################################################################
|
||||
# Find/download Boost
|
||||
################################################################################
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
Boost
|
||||
URL https://boostorg.jfrog.io/artifactory/main/release/1.81.0/source/boost_1_81_0.tar.gz
|
||||
URL_HASH SHA256=205666dea9f6a7cfed87c7a6dfbeb52a2c1b9de55712c9c1a87735d7181452b6
|
||||
SOURCE_SUBDIR "null" # Set to a nonexistent directory so boost is not built (we don't need to build it)
|
||||
DOWNLOAD_EXTRACT_TIMESTAMP false # supress timestamp warning, not needed since the url wont change
|
||||
)
|
||||
|
||||
set(Boost_NO_BOOST_CMAKE false)
|
||||
set(BOOST_INCLUDEDIR ${FETCHCONTENT_BASE_DIR}/boost-src) # Location where FetchContent stores the source
|
||||
message("Searching for Boost installation")
|
||||
find_package(Boost)
|
||||
|
||||
if (NOT ${Boost_FOUND})
|
||||
message("Boost not found. Downloading now...")
|
||||
FetchContent_MakeAvailable(Boost)
|
||||
message("Boost downloaded to " ${FETCHCONTENT_BASE_DIR}/boost-src)
|
||||
set(BOOST-INCLUDE ${FETCHCONTENT_BASE_DIR}/boost-src)
|
||||
else()
|
||||
message("Boost found in " ${Boost_INCLUDE_DIRS})
|
||||
set(BOOST-INCLUDE ${Boost_INCLUDE_DIRS})
|
||||
endif()
|
||||
################################################################################
|
||||
# Compile definitions
|
||||
################################################################################
|
||||
find_package(SDL2)
|
||||
@ -1971,6 +1997,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE assets
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPD/resource/type
|
||||
${SDL2-INCLUDE}
|
||||
${SDL2-NET-INCLUDE}
|
||||
${BOOST-INCLUDE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/assets/
|
||||
.
|
||||
)
|
||||
|
@ -0,0 +1,47 @@
|
||||
// 32 bit implementation based off of Boost hash
|
||||
|
||||
#ifndef BOOST_HASH_DETAIL_HASH_MIX_32_HPP
|
||||
#define BOOST_HASH_DETAIL_HASH_MIX_32_HPP
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <cstddef>
|
||||
#include <climits>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
template<uint32_t Bits> struct hash_mix_impl_32;
|
||||
|
||||
// hash_mix for 32 bit
|
||||
//
|
||||
// We use the "best xmxmx" implementation from
|
||||
// https://github.com/skeeto/hash-prospector/issues/19
|
||||
|
||||
template<> struct hash_mix_impl_32<32>
|
||||
{
|
||||
inline static boost::uint32_t fn( boost::uint32_t x )
|
||||
{
|
||||
boost::uint32_t const m1 = 0x21f0aaad;
|
||||
boost::uint32_t const m2 = 0x735a2d97;
|
||||
|
||||
x ^= x >> 16;
|
||||
x *= m1;
|
||||
x ^= x >> 15;
|
||||
x *= m2;
|
||||
x ^= x >> 15;
|
||||
|
||||
return x;
|
||||
}
|
||||
};
|
||||
|
||||
inline uint32_t hash_mix_32( uint32_t v )
|
||||
{
|
||||
return hash_mix_impl_32<32>::fn( v );
|
||||
}
|
||||
|
||||
} // namespace hash_detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_HASH_DETAIL_HASH_MIX_32_HPP
|
117
soh/include/boost_custom/container_hash/detail/hash_range_32.hpp
Normal file
117
soh/include/boost_custom/container_hash/detail/hash_range_32.hpp
Normal file
@ -0,0 +1,117 @@
|
||||
// 32 bit implementation based off of Boost hash
|
||||
// Only implementing 32 bit version of char based ranges
|
||||
|
||||
#ifndef BOOST_HASH_DETAIL_HASH_RANGE_32_HPP
|
||||
#define BOOST_HASH_DETAIL_HASH_RANGE_32_HPP
|
||||
|
||||
#include <boost_custom/container_hash/hash_fwd_32.hpp>
|
||||
#include <boost_custom/container_hash/version.hpp>
|
||||
|
||||
#if BOOST_VERSION_HAS_HASH_RANGE
|
||||
#include <boost/container_hash/detail/hash_range.hpp>
|
||||
#else
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/type_traits/enable_if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <cstddef>
|
||||
#include <climits>
|
||||
#include <iterator>
|
||||
#endif // #if BOOST_VERSION_HAS_HASH_RANGE
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace hash_detail
|
||||
{
|
||||
|
||||
#if !BOOST_VERSION_HAS_HASH_RANGE
|
||||
|
||||
template<class T> struct is_char_type: public boost::false_type {};
|
||||
|
||||
#if CHAR_BIT == 8
|
||||
|
||||
template<> struct is_char_type<char>: public boost::true_type {};
|
||||
template<> struct is_char_type<signed char>: public boost::true_type {};
|
||||
template<> struct is_char_type<unsigned char>: public boost::true_type {};
|
||||
|
||||
#if defined(__cpp_char8_t) && __cpp_char8_t >= 201811L
|
||||
template<> struct is_char_type<char8_t>: public boost::true_type {};
|
||||
#endif
|
||||
|
||||
#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
|
||||
template<> struct is_char_type<std::byte>: public boost::true_type {};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif // #if !BOOST_VERSION_HAS_HASH_RANGE
|
||||
|
||||
template<class It>
|
||||
inline typename boost::enable_if_<
|
||||
is_char_type<typename std::iterator_traits<It>::value_type>::value &&
|
||||
is_same<typename std::iterator_traits<It>::iterator_category, std::random_access_iterator_tag>::value,
|
||||
std::size_t>::type
|
||||
hash_range_32( uint32_t seed, It first, It last )
|
||||
{
|
||||
std::size_t n = static_cast<std::size_t>( last - first );
|
||||
|
||||
for( ; n >= 4; first += 4, n -= 4 )
|
||||
{
|
||||
// clang 5+, gcc 5+ figure out this pattern and use a single mov on x86
|
||||
// gcc on s390x and power BE even knows how to use load-reverse
|
||||
|
||||
boost::uint32_t w =
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[2] ) ) << 16 |
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[3] ) ) << 24;
|
||||
|
||||
hash_combine_32( seed, w );
|
||||
}
|
||||
|
||||
{
|
||||
// add a trailing suffix byte of 0x01 because otherwise sequences of
|
||||
// trailing zeroes are indistinguishable from end of string
|
||||
|
||||
boost::uint32_t w = 0x01u;
|
||||
|
||||
switch( n )
|
||||
{
|
||||
case 1:
|
||||
|
||||
w =
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
|
||||
0x0100u;
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
|
||||
w =
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
|
||||
0x010000u;
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
|
||||
w =
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[0] ) ) |
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[1] ) ) << 8 |
|
||||
static_cast<boost::uint32_t>( static_cast<unsigned char>( first[2] ) ) << 16 |
|
||||
0x01000000u;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
hash_combine_32( seed, w );
|
||||
}
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
} // namespace hash_detail
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_HASH_DETAIL_HASH_RANGE_32_HPP
|
172
soh/include/boost_custom/container_hash/hash_32.hpp
Normal file
172
soh/include/boost_custom/container_hash/hash_32.hpp
Normal file
@ -0,0 +1,172 @@
|
||||
// 32 bit implementation based off of Boost hash
|
||||
// Only implementing 32 bit versions integral and string based hashes
|
||||
|
||||
#ifndef BOOST_FUNCTIONAL_HASH_HASH_32_HPP
|
||||
#define BOOST_FUNCTIONAL_HASH_HASH_32_HPP
|
||||
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost_custom/container_hash/hash_fwd_32.hpp>
|
||||
#include <boost_custom/container_hash/detail/hash_mix_32.hpp>
|
||||
#include <boost_custom/container_hash/detail/hash_range_32.hpp>
|
||||
#include <boost_custom/container_hash/version.hpp>
|
||||
|
||||
#if !BOOST_VERSION_HAS_HASH_RANGE
|
||||
#include <boost/type_traits/is_unsigned.hpp>
|
||||
#include <boost/type_traits/make_unsigned.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(__GNUC__, < 3) \
|
||||
&& !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
|
||||
#define BOOST_HASH_CHAR_TRAITS string_char_traits
|
||||
#else
|
||||
#define BOOST_HASH_CHAR_TRAITS char_traits
|
||||
#endif
|
||||
|
||||
#endif // #if !BOOST_VERSION_HAS_HASH_RANGE
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
//
|
||||
// boost::hash_value
|
||||
//
|
||||
|
||||
// integral types
|
||||
|
||||
namespace hash_detail
|
||||
{
|
||||
template<class T,
|
||||
bool bigger_than_size_t = (sizeof(T) > sizeof(uint32_t)),
|
||||
bool is_unsigned = boost::is_unsigned<T>::value,
|
||||
std::size_t size_t_bits = sizeof(uint32_t) * CHAR_BIT,
|
||||
std::size_t type_bits = sizeof(T) * CHAR_BIT>
|
||||
struct hash_integral_impl_32;
|
||||
|
||||
template<class T, bool is_unsigned, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl_32<T, false, is_unsigned, size_t_bits, type_bits>
|
||||
{
|
||||
static uint32_t fn( T v )
|
||||
{
|
||||
return static_cast<uint32_t>( v );
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, std::size_t size_t_bits, std::size_t type_bits> struct hash_integral_impl_32<T, true, false, size_t_bits, type_bits>
|
||||
{
|
||||
static uint32_t fn( T v )
|
||||
{
|
||||
typedef typename boost::make_unsigned<T>::type U;
|
||||
|
||||
if( v >= 0 )
|
||||
{
|
||||
return hash_integral_impl_32<U>::fn( static_cast<U>( v ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return ~hash_integral_impl_32<U>::fn( static_cast<U>( ~static_cast<U>( v ) ) );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> struct hash_integral_impl_32<T, true, true, 32, 64>
|
||||
{
|
||||
static uint32_t fn( T v )
|
||||
{
|
||||
uint32_t seed = 0;
|
||||
|
||||
seed = static_cast<uint32_t>( v >> 32 ) + hash_detail::hash_mix_32( seed );
|
||||
seed = static_cast<uint32_t>( v ) + hash_detail::hash_mix_32( seed );
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> struct hash_integral_impl_32<T, true, true, 32, 128>
|
||||
{
|
||||
static uint32_t fn( T v )
|
||||
{
|
||||
uint32_t seed = 0;
|
||||
|
||||
seed = static_cast<uint32_t>( v >> 96 ) + hash_detail::hash_mix_32( seed );
|
||||
seed = static_cast<uint32_t>( v >> 64 ) + hash_detail::hash_mix_32( seed );
|
||||
seed = static_cast<uint32_t>( v >> 32 ) + hash_detail::hash_mix_32( seed );
|
||||
seed = static_cast<uint32_t>( v ) + hash_detail::hash_mix_32( seed );
|
||||
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace hash_detail
|
||||
|
||||
template <typename T>
|
||||
typename boost::enable_if_<boost::is_integral<T>::value, uint32_t>::type
|
||||
hash_value_32( T v )
|
||||
{
|
||||
return hash_detail::hash_integral_impl_32<T>::fn( v );
|
||||
}
|
||||
|
||||
// contiguous ranges (string, vector, array)
|
||||
#if BOOST_VERSION_HAS_HASH_RANGE
|
||||
template <typename T>
|
||||
typename boost::enable_if_<container_hash::is_contiguous_range<T>::value, uint32_t>::type
|
||||
hash_value_32( T const& v )
|
||||
{
|
||||
return boost::hash_range_32( v.data(), v.data() + v.size() );
|
||||
}
|
||||
#else
|
||||
template <class Ch, class A>
|
||||
inline uint32_t hash_value_32(
|
||||
std::basic_string<Ch, std::BOOST_HASH_CHAR_TRAITS<Ch>, A> const& v)
|
||||
{
|
||||
return boost::hash_range_32( v.data(), v.data() + v.size() );
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost::hash_combine
|
||||
//
|
||||
|
||||
template <class T>
|
||||
inline void hash_combine_32( uint32_t& seed, T const& v )
|
||||
{
|
||||
seed = boost::hash_detail::hash_mix_32( seed + 0x9e3779b9 + boost::hash_32<T>()( v ) );
|
||||
}
|
||||
|
||||
//
|
||||
// boost::hash_range
|
||||
//
|
||||
|
||||
template <class It>
|
||||
inline void hash_range_32( uint32_t& seed, It first, It last )
|
||||
{
|
||||
seed = hash_detail::hash_range_32( seed, first, last );
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline uint32_t hash_range_32( It first, It last )
|
||||
{
|
||||
uint32_t seed = 0;
|
||||
|
||||
hash_range_32( seed, first, last );
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
//
|
||||
// boost::hash
|
||||
//
|
||||
|
||||
template <class T> struct hash_32
|
||||
{
|
||||
typedef T argument_type;
|
||||
typedef uint32_t result_type;
|
||||
|
||||
uint32_t operator()( T const& val ) const
|
||||
{
|
||||
return hash_value_32( val );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#undef BOOST_HASH_CHAR_TRAITS
|
||||
|
||||
#endif // #ifndef BOOST_FUNCTIONAL_HASH_HASH_32_HPP
|
25
soh/include/boost_custom/container_hash/hash_fwd_32.hpp
Normal file
25
soh/include/boost_custom/container_hash/hash_fwd_32.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
// 32 bit implementation based off of Boost hash
|
||||
|
||||
#ifndef BOOST_FUNCTIONAL_HASH_FWD_32_HPP
|
||||
#define BOOST_FUNCTIONAL_HASH_FWD_32_HPP
|
||||
|
||||
#include <boost/container_hash/hash_fwd.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace container_hash
|
||||
{
|
||||
|
||||
} // namespace container_hash
|
||||
|
||||
template<class T> struct hash_32;
|
||||
|
||||
template<class T> void hash_combine_32( uint32_t& seed, T const& v );
|
||||
|
||||
template<class It> void hash_range_32( uint32_t&, It, It );
|
||||
template<class It> uint32_t hash_range_32( It, It );
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_FUNCTIONAL_HASH_FWD_32_HPP
|
9
soh/include/boost_custom/container_hash/version.hpp
Normal file
9
soh/include/boost_custom/container_hash/version.hpp
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
#ifndef BOOST_CONTAINER_HASH_VERSION_HPP
|
||||
#define BOOST_CONTAINER_HASH_VERSION_HPP
|
||||
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#define BOOST_VERSION_HAS_HASH_RANGE ((BOOST_VERSION / 100 % 1000) >= 81)
|
||||
|
||||
#endif // #ifndef BOOST_CONTAINER_HASH_VERSION_HPP
|
@ -1157,6 +1157,34 @@ static bool CuccoStormHandler(std::shared_ptr<Ship::Console> Console, const std:
|
||||
}
|
||||
}
|
||||
|
||||
static bool GenerateRandoHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
if (args.size() == 1) {
|
||||
if (GenerateRandomizer()) {
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
uint32_t value = std::stoi(args[1], NULL, 10);
|
||||
std::string seed = "";
|
||||
if (args.size() == 3) {
|
||||
int testing = std::stoi(args[1], nullptr, 10);
|
||||
seed = "seed_testing_count";
|
||||
}
|
||||
|
||||
if (GenerateRandomizer(seed + std::to_string(value))){
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] seed|count value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Rando generation already in progress");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
static bool CosmeticsHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
if (args.size() != 2) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
@ -1448,6 +1476,11 @@ void DebugConsole_Init(void) {
|
||||
|
||||
CMD_REGISTER("cucco_storm", { CuccoStormHandler, "Cucco Storm" });
|
||||
|
||||
CMD_REGISTER("gen_rando", { GenerateRandoHandler, "Generate a randomizer seed", {
|
||||
{ "seed|count", Ship::ArgumentType::NUMBER, true },
|
||||
{ "testing", Ship::ArgumentType::NUMBER, true },
|
||||
}});
|
||||
|
||||
CMD_REGISTER("cosmetics", { CosmeticsHandler, "Change cosmetics.", {
|
||||
{ "reset|randomize", Ship::ArgumentType::TEXT },
|
||||
}});
|
||||
|
@ -33,14 +33,13 @@ void PrintTopScreen() {
|
||||
SPDLOG_DEBUG(" Select: Exit to Homebrew Menu\n");
|
||||
SPDLOG_DEBUG(" Y: New Random Seed\n");
|
||||
SPDLOG_DEBUG(" X: Input Custom Seed\n");
|
||||
SPDLOG_DEBUG("\x1b[11;7HCurrent Seed: %s", Settings::seed.c_str());
|
||||
SPDLOG_DEBUG("\x1b[11;7HCurrent Seed: %u", Settings::seed);
|
||||
}
|
||||
|
||||
void MenuInit() {
|
||||
Settings::InitSettings();
|
||||
|
||||
seedChanged = false;
|
||||
pastSeedLength = Settings::seed.length();
|
||||
|
||||
Menu* main = new Menu("Main", MenuType::MainMenu, &Settings::mainMenu, MAIN_MENU);
|
||||
menuList.push_back(main);
|
||||
@ -191,24 +190,19 @@ void MenuUpdate(uint32_t kDown, bool updatedByHeld) {
|
||||
|
||||
// New Random Seed
|
||||
if (kDown & KEY_Y) {
|
||||
pastSeedLength = Settings::seed.length();
|
||||
Settings::seed = std::to_string(rand());
|
||||
Settings::seed = rand();
|
||||
seedChanged = true;
|
||||
}
|
||||
|
||||
// Input Custom Seed
|
||||
if (kDown & KEY_X) {
|
||||
pastSeedLength = Settings::seed.length();
|
||||
Settings::seed = GetInput("Enter Seed");
|
||||
// Settings::seed = GetInput("Enter Seed");
|
||||
seedChanged = true;
|
||||
}
|
||||
|
||||
// Reprint seed if it changed
|
||||
if (seedChanged) {
|
||||
std::string spaces = "";
|
||||
spaces.append(pastSeedLength, ' ');
|
||||
printf("\x1b[11;21H%s", spaces.c_str());
|
||||
printf("\x1b[11;21H%s", Settings::seed.c_str());
|
||||
printf("\x1b[11;21H%u", Settings::seed);
|
||||
seedChanged = false;
|
||||
}
|
||||
}
|
||||
@ -517,12 +511,34 @@ void PrintOptionDescription() {
|
||||
printf("\x1b[22;0H%s", description.data());
|
||||
}
|
||||
|
||||
std::string GenerateRandomizer(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations) {
|
||||
// if a blank seed was entered, make a random one
|
||||
srand(time(NULL));
|
||||
Settings::seed = std::to_string(rand());
|
||||
std::string GenerateRandomizer(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations,
|
||||
std::string seedInput) {
|
||||
|
||||
int ret = Playthrough::Playthrough_Init(std::hash<std::string>{}(Settings::seed), cvarSettings, excludedLocations);
|
||||
srand(time(NULL));
|
||||
// if a blank seed was entered, make a random one
|
||||
if (seedInput.empty()) {
|
||||
Settings::seed = rand() & 0xFFFFFFFF;
|
||||
} else if (seedInput.rfind("seed_testing_count", 0) == 0 && seedInput.length() > 18) {
|
||||
int count;
|
||||
try {
|
||||
count = std::stoi(seedInput.substr(18), nullptr);
|
||||
} catch (std::invalid_argument &e) {
|
||||
count = 1;
|
||||
} catch (std::out_of_range &e) {
|
||||
count = 1;
|
||||
}
|
||||
Playthrough::Playthrough_Repeat(cvarSettings, excludedLocations, count);
|
||||
return "";
|
||||
} else {
|
||||
try {
|
||||
int seed = std::stoi(seedInput, nullptr);
|
||||
Settings::seed = seed;
|
||||
} catch (...) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
int ret = Playthrough::Playthrough_Init(Settings::seed, cvarSettings, excludedLocations);
|
||||
if (ret < 0) {
|
||||
if (ret == -1) { // Failed to generate after 5 tries
|
||||
printf("\n\nFailed to generate after 5 tries.\nPress B to go back to the menu.\nA different seed might be "
|
||||
|
@ -46,7 +46,7 @@ void PrintResetToDefaultsMenu();
|
||||
void PrintGenerateMenu();
|
||||
void ClearDescription();
|
||||
void PrintOptionDescription();
|
||||
std::string GenerateRandomizer(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSetting, std::set<RandomizerCheck> excludedLocations);
|
||||
std::string GenerateRandomizer(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSetting, std::set<RandomizerCheck> excludedLocations, std::string seedInput);
|
||||
std::string GetInput(const char* hintText);
|
||||
|
||||
extern void MenuInit();
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "playthrough.hpp"
|
||||
|
||||
#include <boost_custom/container_hash/hash_32.hpp>
|
||||
#include "custom_messages.hpp"
|
||||
#include "fill.hpp"
|
||||
#include "location_access.hpp"
|
||||
@ -37,7 +38,8 @@ int Playthrough_Init(uint32_t seed, std::unordered_map<RandomizerSettingKey, uin
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned int finalHash = std::hash<std::string>{}(Settings::seed + settingsStr);
|
||||
|
||||
uint32_t finalHash = boost::hash_32<std::string>{}(std::to_string(Settings::seed) + settingsStr);
|
||||
Random_Init(finalHash);
|
||||
Settings::hash = std::to_string(finalHash);
|
||||
|
||||
@ -81,15 +83,15 @@ int Playthrough_Init(uint32_t seed, std::unordered_map<RandomizerSettingKey, uin
|
||||
}
|
||||
|
||||
// used for generating a lot of seeds at once
|
||||
int Playthrough_Repeat(int count /*= 1*/) {
|
||||
int Playthrough_Repeat(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations, int count /*= 1*/) {
|
||||
printf("\x1b[0;0HGENERATING %d SEEDS", count);
|
||||
uint32_t repeatedSeed = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
repeatedSeed = rand() % 0xFFFFFFFF;
|
||||
Settings::seed = std::to_string(repeatedSeed);
|
||||
CitraPrint("testing seed: " + Settings::seed);
|
||||
Settings::seed = repeatedSeed;
|
||||
CitraPrint("testing seed: " + std::to_string(Settings::seed));
|
||||
ClearProgress();
|
||||
// Playthrough_Init(std::hash<std::string>{}(Settings::seed));
|
||||
Playthrough_Init(Settings::seed, cvarSettings, excludedLocations);
|
||||
printf("\x1b[15;15HSeeds Generated: %d\n", i + 1);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,6 @@
|
||||
#include "item_location.hpp"
|
||||
|
||||
namespace Playthrough {
|
||||
int Playthrough_Init(uint32_t seed, std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations);
|
||||
int Playthrough_Repeat(int count = 1);
|
||||
int Playthrough_Init(uint32_t seed, std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations);
|
||||
int Playthrough_Repeat(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations, int count = 1);
|
||||
}
|
||||
|
@ -11,7 +11,8 @@
|
||||
|
||||
#define TICKS_PER_SEC 268123480.0
|
||||
|
||||
void RandoMain::GenerateRando(std::unordered_map<RandomizerSettingKey, u8> cvarSettings, std::set<RandomizerCheck> excludedLocations) {
|
||||
void RandoMain::GenerateRando(std::unordered_map<RandomizerSettingKey, u8> cvarSettings, std::set<RandomizerCheck> excludedLocations,
|
||||
std::string seedInput) {
|
||||
HintTable_Init();
|
||||
ItemTable_Init();
|
||||
LocationTable_Init();
|
||||
@ -19,7 +20,7 @@ void RandoMain::GenerateRando(std::unordered_map<RandomizerSettingKey, u8> cvarS
|
||||
// std::string settingsFileName = "./randomizer/latest_settings.json";
|
||||
// CVarSetString("gLoadedPreset", settingsFileName.c_str());
|
||||
|
||||
std::string fileName = Ship::Window::GetPathRelativeToAppDirectory(GenerateRandomizer(cvarSettings, excludedLocations).c_str());
|
||||
std::string fileName = Ship::Window::GetPathRelativeToAppDirectory(GenerateRandomizer(cvarSettings, excludedLocations, seedInput).c_str());
|
||||
CVarSetString("gSpoilerLog", fileName.c_str());
|
||||
|
||||
CVarSave();
|
||||
|
@ -3,6 +3,6 @@
|
||||
#include "item.hpp"
|
||||
|
||||
namespace RandoMain {
|
||||
void GenerateRando(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations);
|
||||
void GenerateRando(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettings, std::set<RandomizerCheck> excludedLocations, std::string seedInput);
|
||||
std::array<Item, KEY_ENUM_MAX>* GetFullItemTable();
|
||||
}
|
||||
|
@ -1,14 +1,17 @@
|
||||
#include "random.hpp"
|
||||
|
||||
#include <random>
|
||||
#include <boost/random/mersenne_twister.hpp>
|
||||
#include <boost/random/uniform_int_distribution.hpp>
|
||||
#include <boost/random/uniform_real_distribution.hpp>
|
||||
|
||||
static bool init = false;
|
||||
static std::mt19937_64 generator;
|
||||
static boost::random::mt19937 generator;
|
||||
|
||||
//Initialize with seed specified
|
||||
void Random_Init(uint32_t seed) {
|
||||
init = true;
|
||||
generator = std::mt19937_64{seed};
|
||||
generator = boost::random::mt19937{seed};
|
||||
}
|
||||
|
||||
//Returns a random integer in range [min, max-1]
|
||||
@ -22,12 +25,12 @@ uint32_t Random(int min, int max) {
|
||||
#endif
|
||||
Random_Init(seed);
|
||||
}
|
||||
std::uniform_int_distribution<uint32_t> distribution(min, max-1);
|
||||
boost::random::uniform_int_distribution<uint32_t> distribution(min, max-1);
|
||||
return distribution(generator);
|
||||
}
|
||||
|
||||
//Returns a random floating point number in [0.0, 1.0]
|
||||
double RandomDouble() {
|
||||
std::uniform_real_distribution<double> distribution(0.0, 1.0);
|
||||
boost::random::uniform_real_distribution<double> distribution(0.0, 1.0);
|
||||
return distribution(generator);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ using namespace Music;
|
||||
using namespace SFX;
|
||||
|
||||
namespace Settings {
|
||||
std::string seed;
|
||||
uint32_t seed;
|
||||
std::string hash;
|
||||
std::string version = RANDOMIZER_VERSION "-" COMMIT_NUMBER;
|
||||
std::array<uint8_t, 5> hashIconIndexes;
|
||||
|
@ -887,7 +887,7 @@ void UpdateSettings(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettin
|
||||
const std::vector<Menu*> GetAllOptionMenus();
|
||||
|
||||
|
||||
extern std::string seed;
|
||||
extern uint32_t seed;
|
||||
extern std::string version;
|
||||
extern std::array<uint8_t, 5> hashIconIndexes;
|
||||
extern std::string hash;
|
||||
|
@ -772,11 +772,11 @@ const char* SpoilerLog_Write(int language) {
|
||||
auto rootNode = spoilerLog.NewElement("spoiler-log");
|
||||
spoilerLog.InsertEndChild(rootNode);
|
||||
|
||||
rootNode->SetAttribute("version", Settings::version.c_str());
|
||||
rootNode->SetAttribute("seed", Settings::seed.c_str());
|
||||
|
||||
jsonData.clear();
|
||||
|
||||
jsonData["_version"] = (char*) gBuildVersion;
|
||||
jsonData["_seed"] = Settings::seed;
|
||||
|
||||
// Write Hash
|
||||
int index = 0;
|
||||
for (uint8_t seed_value : Settings::hashIconIndexes) {
|
||||
@ -844,7 +844,7 @@ bool PlacementLog_Write() {
|
||||
placementLog.InsertEndChild(rootNode);
|
||||
|
||||
rootNode->SetAttribute("version", Settings::version.c_str());
|
||||
rootNode->SetAttribute("seed", Settings::seed.c_str());
|
||||
rootNode->SetAttribute("seed", Settings::seed);
|
||||
|
||||
// WriteSettings(placementLog, true); // Include hidden settings.
|
||||
// WriteExcludedLocations(placementLog);
|
||||
|
@ -39,6 +39,7 @@ std::multimap<std::tuple<s16, s16, s32>, RandomizerCheckObject> checkFromActorMu
|
||||
std::set<RandomizerCheck> excludedLocations;
|
||||
|
||||
u8 generated;
|
||||
char* seedInputBuffer;
|
||||
|
||||
const std::string Randomizer::getItemMessageTableID = "Randomizer";
|
||||
const std::string Randomizer::hintMessageTableID = "RandomizerHints";
|
||||
@ -2766,7 +2767,7 @@ RandomizerCheck Randomizer::GetCheckFromRandomizerInf(RandomizerInf randomizerIn
|
||||
|
||||
std::thread randoThread;
|
||||
|
||||
void GenerateRandomizerImgui() {
|
||||
void GenerateRandomizerImgui(std::string seed = "") {
|
||||
CVarSetInteger("gRandoGenerating", 1);
|
||||
CVarSave();
|
||||
|
||||
@ -2938,7 +2939,9 @@ void GenerateRandomizerImgui() {
|
||||
excludedLocations.insert((RandomizerCheck)std::stoi(excludedLocationString));
|
||||
}
|
||||
|
||||
RandoMain::GenerateRando(cvarSettings, excludedLocations);
|
||||
RandoMain::GenerateRando(cvarSettings, excludedLocations, seed);
|
||||
|
||||
memset(seedInputBuffer, 0, MAX_SEED_BUFFER_SIZE);
|
||||
|
||||
CVarSetInteger("gRandoGenerating", 0);
|
||||
CVarSave();
|
||||
@ -2947,6 +2950,14 @@ void GenerateRandomizerImgui() {
|
||||
generated = 1;
|
||||
}
|
||||
|
||||
bool GenerateRandomizer(std::string seed /*= ""*/) {
|
||||
if (CVarGetInteger("gRandoGenerating", 0) == 0) {
|
||||
randoThread = std::thread(&GenerateRandomizerImgui, seed);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DrawRandoEditor(bool& open) {
|
||||
if (generated) {
|
||||
generated = 0;
|
||||
@ -3023,19 +3034,37 @@ void DrawRandoEditor(bool& open) {
|
||||
return;
|
||||
}
|
||||
|
||||
DrawPresetSelector(PRESET_TYPE_RANDOMIZER);
|
||||
|
||||
bool disableEditingRandoSettings = CVarGetInteger("gRandoGenerating", 0) || CVarGetInteger("gOnFileSelectNameEntry", 0);
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, disableEditingRandoSettings);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * (disableEditingRandoSettings ? 0.5f : 1.0f));
|
||||
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
if (ImGui::Button("Generate Seed")) {
|
||||
if (CVarGetInteger("gRandoGenerating", 0) == 0) {
|
||||
randoThread = std::thread(&GenerateRandomizerImgui);
|
||||
}
|
||||
DrawPresetSelector(PRESET_TYPE_RANDOMIZER);
|
||||
|
||||
UIWidgets::Spacer(0);
|
||||
|
||||
ImGui::Text("Seed");
|
||||
if (ImGui::InputText("##RandomizerSeed", seedInputBuffer, MAX_SEED_BUFFER_SIZE, ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CallbackCharFilter, UIWidgets::TextFilters::FilterNumbers)) {
|
||||
uint32_t seedInput;
|
||||
ImGui::DataTypeApplyFromText(seedInputBuffer, ImGuiDataType_U32, &seedInput, "%u");
|
||||
strncpy(seedInputBuffer, std::to_string(seedInput).c_str(), MAX_SEED_BUFFER_SIZE);
|
||||
}
|
||||
ImGui::Dummy(ImVec2(0.0f, 0.0f));
|
||||
UIWidgets::Tooltip("Leaving this field blank will use a random seed value automatically\nSeed range is 0 - 4,294,967,295");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("New Seed")) {
|
||||
strncpy(seedInputBuffer, std::to_string(rand() & 0xFFFFFFFF).c_str(), MAX_SEED_BUFFER_SIZE);
|
||||
}
|
||||
UIWidgets::Tooltip("Creates a new random seed value to be used when generating a randomizer");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Clear Seed")) {
|
||||
memset(seedInputBuffer, 0, MAX_SEED_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
UIWidgets::Spacer(0);
|
||||
if (ImGui::Button("Generate Randomizer")) {
|
||||
GenerateRandomizer(seedInputBuffer);
|
||||
}
|
||||
|
||||
UIWidgets::Spacer(0);
|
||||
std::string spoilerfilepath = CVarGetString("gSpoilerLog", "");
|
||||
ImGui::Text("Spoiler File: %s", spoilerfilepath.c_str());
|
||||
|
||||
@ -5282,6 +5311,7 @@ void InitRandoItemTable() {
|
||||
void InitRando() {
|
||||
SohImGui::AddWindow("Randomizer", "Randomizer Settings", DrawRandoEditor);
|
||||
Randomizer::CreateCustomMessages();
|
||||
seedInputBuffer = (char*)calloc(MAX_SEED_BUFFER_SIZE, sizeof(char));
|
||||
InitRandoItemTable();
|
||||
}
|
||||
|
||||
@ -5292,4 +5322,3 @@ void Rando_Init(void) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,11 @@
|
||||
#include <soh/Enhancements/custom-message/CustomMessageManager.h>
|
||||
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
|
||||
|
||||
#define MAX_SEED_BUFFER_SIZE 11 // digits for uint32
|
||||
#define NUM_NAVI_MESSAGES 19
|
||||
#define NUM_ICE_TRAP_MESSAGES 23
|
||||
#define NUM_GORON_MESSAGES 9
|
||||
|
||||
class Randomizer {
|
||||
private:
|
||||
std::unordered_map<RandomizerCheck, RandomizerGetData> itemLocations;
|
||||
@ -100,6 +102,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
void Rando_Init(void);
|
||||
bool GenerateRandomizer(std::string seed = "");
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -15,6 +15,15 @@
|
||||
|
||||
namespace UIWidgets {
|
||||
|
||||
struct TextFilters {
|
||||
static int FilterNumbers(ImGuiInputTextCallbackData* data) {
|
||||
if (data->EventChar < 256 && strchr("1234567890", (char)data->EventChar)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
// MARK: - Enums
|
||||
|
||||
enum class CheckboxGraphics {
|
||||
|
Loading…
Reference in New Issue
Block a user