JustAnotherDnDGame 0.1.0
Jeu de rôle tactique au d20, vue de dessus, en C++/Qt
Loading...
Searching...
No Matches
DeterministicRandom.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Valentin Eloy
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#pragma once
5
6#include <cstdint>
7
13
14namespace core {
15
25[[nodiscard]] constexpr std::uint64_t splitMix64(std::uint64_t value) noexcept {
26 value = (value ^ (value >> 30)) * 0xBF58476D1CE4E5B9ULL;
27 value = (value ^ (value >> 27)) * 0x94D049BB133111EBULL;
28 return value ^ (value >> 31);
29}
30
43[[nodiscard]] constexpr std::uint64_t deriveSeed(std::uint64_t baseSeed, std::uint64_t step,
44 std::uint64_t entityId) noexcept {
45 std::uint64_t seed = splitMix64(baseSeed);
46 seed = splitMix64(seed ^ step);
47 seed = splitMix64(seed ^ entityId);
48 return seed;
49}
50
60public:
62 explicit DeterministicRandom(std::uint64_t seed) noexcept : _state(seed) {}
63
65 [[nodiscard]] std::uint32_t nextUInt32() noexcept {
66 _state += 0x9E3779B97F4A7C15ULL;
67 return static_cast<std::uint32_t>(splitMix64(_state) >> 32);
68 }
69
71 [[nodiscard]] float nextFloat01() noexcept {
72 constexpr float UINT32_RANGE = 4294967296.0f; // 2^32
73 return static_cast<float>(nextUInt32()) / UINT32_RANGE;
74 }
75
83 [[nodiscard]] float nextRange(float min, float max) noexcept {
84 return min + nextFloat01() * (max - min);
85 }
86
106 [[nodiscard]] int nextInt(int min, int max) noexcept {
107 if (max <= min) {
108 return min;
109 }
110 const std::uint32_t etendue = static_cast<std::uint32_t>(max - min) + 1U;
111 // `2^32 mod etendue` : le nombre de valeurs en trop, celles qui n'ont pas de contrepartie
112 // sur tout l'intervalle. On rejette la queue BASSE, `[0, reste[`, et non la haute.
113 //
114 // Rejeter la queue haute serait plus naturel à lire — « au-delà du dernier multiple
115 // complet » — mais ce seuil vaut `2^32` quand `etendue` divise `2^32`, et `2^32` ne tient
116 // pas dans un `std::uint32_t` : il retombe à 0, la condition devient toujours vraie, et la
117 // boucle ne se termine jamais. Le défaut ne se voit que sur les **puissances de deux** :
118 // un d6 et un d20 passent, un d8 bloque. C'est un test de rejouabilité sur 3d8 qui l'a
119 // trouvé, pas une relecture.
120 const std::uint32_t reste = (std::uint32_t{0} - etendue) % etendue;
121 std::uint32_t tirage = nextUInt32();
122 while (tirage < reste) {
123 tirage = nextUInt32();
124 }
125 return min + static_cast<int>(tirage % etendue);
126 }
127
128private:
129 std::uint64_t _state;
130};
131
132} // namespace core
float nextRange(float min, float max) noexcept
Prochain flottant dans [min, max].
Definition DeterministicRandom.h:83
std::uint64_t _state
Definition DeterministicRandom.h:129
std::uint32_t nextUInt32() noexcept
Definition DeterministicRandom.h:65
float nextFloat01() noexcept
Definition DeterministicRandom.h:71
DeterministicRandom(std::uint64_t seed) noexcept
Definition DeterministicRandom.h:62
int nextInt(int min, int max) noexcept
Prochain entier dans [min, max], bornes comprises, sans biais modulo.
Definition DeterministicRandom.h:106
Espace de noms du moteur et de la logique de jeu.
Definition Bootstrap.h:9
constexpr std::uint64_t deriveSeed(std::uint64_t baseSeed, std::uint64_t step, std::uint64_t entityId) noexcept
Combine une graine de base, un numéro de pas et un identifiant reproductible en une graine unique,...
Definition DeterministicRandom.h:43
constexpr std::uint64_t splitMix64(std::uint64_t value) noexcept
Mélange (SplitMix64) un entier 64 bits en une valeur bien distribuée.
Definition DeterministicRandom.h:25