예제 소스
바둑 on-policy 학습: 대국 로그를 KataGo 라벨로 바꾸기 · 파일 169개
README.md
# Baduk (바둑 19×19) — Qt6
`omook` 프로젝트와 같은 Qt6/CMake 구조로 만든 19×19 바둑 프로그램입니다.
## 모드
- **사람 대 사람**: 한 화면에서 흑/백을 번갈아 클릭.
- **사람 대 AI**: 사람 색을 흑(선) / 백(후) 중 선택. 로컬 휴리스틱 AI 가 상대.
- **AI 대 VLM (TCP)**: 로컬 AI 와 원격 VLM 서버가 자동으로 대국 진행 (학습/평가용).
- **사람 대 VLM (TCP)**: 사람이 직접 VLM 과 대국. VLM 실패 시 로컬 AI 가 대체합니다.
- **VLM 대 VLM (TCP)**: 두 VLM 엔드포인트가 자동 대국. 백 측 host/port 를 비워 두면 흑 측과 같은 서버로 self-play (한 모델끼리 두기). 채워 두면 두 서버(다른 LoRA 어댑터) 의 정책 비교가 됩니다.
- **학습 모드(기보 저장)** 체크박스: 켜 두면 종국되는 모든 판이 `recordings/baduk-<timestamp>.sgf` 로 자동 저장. **자동 재시작 + 학습 모드 + VLM 대 VLM** 조합으로 N판 자가 대국을 자동 수집할 수 있습니다. 수집한 기보는 `sgf_data/` 로 옮겨 `vlm_server/dataset_baduk` 로 학습 데이터에 바로 포함시킬 수 있습니다.
## 규칙
- 정통 바둑 규칙(따냄, 자살수 금지, **위치 슈퍼코 (positional superko)**, 두 번 연속 패스 시 종국).
- 채점은 **중국식(area scoring)** : 자기 색 돌 수 + 자기 색만이 둘러싼 빈 점 + 덤.
- 덤 기본값 **2.5** (백 가산). UI 의 "덤" 스핀박스로 0.0~30.5 범위에서 변경 가능.
- **어림 점수(실시간)**: 게임 진행 중에도 매 수마다 상태바에 한 줄로 표시. `어림 흑 N.N vs 백 N.N (덤 2.5) — 흑 +N.N | 돌·영역·사석·분쟁·공배` 형태. 살아있는 그룹의 돌과 확정 영역만 점수에 반영하고 분쟁(Active) 영역은 점수에서 빼고 따로 표시하므로 종국 정확 계가와 차이가 날 수 있는 보수적 어림입니다(실력에 따른 사석 판정도 휴리스틱).
## 조작
- 교차점을 클릭하면 현재 차례의 돌이 놓입니다.
- 우측 상단 버튼:
- **새 게임**: 같은 모드/설정으로 보드 초기화.
- **패스**: 현재 차례 패스. 두 번 연속 패스되면 종국하여 승패/점수 표시.
- **기권**: 현재 차례가 기권 (상대 승).
- AI 대 VLM 모드에서는 자동 진행됩니다. VLM 응답이 너무 오래 걸리면 **VLM 응답 취소** 를 누르면 로컬 AI 가 대신 둡니다.
### VLM 서버 설정 행 (서버1 / 서버2)
- **서버1** 행: AI 대 VLM / 사람 대 VLM 의 단일 VLM, VLM 대 VLM 의 흑 측 엔드포인트.
- **서버2** 행: VLM 대 VLM 모드에서만 보임. 백 측 VLM 별도 엔드포인트(다른 LoRA 어댑터/포트). host·port 를 비워 두면 서버1 과 같은 서버라는 의미.
- 각 서버 행의 **접속 확인** 버튼은 **타임아웃** 안에 PING/PONG 왕복이 끝나는지 일회성 검사. 결과는 옆 라벨에 색상으로 표시:
- 회색 `● 미확인` — 아직 검사 안 함
- 황갈색 `● 확인 중…` — 검사 진행
- 녹색 `● 응답 OK host:port (NN ms)` — 정상
- 빨강 `● 실패 host:port: 사유 (NN ms)` — 타임아웃/연결 실패 등
접속 확인은 **인게임 영구 소켓을 건드리지 않는 별도 검사** 라서, 진행 중인 게임 도중에 두 서버를 자유롭게 ping 해도 게임 흐름이 끊기지 않습니다.
- 공용 행의 **타임아웃(s)** 값이 추론 요청과 접속 확인 검사 둘 다에 적용됩니다.
- **자동 재접속** 체크박스: 접속 확인이 실패하면 백오프(1.5s → 3s → 4.5s → … 최대 15s) 로 자동 재시도. 라벨이 매 0.25s 마다 갱신되어 `● 재접속 대기 #2 — 2.3s 후 재시도 (host:port)` 카운트다운이 보입니다. 성공하거나 [접속 확인] 을 다시 누르면 카운터가 리셋됩니다. 6회 연속 실패하면 자동 중단되고 `● 자동 재접속 중지 …` 안내가 뜨므로, 서버를 띄운 뒤 다시 [접속 확인] 을 누르면 됩니다. 두 서버는 각자 독립적으로 카운터·대기시간을 갖습니다.
## VLM TCP 프로토콜 (GO19)
- 요청 프레임: `"GO19" (4) | body_len (u32 BE) | body`
- body = `size (u8=19) | ai_side (u8: 1=Black,2=White) | png_len (u32 BE) | png bytes | size*size board bytes (0=빈, 1=흑, 2=백, row-major)`
- 응답 프레임:
- 성공: `"RPLY" (4) | flag=1 (u8) | row (u8) | col (u8)` — 패스는 `row=255, col=255`
- 실패: `"RPLY" (4) | flag=0 (u8) | err_len (u16 BE) | err utf-8 bytes`
- 핑: 클라이언트가 `"PING"` (4 bytes) 를 보내면 서버는 `"PONG"` (4 bytes) 응답.
서버는 `omook/vlm_server` 와 같은 구조로 별도 구현하시면 됩니다 (서버 실행은 사용자가 직접).
## 빌드
```bash
cmake -S . -B build
cmake --build build -j
./build/baduk
# 또는 macOS app bundle: ./build/baduk.app/Contents/MacOS/baduk
```
`Qt6 (Widgets, Network)` 가 설치되어 있어야 합니다.