도로를 그려 영토를 넓히고, 상대의 도로를 밟아 제거하는 실시간 멀티플레이 영토 점령 게임. 기획·구현·배포부터 그 위에 올린 강화학습 에이전트까지 전부 자체 제작했습니다.
80×80 타일 맵에서 최대 6인이 동시에 겨룹니다. 서버가 초당 20회 시뮬레이션을 돌리고 클라이언트는 상태를 받아 그리기만 합니다 — 판정은 전부 서버에 있습니다.
관전 모드 오버뷰 — 테마별 지형·건물·데코가 전부 코드로 생성됩니다
로비 — 테마 10종 중 선택하거나 컨셉을 입력하면 LLM이 팔레트를 생성합니다
테마별로 타일·건물 텍스처가 절차적으로 생성됩니다
게임 로직을 독립 패키지로 분리해 서버와 클라이언트가 같은 코드를 공유합니다. 덕분에 같은 로직을 헤드리스로 돌려 강화학습 환경으로 재사용할 수 있습니다.
Phaser 3 · TypeScript · Vite. 텍스처를 런타임에 절차 생성해 에셋 없이 10종 테마를 지원합니다.
Colyseus 권위 서버. 초당 20틱 시뮬레이션, 상태 동기화, 봇 7기 제어를 단일 프로세스에서 처리합니다.
이동·충돌·점령 판정이 순수 함수로 분리된 game-core. 서버·클라이언트·RL 환경이 함께 씁니다.
| 스택 | TypeScript 모노레포 (pnpm workspace) · Node.js · Python |
| 실시간 통신 | WebSocket (Colyseus) — 서버 권위, 클라이언트 예측 없음 |
| 맵 / 인원 | 80×80 타일 · 최대 6인 · 봇 7기 자동 충원 |
| 배포 | Docker · Nginx 리버스 프록시 · Let's Encrypt |
게임을 직접 만든 이유가 여기 있습니다. 외부 게임은 관측 공간과 보상 함수를 원하는 대로 설계할 수 없습니다. 코어를 소유하면 학습 환경 자체를 설계할 수 있습니다.
| 알고리즘 | MaskablePPO (sb3-contrib) · Self-Play + 스크립트 봇 혼합 |
| 관측 공간 | 3,107 floats — 21×21×7 지역 그리드 + 플레이어 12 + 전역 8 |
| 행동 공간 | Discrete(5) — UP · RIGHT · DOWN · LEFT · NONE (역주행 마스킹) |
| 정책 네트워크 | MLP [256, 128] |
| 총 학습량 | 6M timesteps (v0 2M + v1 2M + v2 CNN 2M) |
| 추론 | ONNX 서버사이드 — 실측 0.18ms/회, 초당 5,500회 처리 |
| 보상 수렴 | ep_rew_mean −82 → ~300 (2M 스텝, 진동 균형점으로 수렴) |
| v1 개선 효과 | 진동 폭 53pt → 23pt (2.3× 안정화) — 적 위치 관측 채널 + 엔트로피 보너스 |
| 학습 처리량 | 2M 스텝 69분 · 평균 479 FPS (헤드리스 시뮬레이션) |
영토 밖으로 나가면 트레일이 그려지고, 돌아와 고리를 닫으면 내부가 점령됩니다
학습된 정책은 ONNX로 내보내 게임 서버에 그대로 탑재됩니다. 지금 접속하면 학습된 에이전트 1기와 스크립트 봇 6기가 함께 플레이합니다.
에이전트가 스스로 학습하고, 결과를 분석하고, 알고리즘을 바꿔가며 재학습하는 오케스트레이터를 세 게임에 차례로 적용했습니다. RoadTown.io는 그중 유일하게 직접 만든 환경입니다.
앞의 둘은 외부 게임이라 코어를 건드릴 수 없었습니다. RoadTown.io에서 비로소 기획 → 구현 → 서비스 → 학습 → 자율 개선의 전체 사이클을 하나의 프로젝트 안에서 닫을 수 있었습니다.
이 게임은 AI 에이전트가 스스로 플레이하며 이상 동작을 찾아내는 QA 자동화의 검증 환경으로도 쓰이고 있습니다.
이상 유형별로 시드 + 액션 시퀀스 + 재현율을 명시한 리포트를 준비하고 있습니다. "버그를 찾았다"가 아니라 "이 순서대로 하면 누구나 재현된다"를 목표로 합니다.