텍스트 프롬프트 → Beyond All Reason(BAR) 미니게임 config(JSON) 생성.
┌────────────────────────┐ ┌────────────────────────┐
│ Frontend │ POST /generate ─────► │ Backend │
│ React + Vite │ GET /catalog ─────► │ FastAPI │
│ │ ◄───── config JSON │ │
│ PromptInput / MiniMap │ │ pipeline.py │
│ SimPlayback / JsonView │ │ (DB match -> script) │
└────────────────────────┘ └────────────────────────┘
프론트는 React+Vite이지만 생성 로직이 Python이라, 둘을 잇는 얇은 FastAPI 백엔드를 둔다. (기존
front_end의 backend/frontend 분리 패턴과 동일)
rtsgame/
├── README.md
├── backend/ # Python: 단순화 파이프라인 + API
│ ├── app.py # FastAPI: POST /generate, GET /catalog, GET /health
│ ├── pipeline.py # ① DB 매칭 → ② gdd 구성 → ③ script 생성 오케스트레이션
│ ├── script_builder.py # ScriptDeveloper (analyst/verify 제거한 경량 그래프)
│ ├── db_call.py # DBCall: scenario LLM 매칭
│ ├── common.py # LLM 클라이언트 + DB 로더
│ ├── developer_prompt.py # 맵선택/유닛배치/rule/조건 프롬프트
│ ├── db/ # 시나리오·rule·map·unit·decision DB (v4에서 복사)
│ ├── info/ # 유닛/맵 정보 (units_info.json 등)
│ ├── requirements.txt
│ └── .env.example
└── frontend/ # React + Vite
├── index.html
├── package.json
├── vite.config.js # /api → http://localhost:8000 프록시
└── src/
├── main.jsx
├── App.jsx # 입력 + 결과 레이아웃 + catalog 로딩
├── api.js # backend 호출 (/api/generate, /api/catalog)
├── styles.css
└── components/
├── PromptInput.jsx # 프롬프트 입력 + 예시 칩 + 생성 버튼
├── ConfigSummary.jsx # 매칭 시나리오/맵/승패조건/유닛/gadget 요약
├── MiniMap.jsx # unit_placement 2D 캔버스 시각화
└── JsonView.jsx # config JSON + 복사/다운로드
- 맵 size는 타일 단위(타일 = 512px). 예: 16×16 맵 → 8192×8192 픽셀.
- 유닛은 픽셀 좌표로 배치.
핵심: GDD를 새로 생성하지 않고, 기존 DB에서 비슷한 시나리오를 찾아 script만 만든다. rule(gadget)도 새로 만들지 않고 DB의 검증된 것만 사용한다.
find_scenario(query)—DBCall이db/scenario/meta.json설명을 LLM으로 매칭해 가장 비슷한 시나리오 선택.load_existing_mode(name)— 시나리오의specification+ 참조 rule로 gdd 구성. rule은 모두action: existing,validated: True(기존 검증본).ScriptDeveloperAgent.run()(script_builder.py) — 맵선택 → 유닛배치 → rule config → end_condition → 조립. analyst/verify 루프 제거로game_simulation(BAR 엔진)·psutil의존성을 런타임에서 완전히 들어냄.
POST /generate {query}→{ scenario, config, raw }(config = 생성된 시나리오 JSON).GET /catalog→ 매칭 가능한 시나리오 + 맵 목록 (프론트 표시용).GET /health, CORS 허용.
- PromptInput: 텍스트 입력 + 예시 칩 + 생성 버튼 (⌘/Ctrl+Enter).
- ConfigSummary: 매칭 시나리오, 맵, 승/패 조건, 팀별 유닛 수, gadget 요약.
- MiniMap: 맵 크기(타일×512px) 비례 캔버스에 팀별 유닛 좌표를 점으로 시각화.
- JsonView: config JSON 표시 + 복사/다운로드.
- 배포 데모: https://rts-game-reokyoung-16359u66u-rlafuruds-projects.vercel.app/ → 프롬프트 생성 + 브라우저 시각화까지 바로 사용 가능.
배포본은 생성 + 시각화까지만 됩니다. 실제 BAR 게임 실행은 아래처럼 게임이 설치된 로컬 PC에서만 가능합니다.
준비물
- Beyond All Reason 설치 (Windows)
- 게임 런처
minigame_generator_v4/폴더 (레포 미포함 — 별도로 보유해야 함) - Python, 그리고
backend/.env에OPENAI_API_KEY입력
실행 (원클릭)
- (최초 1회) 프론트 빌드:
cd frontend && npm install && npm run build - 루트의
start_local.bat더블클릭 → 브라우저가http://localhost:8000자동 열림 - 프롬프트 생성 → 🎮 BAR에서 실행 → 실제 게임 창이 뜸
배포 사이트에서 실행 버튼을 눌러도, 켜져 있는 내 PC의 로컬 백엔드(
localhost:8000)로 자동 연결돼 게임이 켜집니다. (Chrome 권장)
개발 모드(핫리로드)로 따로 띄우려면: backend에서 uvicorn app:app --reload, frontend에서 npm run dev.
cd backend && pip install -r requirements-dev.txt && python -m pytest # 백엔드
cd frontend && npm test # 프론트 (vitest)한 줄 소개: 자연어 프롬프트로 RTS 게임(Beyond All Reason) 미니게임 시나리오를 생성하는 도구입니다. 프롬프트를 입력하면 DB에서 가장 비슷한 게임 시나리오를 매칭하고, 게임 config(JSON)를 생성한 뒤, 브라우저에서 2D 플레이백으로 시각화합니다.
저장소: boostcampwm-snu-2026-1/RTSGame_ReokyoungKim
주요 기술 스택:
| 구분 | 기술 |
|---|---|
| 백엔드 | Python, FastAPI, LangGraph, OpenAI gpt-5.2 |
| 프론트엔드 | React, Vite, Canvas 2D |
폴더 요약:
| 폴더 | 설명 |
|---|---|
backend/ |
Python + FastAPI 서버. 자연어 쿼리를 받아 시나리오 매칭 → gdd 구성 → script 생성의 3단계 파이프라인을 수행. 주요 모듈: pipeline.py, script_builder.py, db_call.py, developer_prompt.py, db/(scenario·rule·map·unit·decision 데이터) |
frontend/ |
React + Vite SPA. 프롬프트 입력(PromptInput), 시나리오/맵/승패조건 요약(ConfigSummary), 2D 배치 미니맵(MiniMap), 브라우저 근사 플레이백(SimPlayback), config JSON 뷰어(JsonView) 컴포넌트로 구성. /api는 localhost:8000으로 프록시 |
main → dev → feature/* 3단계 브랜치 전략을 사용합니다.
| 브랜치 | 역할 |
|---|---|
main |
릴리스(배포) 브랜치. 항상 동작이 보장되는 안정 버전만 유지합니다. |
dev |
통합(개발) 브랜치. 완료된 기능들을 모아 검증하는 기본 작업 브랜치입니다. |
feature/* |
기능 단위 작업 브랜치. 이슈(Task) 하나당 하나의 feature/* 브랜치에서 개발합니다. |
feature/find-scenario ─┐
feature/sim-playback ─┼─▶ dev ─────▶ main
feature/mini-map ─┘ (통합/검증) (릴리스)
feature/*는 항상dev에서 분기하여 작업합니다.- 작업이 끝나면
feature/* → dev로 PR을 올려 병합합니다. dev에서 검증이 끝난 안정 버전을dev → main으로 병합하여 릴리스합니다.
모든 작업(Task)은 GitHub Issues로 등록하고 관리합니다.
- 하나의 이슈는 하나의 작업 단위(기능/버그/문서 등)를 의미하며, 이슈 단위로
feature/*브랜치를 생성합니다. - PR에는 관련 이슈 번호를 연결(
Closes #번호)하여 병합 시 자동으로 이슈가 닫히도록 합니다.
라벨 규칙:
| 라벨 | 용도 |
|---|---|
feature |
신규 기능 개발 |
bug |
버그 수정 |
docs |
문서 작업 |
enhancement |
기존 기능 개선 |
backend |
백엔드(FastAPI/파이프라인) 관련 |
frontend |
프론트엔드(React/시각화) 관련 |
프로젝트 문서는 GitHub Wiki에서 관리합니다.
- 기획서: 프로젝트 목표, 단순화 배경(원본 multi-agent 구조 → 단일 흐름), config(JSON) 구조 및 좌표계(1타일 = 512px) 등 설계 정보를 정리합니다.
- Agent 개발 workflow:
ScriptDeveloperAgent의 LangGraph 그래프 흐름(select_map → place_units → generate_rule_config → get_condition → assemble_draft)과 DB(scenario·rule·map·unit) 활용 방식을 문서화합니다.
{ "information": { "description": ["게임 설명 문장들..."], "match_format": "1v1", "map_name": "altored_divide_bar_remake_1.6.2", "fog_of_war": false }, "end_condition": { "victory_condition": ["and", { "time": [">= 1200"] }], "defeat_condition": ["or", { "1": ["armcom == 0"] }] }, "unit_placement": { "1": [["armcom", [4096, 4096]], ["armlab", [4240, 4096]]], // 팀1 유닛 + 픽셀 좌표 "2": [] // 팀2 }, "customize": { "enemy_wave_spawner": { "enabled": true, "waveIntervalFrames": 1800, ... } } }