게시판SGF 기보로 학습하는 바둑 LLM 인공지능예제 소스

예제 소스

SGF 기보로 학습하는 바둑 LLM 인공지능 · 파일 169개

shapes.py

"""모양 판정: 호구(虎口).

호구 = 빈 점 P 의 네 방향 중 세 방향이 같은 색 돌(판 밖은 벽으로 셈)이고 남은 한 방향(입구)이 빈 점.
  - 상대 호구에 들어가면 입구 하나만 남는 단수 → 바로 잡힌다 (hogu_entry)
  - 내 호구를 메우면 이미 끊기지 않는 곳에 한 수를 쓰는 느린 수 (hogu_fill)
    단, 둘러싼 내 그룹 활로가 2 이하(먹여치기·수부족 위험)이거나 따내는 수면 메워도 된다.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Optional

from .ladder import BOARD_SIZE, _Board

Point = tuple[int, int]


@dataclass
class HoguInfo:
    point: Point
    owner: int  # 호구를 만든 색
    mouth: Point  # 입구(빈 점)
    walls: int  # 판 밖 방향 수


def tiger_mouth(cells: bytes | bytearray, r: int, c: int, *, size: int = BOARD_SIZE) -> Optional[HoguInfo]:
    idx = r * size + c
    if cells[idx] != 0:
        return None
    color = 0
    stones = 0
    walls = 0
    empties: list[Point] = []
    for dr, dc in ((-1, 0), (1, 0), (0, -1), (0, 1)):
        nr, nc = r + dr, c + dc
        if not (0 <= nr < size and 0 <= nc < size):
            walls += 1
            continue
        v = cells[nr * size + nc]
        if v == 0:
            empties.append((nr, nc))
        elif color == 0 or v == color:
            color = v
            stones += 1
        else:
            return None
    if color == 0 or len(empties) != 1 or stones < 2 or stones + walls != 3:
        return None
    return HoguInfo((r, c), color, empties[0], walls)


def hogu_verdict(
    cells: bytes | bytearray, r: int, c: int, who: int, *, size: int = BOARD_SIZE
) -> Optional[str]:
    """who 가 (r,c) 에 둘 때 호구 관련 나쁜 수면 'hogu_entry' | 'hogu_fill', 아니면 None."""
    info = tiger_mouth(cells, r, c, size=size)
    if info is None:
        return None
    b = _Board(cells, size)
    idx = r * size + c
    b2 = b.copy()
    captured = b2.play(idx, who)
    if captured is None or captured > 0:
        return None
    if info.owner != who:
        return "hogu_entry" if len(b2.group(idx)[1]) <= 1 else None
    for dr, dc in ((-1, 0), (1, 0), (0, -1), (0, 1)):
        nr, nc = r + dr, c + dc
        if 0 <= nr < size and 0 <= nc < size and b.c[nr * size + nc] == who:
            if len(b.group(nr * size + nc)[1]) <= 2:
                return None
    return "hogu_fill"


def hogu_points(cells: bytes | bytearray, *, size: int = BOARD_SIZE) -> list[HoguInfo]:
    out = []
    for i in range(size * size):
        if cells[i] == 0:
            h = tiger_mouth(cells, i // size, i % size, size=size)
            if h is not None:
                out.append(h)
    return out