내 Roguelike를 매일 플레이하게 만든 5줄의 코드
I’m ready to translate the article for you, but I’ll need the full text you’d like translated. Could you please paste the content of the article (excluding the source link you already provided)? Once I have the text, I’ll translate it into Korean while preserving the original formatting, markdown, and code blocks.
Background
- v0.10.0에서는 내 로그라이크의 각 실행에 이름을 붙였습니다.
- v0.11.0에서는 각 날에 실행을 붙였습니다.
Endless 모드의 문제
When I shipped Endless Mode (v0.9.9), I added this line to the result screen:
“itch.io 댓글에 Endless 점수를 올려 주세요!”
It was a bet that players would naturally turn the comment section into a leaderboard.
문제: 실행은 모두 다릅니다. 한 플레이어가 “Chain Annihilator로 Wave 27을 살아남았다” 라고 올리면, 다른 플레이어가 비교할 대상이 없습니다. 그들은 다른 맵을 플레이하고, 다른 업그레이드 선택을 했으며, 다른 적 패턴을 마주했습니다.
The itch.io comment section wasn’t a leaderboard. It was just a list of unrelated accomplishments.
What makes a leaderboard work
리더보드에는 고정된 변수가 필요합니다.
- Golf: 코스가 고정되어 있습니다. 플레이어들은 같은 18홀에서 경쟁하므로, 도전 과제가 동일하기 때문에 비교가 유효합니다.
- Wordle: 단어가 고정되어 있습니다. 모든 플레이어가 같은 퍼즐을 받으며, 유일한 변수는 추측 횟수입니다.
- My roguelike: 고정된 것이 전혀 없었습니다. 실행할 때마다 랜덤 시드가 적용되고, 새로 고침할 때마다 또다시 랜덤이었습니다.
문제의 해결책은 명확했습니다: 날짜를 시드로 사용하기.
구현
Spell Cascade의 모든 실행은 다음을 위해 Godot의 전역 난수 생성기를 사용합니다:
- 적 유형 선택 (
randi() % pool) - 적 스폰 위치 (
randf_range()) - 업그레이드 선택 (
array.shuffle()) - 정예 적 등장 확률 (
randf())
아래 코드는 게임 씬을 로드하기 전에 결정적인 일일 시드를 설정합니다:
func _on_start_daily_challenge() -> void:
if _transitioning:
return
_transitioning = true
var date: Dictionary = Time.get_date_dict_from_system()
var seed_base: int = (int(date.year) * 10000) + (int(date.month) * 100) + int(date.day)
var daily_seed: int = seed_base * 31337 # 소수 분포
Engine.set_meta("daily_challenge_seed", daily_seed)
var scene: PackedScene = load("res://scenes/game.tscn")
get_tree().change_scene_to_packed(scene)게임 씬 – 로드 시 시드 설정 (game_main.gd)
# game_main.gd — 게임 로드 시 시드 설정
func _ready() -> void:
if Engine.has_meta("daily_challenge_seed"):
var daily_seed: int = Engine.get_meta("daily_challenge_seed")
seed(daily_seed)
is_daily_challenge = true
Engine.remove_meta("daily_challenge_seed")seed() 호출은 Godot의 전역 RNG 상태를 설정합니다. 이후의 모든 randi(), randf(), array.shuffle()는 이제 결정적입니다.
Engine‑metadata 패턴은 자동 로드 싱글톤 없이도 타이틀 → 게임 씬 전환을 처리합니다: 씬 전환 전에 값을 설정하고, 로드 시 즉시 읽어 삭제합니다.
2026‑02‑21은 어떻게 보이는가
On February 21, 2026, the seed is:
20260221 × 31337 = 634,601,577Every player who clicks “Daily Challenge 02/21” that day gets:
- 동일한 첫 번째 세 적
- 레벨 2, 3, 4…에서 동일한 업그레이드 선택지
- 동일한 정예 적 스폰
- 동일한 보스 트리거 타이밍
What differs is their reaction time, decision making, and skill execution. The “map” is shared; the score is earned.
사회적 메커니즘
이것을 배포한 지 24 시간 이내에, 첫 번째 일일 챌린지 게시물이 itch.io 댓글에 나타났습니다—점수만이 아니라 브리핑도 있었습니다:
“체인 파괴자로서 Wave 19에 도달했습니다. 거의 Endless까지 갔지만 8:30에 있는 스플리터 웨이브 때문에 실패했습니다.”
그 게시물이 의미가 있는 이유는 다른 플레이어들도 정확히 같은 8:30 스플리터 웨이브를 경험했기 때문입니다. 그들은 그 날의 공유된 기준점을 사용해 직접 비교할 수 있습니다.
Source: …
일일 챌린지의 철학
일일 챌린지는 사회적 협조 문제를 해결합니다.
공유된 시드가 없을 때는 로그라이크 플레이를 비교하려면 통계적 유사성을 신뢰해야 합니다—“우리는 평균적으로 같은 난이도로 플레이했어.” 이는 경쟁의 약한 기반이 됩니다.
공유된 시드가 있을 때는 비교가 직접적입니다. “우리는 둘 다 8시 30분에 그 스플리터 웨이브를 봤어”는 근사치가 아닌 사실입니다.
일일 챌린지는 자연스러운 재참여 이유도 제공합니다: “실력이 늘고 싶다”(모호) 대신 “오늘 챌린지를 아직 안 했어”(구체적이고 실행 가능하며 기한이 있는)라는 동기가 됩니다.
AI가 기여한 내용
그 아이디어는 Wordle이 어떻게 참여 루프를 구동하는지에 대한 글을 읽으면서 떠올랐습니다. 구현에 관한 질문—Godot에서 일반 모드를 깨뜨리지 않으면서 결정론적 시드를 설정하는 방법—은 제가 알지 못했던 부분이었습니다.
Claude Code가 확인했습니다:
seed()는 전역 상태를 설정하므로, 이후 모든 호출이 이를 상속합니다.- 싱글톤 없이 씬 간에 데이터를 전달하기 위한 Engine‑metadata 패턴.
이 두 가지는 처음에 저에게 명확하지 않았습니다.
제가 기여한 부분: 댓글 섹션이 리더보드로 작동하지 않는다는 관찰과 공유 시드가 이를 해결할 것이라는 이론.
Claude가 기여한 부분: 작동하게 만든 두 줄 구현.
열린 질문: 올바른 일일 초기화 시간
현재는 현지 자정에 초기화됩니다. 이는 서로 다른 시간대의 플레이어들이 기술적으로 서로 다른 순간에 “다른 날”을 시작한다는 의미입니다.
- UTC 자정을 위한 주장: 하나의 통합된 초기화.
- 문제: UTC 자정은 일본 표준시(JST) 기준으로 오전 9시이며, 일본 플레이어에게는 불편합니다.
아직 해결하지 못했습니다. 현재는 현지 날짜를 사용합니다. 만약 플레이어 기반이 충분히 커져서 시간대 불일치가 문제가 된다면, 이는 실제 문제로 떠오를 것입니다.
현재: 같은 날짜, 같은 시드. 2월 21일에 플레이한다면, 2월 21일 런을 플레이하는 것입니다.
플레이하기
Spell Cascade는 브라우저에서 무료로 이용할 수 있습니다:
당신의 Claude Code 설정은… (원본 텍스트가 여기서 잘렸습니다).
코드가 실제로 안전한가요?npx cc-health-check를 실행하세요 — 무료 20점 진단입니다.
점수가 80 미만인가요? Claude Code Ops Kit은 한 번의 명령으로 모든 문제를 해결합니다.
오늘 당신이 도달한 파장은 무엇인가요?