BurningTimesAi/프로젝트/수상한잡화점/시뮬레이터/02_시나리오_JSON_스키마_v1.md

193 lines
6.4 KiB
Markdown
Raw Normal View History

---
type: 설계문서
project: 수상한잡화점
subject: 시뮬레이션 시나리오 입력 JSON 스키마
version: v1
date: 2026-04-17
status: 초판
author: 개발팀장
---
# 시나리오 JSON 스키마 v1
## 1. 목적
`SimulationRunner`가 받는 **입력 포맷**. 기획팀장이 한 번 작성하면 Unity MCP `execute_code`로 반복 실행 가능. 파라미터 스윕·배치 비교도 본 스키마의 배열 버전으로 처리.
## 2. 최상위 구조
```json
{
"schema_version": "1.0",
"scenario_id": "Anchor_Stage1_NoCard_4Mob",
"description": "앵커 전투 시뮬 — 카드 0장 + 4마리 전열 몬스터 + 터치 방어 전략",
"seed": 12345,
"rng_mode": "deterministic",
"pc": {
"hp": 100,
"max_hp": 100,
"shield": 0,
"attack_dmg": 10,
"attack_cooltime": 1.5,
"defence_strategy": "touch_hold_on_incoming"
},
"monsters": [
{
"id": "mob_front_01",
"hp": 20, "max_hp": 20,
"attack_dmg": 5,
"attack_cooltime": 2.0,
"line": "Frontline",
"attack_type": "Melee"
}
],
"global_value": {
"PCDefence": 1,
"PCDefence_Mul": 0.3
},
"simulation": {
"max_turns": 1000,
"tick_interval": 0.1,
"stop_on_death": true,
"record_detail": true
}
}
```
## 3. 필드 정의
### 3-1. 메타 (필수)
| 필드 | 타입 | 설명 |
|------|------|------|
| `schema_version` | string | 스키마 버전 (`"1.0"`). 하위 호환 체크용 |
| `scenario_id` | string | 고유 식별자. 결과 JSON에 그대로 echo됨 |
| `description` | string | 사람 읽는 설명 (선택) |
| `seed` | int | 난수 시드. 재현성 보장 |
| `rng_mode` | string | `"deterministic"` 또는 `"random"`. 기본값 `"deterministic"` |
### 3-2. PC (필수)
| 필드 | 타입 | 설명 | 기본값 |
|------|------|------|-------|
| `hp` / `max_hp` | float | 시작 HP, 최대 HP | — |
| `shield` | float | 시작 실드 | 0 |
| `attack_dmg` | float | 공격력 | — |
| `attack_cooltime` | float | 공격 쿨타임 (초) | — |
| `defence_strategy` | string | 방어 전략 — 아래 표 참조 | `"never"` |
**defence_strategy 값**:
| 값 | 동작 |
|----|------|
| `"never"` | 방어 사용 안 함 (공격만) |
| `"always"` | 매 tick 방어 (공격 0 DPS) |
| `"touch_hold_on_incoming"` | 몬스터 projectile 발사 감지 시 자동 방어 on, 피격 후 off |
| `"auto_low_hp"` | HP <= `{low_hp_threshold}`% 시 자동 방어 |
### 3-3. Monsters (필수, 배열)
| 필드 | 타입 | 설명 |
|------|------|------|
| `id` | string | 개체 식별자 |
| `hp` / `max_hp` | float | HP |
| `attack_dmg` | float | 공격력 |
| `attack_cooltime` | float | 공격 쿨타임 |
| `line` | string | `"Frontline"` / `"Middleline"` / `"Backline"` |
| `attack_type` | string | `"Melee"` / `"Range"` |
### 3-4. GlobalValue (선택, 미제공 시 실측 기본값 사용)
| 필드 | 타입 | 실측 기본값 | 설명 |
|------|------|-------------|------|
| `PCDefence` | int | 1 | 방어 중 절대값 감소 |
| `PCDefence_Mul` | float | 0.3 | 방어 중 % 감소 (0.3 = 30%) |
실측 기본값 근거: `Assets/ResWork/Table/Export/GlobalValue.json` (Dev 브랜치 `43b6074c4` 시점)
### 3-5. Simulation 제어 (선택)
| 필드 | 타입 | 기본값 | 설명 |
|------|------|-------|------|
| `max_turns` | int | 1000 | 최대 tick 수 (무한루프 방지) |
| `tick_interval` | float | 0.1 | 1 tick당 시간(초) |
| `stop_on_death` | bool | true | PC 또는 몬스터 전멸 시 조기 종료 |
| `record_detail` | bool | false | tick별 상세 로그 생성 여부 (결과 JSON 크기 증가) |
## 4. 파라미터 스윕 (배열 버전)
동일 시나리오를 여러 값으로 돌릴 때:
```json
{
"schema_version": "1.0",
"sweep_id": "Defence_Mul_Grid",
"base_scenario": { /* 위 §2 구조 */ },
"sweep_axes": [
{
"path": "global_value.PCDefence_Mul",
"values": [0.2, 0.3, 0.4, 0.5]
},
{
"path": "monsters[0].attack_dmg",
"values": [3, 5, 7]
}
],
"sweep_mode": "cartesian",
"runs_per_cell": 10
}
```
- `sweep_mode`: `"cartesian"` (모든 조합) 또는 `"zip"` (같은 인덱스끼리)
- `runs_per_cell`: 셀당 반복 횟수 (난수 분산 측정)
## 5. 배치 비교 (시나리오 N개)
```json
{
"schema_version": "1.0",
"batch_id": "Anchor_Strategies_Compare",
"scenarios": [
{ "scenario_id": "strategy_never", /* 전체 시나리오 */ },
{ "scenario_id": "strategy_always", /* ... */ },
{ "scenario_id": "strategy_touch_hold", /* ... */ }
]
}
```
`SimulationRunner.RunBatch(path)`가 배열 순회 실행 후 결과 N건을 모아 반환.
## 6. 검증
`ScenarioLoader`가 로드 시 다음을 검증하여 에러 조기 발견:
1. 필수 필드 부재 → `ScenarioValidationException`
2. `hp > max_hp` → warning
3. `attack_cooltime <= 0` → error
4. 알 수 없는 `defence_strategy` → error
5. `schema_version` 불일치 → warning
## 7. 예시 — 앵커 전투 (카드 0장, 4마리, 터치 방어)
```json
{
"schema_version": "1.0",
"scenario_id": "anchor_stage1_no_card_4mob_touch",
"description": "앵커 전투 Stage 1 — 카드 0장 상태에서 4마리 전열 몬스터와 터치 방어 전략",
"seed": 42,
"pc": {
"hp": 100, "max_hp": 100, "shield": 0,
"attack_dmg": 8, "attack_cooltime": 1.2,
"defence_strategy": "touch_hold_on_incoming"
},
"monsters": [
{"id": "m1", "hp": 15, "max_hp": 15, "attack_dmg": 4, "attack_cooltime": 1.8, "line": "Frontline", "attack_type": "Melee"},
{"id": "m2", "hp": 15, "max_hp": 15, "attack_dmg": 4, "attack_cooltime": 1.8, "line": "Frontline", "attack_type": "Melee"},
{"id": "m3", "hp": 15, "max_hp": 15, "attack_dmg": 4, "attack_cooltime": 1.8, "line": "Frontline", "attack_type": "Melee"},
{"id": "m4", "hp": 15, "max_hp": 15, "attack_dmg": 4, "attack_cooltime": 1.8, "line": "Frontline", "attack_type": "Melee"}
],
"simulation": {"max_turns": 500, "tick_interval": 0.1, "stop_on_death": true, "record_detail": false}
}
```
## 8. 변경 이력
- **v1 (2026-04-17)**: 초판. PD 지시 #37 기반. PCDefence/PCDefence_Mul 실측값 기본 내장.
## 9. 기각안
- **기각안 A**: ScriptableObject 입력 → Unity Editor 외부(MCP)에서 접근 곤란. JSON이 호환성 최고
- **기각안 B**: YAML 입력 → Unity 기본 파서 없음. JSON이 `JsonUtility` 기본 지원
- **기각안 C**: 기존 `Actor.cs`·테이블 구조 그대로 입력 → 시뮬 독립성 훼손. 최소 스키마로 재정의