mirror of
https://github.com/GayPizzaSpecifications/voxelotl-engine.git
synced 2025-08-03 13:11:33 +00:00
broader randomrange extensions
This commit is contained in:
@ -33,7 +33,9 @@ class Game: GameDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func generateWorld() {
|
private func generateWorld() {
|
||||||
var random = DarwinRandom(seed: Arc4Random.instance.next(in: DarwinRandom.max))
|
let newSeed = Arc4Random.instance.next(in: DarwinRandom.max)
|
||||||
|
printErr(newSeed)
|
||||||
|
var random = DarwinRandom(seed: newSeed)
|
||||||
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)
|
||||||
|
@ -17,12 +17,37 @@ public class Arc4Random: RandomProvider {
|
|||||||
arc4random()
|
arc4random()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func next(in bound: Int) -> Int {
|
func next(in bound: UInt32) -> UInt32 {
|
||||||
assert(bound <= Self.max)
|
return arc4random_uniform(bound)
|
||||||
return Int(arc4random_uniform(UInt32(bound)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func next(in range: Range<Int>) -> Int {
|
func next(in bound: Int) -> Int {
|
||||||
return range.lowerBound + next(in: range.upperBound - range.lowerBound)
|
assert(bound <= UInt32.max, "Maximum raw random provider output is smaller than requested bound")
|
||||||
|
return Int(arc4random_uniform(UInt32(bound)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension Arc4Random {
|
||||||
|
func next(in range: Range<UInt32>) -> UInt32 {
|
||||||
|
assert(!range.isEmpty, "Ranged next called with empty range")
|
||||||
|
return range.lowerBound + next(in: range.upperBound - range.lowerBound)
|
||||||
|
}
|
||||||
|
|
||||||
|
func next(in range: ClosedRange<UInt32>) -> UInt32 {
|
||||||
|
if range == 0...UInt32.max {
|
||||||
|
next()
|
||||||
|
} else {
|
||||||
|
next(in: range.upperBound - range.lowerBound + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func next(in range: Range<Int>) -> Int {
|
||||||
|
assert(!range.isEmpty, "Ranged next called with empty range")
|
||||||
|
return range.lowerBound + next(in: range.upperBound - range.lowerBound)
|
||||||
|
}
|
||||||
|
|
||||||
|
func next(in range: ClosedRange<Int>) -> Int {
|
||||||
|
assert(range.upperBound - range.lowerBound < Int.max, "Closed range exceeds Int.max")
|
||||||
|
return range.lowerBound + next(in: range.upperBound - range.lowerBound + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
public extension RandomProvider where Output: BinaryInteger {
|
public extension RandomProvider where Output: BinaryInteger {
|
||||||
mutating func next(in range: Range<Int>) -> Int {
|
mutating func next(in range: Range<Int>) -> Int {
|
||||||
range.lowerBound + self.next(in: range.upperBound - range.lowerBound)
|
assert(!range.isEmpty, "Ranged next called with empty range")
|
||||||
|
return range.lowerBound + self.next(in: range.upperBound - range.lowerBound)
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func next(in range: ClosedRange<Int>) -> Int {
|
mutating func next(in range: ClosedRange<Int>) -> Int {
|
||||||
range.lowerBound + self.next(in: range.upperBound - range.lowerBound + 1)
|
assert(range.upperBound - range.lowerBound < Int.max, "Closed range exceeds Int.max")
|
||||||
|
return range.lowerBound + self.next(in: range.upperBound - range.lowerBound + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func next(in bound: Int) -> Int {
|
mutating func next(in bound: Int) -> Int {
|
||||||
assert(Self.min == 0)
|
assert(Self.min == 0, "Range operations are unsupported on random providers with a non-zero minimum")
|
||||||
assert(Self.max >= bound)
|
assert(Self.max >= bound, "Maximum raw random provider output is smaller than requested bound")
|
||||||
let threshold = Int(Self.max % Output(bound))
|
let threshold = Int(Self.max % Output(bound))
|
||||||
var result: Int
|
var result: Int
|
||||||
repeat {
|
repeat {
|
||||||
@ -18,3 +20,70 @@ public extension RandomProvider where Output: BinaryInteger {
|
|||||||
return result % bound
|
return result % bound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public extension RandomProvider where Output: UnsignedInteger {
|
||||||
|
mutating func next(in range: Range<Output>) -> Output {
|
||||||
|
assert(!range.isEmpty, "Ranged next called with empty range")
|
||||||
|
return range.lowerBound + self.next(in: range.upperBound - range.lowerBound)
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func next(in range: ClosedRange<Output>) -> Output {
|
||||||
|
if range == 0...Output.max {
|
||||||
|
next()
|
||||||
|
} else {
|
||||||
|
range.lowerBound + self.next(in: range.upperBound - range.lowerBound + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func next(in bound: Output) -> Output {
|
||||||
|
assert(Self.min == 0, "Range operations are unsupported on random providers with a non-zero minimum")
|
||||||
|
assert(Self.max >= bound, "Maximum raw random provider output is smaller than requested bound")
|
||||||
|
let threshold = (Self.max &- bound &+ 1) % bound
|
||||||
|
var result: Output
|
||||||
|
repeat {
|
||||||
|
result = self.next()
|
||||||
|
} while result < threshold
|
||||||
|
return result % bound
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: - Experimental
|
||||||
|
|
||||||
|
// Uniform bounded random without modulos, WILL produce different results from the standard bounded next
|
||||||
|
public extension RandomProvider where Output: UnsignedInteger {
|
||||||
|
mutating func nextModless(in range: Range<Output>) -> Output {
|
||||||
|
assert(!range.isEmpty, "Ranged next called with empty range")
|
||||||
|
return range.lowerBound + self.nextModless(in: range.upperBound - range.lowerBound)
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func nextModless(in range: ClosedRange<Output>) -> Output {
|
||||||
|
if range == 0...Output.max {
|
||||||
|
self.next()
|
||||||
|
} else {
|
||||||
|
range.lowerBound + self.nextModless(in: range.upperBound - range.lowerBound + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutating func nextModless(in bound: Output) -> Output {
|
||||||
|
func pow2MaskFrom(range num: Output) -> Output {
|
||||||
|
if num & (num - 1) == 0 {
|
||||||
|
return num - 1
|
||||||
|
}
|
||||||
|
var result: Output = 1
|
||||||
|
for _ in 0..<Output.bitWidth {
|
||||||
|
if result >= num {
|
||||||
|
return result - 1
|
||||||
|
}
|
||||||
|
result <<= 1
|
||||||
|
}
|
||||||
|
return .max
|
||||||
|
}
|
||||||
|
|
||||||
|
let mask = pow2MaskFrom(range: bound)
|
||||||
|
var result: Output
|
||||||
|
repeat {
|
||||||
|
result = next() & mask
|
||||||
|
} while result >= bound
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user