📊 Анализ алгоритмов: Aggressive против Monte-Carlo
Основываясь на исходном коде ботов (AggressiveSearch, MonteCarloSearch, Evaluator, MonteCarloEquity), мы проанализировали их поведение и нашли ключевые архитектурные различия, которые объясняют, почему Monte-Carlo показывает результаты хуже ожидаемых (винрейт 44-50% против более простого бота 5-го уровня сложности).
1. Как работают алгоритмы
Aggressive Bot (Difficulty 5)
Это жадный алгоритм глубины 1 (1-ply), который генерирует все возможные легальные ходы и выбирает тот, который максимизирует функцию evaluateAggressive. Эта функция включает:
- Материальный баланс.
- Штраф за подставление своего короля под бой (
-2000). - Pawn Storm Heuristics: бонус за продвижение пешек вперед.
- King Proximity: бонус за приближение тяжелых и легких фигур к королю противника.
- King Ring Pressure: бонус за атаку полей вокруг вражеского короля.
Бот не смотрит в будущее, но его эвристики заставляют его постоянно нагнетать давление и собирать фигуры вокруг чужого короля, что в Dice Chess является выигрышной тактикой, так как рано или поздно выпадут нужные кубики для мата.
Monte-Carlo Bot (Difficulty 6)
Это алгоритм Flat Monte-Carlo (без построения дерева MCTS, делает роллауты только для корневых ходов). Его логика (при лимите времени):
- Генерирует все легальные ходы.
- Сортирует их с помощью чисто материальной оценки (
evaluateMaterial). - Оставляет топ-16 кандидатов (
MaxCandidates = 16). - Запускает случайные симуляции (rollouts) до конца игры для каждого из 16 кандидатов, распределяя время поровну.
- Выбирает ход с максимальной вероятностью победы.
2. Почему Monte-Carlo проигрывает и как его улучшить?
Мы выделили 3 главные проблемы алгоритма Monte-Carlo в текущей реализации и предлагаем способы их решения:
Идея 1: Улучшить пре-селекцию ходов (Критическая уязвимость)
Проблема: В MonteCarloSearch.scala для фильтрации топ-16 кандидатов используется Evaluator.evaluateMaterial. Это значит, что если ход не выигрывает материал (например, просто подтягивает Ферзя к вражескому королю для атаки), он получит оценку 0 и может вообще не попасть в топ-16, если есть другие ходы, съедающие пешку (оценка +100). Бот просто слеп к позиционным и атакующим ходам на этапе отбора кандидатов.
Решение: Использовать Evaluator.evaluateAggressive (или гибридную оценку) вместо evaluateMaterial на этапе preScored. Это позволит боту делать роллауты для действительно опасных и атакующих ходов, а не только для жадных захватов.
Идея 2: “Тяжелые” (Эвристические) роллауты вместо случайных
Проблема: В MonteCarloEquity.advance симуляции игры делаются абсолютно случайно (random.nextInt). В шахматах чисто случайная игра быстро ведет к потере материала и подставлению короля. Это делает оценку вероятности победы (win probability) очень “шумной” и малоинформативной для стартовой позиции.
Решение: Внедрить ε-жадную стратегию в роллаутах (epsilon-greedy). Например, в 70% случаев выбирать случайный ход, а в 30% — ход, который лучше по оценке evaluateMaterial или evaluateKingSafety. Альтернативно — всегда отбрасывать ходы, которые в один шаг подставляют короля под бой (использовать evaluateKingSafety внутри advance).
Идея 3: MCTS (Построение дерева) вместо Flat Monte-Carlo
Проблема: Сейчас бот распределяет время жестко поровну между топ-16 ходами (или по остаточному принципу). Он не углубляется в наиболее перспективные ветки. Решение: Реализовать полноценный UCT (Upper Confidence bound applied to Trees). Строить дерево, где каждый узел — это состояние игры. Использовать формулу UCB1 для выбора того, какой ход симулировать следующим. Это позволит алгоритму тратить больше времени на обдумывание 2-3 самых лучших кандидатов, вместо того чтобы тратить 1/16 времени на очевидно плохой ход.