69 lines
3.9 KiB
Markdown
69 lines
3.9 KiB
Markdown
# AI 전투 시뮬레이터 (TODO 항목 F) — 설계
|
|
|
|
> 작성: 2026-06-09 / 상태: 승인됨 / 근거: TODO.md 항목 F + gen-slaydeck.mjs 전투 규칙 + D 데이터.
|
|
> 선행: D(데이터 외부화) 완료.
|
|
|
|
## 문제
|
|
|
|
박재오 강점(백엔드·AI 자동화) 활용처로 기획됐으나 코드 없음. 카드/적 밸런싱을 손으로
|
|
검증해야 한다. 데이터 기반 자동 밸런스 검증 도구가 필요하다.
|
|
|
|
## 목표
|
|
|
|
`data/cards.json`·`data/enemies.json`를 입력으로, 전투를 몬테카를로로 N회 자동 시뮬레이션해
|
|
승률·평균 턴·OP 카드 탐지 리포트를 출력하는 오프라인 Node CLI(`tools/sim-balance.mjs`).
|
|
|
|
## 설계
|
|
|
|
### 구조
|
|
`tools/sim-balance.mjs` 단일 파일, 섹션 분리:
|
|
1. **데이터 로드**: `data/cards.json`·`data/enemies.json`(D와 동일 소스). `activeEnemy` 사용.
|
|
2. **시드 PRNG**: mulberry32(시드 고정 → 재현 가능, 데이터 바꾸면 결과 변동).
|
|
3. **전투 엔진**(Lua 규칙 미러): 아래 규칙을 JS로 재현.
|
|
4. **플레이어 정책**(휴리스틱 A).
|
|
5. **집계·리포트**.
|
|
6. **CLI 파싱·출력**.
|
|
|
|
### 전투 규칙 (gen-slaydeck.mjs Lua와 동일)
|
|
- 시작: 플레이어 `hp=PLAYER_HP(상수 80)`, `block=0`; 적 `hp=maxHp`, `block=0`, `intentIdx=0`(0-base).
|
|
덱 = `starterDeck` 셔플(PRNG).
|
|
- 플레이어 턴 시작: `energy=3`, `block=0`, 5장 드로우(덱 소진 시 버림 더미 셔플해 재활용).
|
|
- 플레이어 행동: 정책이 카드 선택 → 사용 시 `energy -= cost`, `Attack`→적에 `damage`(적 block 우선 차감),
|
|
`Skill`→플레이어 `block += block`. 사용 카드는 버림. 더 둘 수 없으면 턴 종료.
|
|
- 적 턴: 적 `block=0` → 현재 의도 실행(`Attack`→플레이어에 피해(플레이어 block 우선 차감),
|
|
`Defend`→적 `block += value`) → `intentIdx=(intentIdx+1)%len`.
|
|
- 승패: 적 hp≤0 승리, 플레이어 hp≤0 패배. 턴 상한 `MAX_TURNS=100`(초과 시 무승부로 집계, 경고).
|
|
|
|
### 플레이어 정책 (휴리스틱 A)
|
|
매 플레이어 행동 루프:
|
|
1. **치사 판단**: 손패의 Attack 카드들로 이번 턴 낼 수 있는 최대 데미지(에너지 한도 내) ≥
|
|
`적 hp + 적 block` 이면 → 그 Attack들을 사용(킬).
|
|
2. 아니면 **적 의도가 Attack**이면 → 손패 Defend(Skill+block) 카드를 사용(에너지 닿는 한),
|
|
이후 잔여 에너지로 Attack 사용.
|
|
3. 아니면(적 Defend 의도) → Attack 우선 사용.
|
|
4. 사용 가능한 카드(에너지≥cost)가 없으면 턴 종료.
|
|
- 동률 선택은 에너지 효율(뎀/E 또는 블록/E) 높은 카드 우선.
|
|
|
|
### 리포트 지표
|
|
- 전체: 승률(%), 평균·중앙값 턴 수, 승리 시 평균 잔여 HP, 패배율, (무승부 시 경고).
|
|
- 카드별: 사용 횟수, 누적 데미지/방어, **에너지당 효율**(Attack=총뎀/총E, Skill=총블록/총E).
|
|
- **OP 탐지**: 같은 kind 내 효율이 그 kind 중앙값의 ≥1.5배인 카드를 ⚠️로 플래그. 최다/최소 사용 카드 표기.
|
|
|
|
### CLI
|
|
`node tools/sim-balance.mjs [N] [--seed S]` — 기본 `N=2000`, `seed=1`. 표 형식 출력.
|
|
|
|
### 동기화 위험
|
|
JS 전투 규칙은 Lua(`gen-slaydeck.mjs`)와 **중복**이다(공유 불가). 데이터(JSON)는 공유.
|
|
파일 상단에 "전투 규칙 변경 시 gen-slaydeck.mjs Lua와 동기화" 주석 명시.
|
|
|
|
## 검증 (TDD + CLI)
|
|
- 전투 엔진/정책 핵심을 순수 함수로 분리해 단위 테스트(Node 내장 `node:test`):
|
|
데미지 방어차감, 치사 판단, 적 의도 사이클, 승/패 종료.
|
|
- `node tools/sim-balance.mjs` → 승률·턴·카드 통계 출력.
|
|
- `data/cards.json`에서 강타 damage↑ → 승률·강타 효율 상승(데이터 반영).
|
|
- 동일 시드 2회 → 동일 출력(결정성).
|
|
|
|
## 범위 밖 (금지)
|
|
- 상태이상·드로우·복합효과, 다중 적, 로그라이크 메타. 메이커 런타임 연동.
|
|
- 새 카드/적 추가(현 데이터로 검증). 정책 고도화(MCTS 등).
|