commit
72f73661ae
@ -35,6 +35,7 @@ Subsections:
|
||||
- [pathfinding](scripting/builtins/libpathfinding.md)
|
||||
- [player](scripting/builtins/libplayer.md)
|
||||
- [quat](scripting/builtins/libquat.md)
|
||||
- [random](scripting/builtins/librandom.md)
|
||||
- [rules](scripting/builtins/librules.md)
|
||||
- [time](scripting/builtins/libtime.md)
|
||||
- [utf8](scripting/builtins/libutf8.md)
|
||||
|
||||
38
doc/en/scripting/builtins/librandom.md
Normal file
38
doc/en/scripting/builtins/librandom.md
Normal file
@ -0,0 +1,38 @@
|
||||
# *random* library
|
||||
|
||||
A library of functions for generating random numbers.
|
||||
|
||||
## Non-deterministic numbers
|
||||
|
||||
```lua
|
||||
-- Generates a random number in the range [0..1)
|
||||
random.random() --> number
|
||||
|
||||
-- Generates a random integer in the range [0..n]
|
||||
random.random(n) --> number
|
||||
|
||||
-- Generates a random integer in the range [a..b]
|
||||
random.random(a, b) --> number
|
||||
|
||||
-- Generates a random byte array of length n
|
||||
random.bytes(n: number) -> Bytearray
|
||||
|
||||
-- Generates a UUID version 4
|
||||
random.uuid() -> str
|
||||
```
|
||||
|
||||
## Pseudorandom numbers
|
||||
|
||||
The library provides the Random class - a generator with its own isolated state.
|
||||
|
||||
```lua
|
||||
local rng = random.Random()
|
||||
|
||||
-- Used similarly to math.random
|
||||
local a = rng:random() --> [0..1)
|
||||
local b = rng:random(10) --> [0..10]
|
||||
local c = rng:random(5, 20) --> [5..20]
|
||||
|
||||
-- Sets the generator state to generate a reproducible sequence of random numbers
|
||||
rng:seed(42)
|
||||
```
|
||||
@ -35,6 +35,7 @@
|
||||
- [pathfinding](scripting/builtins/libpathfinding.md)
|
||||
- [player](scripting/builtins/libplayer.md)
|
||||
- [quat](scripting/builtins/libquat.md)
|
||||
- [random](scripting/builtins/librandom.md)
|
||||
- [rules](scripting/builtins/librules.md)
|
||||
- [time](scripting/builtins/libtime.md)
|
||||
- [utf8](scripting/builtins/libutf8.md)
|
||||
|
||||
38
doc/ru/scripting/builtins/librandom.md
Normal file
38
doc/ru/scripting/builtins/librandom.md
Normal file
@ -0,0 +1,38 @@
|
||||
# Библиотека *random*
|
||||
|
||||
Библиотека функций для генерации случайный чисел.
|
||||
|
||||
## Недетерминированные числа
|
||||
|
||||
```lua
|
||||
-- Генерирует случайное число в диапазоне [0..1)
|
||||
random.random() --> number
|
||||
|
||||
-- Генерирует случайное целое число в диапазоне [0..n]
|
||||
random.random(n) --> number
|
||||
|
||||
-- Генерирует случайное целое число в диапазоне [a..b]
|
||||
random.random(a, b) --> number
|
||||
|
||||
-- Генерирует случайный массив байт длиной n
|
||||
random.bytes(n: number) -> Bytearray
|
||||
|
||||
-- Генерирует UUID версии 4
|
||||
random.uuid() -> str
|
||||
```
|
||||
|
||||
## Псевдослучайные числа
|
||||
|
||||
Библиотека предоставляет класс Random - генератор с собственным изолированным состоянием.
|
||||
|
||||
```lua
|
||||
local rng = random.Random()
|
||||
|
||||
-- Используется аналогично math.random
|
||||
local a = rng:random() --> [0..1)
|
||||
local b = rng:random(10) --> [0..10]
|
||||
local c = rng:random(5, 20) --> [5..20]
|
||||
|
||||
-- Устанавливает состояние генератора для генерации воспроизводимой последовательности случайных чисел
|
||||
rng:seed(42)
|
||||
```
|
||||
35
res/modules/internal/random_generator.lua
Normal file
35
res/modules/internal/random_generator.lua
Normal file
@ -0,0 +1,35 @@
|
||||
local Random = {}
|
||||
|
||||
local M = 2 ^ 31
|
||||
local A = 1103515245
|
||||
local C = 12345
|
||||
|
||||
function Random.randint(self)
|
||||
self._seed = (A * self._seed + C) % M
|
||||
return self._seed
|
||||
end
|
||||
|
||||
function Random.random(self, a, b)
|
||||
local num = self:randint() % M / M
|
||||
if b then
|
||||
return math.floor(num * (b - a + 1) + a)
|
||||
elseif a then
|
||||
return math.floor(num * a + 1)
|
||||
else
|
||||
return num
|
||||
end
|
||||
end
|
||||
|
||||
function Random.seed(self, number)
|
||||
if type(number) ~= "number" then
|
||||
error("number expected")
|
||||
end
|
||||
self._seed = number
|
||||
end
|
||||
|
||||
return function(seed)
|
||||
if seed and type(seed) ~= "number" then
|
||||
error("number expected")
|
||||
end
|
||||
return setmetatable({_seed = seed or random.random(M)}, {__index = Random})
|
||||
end
|
||||
@ -668,3 +668,5 @@ end
|
||||
|
||||
bit.compile = require "core:bitwise/compiler"
|
||||
bit.execute = require "core:bitwise/executor"
|
||||
|
||||
random.Random = require "core:internal/random_generator"
|
||||
|
||||
@ -42,6 +42,7 @@ extern const luaL_Reg pathfindinglib[];
|
||||
extern const luaL_Reg playerlib[];
|
||||
extern const luaL_Reg posteffectslib[]; // gfx.posteffects
|
||||
extern const luaL_Reg quatlib[];
|
||||
extern const luaL_Reg randomlib[];
|
||||
extern const luaL_Reg text3dlib[]; // gfx.text3d
|
||||
extern const luaL_Reg timelib[];
|
||||
extern const luaL_Reg tomllib[];
|
||||
|
||||
46
src/logic/scripting/lua/libs/librandom.cpp
Normal file
46
src/logic/scripting/lua/libs/librandom.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
#include "api_lua.hpp"
|
||||
|
||||
#include "util/random.hpp"
|
||||
|
||||
static std::random_device random_device;
|
||||
|
||||
static int l_random(lua::State* L) {
|
||||
int argc = lua::gettop(L);
|
||||
|
||||
auto randomEngine = util::seeded_random_engine(random_device);
|
||||
if (argc == 0) {
|
||||
std::uniform_real_distribution<> dist(0.0, 1.0);
|
||||
return lua::pushnumber(L, dist(randomEngine));
|
||||
} else if (argc == 1) {
|
||||
std::uniform_int_distribution<integer_t> dist(1, lua::tointeger(L, 1));
|
||||
return lua::pushinteger(L, dist(randomEngine));
|
||||
} else {
|
||||
std::uniform_int_distribution<integer_t> dist(
|
||||
lua::tointeger(L, 1), lua::tointeger(L, 2)
|
||||
);
|
||||
return lua::pushinteger(L, dist(randomEngine));
|
||||
}
|
||||
}
|
||||
|
||||
static int l_bytes(lua::State* L) {
|
||||
size_t size = lua::tointeger(L, 1);
|
||||
|
||||
auto randomEngine = util::seeded_random_engine(random_device);
|
||||
static std::uniform_int_distribution<integer_t> dist(0, 0xFF);
|
||||
std::vector<ubyte> bytes (size);
|
||||
for (size_t i = 0; i < bytes.size(); i++) {
|
||||
bytes[i] = dist(randomEngine);
|
||||
}
|
||||
return lua::create_bytearray(L, bytes);
|
||||
}
|
||||
|
||||
static int l_uuid(lua::State* L) {
|
||||
return lua::pushlstring(L, util::generate_uuid());
|
||||
}
|
||||
|
||||
const luaL_Reg randomlib[] = {
|
||||
{"random", lua::wrap<l_random>},
|
||||
{"bytes", lua::wrap<l_bytes>},
|
||||
{"uuid", lua::wrap<l_uuid>},
|
||||
{NULL, NULL}
|
||||
};
|
||||
@ -51,6 +51,7 @@ static void create_libs(State* L, StateType stateType) {
|
||||
openlib(L, "mat4", mat4lib);
|
||||
openlib(L, "pack", packlib);
|
||||
openlib(L, "quat", quatlib);
|
||||
openlib(L, "random", randomlib);
|
||||
openlib(L, "toml", tomllib);
|
||||
openlib(L, "utf8", utf8lib);
|
||||
openlib(L, "vec2", vec2lib);
|
||||
|
||||
44
src/util/random.cpp
Normal file
44
src/util/random.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "random.hpp"
|
||||
|
||||
#include <random>
|
||||
|
||||
static std::random_device random_device;
|
||||
|
||||
static const char* uuid_hex_chars = "0123456789abcdef";
|
||||
static const char* uuid_hex_variant_chars = "89ab";
|
||||
|
||||
std::string util::generate_uuid() {
|
||||
auto randomEngine = seeded_random_engine(random_device);
|
||||
static std::uniform_int_distribution<> dist(0, 15);
|
||||
static std::uniform_int_distribution<> dist2(0, 3);
|
||||
|
||||
std::string uuid;
|
||||
uuid.resize(36);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uuid[i] = uuid_hex_chars[dist(randomEngine)];
|
||||
}
|
||||
uuid[8] = '-';
|
||||
for (int i = 9; i < 13; i++) {
|
||||
uuid[i] = uuid_hex_chars[dist(randomEngine)];
|
||||
}
|
||||
uuid[13] = '-';
|
||||
uuid[14] = '4';
|
||||
|
||||
for (int i = 15; i < 18; i++) {
|
||||
uuid[i] = uuid_hex_chars[dist(randomEngine)];
|
||||
}
|
||||
|
||||
uuid[18] = '-';
|
||||
uuid[19] = uuid_hex_variant_chars[dist2(randomEngine)];
|
||||
|
||||
for (int i = 20; i < 23; i++) {
|
||||
uuid[i] = uuid_hex_chars[dist(randomEngine)];
|
||||
}
|
||||
|
||||
uuid[23] = '-';
|
||||
for (int i = 24; i < 36; i++) {
|
||||
uuid[i] = uuid_hex_chars[dist(randomEngine)];
|
||||
}
|
||||
return uuid;
|
||||
}
|
||||
19
src/util/random.hpp
Normal file
19
src/util/random.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <random>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
namespace util {
|
||||
template <
|
||||
class T = std::mt19937,
|
||||
std::size_t N = T::state_size * sizeof(typename T::result_type)>
|
||||
auto seeded_random_engine(std::random_device& source) {
|
||||
std::random_device::result_type randomData[(N - 1) / sizeof(source()) + 1];
|
||||
std::generate(std::begin(randomData), std::end(randomData), std::ref(source));
|
||||
std::seed_seq seeds(std::begin(randomData), std::end(randomData));
|
||||
return T(seeds);
|
||||
}
|
||||
|
||||
std::string generate_uuid();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user