# chess_detect

Библиотека для автоматического распознавания шахматных тактических тем в PGN-партиях с использованием [python-chess](https://python-chess.readthedocs.io/).

Анализирует PGN-файлы и добавляет к ходам комментарии с тактическими мотивами: вилки, связки, копья, вскрытые шахи и другие. Поддержка русского и английского языков, визуальные стрелки в PGN.

[English documentation](README.md)

## Установка

```bash
pip install chess-detect
```

Для разработки:

```bash
git clone https://github.com/aslyamov/chess_detect.git
cd chess_detect
pip install -e ".[dev]"
```

## Использование

```python
from chess_detect import ChessDetector

detector = ChessDetector(lang="ru")  # или lang="en"

pgn = """
1. e4 e5 2. Nf3 Nc6 3. Bb5 a6
"""

result = detector.analyze(pgn)
print(result)
# PGN с комментариями о тактических темах
```

---

## Реализованные детекторы

### 1. Двойной шах (Double Check)

**Что это:** Две фигуры одновременно атакуют короля противника.

**Пример:** Белый слон на c4 смотрит на короля e8. Белый конь с e5 прыгает на f7, давая шах. Одновременно слон c4 тоже даёт шах через открывшуюся диагональ. Король обязан ходить — нельзя ни заблокировать, ни взять обе фигуры.

---

### 2. Вилка (Fork)

**Что это:** Одна фигура атакует две или более ценных фигуры противника одновременно.

**Пример:** Чёрный король на e8, чёрный ферзь на d7. Белый конь прыгает на c5, атакуя и короля, и ферзя. Король уходит — ферзь теряется.

**Условия:**
- Минимум 2 ценных цели (король, или фигура дороже атакующей, или висящая)
- Если нет шаха и атакующая фигура висит — вилка не работает

---

### 3. Вскрытый шах (Discovered Check)

**Что это:** Фигура уходит с линии, открывая шах от другой фигуры. При этом уходящая фигура делает полезную атаку или взятие.

**Пример:** Белая ладья на e1, белый конь на e4, чёрный король на e8. Конь уходит на f6, атакуя чёрного ферзя на d7. Одновременно ладья e1 даёт шах королю e8. Противник отвечает на шах, а конь забирает ферзя.

---

### 4. Связка (Pin)

**Что это:** Фигура атакует две фигуры противника на одной линии. Передняя не может уйти, иначе откроет более ценную заднюю.

**Пример:** Чёрный король на e8, чёрный конь на e5. Белый слон идёт на c3, связывая коня с королём. Конь не может ходить — иначе слон возьмёт короля.

**Виды:**
- **Абсолютная** — сзади король (связанная фигура не может ходить легально)
- **Относительная** — сзади фигура дороже передней

---

### 5. Копьё (Skewer)

**Что это:** Обратная связка. Более ценная фигура спереди, менее ценная сзади. Передняя вынуждена уйти, открывая заднюю.

**Пример:** Чёрный король на e5, чёрная ладья на e1. Белый слон идёт на a1, атакуя короля по диагонали. Король уходит — слон берёт ладью.

---

### 6. Пойманная фигура (Trapped Piece)

**Что это:** После хода фигура противника в ловушке — все её ходы ведут на поля под боем.

**Пример:** Чёрный конь на h8. Белый ферзь на h1 атакует по вертикали. Ладья f6 контролирует f7, слон f5 контролирует g6. После хода g5-g6 конь полностью заблокирован: Nf7 под ладьёй, Nxg6 под слоном.

---

### 7. Взятие висящей фигуры (Hanging Capture)

**Что это:** Взятие фигуры, которая была незащищённой или могла быть взята с выигрышем материала.

**Пример:** Чёрный конь на e5 никем не защищён. Белая ладья берёт — бесплатное взятие.

**Условия:**
- Фигура не защищена, ИЛИ
- Может быть взята более дешёвой фигурой

---

### 8. Уничтожение защитника — выигрыш фигуры

**Что это:** Взятие фигуры, которая защищала другую. Теперь та фигура висит.

**Пример:** Чёрный конь на c3 защищает слона на e4. Белый слон b1 атакует e4. Белый ферзь берёт коня c3 — теперь слон e4 не защищён.

---

### 9. Уничтожение защитника — угроза мата

**Что это:** Взятие фигуры, которая защищала ключевое поле. Появляется угроза мата в 1 ход.

**Пример:** Чёрный король на h8, ладья h7 защищает поле h2. Белый ферзь на g2 хочет Qh2#, но ладья защищает. Белая ладья берёт Rxh7 — теперь Qh2# неизбежен.

---

### 10. Использование связки (Exploiting Pin)

**Что это:** Атака на связанную фигуру (она не может убежать) или взятие через связанного защитника (он не может отбить).

**Пример:** Чёрный конь на e4 связан ладьёй e1 с королём e8. Белая пешка d2 идёт на d3, атакуя связанного коня. Конь не может уйти — будет взят.

---

## Таблица статусов

| Тема | Русский | English | Статус |
|------|---------|---------|--------|
| Двойной шах | Двойной шах | Double Check | ✅ |
| Вилка | Вилка | Fork | ✅ |
| Вскрытый шах | Вскрытый шах | Discovered Check | ✅ |
| Связка | Связка | Pin | ✅ |
| Копьё | Копьё | Skewer | ✅ |
| Пойманная фигура | Пойманная фигура | Trapped Piece | ✅ |
| Взятие висящей | Взятие висящей фигуры | Hanging Capture | ✅ |
| Уничт. защитника (материал) | Уничтожение защитника (выигрыш фигуры) | Removing Defender (winning material) | ✅ |
| Уничт. защитника (мат) | Уничтожение защитника (угроза мата) | Removing Defender (mate threat) | ✅ |
| Использование связки | Использование связки | Exploiting Pin | ✅ |

### Планируемые

| Тема | Статус |
|------|--------|
| Отвлечение (Deflection) | ⬜ |
| Завлечение (Decoy) | ⬜ |
| Промежуточный ход (Zwischenzug) | ⬜ |
| Вскрытая атака (Discovered Attack) | ⬜ |
| Линейный мат (Back Rank Mate) | ⬜ |
| Спёртый мат (Smothered Mate) | ⬜ |

---

## Стрелки в PGN

Обнаруженные тактики визуализируются зелёными стрелками (`[%cal]`) и подсветкой полей (`[%csl]`) в PGN-выводе. Эти аннотации отображаются на Lichess, chess.com и других шахматных платформах.

Пример вывода:

```
1. Nc7+ { [%csl Ga8,Ge8][%cal Gc7a8,Gc7e8] Вилка (Кc7 → Фa8, Крe8) }
```

---

## Архитектура

```
chess_detect/
├── __init__.py          # Экспорт ChessDetector
├── detector.py          # Главный класс
├── context.py           # MoveContext — ленивые вычисления
├── utils.py             # Утилиты (ценности фигур)
├── i18n/                # Переводы
│   ├── ru.py
│   └── en.py
└── detectors/
    ├── base.py          # BaseDetector
    └── tactics/
        ├── double_check.py
        ├── fork.py
        ├── discovered_check.py
        ├── pin.py
        ├── skewer.py
        ├── trapped.py
        ├── hanging_capture.py
        ├── removing_defender.py
        └── exploiting_pin.py
```

---

## Добавление нового детектора

```python
from ..base import BaseDetector
from ...context import MoveContext

class MyTacticDetector(BaseDetector):
    key = "my_tactic"  # ключ для i18n

    def detect(self, ctx: MoveContext) -> bool:
        # ctx.board_before — позиция до хода
        # ctx.board_after — позиция после хода
        # ctx.move — сам ход
        # ctx.is_check — шах ли после хода
        # ctx.is_capture — взятие ли
        # ctx.captured_piece — взятая фигура
        return False
```

1. Создайте файл в `detectors/tactics/`
2. Добавьте переводы в `i18n/ru.py` и `i18n/en.py`
3. Зарегистрируйте в `detector.py`

---

## Тесты

```bash
python -m pytest tests/ -v
```

**89 тестов** — все проходят.

---

## Лицензия

[MIT](LICENSE)
