Improve(?) wildcard rules
This commit is contained in:
parent
ec5c6b2bec
commit
f6c0e07489
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "third/tracy"]
|
||||||
|
path = third/tracy
|
||||||
|
url = https://github.com/wolfpld/tracy.git
|
||||||
@ -22,6 +22,16 @@ set_target_properties(sand PROPERTIES
|
|||||||
CXX_STANDARD_REQUIRED ON
|
CXX_STANDARD_REQUIRED ON
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (EXISTS third/tracy/CMakeLists.txt)
|
||||||
|
option(TRACY_ENABLE "Enable Tracy" ON)
|
||||||
|
set(TRACY_STATIC OFF)
|
||||||
|
set(TRACY_ON_DEMAND ON)
|
||||||
|
add_subdirectory(third/tracy)
|
||||||
|
target_link_libraries(sand PUBLIC Tracy::TracyClient)
|
||||||
|
else()
|
||||||
|
target_compile_definitions(sand PUBLIC FrameMark ZoneScoped)
|
||||||
|
endif()
|
||||||
|
|
||||||
find_package(SDL3 CONFIG REQUIRED)
|
find_package(SDL3 CONFIG REQUIRED)
|
||||||
|
|
||||||
add_executable(sandtest
|
add_executable(sandtest
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
#define SAND_H
|
#define SAND_H
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -22,6 +23,8 @@ class TypeBuilder
|
|||||||
friend RulesBuilder;
|
friend RulesBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
TypeBuilder();
|
||||||
|
|
||||||
TypeBuilder& add_type(const std::string& name);
|
TypeBuilder& add_type(const std::string& name);
|
||||||
TypeBuilder& add_type(const std::string& name,
|
TypeBuilder& add_type(const std::string& name,
|
||||||
const std::string& default_result);
|
const std::string& default_result);
|
||||||
@ -62,7 +65,7 @@ class Rule
|
|||||||
friend RulesBuilder;
|
friend RulesBuilder;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using match_fn = bool (*)(const std::string& name);
|
using match_fn = std::function<bool(const std::string&)>;
|
||||||
|
|
||||||
~Rule();
|
~Rule();
|
||||||
|
|
||||||
@ -98,6 +101,10 @@ private:
|
|||||||
Sand(const RulesBuilder& builder, uint16_t width, uint16_t height,
|
Sand(const RulesBuilder& builder, uint16_t width, uint16_t height,
|
||||||
const std::string& initial);
|
const std::string& initial);
|
||||||
|
|
||||||
|
uint16_t apply_rule(uint16_t tile, unsigned __int128 key) const;
|
||||||
|
|
||||||
|
static unsigned __int128 apply_mask(unsigned __int128 key, uint8_t mask);
|
||||||
|
|
||||||
uint16_t width;
|
uint16_t width;
|
||||||
uint16_t height;
|
uint16_t height;
|
||||||
type_map types;
|
type_map types;
|
||||||
|
|||||||
145
src/main.cpp
145
src/main.cpp
@ -6,47 +6,109 @@
|
|||||||
#include <SDL3/SDL_timer.h>
|
#include <SDL3/SDL_timer.h>
|
||||||
#include <SDL3/SDL_video.h>
|
#include <SDL3/SDL_video.h>
|
||||||
#include <sand.h>
|
#include <sand.h>
|
||||||
|
#include <tracy/Tracy.hpp>
|
||||||
|
|
||||||
constexpr uint16_t WIDTH = 256;
|
constexpr uint16_t WIDTH = 128;
|
||||||
constexpr uint16_t HEIGHT = 256;
|
constexpr uint16_t HEIGHT = 128;
|
||||||
|
|
||||||
constexpr int WINDOW_WIDTH = 1024;
|
constexpr int WINDOW_WIDTH = 1024;
|
||||||
constexpr int WINDOW_HEIGHT = 1024;
|
constexpr int WINDOW_HEIGHT = 1024;
|
||||||
|
|
||||||
uint8_t lookup[][3]
|
struct color
|
||||||
= { { 0, 0, 0 }, { 50, 0, 0 }, { 100, 100, 100 }, { 100, 100, 100 } };
|
{
|
||||||
|
uint8_t c[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
color lookup_color(uint16_t id)
|
||||||
|
{
|
||||||
|
if (id == 0)
|
||||||
|
{
|
||||||
|
return { 0, 0, 0 };
|
||||||
|
}
|
||||||
|
else if (id == 1)
|
||||||
|
{
|
||||||
|
return { 150, 150, 255 };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color c;
|
||||||
|
c.c[0] = 257 - id;
|
||||||
|
c.c[1] = 257 - id;
|
||||||
|
c.c[2] = 257 - id;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
auto rb = sand::TypeBuilder()
|
auto tb = sand::TypeBuilder().add_type("air");
|
||||||
.add_type("offgrid")
|
|
||||||
.add_type("air")
|
|
||||||
.add_type("stone1", "stone2")
|
|
||||||
.add_type("stone2", "stone1")
|
|
||||||
.finish();
|
|
||||||
|
|
||||||
rb.add_rule("air", "stone2")
|
for (int i = 0; i < 255; i++)
|
||||||
.top_middle([](const auto& t) { return t == "stone1"; });
|
{
|
||||||
rb.add_rule("air", "stone1")
|
tb.add_type("stone" + std::to_string(i), "stone" + std::to_string(i + 1));
|
||||||
.top_middle([](const auto& t) { return t == "stone2"; });
|
}
|
||||||
rb.add_rule("air", "stone2")
|
|
||||||
.top_right([](const auto& t) { return t == "stone1"; })
|
|
||||||
.middle_right([](const auto& t) { return t != "air"; });
|
|
||||||
rb.add_rule("air", "stone1")
|
|
||||||
.top_left([](const auto& t) { return t == "stone2"; })
|
|
||||||
.middle_left([](const auto& t) { return t != "air"; });
|
|
||||||
|
|
||||||
rb.add_rule("stone1", "air")
|
auto rb = tb.finish();
|
||||||
.bottom_middle([](const auto& t) { return t == "air"; });
|
|
||||||
rb.add_rule("stone1", "air")
|
|
||||||
.bottom_left([](const auto& t) { return t == "air"; })
|
|
||||||
.bottom_middle([](const auto& t) { return t != "air"; });
|
|
||||||
|
|
||||||
rb.add_rule("stone2", "air")
|
rb.add_rule("air", "stone0")
|
||||||
.bottom_middle([](const auto& t) { return t == "air"; });
|
.bottom_middle([](const std::string& t) { return t == "offgrid"; })
|
||||||
rb.add_rule("stone2", "air")
|
.top_middle([](const std::string& t) { return t == "air"; });
|
||||||
.bottom_right([](const auto& t) { return t == "air"; })
|
|
||||||
.bottom_middle([](const auto& t) { return t != "air"; });
|
for (int i = 0; i < 128; i++)
|
||||||
|
{
|
||||||
|
auto ar = rb.add_rule("air", "stone" + std::to_string(i + 1));
|
||||||
|
auto afn
|
||||||
|
= [i](const std::string& t) { return t == "stone" + std::to_string(i); };
|
||||||
|
|
||||||
|
auto sr = rb.add_rule("stone" + std::to_string(i), "air");
|
||||||
|
auto sfn = [](const std::string& t) { return t == "air"; };
|
||||||
|
|
||||||
|
switch (i % 3)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
ar.bottom_left(afn);
|
||||||
|
sr.top_right(sfn);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
ar.bottom_middle(afn);
|
||||||
|
sr.top_middle(sfn);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
ar.bottom_right(afn);
|
||||||
|
sr.top_left(sfn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 128; i < 255; i++)
|
||||||
|
{
|
||||||
|
auto ar = rb.add_rule("air", "stone" + std::to_string(i + 1));
|
||||||
|
auto afn
|
||||||
|
= [i](const std::string& t) { return t == "stone" + std::to_string(i); };
|
||||||
|
|
||||||
|
auto sr = rb.add_rule("stone" + std::to_string(i), "air");
|
||||||
|
auto sfn = [](const std::string& t) { return t == "air"; };
|
||||||
|
|
||||||
|
switch (i % 3)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
ar.top_left(afn);
|
||||||
|
sr.bottom_right(sfn);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
ar.top_middle(afn);
|
||||||
|
sr.bottom_middle(sfn);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
ar.top_right(afn);
|
||||||
|
sr.bottom_left(sfn);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto s = rb.build(WIDTH, HEIGHT, "air");
|
auto s = rb.build(WIDTH, HEIGHT, "air");
|
||||||
|
|
||||||
@ -77,20 +139,17 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
float x, y;
|
float x, y;
|
||||||
int state;
|
int state;
|
||||||
if (time > 1 / 1000.0f)
|
time = 0;
|
||||||
|
s.update();
|
||||||
|
|
||||||
|
if ((state = SDL_GetMouseState(&x, &y)))
|
||||||
{
|
{
|
||||||
time = 0;
|
int ix = x * WIDTH / WINDOW_WIDTH;
|
||||||
s.update();
|
int iy = y * HEIGHT / WINDOW_HEIGHT;
|
||||||
|
|
||||||
if ((state = SDL_GetMouseState(&x, &y)))
|
if (ix >= 0 && ix < WIDTH && iy >= 0 && iy < HEIGHT)
|
||||||
{
|
{
|
||||||
int ix = x * WIDTH / WINDOW_WIDTH;
|
s.set(ix, iy, "stone0");
|
||||||
int iy = y * HEIGHT / WINDOW_HEIGHT;
|
|
||||||
|
|
||||||
if (ix >= 0 && ix < WIDTH && iy >= 0 && iy < HEIGHT)
|
|
||||||
{
|
|
||||||
s.set(ix, iy, state == 1 ? "stone1" : "stone2");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,13 +159,15 @@ int main(int argc, char** argv)
|
|||||||
for (int j = 0; j < HEIGHT; j++)
|
for (int j = 0; j < HEIGHT; j++)
|
||||||
{
|
{
|
||||||
memcpy(&static_cast<uint8_t*>(surface->pixels)[3 * (i + j * WIDTH)],
|
memcpy(&static_cast<uint8_t*>(surface->pixels)[3 * (i + j * WIDTH)],
|
||||||
lookup[s.get(i, j)], 3);
|
lookup_color(s.get(i, j)).c, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SDL_UnlockSurface(surface);
|
SDL_UnlockSurface(surface);
|
||||||
SDL_BlitSurfaceScaled(surface, nullptr, SDL_GetWindowSurface(window),
|
SDL_BlitSurfaceScaled(surface, nullptr, SDL_GetWindowSurface(window),
|
||||||
nullptr, SDL_SCALEMODE_NEAREST);
|
nullptr, SDL_SCALEMODE_NEAREST);
|
||||||
SDL_UpdateWindowSurface(window);
|
SDL_UpdateWindowSurface(window);
|
||||||
|
|
||||||
|
FrameMark;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_DestroySurface(surface);
|
SDL_DestroySurface(surface);
|
||||||
|
|||||||
271
src/sand.cpp
271
src/sand.cpp
@ -1,40 +1,59 @@
|
|||||||
#include "sand.h"
|
#include "sand.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <compare>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <tracy/Tracy.hpp>
|
||||||
|
|
||||||
using namespace sand;
|
using namespace sand;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
constexpr uint16_t OFFGRID_VALUE = 0;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T& binary_search(T element, T* elements, size_t begin, size_t end,
|
int binary_search(T element, const T* elements, size_t begin, size_t end,
|
||||||
auto (*fn)(T, T)->bool)
|
auto (*fn)(T, T)->std::strong_ordering)
|
||||||
{
|
{
|
||||||
if (end - begin == 1)
|
if (end - begin == 1)
|
||||||
{
|
{
|
||||||
return elements[begin];
|
if (fn(element, elements[begin]) == std::strong_ordering::equal)
|
||||||
|
{
|
||||||
|
return begin;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = begin + (end - begin) / 2;
|
size_t index = begin + (end - begin) / 2;
|
||||||
|
|
||||||
if (!fn(element, elements[index]) && !fn(elements[index], element))
|
auto comparison_result = fn(element, elements[index]);
|
||||||
{
|
|
||||||
return elements[index];
|
if (comparison_result == std::strong_ordering::less)
|
||||||
}
|
|
||||||
else if (fn(element, elements[index]))
|
|
||||||
{
|
|
||||||
return binary_search<T>(element, elements, index, end, fn);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
return binary_search<T>(element, elements, begin, index, fn);
|
return binary_search<T>(element, elements, begin, index, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (comparison_result == std::strong_ordering::greater)
|
||||||
|
{
|
||||||
|
return binary_search<T>(element, elements, index, end, fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
TypeBuilder::TypeBuilder() :
|
||||||
|
next_type_id(OFFGRID_VALUE)
|
||||||
|
{
|
||||||
|
add_type("offgrid");
|
||||||
|
}
|
||||||
|
|
||||||
TypeBuilder& TypeBuilder::add_type(const std::string& name)
|
TypeBuilder& TypeBuilder::add_type(const std::string& name)
|
||||||
{
|
{
|
||||||
if (!types.contains(name))
|
if (!types.contains(name))
|
||||||
@ -126,28 +145,84 @@ void RulesBuilder::finish_rule(const Rule& rule)
|
|||||||
{
|
{
|
||||||
unsigned __int128 neighbors = 0;
|
unsigned __int128 neighbors = 0;
|
||||||
|
|
||||||
neighbors += tl_type.id;
|
if (rule.matches[0])
|
||||||
|
{
|
||||||
|
neighbors += tl_type.id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += 0xFFFF;
|
||||||
|
}
|
||||||
neighbors <<= 16;
|
neighbors <<= 16;
|
||||||
|
|
||||||
neighbors += tm_type.id;
|
if (rule.matches[1])
|
||||||
|
{
|
||||||
|
neighbors += tm_type.id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += 0xFFFF;
|
||||||
|
}
|
||||||
neighbors <<= 16;
|
neighbors <<= 16;
|
||||||
|
|
||||||
neighbors += tr_type.id;
|
if (rule.matches[2])
|
||||||
|
{
|
||||||
|
neighbors += tr_type.id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += 0xFFFF;
|
||||||
|
}
|
||||||
neighbors <<= 16;
|
neighbors <<= 16;
|
||||||
|
|
||||||
neighbors += ml_type.id;
|
if (rule.matches[3])
|
||||||
|
{
|
||||||
|
neighbors += ml_type.id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += 0xFFFF;
|
||||||
|
}
|
||||||
neighbors <<= 16;
|
neighbors <<= 16;
|
||||||
|
|
||||||
neighbors += mr_type.id;
|
if (rule.matches[4])
|
||||||
|
{
|
||||||
|
neighbors += mr_type.id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += 0xFFFF;
|
||||||
|
}
|
||||||
neighbors <<= 16;
|
neighbors <<= 16;
|
||||||
|
|
||||||
neighbors += bl_type.id;
|
if (rule.matches[5])
|
||||||
|
{
|
||||||
|
neighbors += bl_type.id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += 0xFFFF;
|
||||||
|
}
|
||||||
neighbors <<= 16;
|
neighbors <<= 16;
|
||||||
|
|
||||||
neighbors += bm_type.id;
|
if (rule.matches[6])
|
||||||
|
{
|
||||||
|
neighbors += bm_type.id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += 0xFFFF;
|
||||||
|
}
|
||||||
neighbors <<= 16;
|
neighbors <<= 16;
|
||||||
|
|
||||||
neighbors += br_type.id;
|
if (rule.matches[7])
|
||||||
|
{
|
||||||
|
neighbors += br_type.id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
if (!rules.contains(rule.source))
|
if (!rules.contains(rule.source))
|
||||||
{
|
{
|
||||||
@ -157,21 +232,61 @@ void RulesBuilder::finish_rule(const Rule& rule)
|
|||||||
rules[rule.source].push_back(
|
rules[rule.source].push_back(
|
||||||
{ neighbors, rule.to });
|
{ neighbors, rule.to });
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (!rule.matches[7])
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // bottom right
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (!rule.matches[6])
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // bottom middle
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (!rule.matches[5])
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // bottom left
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (!rule.matches[4])
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // middle right
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (!rule.matches[3])
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // middle left
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (!rule.matches[2])
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // top right
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (!rule.matches[1])
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // top middle
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (!rule.matches[0])
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // top left
|
||||||
}
|
}
|
||||||
|
|
||||||
Rule::~Rule() { builder.finish_rule(*this); }
|
Rule::~Rule() { builder.finish_rule(*this); }
|
||||||
@ -253,6 +368,12 @@ Sand::Sand(const RulesBuilder& builder, uint16_t width, uint16_t height,
|
|||||||
{
|
{
|
||||||
default_conversions[type.id] = type.default_result;
|
default_conversions[type.id] = type.default_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cnt = 0;
|
||||||
|
for (const auto& [key, elem] : rules)
|
||||||
|
{
|
||||||
|
cnt += elem.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sand::set(uint16_t x, uint16_t y, const std::string& type)
|
void Sand::set(uint16_t x, uint16_t y, const std::string& type)
|
||||||
@ -267,6 +388,8 @@ uint16_t Sand::get(uint16_t x, uint16_t y)
|
|||||||
|
|
||||||
void Sand::update()
|
void Sand::update()
|
||||||
{
|
{
|
||||||
|
ZoneScoped;
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
#pragma omp parallel for private(n)
|
#pragma omp parallel for private(n)
|
||||||
for (n = 0; n < width * height; n++)
|
for (n = 0; n < width * height; n++)
|
||||||
@ -274,73 +397,133 @@ void Sand::update()
|
|||||||
int i = n % width;
|
int i = n % width;
|
||||||
int j = n / height;
|
int j = n / height;
|
||||||
|
|
||||||
auto& current_rule = rules[get(i, j)];
|
|
||||||
|
|
||||||
unsigned __int128 neighbors = 0;
|
unsigned __int128 neighbors = 0;
|
||||||
if (i > 0 && j > 0)
|
if (i > 0 && j > 0)
|
||||||
{
|
{
|
||||||
neighbors += get(i - 1, j - 1);
|
neighbors += get(i - 1, j - 1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += OFFGRID_VALUE;
|
||||||
|
}
|
||||||
neighbors <<= 16;
|
neighbors <<= 16;
|
||||||
|
|
||||||
if (j > 0)
|
if (j > 0)
|
||||||
{
|
{
|
||||||
neighbors += get(i, j - 1);
|
neighbors += get(i, j - 1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += OFFGRID_VALUE;
|
||||||
|
}
|
||||||
neighbors <<= 16;
|
neighbors <<= 16;
|
||||||
|
|
||||||
if (i < width - 1 && j > 0)
|
if (i < width - 1 && j > 0)
|
||||||
{
|
{
|
||||||
neighbors += get(i + 1, j - 1);
|
neighbors += get(i + 1, j - 1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += OFFGRID_VALUE;
|
||||||
|
}
|
||||||
neighbors <<= 16;
|
neighbors <<= 16;
|
||||||
|
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
{
|
{
|
||||||
neighbors += get(i - 1, j);
|
neighbors += get(i - 1, j);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += OFFGRID_VALUE;
|
||||||
|
}
|
||||||
neighbors <<= 16;
|
neighbors <<= 16;
|
||||||
|
|
||||||
if (i < width - 1)
|
if (i < width - 1)
|
||||||
{
|
{
|
||||||
neighbors += get(i + 1, j);
|
neighbors += get(i + 1, j);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += OFFGRID_VALUE;
|
||||||
|
}
|
||||||
neighbors <<= 16;
|
neighbors <<= 16;
|
||||||
|
|
||||||
if (i > 0 && j < height - 1)
|
if (i > 0 && j < height - 1)
|
||||||
{
|
{
|
||||||
neighbors += get(i - 1, j + 1);
|
neighbors += get(i - 1, j + 1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += OFFGRID_VALUE;
|
||||||
|
}
|
||||||
neighbors <<= 16;
|
neighbors <<= 16;
|
||||||
|
|
||||||
if (j < height - 1)
|
if (j < height - 1)
|
||||||
{
|
{
|
||||||
neighbors += get(i, j + 1);
|
neighbors += get(i, j + 1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
neighbors += OFFGRID_VALUE;
|
||||||
|
}
|
||||||
neighbors <<= 16;
|
neighbors <<= 16;
|
||||||
|
|
||||||
if (i < width - 1 && j < height - 1)
|
if (i < width - 1 && j < height - 1)
|
||||||
{
|
{
|
||||||
neighbors += get(i + 1, j + 1);
|
neighbors += get(i + 1, j + 1);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
uint16_t result = default_conversions[get(i, j)];
|
|
||||||
if (!current_rule.empty())
|
|
||||||
{
|
{
|
||||||
std::pair<unsigned __int128, uint16_t> element = { neighbors, 0 };
|
neighbors += OFFGRID_VALUE;
|
||||||
bool (*fn)(decltype(element), decltype(element))
|
|
||||||
= [](decltype(element) a, decltype(element) b) -> bool
|
|
||||||
{ return a.first > b.first; };
|
|
||||||
const auto& found = binary_search(element, current_rule.data(), 0,
|
|
||||||
current_rule.size(), fn);
|
|
||||||
if (found.first == neighbors)
|
|
||||||
{
|
|
||||||
result = found.second;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
elements[i + j * width + !iter * width * height] = result;
|
elements[i + j * width + !iter * width * height]
|
||||||
|
= apply_rule(get(i, j), neighbors);
|
||||||
}
|
}
|
||||||
|
|
||||||
iter = !iter;
|
iter = !iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t Sand::apply_rule(uint16_t tile, unsigned __int128 key) const
|
||||||
|
{
|
||||||
|
if (rules.contains(tile))
|
||||||
|
{
|
||||||
|
auto& rules_for_tile = rules.at(tile);
|
||||||
|
|
||||||
|
if (!rules_for_tile.empty())
|
||||||
|
{
|
||||||
|
for (int mask = 0; mask < 256; mask++)
|
||||||
|
{
|
||||||
|
std::pair<unsigned __int128, uint16_t> element
|
||||||
|
= { apply_mask(key, mask), 0 };
|
||||||
|
std::strong_ordering (*fn)(decltype(element), decltype(element))
|
||||||
|
= [](auto a, auto b) { return a.first <=> b.first; };
|
||||||
|
|
||||||
|
auto found = binary_search(element, rules_for_tile.data(), 0,
|
||||||
|
rules_for_tile.size(), fn);
|
||||||
|
if (found >= 0)
|
||||||
|
{
|
||||||
|
return rules_for_tile[found].second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_conversions.at(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned __int128 Sand::apply_mask(unsigned __int128 key, uint8_t mask)
|
||||||
|
{
|
||||||
|
unsigned __int128 any = 0xFFFF;
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
if (mask & 1)
|
||||||
|
{
|
||||||
|
key |= any;
|
||||||
|
}
|
||||||
|
|
||||||
|
mask >>= 1;
|
||||||
|
any <<= 16;
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|||||||
1
third/tracy
Submodule
1
third/tracy
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 25f09bee2cdb680d025d150188925e116fc1e8d4
|
||||||
Loading…
x
Reference in New Issue
Block a user