-
Notifications
You must be signed in to change notification settings - Fork 0
feat(simulation): thermal diffusion, transformation rules, and projected appearances #89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
42781dc
feat(simulation): add WorldRuleEngine with 8 default transformation r…
mannie-exe 1e40d3e
feat(simulation): add TransformationPass with thermal diffusion and r…
mannie-exe c72bca2
fix(simulation): address PR #89 review findings across rule engine an…
mannie-exe a6389d5
fix(simulation): eliminate density duplication and activate tracker a…
mannie-exe f6e7390
fix(simulation): address PR #89 round 3 review findings
mannie-exe 1d1de6b
fix(simulation): cool R7 quench output below melt threshold
mannie-exe a5c694b
fix(simulation): thread frameIndex into RNG seed for stochastic rules
mannie-exe File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| #pragma once | ||
| #include "fabric/platform/JobScheduler.hh" | ||
| #include "recurse/simulation/ChunkActivityTracker.hh" | ||
| #include "recurse/simulation/GhostCells.hh" | ||
| #include "recurse/simulation/MaterialRegistry.hh" | ||
| #include "recurse/simulation/SimulationGrid.hh" | ||
| #include "recurse/simulation/WorldRuleEngine.hh" | ||
| #include <atomic> | ||
| #include <cstdint> | ||
| #include <random> | ||
| #include <vector> | ||
|
|
||
| namespace recurse::simulation { | ||
|
|
||
| struct ActiveChunkEntry; // forward declare | ||
|
|
||
| struct SubRegionActivation { | ||
| ChunkCoord pos; | ||
| int lx, ly, lz; | ||
| }; | ||
|
|
||
| class TransformationPass { | ||
| public: | ||
| struct Config { | ||
| float diffusionRate = 0.25f; | ||
| int maxTransformsPerChunk = K_MAX_TRANSFORMS_PER_CHUNK; | ||
| }; | ||
|
|
||
| TransformationPass(const WorldRuleEngine& rules, const MaterialRegistry& registry, SimulationGrid& grid, | ||
| const GhostCellManager& ghosts, ChunkActivityTracker& tracker); | ||
|
|
||
| /// Execute Phase 3c across all active chunks. | ||
| void execute(const std::vector<ActiveChunkEntry>& active, fabric::JobScheduler& scheduler, int64_t worldSeed, | ||
| uint64_t frameIndex); | ||
|
|
||
| /// Per-chunk execution (single-threaded; flushes activations to tracker directly). | ||
| void executeChunk(ChunkCoord pos, std::mt19937& rng); | ||
|
|
||
| Config& config() { return config_; } | ||
|
|
||
| /// Stats from last execute() call. | ||
| int totalTransforms() const { return totalTransforms_.load(std::memory_order_relaxed); } | ||
|
|
||
| private: | ||
| const WorldRuleEngine& rules_; | ||
| const MaterialRegistry& registry_; | ||
| SimulationGrid& grid_; | ||
| const GhostCellManager& ghosts_; | ||
| ChunkActivityTracker& tracker_; | ||
| Config config_; | ||
| std::atomic<int> totalTransforms_{0}; | ||
|
|
||
| void thermalKernel(ChunkCoord pos); | ||
| void executeChunk(ChunkCoord pos, std::mt19937& rng, std::vector<SubRegionActivation>& activations); | ||
| int ruleEvaluation(ChunkCoord pos, std::mt19937& rng, std::vector<SubRegionActivation>& activations); | ||
| VoxelCell readCell(ChunkCoord pos, int lx, int ly, int lz) const; | ||
| }; | ||
|
|
||
| } // namespace recurse::simulation |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| #pragma once | ||
| #include "recurse/simulation/VoxelMaterial.hh" | ||
| #include <cstdint> | ||
| #include <span> | ||
| #include <vector> | ||
|
|
||
| namespace recurse::simulation { | ||
|
|
||
| /// Flat 14-byte rule for world simulation behaviors. | ||
| /// Locked design: Decision 2 (2026-03-22). No nested types. | ||
| /// Tag is plain uint8_t for debugging (0=Thermal, 1=Contact, 2=Gravity). | ||
| /// | ||
| /// Sentinel conventions for result fields: | ||
| /// resultEssenceA/B = 255: leave essence unchanged | ||
| /// resultPhaseA/B = Phase::Unchanged: leave phase unchanged | ||
| /// resultTempA/B = 0: leave temperature unchanged (temp cannot be set to literal zero) | ||
| struct WorldRule { | ||
| uint8_t essenceIdxA; // self (255 = wildcard) | ||
| uint8_t essenceIdxB; // neighbor (255 = self-transform) | ||
| Phase requiredPhaseA{Phase::Unchanged}; | ||
| uint8_t temperatureMin{0}; | ||
| uint8_t temperatureMax{255}; | ||
| uint8_t resultEssenceA{255}; // 255 = unchanged | ||
| uint8_t resultEssenceB{255}; // 255 = unchanged | ||
| Phase resultPhaseA{Phase::Unchanged}; | ||
| Phase resultPhaseB{Phase::Unchanged}; | ||
| uint8_t resultTempA{0}; // 0 = unchanged | ||
| uint8_t resultTempB{0}; // 0 = unchanged | ||
| uint8_t probability{255}; // 0-255, 255 = always fire | ||
| uint8_t priority{128}; // higher = evaluated first | ||
| uint8_t tag{0}; // system origin for debugging | ||
| }; | ||
| static_assert(sizeof(WorldRule) == 14, "WorldRule must be exactly 14 bytes"); | ||
|
|
||
| /// Configurable max transformations per chunk per tick. | ||
| inline constexpr int K_MAX_TRANSFORMS_PER_CHUNK = 64; | ||
|
|
||
| class WorldRuleEngine { | ||
| public: | ||
| WorldRuleEngine(); | ||
|
|
||
| /// Add a rule to the engine. Rules are kept sorted by priority (descending). | ||
| void addRule(WorldRule rule); | ||
|
|
||
| /// Query matching rules for a cell pair at a given temperature. | ||
| /// Appends matching rules (sorted by priority, highest first) to caller-owned buffer. | ||
| /// selfEssence: essenceIdx of the cell being evaluated | ||
| /// neighborEssence: essenceIdx of the adjacent cell (255 for self-transform queries) | ||
| /// selfPhase: phase of the cell being evaluated | ||
| /// temperature: temperature byte of the cell | ||
| /// results: caller-owned output buffer (cleared then filled) | ||
| void query(uint8_t selfEssence, uint8_t neighborEssence, Phase selfPhase, uint8_t temperature, | ||
| std::vector<WorldRule>& results) const; | ||
|
|
||
| /// Number of registered rules. | ||
| size_t ruleCount() const; | ||
|
|
||
| /// Access to all rules (for testing/debugging). | ||
| std::span<const WorldRule> allRules() const; | ||
|
|
||
| private: | ||
| std::vector<WorldRule> rules_; | ||
|
|
||
| void sortByPriority(); | ||
| bool matches(const WorldRule& rule, uint8_t selfEssence, uint8_t neighborEssence, Phase selfPhase, | ||
| uint8_t temperature) const; | ||
| }; | ||
|
|
||
| } // namespace recurse::simulation | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.