mirror of https://github.com/OpenRCT2/OpenRCT2.git
Implement custom BitSet and replace std::bitset
This commit is contained in:
parent
f55bc799cc
commit
16635b9192
|
@ -14,10 +14,13 @@
|
||||||
#include <openrct2-ui/interface/Widget.h>
|
#include <openrct2-ui/interface/Widget.h>
|
||||||
#include <openrct2/Context.h>
|
#include <openrct2/Context.h>
|
||||||
#include <openrct2/Input.h>
|
#include <openrct2/Input.h>
|
||||||
|
#include <openrct2/core/BitSet.hpp>
|
||||||
#include <openrct2/drawing/Drawing.h>
|
#include <openrct2/drawing/Drawing.h>
|
||||||
#include <openrct2/localisation/Localisation.h>
|
#include <openrct2/localisation/Localisation.h>
|
||||||
#include <openrct2/sprites.h>
|
#include <openrct2/sprites.h>
|
||||||
|
|
||||||
|
using namespace OpenRCT2;
|
||||||
|
|
||||||
// The maximum number of rows to list before items overflow into new columns
|
// The maximum number of rows to list before items overflow into new columns
|
||||||
constexpr int32_t DROPDOWN_TEXT_MAX_ROWS = 32;
|
constexpr int32_t DROPDOWN_TEXT_MAX_ROWS = 32;
|
||||||
|
|
||||||
|
@ -47,8 +50,8 @@ int32_t gDropdownNumItems;
|
||||||
rct_string_id gDropdownItemsFormat[Dropdown::ItemsMaxSize];
|
rct_string_id gDropdownItemsFormat[Dropdown::ItemsMaxSize];
|
||||||
int64_t gDropdownItemsArgs[Dropdown::ItemsMaxSize];
|
int64_t gDropdownItemsArgs[Dropdown::ItemsMaxSize];
|
||||||
static ImageId _dropdownItemsImages[Dropdown::ItemsMaxSize];
|
static ImageId _dropdownItemsImages[Dropdown::ItemsMaxSize];
|
||||||
static std::bitset<Dropdown::ItemsMaxSize> _dropdownItemsChecked = {};
|
static BitSet<Dropdown::ItemsMaxSize> _dropdownItemsChecked = {};
|
||||||
static std::bitset<Dropdown::ItemsMaxSize> _dropdownItemsDisabled = {};
|
static BitSet<Dropdown::ItemsMaxSize> _dropdownItemsDisabled = {};
|
||||||
bool gDropdownIsColour;
|
bool gDropdownIsColour;
|
||||||
int32_t gDropdownLastColourHover;
|
int32_t gDropdownLastColourHover;
|
||||||
int32_t gDropdownHighlightedIndex;
|
int32_t gDropdownHighlightedIndex;
|
||||||
|
|
|
@ -13,12 +13,15 @@
|
||||||
#include <openrct2-ui/windows/Window.h>
|
#include <openrct2-ui/windows/Window.h>
|
||||||
#include <openrct2/Game.h>
|
#include <openrct2/Game.h>
|
||||||
#include <openrct2/actions/ParkMarketingAction.h>
|
#include <openrct2/actions/ParkMarketingAction.h>
|
||||||
|
#include <openrct2/core/BitSet.hpp>
|
||||||
#include <openrct2/drawing/Drawing.h>
|
#include <openrct2/drawing/Drawing.h>
|
||||||
#include <openrct2/localisation/Localisation.h>
|
#include <openrct2/localisation/Localisation.h>
|
||||||
#include <openrct2/ride/Ride.h>
|
#include <openrct2/ride/Ride.h>
|
||||||
#include <openrct2/ride/RideData.h>
|
#include <openrct2/ride/RideData.h>
|
||||||
#include <openrct2/ride/ShopItem.h>
|
#include <openrct2/ride/ShopItem.h>
|
||||||
|
|
||||||
|
using namespace OpenRCT2;
|
||||||
|
|
||||||
static constexpr const rct_string_id WINDOW_TITLE = STR_NONE;
|
static constexpr const rct_string_id WINDOW_TITLE = STR_NONE;
|
||||||
static constexpr const int32_t WH = 109;
|
static constexpr const int32_t WH = 109;
|
||||||
static constexpr const int32_t WW = 350;
|
static constexpr const int32_t WW = 350;
|
||||||
|
@ -95,7 +98,7 @@ private:
|
||||||
*/
|
*/
|
||||||
void GetShopItems()
|
void GetShopItems()
|
||||||
{
|
{
|
||||||
std::bitset<EnumValue(ShopItem::Count)> items = {};
|
BitSet<EnumValue(ShopItem::Count)> items = {};
|
||||||
for (auto& curRide : GetRideManager())
|
for (auto& curRide : GetRideManager())
|
||||||
{
|
{
|
||||||
auto rideEntry = curRide.GetRideEntry();
|
auto rideEntry = curRide.GetRideEntry();
|
||||||
|
|
|
@ -0,0 +1,514 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* Copyright (c) 2014-2021 OpenRCT2 developers
|
||||||
|
*
|
||||||
|
* For a complete list of all authors, please refer to contributors.md
|
||||||
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
||||||
|
*
|
||||||
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
||||||
|
*****************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace OpenRCT2
|
||||||
|
{
|
||||||
|
namespace Detail
|
||||||
|
{
|
||||||
|
namespace BitSet
|
||||||
|
{
|
||||||
|
static constexpr size_t byte_bits = std::numeric_limits<std::underlying_type_t<std::byte>>::digits;
|
||||||
|
|
||||||
|
static constexpr size_t round_bits(size_t v)
|
||||||
|
{
|
||||||
|
const auto reminder = v % byte_bits;
|
||||||
|
if (reminder == 0u)
|
||||||
|
return v;
|
||||||
|
return v + (byte_bits - (v % byte_bits));
|
||||||
|
}
|
||||||
|
#ifdef _DEBUG
|
||||||
|
static_assert(round_bits(1) == 8);
|
||||||
|
static_assert(round_bits(4) == 8);
|
||||||
|
static_assert(round_bits(8) == 8);
|
||||||
|
static_assert(round_bits(9) == 16);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Returns the amount of bytes required for a single block.
|
||||||
|
static constexpr size_t storage_byte_size(size_t numBits)
|
||||||
|
{
|
||||||
|
numBits = round_bits(numBits);
|
||||||
|
if (numBits >= std::numeric_limits<uintptr_t>::digits)
|
||||||
|
return sizeof(uintptr_t);
|
||||||
|
|
||||||
|
const auto numBytes = numBits / byte_bits;
|
||||||
|
auto mask = 1u;
|
||||||
|
while (mask < numBytes)
|
||||||
|
{
|
||||||
|
mask <<= 1u;
|
||||||
|
}
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Replace with std::popcount when C++20 is enabled.
|
||||||
|
template<typename T> static constexpr size_t popcount(const T val)
|
||||||
|
{
|
||||||
|
size_t res = 0;
|
||||||
|
auto x = static_cast<std::make_unsigned_t<T>>(val);
|
||||||
|
while (x > 0u)
|
||||||
|
{
|
||||||
|
if (x & 1u)
|
||||||
|
res++;
|
||||||
|
x >>= 1u;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
static_assert(storage_byte_size(1) == 1);
|
||||||
|
static_assert(storage_byte_size(4) == 1);
|
||||||
|
static_assert(storage_byte_size(8) == 1);
|
||||||
|
static_assert(storage_byte_size(9) == 2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<size_t TByteSize> struct storage_block_type;
|
||||||
|
|
||||||
|
template<> struct storage_block_type<1>
|
||||||
|
{
|
||||||
|
using value_type = uint8_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct storage_block_type<2>
|
||||||
|
{
|
||||||
|
using value_type = uint16_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct storage_block_type<4>
|
||||||
|
{
|
||||||
|
using value_type = uint32_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<> struct storage_block_type<8>
|
||||||
|
{
|
||||||
|
using value_type = uint64_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<size_t TBitSize> struct storage_block_type_aligned
|
||||||
|
{
|
||||||
|
using value_type = typename storage_block_type<storage_byte_size(TBitSize)>::value_type;
|
||||||
|
};
|
||||||
|
} // namespace BitSet
|
||||||
|
} // namespace Detail
|
||||||
|
|
||||||
|
template<uint32_t TBitSize> class BitSet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr size_t storage_capacity_bits = Detail::BitSet::round_bits(TBitSize);
|
||||||
|
static constexpr size_t storage_capacity_bytes = storage_capacity_bits / Detail::BitSet::byte_bits;
|
||||||
|
|
||||||
|
using storage_block_type = typename Detail::BitSet::storage_block_type_aligned<storage_capacity_bits>::value_type;
|
||||||
|
|
||||||
|
static constexpr storage_block_type value_zero = storage_block_type{ 0u };
|
||||||
|
static constexpr storage_block_type value_one = storage_block_type{ 1u };
|
||||||
|
|
||||||
|
static constexpr size_t block_type_bit_size = sizeof(storage_block_type) * Detail::BitSet::byte_bits;
|
||||||
|
static constexpr size_t block_count = storage_capacity_bits / block_type_bit_size;
|
||||||
|
|
||||||
|
static constexpr storage_block_type block_init_value{};
|
||||||
|
static constexpr storage_block_type block_mask_value = ~block_init_value;
|
||||||
|
|
||||||
|
static constexpr bool requires_trim = TBitSize != storage_capacity_bits;
|
||||||
|
|
||||||
|
using storage_data = std::array<storage_block_type, block_count>;
|
||||||
|
|
||||||
|
// Proxy object to access the bits as single value.
|
||||||
|
template<typename T> class reference_base
|
||||||
|
{
|
||||||
|
T& storage_;
|
||||||
|
const size_t blockIndex_;
|
||||||
|
const size_t blockOffset_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr reference_base(T& data, size_t blockIndex, size_t blockOffset) noexcept
|
||||||
|
: storage_(data)
|
||||||
|
, blockIndex_(blockIndex)
|
||||||
|
, blockOffset_(blockOffset)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr reference_base& operator=(const bool value) noexcept
|
||||||
|
{
|
||||||
|
if (!value)
|
||||||
|
storage_[blockIndex_] &= ~(value_one << blockOffset_);
|
||||||
|
else
|
||||||
|
storage_[blockIndex_] |= (value_one << blockOffset_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr reference_base& operator=(const reference_base& value) noexcept
|
||||||
|
{
|
||||||
|
return reference_base::operator=(value.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool value() const noexcept
|
||||||
|
{
|
||||||
|
return (storage_[blockIndex_] & (value_one << blockOffset_)) != value_zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr operator bool() const noexcept
|
||||||
|
{
|
||||||
|
return value();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using reference = reference_base<storage_data>;
|
||||||
|
using const_reference = reference_base<const storage_data>;
|
||||||
|
|
||||||
|
template<typename T, typename TValue> class iterator_base
|
||||||
|
{
|
||||||
|
T* _bitset{};
|
||||||
|
size_t _pos{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr iterator_base() = default;
|
||||||
|
|
||||||
|
constexpr iterator_base(T* bset, size_t pos)
|
||||||
|
: _bitset(bset)
|
||||||
|
, _pos(pos)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr auto operator*() const
|
||||||
|
{
|
||||||
|
const auto blockIndex = compute_block_index(_pos);
|
||||||
|
const auto blockOffset = compute_block_offset(_pos);
|
||||||
|
return TValue(_bitset->data(), blockIndex, blockOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(iterator_base other) const
|
||||||
|
{
|
||||||
|
return _bitset == other._bitset && _pos == other._pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator!=(iterator_base other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator_base& operator++()
|
||||||
|
{
|
||||||
|
_pos++;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator_base operator++(int)
|
||||||
|
{
|
||||||
|
iterator_base res = *this;
|
||||||
|
++(*this);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator_base& operator--()
|
||||||
|
{
|
||||||
|
_pos--;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator_base operator--(int)
|
||||||
|
{
|
||||||
|
iterator_base res = *this;
|
||||||
|
--(*this);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
using difference_type = std::size_t;
|
||||||
|
using value_type = TValue;
|
||||||
|
using pointer = const TValue*;
|
||||||
|
using reference = const TValue&;
|
||||||
|
using iterator_category = std::forward_iterator_tag;
|
||||||
|
};
|
||||||
|
|
||||||
|
using iterator = iterator_base<BitSet, reference>;
|
||||||
|
using const_iterator = iterator_base<const BitSet, const_reference>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
storage_data data_{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr BitSet() = default;
|
||||||
|
|
||||||
|
constexpr BitSet(const storage_block_type val)
|
||||||
|
: data_{ val }
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr BitSet(const std::initializer_list<size_t>& indices)
|
||||||
|
{
|
||||||
|
for (auto idx : indices)
|
||||||
|
{
|
||||||
|
set(idx, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t size() const noexcept
|
||||||
|
{
|
||||||
|
return TBitSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t count() const noexcept
|
||||||
|
{
|
||||||
|
size_t numBits = 0;
|
||||||
|
for (auto& data : data_)
|
||||||
|
{
|
||||||
|
numBits += Detail::BitSet::popcount(data);
|
||||||
|
}
|
||||||
|
return numBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_t capacity() const noexcept
|
||||||
|
{
|
||||||
|
return storage_capacity_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr storage_data& data() noexcept
|
||||||
|
{
|
||||||
|
return data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const storage_data& data() const noexcept
|
||||||
|
{
|
||||||
|
return data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr BitSet& set(size_t index, bool value) noexcept
|
||||||
|
{
|
||||||
|
const auto blockIndex = compute_block_index(index);
|
||||||
|
const auto blockOffset = compute_block_offset(index);
|
||||||
|
if (!value)
|
||||||
|
data_[blockIndex] &= ~(value_one << blockOffset);
|
||||||
|
else
|
||||||
|
data_[blockIndex] |= (value_one << blockOffset);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool get(size_t index) const noexcept
|
||||||
|
{
|
||||||
|
const auto blockIndex = compute_block_index(index);
|
||||||
|
const auto blockOffset = compute_block_offset(index);
|
||||||
|
return (data_[blockIndex] & (value_one << blockOffset)) != value_zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator[](const size_t index) const noexcept
|
||||||
|
{
|
||||||
|
const auto blockIndex = compute_block_index(index);
|
||||||
|
const auto blockOffset = compute_block_offset(index);
|
||||||
|
const_reference ref(data_, blockIndex, blockOffset);
|
||||||
|
return ref.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr reference operator[](const size_t index) noexcept
|
||||||
|
{
|
||||||
|
const auto blockIndex = compute_block_index(index);
|
||||||
|
const auto blockOffset = compute_block_offset(index);
|
||||||
|
return reference(data_, blockIndex, blockOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr BitSet& flip() noexcept
|
||||||
|
{
|
||||||
|
for (auto& data : data_)
|
||||||
|
{
|
||||||
|
data ^= block_mask_value;
|
||||||
|
}
|
||||||
|
if constexpr (requires_trim)
|
||||||
|
{
|
||||||
|
trim();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr BitSet& reset() noexcept
|
||||||
|
{
|
||||||
|
std::fill(data_.begin(), data_.end(), block_init_value);
|
||||||
|
if constexpr (requires_trim)
|
||||||
|
{
|
||||||
|
trim();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const_iterator begin() const noexcept
|
||||||
|
{
|
||||||
|
return const_iterator(this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const_iterator end() const noexcept
|
||||||
|
{
|
||||||
|
return const_iterator(this, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator begin() noexcept
|
||||||
|
{
|
||||||
|
return iterator(this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr iterator end() noexcept
|
||||||
|
{
|
||||||
|
return iterator(this, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class TChar = char, class TTraits = std::char_traits<TChar>, class TAlloc = std::allocator<TChar>>
|
||||||
|
std::basic_string<TChar, TTraits, TAlloc> to_string(TChar zero = TChar{ '0' }, TChar one = TChar{ '1' }) const
|
||||||
|
{
|
||||||
|
std::basic_string<TChar, TTraits, TAlloc> res;
|
||||||
|
res.resize(TBitSize);
|
||||||
|
for (size_t i = 0; i < TBitSize; ++i)
|
||||||
|
{
|
||||||
|
// Printed as little-endian.
|
||||||
|
res[TBitSize - i - 1] = get(i) ? one : zero;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr BitSet operator^(const BitSet& other) const noexcept
|
||||||
|
{
|
||||||
|
BitSet res = *this;
|
||||||
|
for (size_t i = 0; i < data_.size(); i++)
|
||||||
|
{
|
||||||
|
res.data_[i] ^= other.data_[i];
|
||||||
|
}
|
||||||
|
if constexpr (requires_trim)
|
||||||
|
{
|
||||||
|
res.trim();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr BitSet& operator^=(const BitSet& other) noexcept
|
||||||
|
{
|
||||||
|
*this = *this ^ other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr BitSet operator|(const BitSet& other) const noexcept
|
||||||
|
{
|
||||||
|
BitSet res = *this;
|
||||||
|
for (size_t i = 0; i < data_.size(); i++)
|
||||||
|
{
|
||||||
|
res.data_[i] |= other.data_[i];
|
||||||
|
}
|
||||||
|
if constexpr (requires_trim)
|
||||||
|
{
|
||||||
|
res.trim();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr BitSet& operator|=(const BitSet& other) noexcept
|
||||||
|
{
|
||||||
|
*this = *this | other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr BitSet operator&(const BitSet& other) const noexcept
|
||||||
|
{
|
||||||
|
BitSet res = *this;
|
||||||
|
for (size_t i = 0; i < data_.size(); i++)
|
||||||
|
{
|
||||||
|
res.data_[i] &= other.data_[i];
|
||||||
|
}
|
||||||
|
if constexpr (requires_trim)
|
||||||
|
{
|
||||||
|
res.trim();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr BitSet& operator&=(const BitSet& other) noexcept
|
||||||
|
{
|
||||||
|
*this = *this & other;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr BitSet operator~() const noexcept
|
||||||
|
{
|
||||||
|
BitSet res = *this;
|
||||||
|
for (size_t i = 0; i < data_.size(); i++)
|
||||||
|
{
|
||||||
|
res.data_[i] = ~res.data_[i];
|
||||||
|
}
|
||||||
|
if constexpr (requires_trim)
|
||||||
|
{
|
||||||
|
res.trim();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator<(const BitSet& other) const noexcept
|
||||||
|
{
|
||||||
|
return std::lexicographical_compare(data_.begin(), data_.end(), other.data_.begin(), other.data_.end(), std::less);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator<=(const BitSet& other) const noexcept
|
||||||
|
{
|
||||||
|
return std::lexicographical_compare(
|
||||||
|
data_.begin(), data_.end(), other.data_.begin(), other.data_.end(), std::less_equal);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator>(const BitSet& other) const noexcept
|
||||||
|
{
|
||||||
|
return std::lexicographical_compare(
|
||||||
|
data_.begin(), data_.end(), other.data_.begin(), other.data_.end(), std::greater);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator>=(const BitSet& other) const noexcept
|
||||||
|
{
|
||||||
|
return std::lexicographical_compare(
|
||||||
|
data_.begin(), data_.end(), other.data_.begin(), other.data_.end(), std::greater_equal);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr size_t compute_block_index(size_t idx) noexcept
|
||||||
|
{
|
||||||
|
if constexpr (block_count == 1)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return idx / block_type_bit_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr size_t compute_block_offset(size_t idx) noexcept
|
||||||
|
{
|
||||||
|
if constexpr (block_count == 1)
|
||||||
|
{
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return idx % block_type_bit_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some operations require to trim of the excess.
|
||||||
|
constexpr void trim() noexcept
|
||||||
|
{
|
||||||
|
const auto byteIdx = TBitSize / block_type_bit_size;
|
||||||
|
const auto bitIdx = TBitSize % block_type_bit_size;
|
||||||
|
if constexpr (bitIdx == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto trimMask = block_mask_value;
|
||||||
|
trimMask <<= (block_type_bit_size - bitIdx);
|
||||||
|
trimMask >>= (block_type_bit_size - bitIdx);
|
||||||
|
|
||||||
|
data_[byteIdx] &= trimMask;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace OpenRCT2
|
|
@ -1854,9 +1854,9 @@ Ride* Guest::FindBestRideToGoOn()
|
||||||
return mostExcitingRide;
|
return mostExcitingRide;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::bitset<MAX_RIDES> Guest::FindRidesToGoOn()
|
BitSet<MAX_RIDES> Guest::FindRidesToGoOn()
|
||||||
{
|
{
|
||||||
std::bitset<MAX_RIDES> rideConsideration;
|
BitSet<MAX_RIDES> rideConsideration;
|
||||||
|
|
||||||
// FIX Originally checked for a toy, likely a mistake and should be a map,
|
// FIX Originally checked for a toy, likely a mistake and should be a map,
|
||||||
// but then again this seems to only allow the peep to go on
|
// but then again this seems to only allow the peep to go on
|
||||||
|
@ -3111,7 +3111,7 @@ template<typename T> static void peep_head_for_nearest_ride(Guest* peep, bool co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::bitset<MAX_RIDES> rideConsideration;
|
BitSet<MAX_RIDES> rideConsideration;
|
||||||
if (!considerOnlyCloseRides && (peep->HasItem(ShopItem::Map)))
|
if (!considerOnlyCloseRides && (peep->HasItem(ShopItem::Map)))
|
||||||
{
|
{
|
||||||
// Consider all rides in the park
|
// Consider all rides in the park
|
||||||
|
|
|
@ -9,13 +9,12 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../core/BitSet.hpp"
|
||||||
#include "../management/Finance.h"
|
#include "../management/Finance.h"
|
||||||
#include "../ride/Ride.h"
|
#include "../ride/Ride.h"
|
||||||
#include "../ride/ShopItem.h"
|
#include "../ride/ShopItem.h"
|
||||||
#include "Peep.h"
|
#include "Peep.h"
|
||||||
|
|
||||||
#include <bitset>
|
|
||||||
|
|
||||||
#define PEEP_MAX_THOUGHTS 5
|
#define PEEP_MAX_THOUGHTS 5
|
||||||
|
|
||||||
#define PEEP_HUNGER_WARNING_THRESHOLD 25
|
#define PEEP_HUNGER_WARNING_THRESHOLD 25
|
||||||
|
@ -33,6 +32,8 @@
|
||||||
#define PEEP_MAX_NAUSEA 255
|
#define PEEP_MAX_NAUSEA 255
|
||||||
#define PEEP_MAX_THIRST 255
|
#define PEEP_MAX_THIRST 255
|
||||||
|
|
||||||
|
using namespace OpenRCT2;
|
||||||
|
|
||||||
enum class PeepThoughtType : uint8_t
|
enum class PeepThoughtType : uint8_t
|
||||||
{
|
{
|
||||||
CantAffordRide = 0, // "I can't afford"
|
CantAffordRide = 0, // "I can't afford"
|
||||||
|
@ -419,7 +420,7 @@ private:
|
||||||
void MakePassingPeepsSick(Guest* passingPeep);
|
void MakePassingPeepsSick(Guest* passingPeep);
|
||||||
void GivePassingPeepsIceCream(Guest* passingPeep);
|
void GivePassingPeepsIceCream(Guest* passingPeep);
|
||||||
Ride* FindBestRideToGoOn();
|
Ride* FindBestRideToGoOn();
|
||||||
std::bitset<MAX_RIDES> FindRidesToGoOn();
|
BitSet<MAX_RIDES> FindRidesToGoOn();
|
||||||
bool FindVehicleToEnter(Ride* ride, std::vector<uint8_t>& car_array);
|
bool FindVehicleToEnter(Ride* ride, std::vector<uint8_t>& car_array);
|
||||||
void GoToRideEntrance(Ride* ride);
|
void GoToRideEntrance(Ride* ride);
|
||||||
};
|
};
|
||||||
|
|
|
@ -149,6 +149,7 @@
|
||||||
<ClInclude Include="config\IniReader.hpp" />
|
<ClInclude Include="config\IniReader.hpp" />
|
||||||
<ClInclude Include="config\IniWriter.hpp" />
|
<ClInclude Include="config\IniWriter.hpp" />
|
||||||
<ClInclude Include="Context.h" />
|
<ClInclude Include="Context.h" />
|
||||||
|
<ClInclude Include="core\BitSet.hpp" />
|
||||||
<ClInclude Include="core\ChecksumStream.h" />
|
<ClInclude Include="core\ChecksumStream.h" />
|
||||||
<ClInclude Include="core\CircularBuffer.h" />
|
<ClInclude Include="core\CircularBuffer.h" />
|
||||||
<ClInclude Include="core\Collections.hpp" />
|
<ClInclude Include="core\Collections.hpp" />
|
||||||
|
@ -942,4 +943,4 @@
|
||||||
<ClCompile Include="world\Wall.cpp" />
|
<ClCompile Include="world\Wall.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
</Project>
|
</Project>
|
|
@ -13,6 +13,7 @@
|
||||||
#include "../OpenRCT2.h"
|
#include "../OpenRCT2.h"
|
||||||
#include "../actions/ParkSetResearchFundingAction.h"
|
#include "../actions/ParkSetResearchFundingAction.h"
|
||||||
#include "../config/Config.h"
|
#include "../config/Config.h"
|
||||||
|
#include "../core/BitSet.hpp"
|
||||||
#include "../core/Guard.hpp"
|
#include "../core/Guard.hpp"
|
||||||
#include "../core/Memory.hpp"
|
#include "../core/Memory.hpp"
|
||||||
#include "../interface/Window.h"
|
#include "../interface/Window.h"
|
||||||
|
@ -36,6 +37,8 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
|
using namespace OpenRCT2;
|
||||||
|
|
||||||
static constexpr const int32_t _researchRate[] = {
|
static constexpr const int32_t _researchRate[] = {
|
||||||
0,
|
0,
|
||||||
160,
|
160,
|
||||||
|
@ -966,7 +969,7 @@ bool ResearchItem::operator==(const ResearchItem& rhs) const
|
||||||
return (entryIndex == rhs.entryIndex && baseRideType == rhs.baseRideType && type == rhs.type);
|
return (entryIndex == rhs.entryIndex && baseRideType == rhs.baseRideType && type == rhs.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::bitset<RIDE_TYPE_COUNT> _seenRideType = {};
|
static BitSet<RIDE_TYPE_COUNT> _seenRideType = {};
|
||||||
|
|
||||||
static void research_update_first_of_type(ResearchItem* researchItem)
|
static void research_update_first_of_type(ResearchItem* researchItem)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1936,7 +1936,7 @@ static void get_ride_queue_end(TileCoordsXYZ& loc)
|
||||||
* appropriate.
|
* appropriate.
|
||||||
*/
|
*/
|
||||||
static StationIndex guest_pathfinding_select_random_station(
|
static StationIndex guest_pathfinding_select_random_station(
|
||||||
const Guest* guest, int32_t numEntranceStations, std::bitset<MAX_STATIONS>& entranceStations)
|
const Guest* guest, int32_t numEntranceStations, BitSet<MAX_STATIONS>& entranceStations)
|
||||||
{
|
{
|
||||||
int32_t select = guest->GuestNumRides % numEntranceStations;
|
int32_t select = guest->GuestNumRides % numEntranceStations;
|
||||||
while (select > 0)
|
while (select > 0)
|
||||||
|
@ -2174,7 +2174,7 @@ int32_t guest_path_finding(Guest* peep)
|
||||||
StationIndex closestStationNum = 0;
|
StationIndex closestStationNum = 0;
|
||||||
|
|
||||||
int32_t numEntranceStations = 0;
|
int32_t numEntranceStations = 0;
|
||||||
std::bitset<MAX_STATIONS> entranceStations = {};
|
BitSet<MAX_STATIONS> entranceStations = {};
|
||||||
|
|
||||||
for (StationIndex stationNum = 0; stationNum < MAX_STATIONS; ++stationNum)
|
for (StationIndex stationNum = 0; stationNum < MAX_STATIONS; ++stationNum)
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "../ParkImporter.h"
|
#include "../ParkImporter.h"
|
||||||
#include "../actions/WallPlaceAction.h"
|
#include "../actions/WallPlaceAction.h"
|
||||||
#include "../audio/audio.h"
|
#include "../audio/audio.h"
|
||||||
|
#include "../core/BitSet.hpp"
|
||||||
#include "../core/Collections.hpp"
|
#include "../core/Collections.hpp"
|
||||||
#include "../core/Console.hpp"
|
#include "../core/Console.hpp"
|
||||||
#include "../core/FileStream.h"
|
#include "../core/FileStream.h"
|
||||||
|
@ -119,8 +120,8 @@ namespace RCT1
|
||||||
ObjectEntryIndex _footpathRailingsTypeToEntryMap[4]{};
|
ObjectEntryIndex _footpathRailingsTypeToEntryMap[4]{};
|
||||||
|
|
||||||
// Research
|
// Research
|
||||||
std::bitset<MAX_RIDE_OBJECTS> _researchRideEntryUsed{};
|
BitSet<MAX_RIDE_OBJECTS> _researchRideEntryUsed{};
|
||||||
std::bitset<EnumValue(RideType::Count)> _researchRideTypeUsed{};
|
BitSet<EnumValue(RideType::Count)> _researchRideTypeUsed{};
|
||||||
|
|
||||||
// Scenario repository - used for determining scenario name
|
// Scenario repository - used for determining scenario name
|
||||||
IScenarioRepository* _scenarioRepository = GetScenarioRepository();
|
IScenarioRepository* _scenarioRepository = GetScenarioRepository();
|
||||||
|
@ -422,7 +423,7 @@ namespace RCT1
|
||||||
{
|
{
|
||||||
size_t researchListCount;
|
size_t researchListCount;
|
||||||
const ResearchItem* researchList = GetResearchList(&researchListCount);
|
const ResearchItem* researchList = GetResearchList(&researchListCount);
|
||||||
std::bitset<EnumValue(RideType::Count)> rideTypeInResearch = GetRideTypesPresentInResearchList(
|
BitSet<EnumValue(RideType::Count)> rideTypeInResearch = GetRideTypesPresentInResearchList(
|
||||||
researchList, researchListCount);
|
researchList, researchListCount);
|
||||||
for (size_t i = 0; i < researchListCount; i++)
|
for (size_t i = 0; i < researchListCount; i++)
|
||||||
{
|
{
|
||||||
|
@ -2052,10 +2053,10 @@ namespace RCT1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::bitset<EnumValue(RideType::Count)> GetRideTypesPresentInResearchList(
|
static BitSet<EnumValue(RideType::Count)> GetRideTypesPresentInResearchList(
|
||||||
const RCT1::ResearchItem* researchList, size_t researchListCount)
|
const RCT1::ResearchItem* researchList, size_t researchListCount)
|
||||||
{
|
{
|
||||||
std::bitset<EnumValue(RideType::Count)> ret = {};
|
BitSet<EnumValue(RideType::Count)> ret = {};
|
||||||
|
|
||||||
for (size_t i = 0; i < researchListCount; i++)
|
for (size_t i = 0; i < researchListCount; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,7 +91,7 @@ namespace RCT2
|
||||||
S6Data _s6{};
|
S6Data _s6{};
|
||||||
uint8_t _gameVersion = 0;
|
uint8_t _gameVersion = 0;
|
||||||
bool _isSV7 = false;
|
bool _isSV7 = false;
|
||||||
std::bitset<Limits::MaxRidesInPark> _isFlatRide{};
|
BitSet<Limits::MaxRidesInPark> _isFlatRide{};
|
||||||
ObjectEntryIndex _pathToSurfaceMap[16];
|
ObjectEntryIndex _pathToSurfaceMap[16];
|
||||||
ObjectEntryIndex _pathToQueueSurfaceMap[16];
|
ObjectEntryIndex _pathToQueueSurfaceMap[16];
|
||||||
ObjectEntryIndex _pathToRailingMap[16];
|
ObjectEntryIndex _pathToRailingMap[16];
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "../ParkImporter.h"
|
#include "../ParkImporter.h"
|
||||||
#include "../audio/audio.h"
|
#include "../audio/audio.h"
|
||||||
#include "../config/Config.h"
|
#include "../config/Config.h"
|
||||||
|
#include "../core/BitSet.hpp"
|
||||||
#include "../core/Guard.hpp"
|
#include "../core/Guard.hpp"
|
||||||
#include "../core/Random.hpp"
|
#include "../core/Random.hpp"
|
||||||
#include "../entity/Duck.h"
|
#include "../entity/Duck.h"
|
||||||
|
@ -53,7 +54,6 @@
|
||||||
#include "ScenarioSources.h"
|
#include "ScenarioSources.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <bitset>
|
|
||||||
|
|
||||||
const rct_string_id ScenarioCategoryStringIds[SCENARIO_CATEGORY_COUNT] = {
|
const rct_string_id ScenarioCategoryStringIds[SCENARIO_CATEGORY_COUNT] = {
|
||||||
STR_BEGINNER_PARKS, STR_CHALLENGING_PARKS, STR_EXPERT_PARKS, STR_REAL_PARKS, STR_OTHER_PARKS,
|
STR_BEGINNER_PARKS, STR_CHALLENGING_PARKS, STR_EXPERT_PARKS, STR_REAL_PARKS, STR_OTHER_PARKS,
|
||||||
|
@ -658,7 +658,7 @@ ObjectiveStatus Objective::CheckParkValueBy() const
|
||||||
ObjectiveStatus Objective::Check10RollerCoasters() const
|
ObjectiveStatus Objective::Check10RollerCoasters() const
|
||||||
{
|
{
|
||||||
auto rcs = 0;
|
auto rcs = 0;
|
||||||
std::bitset<MAX_RIDE_OBJECTS> type_already_counted;
|
BitSet<MAX_RIDE_OBJECTS> type_already_counted;
|
||||||
for (const auto& ride : GetRideManager())
|
for (const auto& ride : GetRideManager())
|
||||||
{
|
{
|
||||||
if (ride.status == RideStatus::Open && ride.excitement >= RIDE_RATING(6, 00) && ride.subtype != OBJECT_ENTRY_INDEX_NULL)
|
if (ride.status == RideStatus::Open && ride.excitement >= RIDE_RATING(6, 00) && ride.subtype != OBJECT_ENTRY_INDEX_NULL)
|
||||||
|
@ -757,7 +757,7 @@ ObjectiveStatus Objective::CheckMonthlyRideIncome() const
|
||||||
*/
|
*/
|
||||||
ObjectiveStatus Objective::Check10RollerCoastersLength() const
|
ObjectiveStatus Objective::Check10RollerCoastersLength() const
|
||||||
{
|
{
|
||||||
std::bitset<MAX_RIDE_OBJECTS> type_already_counted;
|
BitSet<MAX_RIDE_OBJECTS> type_already_counted;
|
||||||
auto rcs = 0;
|
auto rcs = 0;
|
||||||
for (const auto& ride : GetRideManager())
|
for (const auto& ride : GetRideManager())
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue