OpenTTD Source 20251213-master-g1091fa6071
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
10#include "../stdafx.h"
11#include "random_func.hpp"
12#include "../debug.h"
13
14#ifdef RANDOM_DEBUG
15#include "../network/network.h"
16#include "../network/network_server.h"
17#include "../network/network_internal.h"
18#include "../company_func.h"
19#include "../fileio_func.h"
20#include "../timer/timer_game_calendar.h"
21#endif /* RANDOM_DEBUG */
22
23#if defined(_WIN32)
24# include <windows.h>
25# include <bcrypt.h>
26#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__)
27/* No includes required. */
28#elif defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25)))
29# include <sys/random.h>
30#elif defined(__EMSCRIPTEN__)
31# include <emscripten.h>
32#endif
33
34#include "../safeguards.h"
35
37
43{
44 const uint32_t s = this->state[0];
45 const uint32_t t = this->state[1];
46
47 this->state[0] = s + std::rotr(t ^ 0x1234567F, 7) + 1;
48 return this->state[1] = std::rotr(s, 3) - 1;
49}
50
55void Randomizer::SetSeed(uint32_t seed)
56{
57 this->state[0] = seed;
58 this->state[1] = seed;
59}
60
65void SetRandomSeed(uint32_t seed)
66{
67 _random.SetSeed(seed);
68 _interactive_random.SetSeed(seed * 0x1234567);
69}
70
71#ifdef RANDOM_DEBUG
72uint32_t Random(const std::source_location location)
73{
74 if (_networking && (!_network_server || (NetworkClientSocket::IsValidID(0) && NetworkClientSocket::Get(0)->status != NetworkClientSocket::STATUS_INACTIVE))) {
75 Debug(random, 0, "{:08x}; {:02x}; {:04x}; {:02x}; {}:{}", TimerGameEconomy::date, TimerGameEconomy::date_fract, _frame_counter, _current_company, location.file_name(), location.line());
76 }
77
78 return _random.Next();
79}
80#endif /* RANDOM_DEBUG */
81
94void RandomBytesWithFallback(std::span<uint8_t> buf)
95{
96#if defined(_WIN32)
97 auto res = BCryptGenRandom(nullptr, static_cast<PUCHAR>(buf.data()), static_cast<ULONG>(buf.size()), BCRYPT_USE_SYSTEM_PREFERRED_RNG);
98 if (res >= 0) return;
99#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
100 arc4random_buf(buf.data(), buf.size());
101 return;
102#elif defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25)))
103 auto res = getrandom(buf.data(), buf.size(), 0);
104 if (res > 0 && static_cast<size_t>(res) == buf.size()) return;
105#elif defined(__EMSCRIPTEN__)
106 auto res = EM_ASM_INT({
107 var buf = $0;
108 var bytes = $1;
109
110 var crypto = window.crypto;
111 if (crypto === undefined || crypto.getRandomValues === undefined) {
112 return -1;
113 }
114
115 crypto.getRandomValues(Module.HEAPU8.subarray(buf, buf + bytes));
116 return 1;
117 }, buf.data(), buf.size());
118 if (res > 0) return;
119#else
120# warning "No cryptographically-strong random generator available; using a fallback instead"
121#endif
122
123 static bool warned_once = false;
124 Debug(misc, warned_once ? 1 : 0, "Cryptographically-strong random generator unavailable; using fallback");
125 warned_once = true;
126
127 for (uint i = 0; i < buf.size(); i++) {
128 buf[i] = static_cast<uint8_t>(InteractiveRandom());
129 }
130}
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,...)
Output a line of debugging information.
Definition debug.h:37
@ Random
Randomise borders.
uint32_t _frame_counter
The current frame.
Definition network.cpp:79
bool _networking
are we in networking mode?
Definition network.cpp:66
bool _network_server
network-server is active
Definition network.cpp:67
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.