TRENDSHIFT 딥다이브 · levy-street/world-of-claudecraft

World of Claudecraft —
"WoW 클래식"을 흉내 낸 미니 MMO이자,
실은 에이전트 루프를 시험하는 실험 하니스

바닐라 월드 오브 워크래프트 느낌의 작은 MMO를 브라우저에서 직접 플레이하고 직접 호스팅까지 할 수 있는 레포다. 그런데 진짜 핵심은 게임이 아니다. 똑같은 결정론적 시뮬레이션 코어(src/sim/)를 화면 없이(headless) 돌려, RL 에이전트·LLM 에이전트가 "정말로 게임을 플레이하면서 학습·검증되는지"를 측정하는 실험 환경으로 재활용한다. Three.js 렌더러, Postgres 권위 서버, Python Gymnasium 래퍼가 모두 같은 게임 규칙 위에 얹혀 있다 — 게임을 가지고 "에이전트 루프"를 게임처럼 검증하는 프로젝트다.

v0.7.0 · MIT
private 빌드 / 코드 MIT, 에셋은 대부분 CC0
TypeScript + Python
sim/render/server는 TS, RL 래퍼는 Python
~200k step/s
단일 코어 헤드리스 벤치 목표치 (frameSkip=5)
3존 · 9직업 · ~60퀘스트
1~20레벨, 5인 던전 4개, 1v1 랭크 아레나

1프로젝트 한줄 요약

한 문장으로: "WoW 클래식을 닮은 미니 MMO를 만들되, 그 시뮬레이션 코어를 그대로 떼어내 에이전트 학습/검증용 RL 환경으로 쓰는 실험."

world-of-claudecraft(이하 WoC)는 두 얼굴을 가진 단일 코드베이스다.

두 얼굴이 완전히 똑같은 결정론적 시뮬레이션(src/sim/)을 공유한다는 점이 이 레포의 정체성이다. "게임으로 보이지만, 사실은 에이전트가 장시간 루프를 도는지 검증하는 실험대"라는 표현이 정확하다.

한 컷 비유

"자동차 충돌 시험장"을 게임으로 만든 셈

자동차 회사는 진짜 도로에서 사고를 낼 수 없으니, 모든 조건을 통제한 충돌 시험장에서 더미를 태우고 같은 코스를 수천 번 반복한다. WoC의 src/sim/이 바로 그 시험장이다 — 시드만 같으면 월드가 매번 똑같이 재현되고(결정론적), 화면 없이 초당 수십만 스텝을 돌릴 수 있다.

사람이 브라우저로 들어가면 "게임"이 되고, 에이전트(더미)를 태우면 "에이전트 루프 시험장"이 된다. 같은 시험장, 다른 탑승자.

2왜 주목받는가

"또 하나의 웹 게임"이 아니라, 에이전트 시대에 필요한 "측정 가능한 놀이터"라서 화제가 됐다.

① 게임이 곧 벤치마크 — "에이전트가 정말 플레이하나"를 잴 수 있다

LLM/에이전트 평가의 가장 큰 고민은 "긴 호흡의 과제를 끝까지 해내는지"를 객관적으로 재기 어렵다는 점이다. WoC는 이걸 게임 점수로 환원한다. 레벨, 처치 수, 완료 퀘스트, 획득 골드 같은 게 그대로 info로 떨어지고, XP·처치·퀘스트 진행에 가중치를 둔 보상 함수가 매 스텝 점수를 매긴다. "에이전트가 똑똑해졌나?"를 "20레벨까지 몇 스텝 만에 갔나?"로 바꿔 측정할 수 있다.

② "같은 코어, 세 타깃" — 결정론이 만드는 신뢰

오프라인 브라우저, 온라인 멀티플레이 서버, 헤드리스 RL 환경이 전부 src/sim/의 같은 규칙으로 돈다. 시드가 같으면 결과가 같다. 즉 에이전트가 학습한 환경과 사람이 실제로 플레이하는 환경이 한 치도 다르지 않다. "시뮬레이터에서만 잘 되고 실전에서 안 되는" 흔한 함정을 구조적으로 차단한다.

③ 바닐라 WoW "진짜 공식"을 그대로 구현한 깊이

분노(rage) 전환식 c = 0.0091L² + 3.23L + 4.27, +3레벨 절벽이 있는 주문 적중 테이블, 방어도 감쇠 armor/(armor + 85·레벨 + 400), 1.5초 GCD, 5초 마나 룰까지 — README가 "클래식 충실도 체크리스트"로 공개할 만큼 세밀하다. 장난감 규칙이 아니라 충분히 복잡해서 학습 가치가 있는 환경이라는 점이 평가자들의 흥미를 끌었다.

④ "Claude 시대" 밈 + 진지한 엔지니어링의 결합

이름부터 "World of Claudecraft"라는 농담이지만, 내용은 Three.js 렌더러·권위 서버·Gymnasium 래퍼·E2E 브라우저 테스트까지 갖춘 진짜 풀스택이다. 밈으로 눈길을 끌고 엔지니어링으로 붙잡는 전형적인 트렌딩 패턴.

경쟁/유사 프로젝트 대비 자리

비교 대상성격WoC의 차이
MineRL · CrafterRL 연구용 게임 환경"렌더링 가능한 진짜 멀티플레이 게임"이자 RL 환경 — 사람이 직접 같은 월드를 플레이할 수 있음
Gymnasium / PettingZooRL 환경 인터페이스 표준표준을 "구현해서 제공" — WoC는 그 위에 올라타는 콘텐츠
일반 웹 MMO 클론플레이 자체가 목적헤드리스 시뮬레이션 + 보상 함수 + Python 래퍼로 "에이전트 실험"이 1급 시민
LLM 에이전트 벤치(WebArena 등)브라우저/툴 조작 평가고속·결정론·저비용(초당 수십만 스텝)으로 RL식 반복 학습까지 가능

3기술 스택 전체 지도

package.json·Dockerfile·vite.config.ts·소스까지 뜯어본 실제 구성. 한 코어 위에 세 개의 출력(브라우저/서버/RL)이 얹혀 있다.

핵심 공유 코어 — 결정론적 시뮬레이션

프론트엔드 — 브라우저 게임 클라이언트

레이어기술역할
3D 렌더링three ^0.165지형·건물·12종 크리처 리그·애니메이션. 모델/텍스처는 절차적 생성
후처리postprocessing · n8ao앰비언트 오클루전 등 화면 효과(src/render/post.ts)
빌드/번들vite ^8개발 서버(:5173)는 /api·/ws를 게임 서버로 프록시
UI순수 TS + Canvas유닛 프레임·툴팁·맵·전투 텍스트, 주문/아이템 아이콘을 런타임에 canvas로 그림(에셋 파일 0개)
오디오WebAudio 합성타격·레벨업·코인 소리까지 절차적 생성 — 오디오 파일도 0개

백엔드 — 권위(authoritative) 게임 서버

레이어기술역할
실행Node + esbuild 번들server/main.ts를 단일 .cjs로 묶어 실행(build:server)
통신REST + ws(WebSocket)인증은 REST, 월드 동기화는 20Hz WebSocket 스냅샷
영속pg + Postgres 16캐릭터 상태를 JSONB로 저장. 30초마다·로그아웃·종료 시 세이브
인증/보안scrypt + 베어러 토큰비밀번호 scrypt 해시, 7일 토큰, IP별 레이트리밋(ratelimit.ts)
모더레이션obscenity채팅 욕설 필터 + 신고/제재 DB(moderation_db.ts)

서버가 "권위"라는 말의 의미: 클라이언트는 입력 의도만 보내고, 모든 전투 계산·루팅·퀘스트 판정은 서버에서 한다. 클라이언트는 렌더러일 뿐. 이건 멀티플레이 보안의 정석이자, 동시에 "권위 서버 = 검증자"라는 에이전트 검증 구조와 맞닿는다.

RL / 에이전트 환경 레이어

레이어기술역할
환경 서버headless/env_server.tsstdin/stdout으로 NDJSON 주고받는 헤드리스 시뮬. esbuilddist-env/env_server.cjs 번들
Python 래퍼gymnasium + numpyWoWClassicEnv(python/wow_env.py)가 Node 서브프로세스를 띄워 reset()/step() 표준 인터페이스 제공
벤치마크--bench 플래그20만 스텝을 돌려 단일 코어 처리량(steps/sec)을 측정

인프라 / 테스트

4아키텍처 심화 분석

"같은 시뮬레이션 코어"가 어떻게 세 갈래로 갈라지는지, 그리고 에이전트 루프가 어떻게 도는지.

전체 구조도 — 하나의 코어, 세 개의 탑승구

┌───────────────────────────────────┐ │ src/sim/ (결정론 코어) │ │ sim.ts · world.ts · entity.ts │ │ threat.ts · pathfind.ts · rng.ts │ │ content/(zones·classes·items) │ │ ── DOM/Three.js import 전혀 없음 ──│ └───────────────────────────────────┘ ▲ ▲ ▲ IWorld 인터페이스 │ │ │ encodeObs/applyAction ┌──────────────────────┘ │ └────────────────────────┐ │ │ │ ┌──┴───────────────┐ ┌──────────┴──────────┐ ┌────────────────┴───────┐ │ 브라우저 클라이언트 │ │ 권위 게임 서버 │ │ 헤드리스 RL 환경 │ │ src/render (Three)│ │ server/main.ts │ │ headless/env_server.ts │ │ src/ui src/game │ │ REST 인증 + WS 20Hz │ │ NDJSON over stdio │ │ ── 오프라인 플레이 ─│ │ Postgres(JSONB)영속 │ │ ▼ │ └──────────────────┘ │ obscenity 모더레이션│ │ python/wow_env.py │ 사람이 직접 플레이 │ ── 멀티플레이 권위 ──│ │ Gymnasium(numpy) │ └─────────────────────┘ └─────────────────────────┘ src/net/online.ts ────────────▲ (ClientWorld도 IWorld 구현) 에이전트가 학습/검증 (온라인 클라이언트) │ └── 클라이언트는 입력 의도만, 서버가 모든 판정

핵심 설계는 src/world_api.tsIWorld 인터페이스다. 로컬 시뮬(Sim)과 온라인 클라이언트(ClientWorld)가 둘 다 이 인터페이스를 만족시키므로, 렌더러·UI는 "지금 오프라인인지 온라인인지"를 몰라도 된다. 같은 화면 코드가 두 백엔드를 갈아끼운다.

에이전트 루프 / 실험 하니스 패턴

RL의 표준 루프는 관측 → 행동 → 보상 → 다음 관측의 반복이다. WoC는 이걸 두 프로세스 사이의 한 줄 JSON 대화로 구현했다. 파이썬(에이전트 쪽)이 명령을 한 줄 쓰면, Node(시뮬 쪽)가 결과를 한 줄로 답한다.

┌─────────────────────┐ ┌──────────────────────────────┐ │ Python 에이전트 │ NDJSON(stdio) │ Node 헤드리스 시뮬 │ │ WoWClassicEnv │ ───────────────▶│ env_server.ts │ │ (gymnasium.Env) │ │ │ │ │ {"cmd":"info"} │ → obs_size·num_actions·actions │ reset(seed) ───────────────────────▶ │ {"cmd":"reset","seed":42} │ │ │ ◀───────────── │ {"obs":[...],"info":{...}} │ │ while not done: │ │ │ │ a = policy(obs) ─────────────────▶ │ {"cmd":"step","action":9} │ │ │ │ applyAction → tick × 5 │ │ │ │ reward = Δcounters · 가중치 │ │ obs,r,term,trunc ◀────────────────── │ {"obs":[...],"reward":0.2, │ │ │ │ "terminated":false,...} │ └─────────────────────┘ └──────────────────────────────┘ 반복(루프) 매 step = sim 5틱(=1초의 1/4)
용어
NDJSON (Newline-Delimited JSON)
한 줄에 JSON 하나씩, 줄바꿈으로 메시지를 구분하는 스트리밍 포맷. WoC는 프로세스 간 표준입출력(stdin/stdout)으로 이걸 흘려보낸다. 무겁고 느린 HTTP 대신, "같은 머신의 두 프로세스가 초고속으로 대화"하는 데 최적이다. info / reset / step / close 네 가지 명령만 있다.

① 관측(Observation) — 게임 상태를 숫자 벡터로

obs.tsencodeObs()는 게임 상태를 정규화된 float 배열로 납작하게 편다. 크기를 하드코딩하지 말고 info 명령으로 물어보라고 주석이 못 박아 둔다. 구성:

블록내용차원
selfHP·자원·레벨·XP비율·위치(x/z)·바라보는 방향(sin/cos)·GCD·시전 진행률·사망 여부·전투 중·자동공격 중·콤보포인트·앉기/먹기/마시기·Overpower proc 여부16
abilities스킬 N칸 각각 "지금 쓸 수 있나(ready)" + "쿨다운 비율" (N은 직업 최대 스킬 수, 현재 21)N×2
target현재 타깃의 HP·레벨차·거리·상대각도·적대/루팅 가능/나를 노리는지9
nearby mobs가까운 적 5마리의 거리·각도·HP·레벨차·어그로 여부5×6
interactable가장 가까운 시체/획득물/퀘스트NPC의 거리·각도·종류5
quests퀘스트 10개의 상태(미수락/진행/완료가능/완료)와 진척도10×2

모든 값이 대략 −2~2 범위로 정규화돼 있어(거리는 40야드로 나누는 식), 신경망이 학습하기 좋다. 각도를 직접 주지 않고 sin/cos 쌍으로 주는 건 0도와 360도가 끊기지 않게 하는 정석 기법이다.

② 행동(Action) — 이산 행동 (직업별 동적 산출)

행동 공간은 Discrete(N) — N은 직업별 최대 스킬 수(현재 드루이드 21개)에 따라 동적 산출(고정값 아님). 고정 13개 행동(이동(앞/뒤/좌우 회전·스트레이프·점프), 타깃팅, 자동공격, 상호작용(루팅/대화), 정지, 먹기/마시기) + 스킬 슬롯 N개로 구성되며, 실행 시 info 명령으로 실제 num_actions를 확인 권장. 이동 계열은 한 스텝(=frameSkip 5틱) 동안 "눌려 있는" 것으로 처리되어, 한 번의 결정이 일정 시간 지속된다. 죽은 상태에서 아무 행동이나 하면 영혼을 풀어(부활) 게임이 멈추지 않게 한 디테일도 있다.

③ 보상(Reward) — 게임 카운터의 변화량에 가중치

보상은 매 스텝 카운터(RewardCounters)의 증가분에 가중치를 곱해 합산한다. 기본값:

// headless/env_server.ts — DEFAULT_CONFIG.rewards xp: 0.01 // 경험치 1점당 damageDealt: 0.002 damageTaken: -0.001 kill: 0.2 // 처치 death: -5 // 죽으면 큰 페널티 questDone: 5 // 퀘스트 완료가 가장 값짐 questProgress:0.5 levelUp: 2

이 가중치를 reset 명령의 config로 통째로 갈아끼울 수 있다. 즉 "무엇을 잘하는 에이전트를 원하는가"를 보상으로 정의하는 게 실험자의 몫이다. 에피소드는 maxSteps(기본 8000)에서 잘리거나(truncated), 20레벨 도달/사망 시 종료(terminated)된다.

비유

이 구조는 "강아지 훈련"과 똑같다. 관측 = 강아지가 보는 상황, 행동 = 강아지의 동작, 보상 = 간식(잘하면 +, 못하면 −). frameSkip은 "명령 한 번에 몇 초 동안 그 동작을 유지시키나"이고, 보상 가중치는 "어떤 행동에 간식을 더 많이 줄 것인가"라는 훈련 방침이다. 같은 강아지(에이전트)라도 방침을 바꾸면 전혀 다른 습관이 든다.

왜 이게 "에이전트 루프 검증"인가

핵심은 속도·결정론·종료조건이다. ① 화면이 없으니 단일 코어로도 초당 수십만 스텝(--bench)이 나와 싸고 빠르게 수만 번 반복할 수 있다. ② 시드가 같으면 결과가 같으니 "이 변경이 정말 성능을 올렸나"를 깨끗이 비교한다. ③ 처치·레벨·퀘스트라는 명확한 성공 지표가 있어 "에이전트가 진짜로 게임을 플레이하며 발전하는가"를 숫자로 본다. 게임이라는 외피를 쓴 채, 사실은 장기 에이전트 루프가 끝까지 도는지를 측정하는 실험 하니스인 것이다.

5디렉토리 구조 해부

어디를 먼저 읽어야 하는지 — "코어 → 세 타깃 → 도구" 순서로 본다.

world-of-claudecraft/ ├─ src/ │ ├─ sim/ ★ 결정론 게임 코어 (모든 타깃이 공유, 여기부터 읽기) │ │ ├─ sim.ts 메인 시뮬레이션 루프 + RewardCounters │ │ ├─ world.ts 월드/엔티티 상태 │ │ ├─ entity.ts threat.ts pathfind.ts AI·어그로·길찾기 │ │ ├─ rng.ts 시드 기반 결정론 난수 │ │ ├─ obs.ts ★ RL 관측/행동 인코더 (ACTIONS·encodeObs·applyAction) │ │ └─ content/ zone1~3 · classes · items · dungeons (콘텐츠 데이터) │ ├─ world_api.ts ★ IWorld 인터페이스 (Sim·ClientWorld 공통 계약) │ ├─ render/ Three.js 렌더러 (terrain·water·characters·vfx·post) │ ├─ ui/ 클래식 HUD (hud·hotbar·meters·i18n·icons) │ ├─ game/ 입력·카메라·WebAudio (input·click_move·audio·music) │ ├─ net/online.ts 온라인 클라이언트 (REST 인증 + WS 미러) │ ├─ admin/ 운영 대시보드 프론트 │ └─ main.ts 클라이언트 진입점 (월드 시드 고정) ├─ server/ 권위 게임 서버 │ ├─ main.ts HTTP + WebSocket 진입 │ ├─ game.ts realm.ts 월드 루프 / 렐름 │ ├─ db.ts auth.ts Postgres + scrypt 인증 │ ├─ ratelimit.ts IP 레이트리밋 │ └─ social*.ts moderation_db.ts chat_log.ts 파티/거래/모더레이션 ├─ headless/ │ └─ env_server.ts ★ 헤드리스 RL 환경 서버 (NDJSON · 보상 설정 · --bench) ├─ python/ │ ├─ wow_env.py ★ Gymnasium 래퍼 (WoWClassicEnv · make_env) │ └─ example_random_agent.py 랜덤 에이전트 스모크 테스트 ├─ scripts/ E2E·스크린샷 투어·멀티플레이 검증·5봇 던전 레이드(.mjs) ├─ tests/ Vitest (수식·전투·AI·9직업·파티/결투/거래/던전) ├─ docs/ 스크린샷 + 문서 ├─ docker-compose.yml postgres:16-alpine + 게임 서버 ├─ Dockerfile DEPLOY.md 배포 └─ package.json dev/build/server/env/bench/db 스크립트 모음

읽는 순서 추천: src/sim/sim.tssrc/sim/obs.tsheadless/env_server.tspython/wow_env.py. 이 네 파일만 따라가면 "게임이 어떻게 RL 환경으로 변신하는지"의 전 과정을 본다. 렌더러(src/render)와 서버(server/)는 그다음에 봐도 늦지 않다.

6학습 포인트

이 레포에서 "무엇을 배울 수 있는가"를 기술별로.

강화학습 / 에이전트

RL 환경을 "직접 만드는" 정석

대부분은 기성 Gym 환경을 가져다 쓰지만, WoC는 환경을 처음부터 짜는 법을 보여준다. 관측 정규화, 이산 행동 매핑, 보상 셰이핑, 에피소드 종료/절단 구분, frameSkip, 결정론 시드 — RL 환경 설계의 모든 결정이 코드에 노출돼 있다. Gymnasium의 reset/step/close 계약을 어떻게 구현하는지 살아있는 예제로 본다.

시스템 설계

"하나의 코어, 여러 출구" 패턴

IWorld 인터페이스로 로컬 시뮬과 네트워크 클라이언트를 호환시키고, DOM 의존을 코어에서 완전히 분리해 같은 코드가 브라우저·Node·헤드리스에서 도는 구조. "순수 코어 + 얇은 어댑터"가 얼마나 강력한지를 체감할 수 있다.

멀티플레이 / 백엔드

권위 서버와 보안의 정석

클라이언트는 입력만, 서버가 모든 판정. 20Hz 스냅샷 + 관심영역(interest scoping) 동기화, scrypt 해시·토큰 만료·IP 레이트리밋, 거래의 원자성·서버 검증 — 실전 멀티플레이 게임 서버의 축약판을 통째로 읽을 수 있다.

프로세스 간 통신

NDJSON over stdio

HTTP·gRPC 없이 표준입출력에 한 줄 JSON을 흘려 두 언어(Python↔Node) 프로세스를 잇는 가볍고 빠른 IPC. 언어가 달라도 프로토콜만 맞추면 된다는 걸 보여주는 간결한 예제.

절차적 생성

에셋 0개로 만드는 세계

모델·텍스처·아이콘·사운드를 모두 런타임에 코드로 생성한다(src/render/textures.ts, canvas 아이콘, WebAudio). "에셋 파이프라인 없이" 게임을 만드는 극단적 사례 — 절차적 그래픽/오디오의 좋은 교재.

7시스템 요구사항

목적별로 필요한 게 다르다 — 게임 플레이만, 호스팅, RL 학습.

목적필요한 것비고
오프라인 플레이Node 18+ · 최신 브라우저(WebGL2)npm installnpm run dev → Play Offline
온라인 개발위 + Docker(Postgres 16)npm run db:up + npm run server + npm run dev
원클릭 호스팅Docker / Docker Composedocker compose up -d --build → :8787. 운영 시 TLS 리버스 프록시(Caddy 등)
RL 학습Node + Python 3 · gymnasium · numpynpm run build:env로 번들 생성 후 WoWClassicEnv 사용. GPU는 정책망 학습 시 권장(환경 자체는 CPU)
주의
운영에서 ALLOW_DEV_COMMANDS=1 금지

레벨/순간이동 치트를 여는 개발 플래그다. 테스트 봇(5봇 던전 레이드 등)에만 쓰고, 공개 서버에는 절대 켜지 말 것. 비밀번호(POSTGRES_PASSWORD)는 길고 무작위로.

8직접 해볼 실습 과제

난이도별 5개. 위에서 아래로 갈수록 어렵다.

난이도 ★ — 입문

1. 랜덤 에이전트 돌려보고 점수 읽기

npm run build:envpython/example_random_agent.py를 실행한다. 출력되는 obs 크기·행동 수·steps/sec·총 보상·최종 info(레벨/처치/골드)를 확인하고, "무작위로 움직이면 몇 레벨까지 가나"를 기준점으로 삼아본다.

난이도 ★★ — 보상 셰이핑

2. 보상 가중치 바꿔 "성향"이 바뀌는지 관찰

WoWClassicEnv(rewards={...})questDone을 0으로, kill을 크게 올려본다. 같은 랜덤/규칙 기반 정책에서 처치 수와 퀘스트 완료 수가 어떻게 달라지는지 비교해 "보상이 행동을 만든다"를 체감한다.

난이도 ★★★ — 규칙 기반 에이전트

3. "타깃→공격→루팅" 휴리스틱 봇 작성

관측 벡터에서 가장 가까운 적과 루팅 가능 시체를 읽어, target_nearest → attack → interact를 상황에 맞게 내보내는 손코딩 정책을 만든다. HP가 낮으면 eat_drink를 끼워넣어 생존율을 올려보라. 랜덤 대비 레벨업 속도가 얼마나 빨라지는지 측정.

난이도 ★★★★ — RL 학습

4. PPO로 정책 학습 + 벡터 환경 병렬화

make_envgymnasium.vector.SyncVectorEnv로 환경 N개를 병렬로 띄우고, Stable-Baselines3 PPO 등으로 워리어를 학습시킨다. 학습 곡선(에피소드 보상·도달 레벨)을 로깅해 랜덤/휴리스틱 대비 우위를 보인다.

난이도 ★★★★★ — 환경 확장

5. 관측·행동·종료조건을 직접 손보기

obs.ts에 새 관측(예: 인벤토리 요약)을 추가하거나, 새 행동/보상 항목을 정의하고, env_server.ts의 종료조건을 "특정 퀘스트 완료 시 terminate"로 바꿔본다. npm test로 시뮬 무결성을 깨지 않았는지 검증하면서 진행한다 — 이게 진짜 "실험 하니스를 손보는" 작업이다.

9심화 학습 로드맵

RL 환경 + 멀티플레이 백엔드를 4주에 걸쳐 내 것으로 만드는 경로.

1주차
RL 기초와 Gymnasium — MDP(관측/행동/보상/전이), 에피소드와 종료/절단의 차이, reset/step 계약. WoC의 wow_env.py를 줄 단위로 읽으며 표준 환경의 모양을 익힌다.
2주차
환경 내부 — 관측·행동·보상 설계obs.ts의 정규화/각도 인코딩, 보상 셰이핑 이론(스파스 vs 덴스), frameSkip의 트레이드오프. 실습 2·3번으로 직접 보상을 바꿔본다.
3주차
정책 학습 — 정책 경사/PPO 개념, 벡터 환경 병렬화, 학습 안정화. 실습 4번으로 실제 학습을 돌리고 로깅·평가 루프를 짠다.
4주차
시스템 측 — 권위 서버와 결정론server/의 권위 모델, WS 스냅샷 동기화, 결정론 시뮬의 가치(rng.ts), 그리고 IPC로 두 언어를 잇는 설계. 실습 5번으로 환경 자체를 확장한다.

10핵심 키워드 사전

키워드
결정론 시뮬레이션시드가 같으면 결과가 항상 같은 시뮬. 비교 실험과 RL 재현성의 전제.
헤드리스(headless)화면·DOM 없이 로직만 실행. 초당 수십만 스텝의 고속 반복을 가능하게 함.
관측(observation)에이전트가 매 스텝 보는 상태 벡터. WoC는 self/스킬/타깃/주변몹/상호작용/퀘스트로 구성된 float 배열.
행동 공간(action space)에이전트가 고를 수 있는 동작 집합. WoC는 Discrete(N) 이산 행동 — N은 직업 최대 스킬 수(현재 21)에 따라 동적 산출. 고정 13개 행동 + 스킬 슬롯 N개.
보상 셰이핑원하는 행동을 유도하도록 보상에 가중치를 설계하는 일. WoC는 config로 통째 교체 가능.
frameSkip한 번의 행동을 몇 sim 틱 동안 유지할지. WoC 기본 5틱(=1초의 1/4 결정 주기).
terminated / truncated각각 "게임 규칙상 종료(20렙·사망)"와 "시간 제한으로 절단(maxSteps)". Gymnasium이 구분.
권위 서버모든 판정을 서버가 하는 멀티플레이 구조. 클라이언트는 입력 의도만 전송하는 렌더러.
IWorld로컬 Sim과 온라인 ClientWorld가 공유하는 인터페이스. 렌더러가 백엔드를 몰라도 되게 함.
NDJSON줄바꿈으로 구분된 JSON 스트림. WoC가 stdio로 환경↔에이전트를 잇는 프로토콜.
GymnasiumRL 환경의 사실상 표준 인터페이스(구 OpenAI Gym 후속). reset/step/close.

11참고 링크

지금 바로 해보기

"게임을 켜기 전에, 에이전트부터 태워보자"

  1. 레포 클론 + 의존성 설치git clonenpm install.
  2. RL 환경 번들 빌드npm run build:envdist-env/env_server.cjs를 만든다.
  3. 처리량부터 체감npm run bench 로 단일 코어 steps/sec를 눈으로 확인(왜 이게 "빠른 실험대"인지 즉시 와닿는다).
  4. 랜덤 에이전트 실행pip install gymnasium numpypython python/example_random_agent.py. 무작위로 몇 레벨까지 가는지 기준점을 잡는다.
  5. 그다음 사람으로 입장npm run dev → Play Offline. 방금 에이전트가 돌던 "그 월드"에 직접 들어가 본다.
levy-street/world-of-claudecraft 딥다이브 · WoW-Classic 미니 MMO이자 헤드리스 RL/에이전트 실험 하니스 · 분석 기준 v0.7.0
원본: github.com/levy-street/world-of-claudecraft · 코드 MIT · 번들 에셋 대부분 CC0