slow.monster

STUDIO HAZE · jeniapp

Topaz source

Open by house policy. Topaz is our own language.

Topaz 5.20.2 · 63 files

apps/slow-monster/core/genome.tpz

Topaz · 7403 B · Original file

1// 크리처의 게놈과 드리프트를 계산합니다. 게놈은 계통시드에서 유도한 다섯 개의 작은 정수이고 드리프트는 성장으로 천천히 쌓이는 카운터입니다.
2// 계통시드는 월드시드와 크리처의 기원으로 만든 문자열입니다. 표현형은 원본 게놈에 드리프트 단계만큼 흔들림을 더한 값이고, 드리프트가 진화임계에 닿으면 진화 준비입니다.
3// 게놈과 흔들림은 mutation 도메인 난수만 쓰므로 조우와 전투 난수가 게놈을 바꿀 수 없고, 같은 시드와 플레이는 같은 게놈을 만듭니다.
4// 상태, 데이터, 전투 모듈을 가져오지 않습니다. 모든 값을 가둬 손상된 저장이 정수 넘침이나 느린 그리기를 일으키지 않게 합니다.
5// Genome and drift: a five-trait genome derived from a lineage seed, slow drift, phenotype nudges and evolution readiness.
7import core.rng { 난수 }
8import core.util { 범위가두기 }
10// 색소, 막, 크기, 대사, 촉수는 연못 미생물의 형질이고 값은 [0, 강도상한) 입니다.
11export record 게놈 {
12 색소: int,
13 막: int,
14 크기: int,
15 대사: int,
16 촉수: int,
19// 토파즈 과제 '구조 타입 주석 속 다른 모듈 레코드' 때문에 모듈째 가져오며 TPZ3017 때문에 레코드를 따로 가져올 수 없어 이 함수로 만듭니다.
20// 5.21 에서 그 과제가 고쳐지면 제거 여부를 다시 봅니다.
21export function 게놈만들기(색소: int, 막: int, 크기: int, 대사: int, 촉수: int) -> 게놈 {
22 게놈 { 색소: 색소, 막: 막, 크기: 크기, 대사: 대사, 촉수: 촉수 }
25export let 트레이트수 = 5
26export let 강도상한 = 8
28// 10 이면 유한한 야생을 다 비울 때 3~4 세대까지 진화해 자동 진행이 보스를 이길 수 있습니다.
29export let 진화임계 = 10
30export let 드리프트상한 = 1000000
32// 흔들림 계산이 단계에 비례하므로 단계를 상수로 가둡니다. 진화임계 / 8 = 3 까지만 미리 보여 줍니다.
33export let 단계상한 = 3
35enum 기원 {
36 시조,
37 야생(string),
38 모름,
41export function 시작계통시드(월드시드: string) -> string {
42 "{월드시드}#starter"
45// 같은 시드에서 같은 스텝, 칸, 종으로 잡으면 같은 계통시드입니다.
46export function 야생계통시드(월드시드: string, 스텝: int, x: int, y: int, 종아이디: int) -> string {
47 "{월드시드}#wild@{스텝}:{x}:{y}:{종아이디}"
50// 진화는 계통시드 뒤에 ">분기" 를 붙이므로 맨 앞의 기원 표시는 어느 노드에도 남습니다.
51function 기원읽기(계통시드: string) -> 기원 {
52 let 해시조각들 = 계통시드.split("#")
53 if 해시조각들.length < 2 { return 기원.모름 }
54 let 핵심 = 해시조각들[1].split(">")[0]
55 if 핵심 == "starter" { return 기원.시조 }
56 let 야생조각들 = 핵심.split("@")
57 if 야생조각들.length < 2 { return 기원.모름 }
58 기원.야생(야생조각들[1].split(":")[0])
61export function 출처(계통시드: string) -> string {
62 match 기원읽기(계통시드) {
63 case 시조 => "시조"
64 case 야생(스텝) => "야생 #{스텝}"
65 case 모름 => "야생"
66 }
69// 숲 공유 코드에 쓰는 짧은 기원 키입니다.
70export function 출처키(계통시드: string) -> string {
71 match 기원읽기(계통시드) {
72 case 시조 => "S"
73 case 야생(스텝) => "W{스텝}"
74 case 모름 => "W"
75 }
78// 시드 문자열이 크리처마다 게놈 스트림을 가르므로 엔티티 인자는 0 입니다.
79export function 계통엔티티(계통시드: string) -> int {
80 난수("mutation", 0, 0, 계통시드)
83// 선형합동 난수의 아래 비트는 규칙적이라 작은 폭으로 줄이면 치우치므로 위 비트를 씁니다.
84function 트레이트유도(엔티티: int, 트레이트번호: int, 계통시드: string) -> int {
85 (난수("mutation", 엔티티, 트레이트번호, 계통시드) / 21474836) % 강도상한
88export function 게놈유도(계통시드: string) -> 게놈 {
89 let 엔티티 = 계통엔티티(계통시드)
90 게놈 {
91 색소: 트레이트유도(엔티티, 0, 계통시드),
92 막: 트레이트유도(엔티티, 1, 계통시드),
93 크기: 트레이트유도(엔티티, 2, 계통시드),
94 대사: 트레이트유도(엔티티, 3, 계통시드),
95 촉수: 트레이트유도(엔티티, 4, 계통시드),
96 }
99// 기본은 레벨업 하나에 3, 레벨업 없는 승리에 2 입니다. 데모는 어떤 승리든 두 번이면 임계를 넘도록 14 와 12 를 씁니다.
100export function 드리프트증가(오른레벨: int, 승리: bool, 데모: bool) -> int {
101 let 레벨당 = if 데모 { 14 } else { 3 }
102 let 승리몫 = if 데모 { 12 } else { 2 }
103 if 오른레벨 > 0 { 오른레벨 * 레벨당 } else if 승리 { 승리몫 } else { 0 }
106export function 드리프트가두기(드리프트: int) -> int {
107 범위가두기(드리프트, 0, 드리프트상한)
110// 여덟마다 한 단계라 흔들림이 드물고 느리게 보입니다.
111function 드리프트단계(드리프트: int) -> int {
112 (드리프트가두기(드리프트) / 8).atMost(단계상한)
115// 단계마다 -1, 0, +1 중 하나를 더합니다. 카운터를 트레이트수만큼 띄워 게놈유도의 카운터 0~4 와 겹치지 않게 합니다.
116function 너지(엔티티: int, 트레이트번호: int, 단계: int, 계통시드: string) -> int {
117 let 방향들 = map(1..<(단계 + 1), k => (난수("mutation", 엔티티, 트레이트번호 + k * 트레이트수, 계통시드) / 21474836) % 3 - 1)
118 방향들.reduce(0, (합, 방향) => 합 + 방향)
121// 페이지가 표현형으로 블롭의 색조와 모양을 조금 흔들어 다가올 진화를 미리 보여 줍니다.
122export function 표현형(원본: 게놈, 계통시드: string, 드리프트: int) -> 게놈 {
123 let 단계 = 드리프트단계(드리프트)
124 if 단계 <= 0 { return 원본 }
125 let 엔티티 = 계통엔티티(계통시드)
126 게놈 {
127 색소: 원본.색소 + 너지(엔티티, 0, 단계, 계통시드),
128 막: 원본.막 + 너지(엔티티, 1, 단계, 계통시드),
129 크기: 원본.크기 + 너지(엔티티, 2, 단계, 계통시드),
130 대사: 원본.대사 + 너지(엔티티, 3, 단계, 계통시드),
131 촉수: 원본.촉수 + 너지(엔티티, 4, 단계, 계통시드),
132 }
135export function 진화준비(드리프트: int) -> bool {
136 드리프트가두기(드리프트) >= 진화임계
139export function 드리프트퍼센트(드리프트: int) -> int {
140 범위가두기(드리프트가두기(드리프트) * 100 / 진화임계, 0, 100)
143export function 게놈요약(대상: 게놈) -> string {
144 "{대상.색소},{대상.막},{대상.크기},{대상.대사},{대상.촉수}"
147function 트레이트칸(칸들: Array<string>, i: int) -> int {
148 범위가두기(if 칸들.length > i { toInt(칸들[i]) ?? 0 } else { 0 }, 0, 강도상한 - 1)
151// 게놈요약의 역입니다. 도감이 가지 않은 형제 후보를 다시 유도할 때 씁니다.
152export function 게놈요약파싱(요약: string) -> 게놈 {
153 let 칸들 = 요약.split(",")
154 게놈 {
155 색소: 트레이트칸(칸들, 0),
156 막: 트레이트칸(칸들, 1),
157 크기: 트레이트칸(칸들, 2),
158 대사: 트레이트칸(칸들, 3),
159 촉수: 트레이트칸(칸들, 4),
160 }

SHA256 e48f9c8d127a43e18ee716cd28b83ae33417c4becca0d9826d3779f2954ef8d9