STUDIO HAZE · jeniapp
Topaz source
Open by house policy. Topaz is our own language.
Topaz 5.20.2 · 63 files
apps/slow-monster/core/rng.tpz
Topaz · 3212 B · Original file
1
// 게임의 모든 무작위를 정하는 결정론 난수입니다. 시드 문자열, 도메인 문자열, 엔티티 번호, 카운터를 섞어 [0, 2^31) 정수를 만듭니다.2
// 난수범위는 그 값을 닫힌 구간 [하한, 상한] 으로 줄입니다.3
// 같은 네 입력은 늘 같은 값이고, 도메인이 다르면 스트림이 갈려 배틀 굴림이 돌연변이 굴림을 흔들지 않습니다. 전역 상태가 없어 재생과 시드 공유가 그대로 됩니다.4
// 비트 연산과 실수를 쓰지 않고 다른 모듈을 가져오지 않습니다.5
// Counter-based deterministic RNG over seed, domain, entity and counter, using only integer arithmetic.7
// 정수 산술은 넘치면 실행 오류이므로 모든 상태를 2^31 안에 둡니다. 가장 큰 곱 1013904223 * (2^31 - 1) 이 약 2.18e18 로 부호 있는 64비트 한계 9.22e18 아래입니다.8
let 모듈러스 = 21474836489
// 증분이 홀수라 선형 합동 생성기의 주기가 2^31 전체가 됩니다.10
let 곱수 = 166452511
let 증분 = 101390422312
let 섞기곱수 = 101390422314
// 공용 도우미 시작 (다항31해시)15
// 여러 도구가 같은 원본을 씁니다. 여기서 고치지 않고 원본에서 고친 뒤 다시 생성합니다.17
// FNV 오프셋 기저에서 시작하는 31 배 다항 해시입니다. 글자마다 2^31 로 줄여 중간값이 2^31 * 31 을 넘지 않습니다.18
function 다항31해시(글: string) -> int {19
글.scalars().reduce(2166136261 % 2147483648, (해시, 글자) => (해시 * 31 + (글자.codePointAt(0) ?? 0)) % 2147483648)20
}22
// 공용 도우미 끝24
function 선형합동(x: int) -> int {25
(곱수 * x + 증분) % 모듈러스26
}28
// 나머지 연산은 음수에 음수를 돌려주므로 음수 엔티티와 카운터를 [0, 모듈러스) 로 옮깁니다.29
function 정규화(값: int) -> int {30
((값 % 모듈러스) + 모듈러스) % 모듈러스31
}33
// 더한 뒤 곱하고 한 걸음 더 가서 이웃한 카운터의 결과가 선형으로 늘어서지 않게 합니다.34
function 섞기(상태: int, 값: int) -> int {35
선형합동((섞기곱수 * ((상태 + 정규화(값)) % 모듈러스)) % 모듈러스)36
}38
// 카운터 뒤에 도메인을 한 번 더 섞고, 마지막에 상위 15비트와 하위 16비트를 다시 섞어 작은 구간으로 줄여도 고르게 퍼지게 합니다.39
export function 난수(도메인: string, 엔티티: int, 카운터: int, 시드: string) -> int {40
let 도메인값 = 다항31해시(도메인)41
let 상태 = 다항31해시(시드)42
|> 섞기(_, 도메인값)43
|> 섞기(_, 엔티티)44
|> 섞기(_, 카운터)45
|> 섞기(_, 도메인값)46
|> 선형합동47
let 상위 = 상태 / 6553648
let 하위 = 상태 % 6553649
선형합동((섞기곱수 * ((상위 + 하위 * 3) % 모듈러스)) % 모듈러스)50
}52
// 선형 합동의 하위 비트는 규칙적이라 2^31 / 100 에 가까운 21474836 으로 나눠 상위 비트에서 구간을 고릅니다.53
export function 난수범위(도메인: string, 엔티티: int, 카운터: int, 시드: string, 하한: int, 상한: int) -> int {54
let 폭 = 상한 - 하한 + 155
하한 + ((난수(도메인, 엔티티, 카운터, 시드) / 21474836) % 폭)56
}SHA256 367ab8b636210fac692f3ddcb5c006012f11e85c675a54c381853db0f837bc21