OpenTTD Source 20241224-master-gf74b0cf984
random_func.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "../stdafx.h"
11#include "random_func.hpp"
12#include "bitmath_func.hpp"
13#include "../debug.h"
14
15#ifdef RANDOM_DEBUG
16#include "../network/network.h"
17#include "../network/network_server.h"
18#include "../network/network_internal.h"
19#include "../company_func.h"
20#include "../fileio_func.h"
21#include "../timer/timer_game_calendar.h"
22#endif /* RANDOM_DEBUG */
23
24#if defined(_WIN32)
25# include <windows.h>
26# include <bcrypt.h>
27#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
28// No includes required.
29#elif defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25)))
30# include <sys/random.h>
31#elif defined(__EMSCRIPTEN__)
32# include <emscripten.h>
33#endif
34
35#include "../safeguards.h"
36
38
44{
45 const uint32_t s = this->state[0];
46 const uint32_t t = this->state[1];
47
48 this->state[0] = s + std::rotr(t ^ 0x1234567F, 7) + 1;
49 return this->state[1] = std::rotr(s, 3) - 1;
50}
51
56void Randomizer::SetSeed(uint32_t seed)
57{
58 this->state[0] = seed;
59 this->state[1] = seed;
60}
61
66void SetRandomSeed(uint32_t seed)
67{
68 _random.SetSeed(seed);
69 _interactive_random.SetSeed(seed * 0x1234567);
70}
71
72#ifdef RANDOM_DEBUG
73uint32_t Random(const std::source_location location)
74{
75 if (_networking && (!_network_server || (NetworkClientSocket::IsValidID(0) && NetworkClientSocket::Get(0)->status != NetworkClientSocket::STATUS_INACTIVE))) {
76 Debug(random, 0, "{:08x}; {:02x}; {:04x}; {:02x}; {}:{}", TimerGameEconomy::date, TimerGameEconomy::date_fract, _frame_counter, (uint8_t)_current_company, location.file_name(), location.line());
77 }
78
79 return _random.Next();
80}
81#endif /* RANDOM_DEBUG */
82
95void RandomBytesWithFallback(std::span<uint8_t> buf)
96{
97#if defined(_WIN32)
98 auto res = BCryptGenRandom(nullptr, static_cast<PUCHAR>(buf.data()), static_cast<ULONG>(buf.size()), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
99 if (res >= 0) return;
100#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
101 arc4random_buf(buf.data(), buf.size());
102 return;
103#elif defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25)))
104 auto res = getrandom(buf.data(), buf.size(), 0);
105 if (res > 0 && static_cast<size_t>(res) == buf.size()) return;
106#elif defined(__EMSCRIPTEN__)
107 auto res = EM_ASM_INT({
108 var buf = $0;
109 var bytes = $1;
110
111 var crypto = window.crypto;
112 if (crypto === undefined || crypto.getRandomValues === undefined) {
113 return -1;
114 }
115
116 crypto.getRandomValues(Module.HEAPU8.subarray(buf, buf + bytes));
117 return 1;
118 }, buf.data(), buf.size());
119 if (res > 0) return;
120#else
121# warning "No cryptographically-strong random generator available; using a fallback instead"
122#endif
123
124 static bool warned_once = false;
125 Debug(misc, warned_once ? 1 : 0, "Cryptographically-strong random generator unavailable; using fallback");
126 warned_once = true;
127
128 for (uint i = 0; i < buf.size(); i++) {
129 buf[i] = static_cast<uint8_t>(InteractiveRandom());
130 }
131}
Functions related to bit mathematics.
static Date date
Current date in days (day counter).
static DateFract date_fract
Fractional part of the day.
CompanyID _current_company
Company currently doing an action.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition debug.h:37
uint32_t _frame_counter
The current frame.
Definition network.cpp:78
bool _networking
are we in networking mode?
Definition network.cpp:65
bool _network_server
network-server is active
Definition network.cpp:66
Randomizer _random
Random used in the game state calculations.
void RandomBytesWithFallback(std::span< uint8_t > buf)
Fill the given buffer with random bytes.
Randomizer _interactive_random
Random used everywhere else, where it does not (directly) influence the game state.
void SetRandomSeed(uint32_t seed)
(Re)set the state of the random number generators.
Pseudo random number generator.
Structure to encapsulate the pseudo random number generators.
void SetSeed(uint32_t seed)
(Re)set the state of the random number generator.
uint32_t state[2]
The state of the randomizer.
uint32_t Next()
Generate the next pseudo random number.