mirror of
https://github.com/GayPizzaSpecifications/voxelotl-engine.git
synced 2025-08-03 13:11:33 +00:00
replace darwin prng with higher quality prngs
This commit is contained in:
@ -18,7 +18,8 @@ add_executable(Voxelotl MACOSX_BUNDLE
|
|||||||
Random/RandomProvider.swift
|
Random/RandomProvider.swift
|
||||||
Random/RandomRange.swift
|
Random/RandomRange.swift
|
||||||
Random/Arc4Random.swift
|
Random/Arc4Random.swift
|
||||||
Random/DarwinRandom.swift
|
Random/PCG32Random.swift
|
||||||
|
Random/Xoroshiro128.swift
|
||||||
|
|
||||||
# Resource classes
|
# Resource classes
|
||||||
NSImageLoader.swift
|
NSImageLoader.swift
|
||||||
|
@ -33,9 +33,15 @@ class Game: GameDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func generateWorld() {
|
private func generateWorld() {
|
||||||
let newSeed = Arc4Random.instance.next(in: DarwinRandom.max)
|
#if true
|
||||||
|
let newSeed = UInt64(Arc4Random.instance.next()) | UInt64(Arc4Random.instance.next()) << 32
|
||||||
printErr(newSeed)
|
printErr(newSeed)
|
||||||
var random = DarwinRandom(seed: newSeed)
|
var random = Xoroshiro128PlusPlus(seed: newSeed)
|
||||||
|
#else
|
||||||
|
var random = PCG32Random(
|
||||||
|
seed: UInt64(Arc4Random.instance.next()) | UInt64(Arc4Random.instance.next()) << 32,
|
||||||
|
sequence: UInt64(Arc4Random.instance.next()) | UInt64(Arc4Random.instance.next()) << 32)
|
||||||
|
#endif
|
||||||
self.chunk.fill(allBy: {
|
self.chunk.fill(allBy: {
|
||||||
if (random.next() & 0x1) == 0x1 {
|
if (random.next() & 0x1) == 0x1 {
|
||||||
.solid(.init(rgb888: UInt32(random.next(in: 0..<0xFFFFFF+1))).linear)
|
.solid(.init(rgb888: UInt32(random.next(in: 0..<0xFFFFFF+1))).linear)
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
public struct DarwinRandom: RandomProvider {
|
|
||||||
public typealias Output = Int
|
|
||||||
|
|
||||||
public static var min: Int { 0x00000000 }
|
|
||||||
public static var max: Int { 0x7FFFFFFF }
|
|
||||||
|
|
||||||
private var state: Int
|
|
||||||
|
|
||||||
init() {
|
|
||||||
self.state = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(seed: Int) {
|
|
||||||
self.state = seed
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating public func seed(with seed: Int) {
|
|
||||||
self.state = seed
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating public func next() -> Int {
|
|
||||||
if self.state == 0 {
|
|
||||||
self.state = 123459876
|
|
||||||
}
|
|
||||||
let hi = self.state / 127773
|
|
||||||
let lo = self.state - hi * 127773
|
|
||||||
self.state = 16807 * lo - 2836 * hi
|
|
||||||
if self.state < 0 {
|
|
||||||
self.state += Self.max
|
|
||||||
}
|
|
||||||
return self.state % (Self.max + 1)
|
|
||||||
}
|
|
||||||
}
|
|
47
Sources/Voxelotl/Random/PCG32Random.swift
Normal file
47
Sources/Voxelotl/Random/PCG32Random.swift
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
public struct PCG32Random: RandomProvider {
|
||||||
|
public typealias Output = UInt32
|
||||||
|
|
||||||
|
public static var min: UInt32 { .min }
|
||||||
|
public static var max: UInt32 { .max }
|
||||||
|
|
||||||
|
private var _state: UInt64, _inc: UInt64
|
||||||
|
|
||||||
|
public var state: (UInt64, UInt64) {
|
||||||
|
get { (self._state, self._inc) }
|
||||||
|
set {
|
||||||
|
self._state = newValue.0
|
||||||
|
self._inc = newValue.1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
self._state = 0x853C49E6748FEA9B
|
||||||
|
self._inc = 0xDA3E39CB94B95BDB
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(seed: UInt64, sequence: UInt64) {
|
||||||
|
self.init()
|
||||||
|
self.seed(state: _state, sequence: sequence)
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func seed(state: UInt64, sequence: UInt64) {
|
||||||
|
self._state = 0
|
||||||
|
self._inc = sequence << 1 | 0x1
|
||||||
|
_ = next()
|
||||||
|
self._state &+= state
|
||||||
|
_ = next()
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func next() -> UInt32 {
|
||||||
|
let prevState = self._state
|
||||||
|
|
||||||
|
// LCG component
|
||||||
|
self._state &*= 6364136223846793005
|
||||||
|
self._state &+= self._inc
|
||||||
|
|
||||||
|
// Permutation (XorShift + RotRight)
|
||||||
|
let xorShifted = UInt32(truncatingIfNeeded: (prevState &>> 18 ^ prevState) &>> 27)
|
||||||
|
let rot59 = UInt32(truncatingIfNeeded: prevState &>> 59)
|
||||||
|
return xorShifted &>> rot59 | xorShifted &<< UInt32(bitPattern: -Int32(bitPattern: rot59) & 0x1F)
|
||||||
|
}
|
||||||
|
}
|
126
Sources/Voxelotl/Random/Xoroshiro128.swift
Normal file
126
Sources/Voxelotl/Random/Xoroshiro128.swift
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
struct Xoroshiro128Plus: RandomProvider {
|
||||||
|
public typealias Output = UInt64
|
||||||
|
|
||||||
|
static public var min: UInt64 { .min }
|
||||||
|
static public var max: UInt64 { .max }
|
||||||
|
|
||||||
|
public var state: (UInt64, UInt64)
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
self.state = (0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(state: (UInt64, UInt64)) {
|
||||||
|
self.state = (state.0, state.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(seed: UInt64) {
|
||||||
|
let s0 = splitMix64(seed: seed)
|
||||||
|
self.init(state: (s0, splitMix64(seed: s0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func seed(_ seed: UInt64) {
|
||||||
|
let s0 = splitMix64(seed: seed)
|
||||||
|
self.state = (s0, splitMix64(seed: s0))
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func next() -> UInt64 {
|
||||||
|
let result = self.state.0 &+ self.state.1
|
||||||
|
|
||||||
|
let xor = state.1 ^ self.state.0
|
||||||
|
self.state = (
|
||||||
|
self.state.0.rotate(left: 24) ^ xor ^ xor &<< 16,
|
||||||
|
xor.rotate(left: 37))
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Xoroshiro128PlusPlus: RandomProvider {
|
||||||
|
public typealias Output = UInt64
|
||||||
|
|
||||||
|
static public var min: UInt64 { .min }
|
||||||
|
static public var max: UInt64 { .max }
|
||||||
|
|
||||||
|
public var state: (UInt64, UInt64)
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
self.state = (0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(state: (UInt64, UInt64)) {
|
||||||
|
self.state = (state.0, state.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(seed: UInt64) {
|
||||||
|
let s0 = splitMix64(seed: seed)
|
||||||
|
self.init(state: (s0, splitMix64(seed: s0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func seed(_ seed: UInt64) {
|
||||||
|
let s0 = splitMix64(seed: seed)
|
||||||
|
self.state = (s0, splitMix64(seed: s0))
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func next() -> UInt64 {
|
||||||
|
let result = (self.state.0 &+ self.state.1).rotate(left: 17) &+ self.state.0
|
||||||
|
|
||||||
|
let xor = state.1 ^ self.state.0
|
||||||
|
self.state = (
|
||||||
|
self.state.0.rotate(left: 49) ^ xor ^ xor << 21,
|
||||||
|
xor.rotate(left: 28))
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Xoroshiro128StarStar: RandomProvider {
|
||||||
|
public typealias Output = UInt64
|
||||||
|
|
||||||
|
static public var min: UInt64 { .min }
|
||||||
|
static public var max: UInt64 { .max }
|
||||||
|
|
||||||
|
public var state: (UInt64, UInt64)
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
self.state = (0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(state: (UInt64, UInt64)) {
|
||||||
|
self.state = (state.0, state.1)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(seed: UInt64) {
|
||||||
|
let s0 = splitMix64(seed: seed)
|
||||||
|
self.init(state: (s0, splitMix64(seed: s0)))
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func seed(_ seed: UInt64) {
|
||||||
|
let s0 = splitMix64(seed: seed)
|
||||||
|
self.state = (s0, splitMix64(seed: s0))
|
||||||
|
}
|
||||||
|
|
||||||
|
public mutating func next() -> UInt64 {
|
||||||
|
let result = (self.state.0 &* 5).rotate(left: 7) &* 9
|
||||||
|
|
||||||
|
let xor = self.state.1 ^ self.state.0
|
||||||
|
self.state = (
|
||||||
|
self.state.0.rotate(left: 24) ^ xor ^ xor << 16,
|
||||||
|
xor.rotate(left: 37))
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate extension UInt64 {
|
||||||
|
func rotate(left count: Int) -> Self {
|
||||||
|
self &<< count | self &>> (Self.bitWidth &- count)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func splitMix64(seed: UInt64) -> UInt64 {
|
||||||
|
var x = seed &+ 0x9E3779B97F4A7C15
|
||||||
|
x = (x ^ x &>> 30) &* 0xBF58476D1CE4E5B9
|
||||||
|
x = (x ^ x &>> 27) &* 0x94D049BB133111EB
|
||||||
|
return x ^ x &>> 31
|
||||||
|
}
|
Reference in New Issue
Block a user