gambit

Шахматный движок на Scala 3. Генерация ходов, оценка позиции и поиск - полноценный мозг для игры в шахматы, собранный с помощью scala-cli.

gambit
TL;DR

Шахматный движок на Scala 3. Три трудные вещи сразу: безошибочная генерация ходов, осмысленная оценка позиции и поиск, который за разумное время выберет хороший ход. Полноценный мозг для игры.

Введение

Шахматный движок лишь на первый взгляд кажется одним проектом. Это три подсистемы, каждая из которых может испортить целое по-своему, и только вместе они дают нечто, что играет осмысленно. gambit о том, чтобы эти три части согласовались между собой настолько хорошо, что результат начинает напоминать настоящего соперника, а не генератор случайных ходов.

Scala 3 дает здесь выразительный язык для моделирования доски, ходов и дерева вариантов. Но настоящий вызов не синтаксический, а алгоритмический: безошибочный генератор, честная оценка и поиск, который не считает бесконечно.

Три проблемы, которые должны согласоваться

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

1
Генерация ходов

все легальные ходы в любой позиции, включая рокировку, взятие на проходе и превращение.

2
Оценка позиции

число, показывающее, кто стоит лучше, пока партия еще идет.

3
Поиск

альфа-бета, который отбрасывает ветви, которые не стоит считать.

Ни одну из этих трех нельзя отбросить. Слабый в любой из них движок проиграет, и по конкретной, указуемой причине, а не из-за общей слабости.

Альфа-бета, или искусство не считать

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

Узлы для перебора на той же глубине (ориентировочно, тыс.)

Наивный поиск
1000
С отсечением альфа-бета
60

Это не мелкая оптимизация, а разница между движком, который видит три хода вперед, и таким, который видит шесть. В шахматах эта глубина напрямую переводится в силу игры.

Perft, или доказательство корректности генератора

Корректность генератора ходов проверяется так называемым perft: вы считаете все позиции, достижимые на заданную глубину, и сравниваете с числами, которые все шахматное сообщество знает наизусть. Если ваше число не сходится, где-то есть баг, и точно видно, на какой глубине начинается расхождение.

Perft из начальной позиции

ГлубинаЧисло позиций
120
2400
38902
4197281
54865609

Результат - полноценный движок, который берет позицию и отдает ход: генератор выкладывает все легальные продолжения, оценка говорит, какое ведет в лучшую сторону, а альфа-бета ищет настолько глубоко, насколько позволяет время. Три подсистемы, которые по отдельности лишь части, вместе дают соперника, который умеет играть.

➜
Совет

Perft - эталонный пример теста, который действительно может упасть. Он проверяет не то, что что-то работает, а сравнивает ваше число с числом, известным заранее, поэтому любой баг в генераторе тут же уводит результат в сторону.

Больше проектов

Другие работы из той же категории - посмотрите, как мы решаем похожие задачи.

Есть похожий проект?

Напишите нам - смета бесплатна и приходит в течение часа.