Комментарии 19
Мои выводы основаны на полезной обзорной статье, собственном опыте написания минимакса (не для шахмат) и скромном опыте игры:
1. У вас не описана рокировка (потому что это движение одновременно короля и ладьи, из кода навскидку непонятно, как это должно работать)
2. Не хватает «взятия на проходе» для пешки.
3. Оценка веса позиции не учитывает мобильности фигур — с одной стороны, мало проку от зажатого со всех сторон ферзя (у которого большой вес), с другой стороны, проходная пешка может навести много суеты, когда протопает доску насквозь. Также неучет мобильности может, вероятно, привести к тому, что вашему движку можно будет поставить детский мат. Простейший способ учета мобильности — умножить вес фигуры на число возможных ходов.
4. Использование в крайней степени неэкономичного способа хранения данных лишит вашу программу преимущества в виде возможности хранить (да и перебирать — перекидывание нескольких бит в регистрах CPU на порядки быстрее ковыряния в мапе) больше состояний в памяти. С другой стороны, это может мотивировать на поиск более оптимальных эвристик для отсечения и более точных оценок для позиций. Может показаться интересной задача сделать код и читаемым и оптимальным по ресурсам одновременно.
1. У вас не описана рокировка (потому что это движение одновременно короля и ладьи, из кода навскидку непонятно, как это должно работать)
2. Не хватает «взятия на проходе» для пешки.
3. Оценка веса позиции не учитывает мобильности фигур — с одной стороны, мало проку от зажатого со всех сторон ферзя (у которого большой вес), с другой стороны, проходная пешка может навести много суеты, когда протопает доску насквозь. Также неучет мобильности может, вероятно, привести к тому, что вашему движку можно будет поставить детский мат. Простейший способ учета мобильности — умножить вес фигуры на число возможных ходов.
4. Использование в крайней степени неэкономичного способа хранения данных лишит вашу программу преимущества в виде возможности хранить (да и перебирать — перекидывание нескольких бит в регистрах CPU на порядки быстрее ковыряния в мапе) больше состояний в памяти. С другой стороны, это может мотивировать на поиск более оптимальных эвристик для отсечения и более точных оценок для позиций. Может показаться интересной задача сделать код и читаемым и оптимальным по ресурсам одновременно.
Все ваши замечания справедливы, однако я перед собой и не ставил цели сразу написать полноценный движок.
1. Да, рокировка не описана, но можно сделать ещё одну реализацию интерфейса Turn, которая будет содержать всю необходимую информацию для рокировки (например, с какой ладьёй меняемся). В моём подходе все варианты рокировки должен возвращать движок, если рокировка возможна (король не двигался, ладья не двигалась, между ними нет других фигур и рокировка не поставит короля под мат).
2. В силу специфичности данного хода я даже не пытался его реализовать в первой итерации. Довольно легко избежать взятия на проходе, если знаешь про это правило. Однако это будет ещё одна реализация Turn.
3. Про мобильность интересное замечание. Приму к сведению.
4. Вы абсолютно правы, но я на это пошёл сознательно. Хотя бы потому что в основном все пишут про битовые поля, а других вариантов особо не предлагают. Хотелось продемонстрировать такую структуру данных, которая была бы максимально простой для понимания.
1. Да, рокировка не описана, но можно сделать ещё одну реализацию интерфейса Turn, которая будет содержать всю необходимую информацию для рокировки (например, с какой ладьёй меняемся). В моём подходе все варианты рокировки должен возвращать движок, если рокировка возможна (король не двигался, ладья не двигалась, между ними нет других фигур и рокировка не поставит короля под мат).
2. В силу специфичности данного хода я даже не пытался его реализовать в первой итерации. Довольно легко избежать взятия на проходе, если знаешь про это правило. Однако это будет ещё одна реализация Turn.
3. Про мобильность интересное замечание. Приму к сведению.
4. Вы абсолютно правы, но я на это пошёл сознательно. Хотя бы потому что в основном все пишут про битовые поля, а других вариантов особо не предлагают. Хотелось продемонстрировать такую структуру данных, которая была бы максимально простой для понимания.
Есть прекрасный сайт www.chessprogramming.org — там очень много интересного на эту тему.
«Довольно легко избежать взятия на проходе, если знаешь про это правило» — это правило было придумано примерно тогда, когда появилось правило хода пешкой на две клетки вперёд, чтобы нельзя было запирать позицию. Это такое особое правило, и как правило взятие на проходе «допускают» вполне осознанно, и не стараются его избегать.
«король не двигался, ладья не двигалась, между ними нет других фигур и рокировка не поставит короля под мат»
— между ними нет других фигур
— поле, на котором стоит король, поле которое пересекает король и поле, на которое становится король — не атакуется вражескими фигурами.
«Довольно легко избежать взятия на проходе, если знаешь про это правило» — это правило было придумано примерно тогда, когда появилось правило хода пешкой на две клетки вперёд, чтобы нельзя было запирать позицию. Это такое особое правило, и как правило взятие на проходе «допускают» вполне осознанно, и не стараются его избегать.
«король не двигался, ладья не двигалась, между ними нет других фигур и рокировка не поставит короля под мат»
— между ними нет других фигур
— поле, на котором стоит король, поле которое пересекает король и поле, на которое становится король — не атакуется вражескими фигурами.
Спасибо за ссылку, почитаю! Что касается рокировки, то даже не все именитые шахматисты соблюдали эти правила. То есть имеется некоторая вариативность в правилах.
Если мы говорим про классические шахматы, то вариативности никакой нет и не было. Если говорить о шахматах Фишера, где фигуры в начальной позиции случайным образом меняются местами, то там тоже всё хорошо. После рокировки король и ладья становятся на привычные в классических шахматах места.
Была одна забавная шахматная задача в 1972 году, которая привела к уточнению формулировки правил рокировки в шахматах, но, разумеется, никто этой неоднозначностью не пользовался.
Была одна забавная шахматная задача в 1972 году, которая привела к уточнению формулировки правил рокировки в шахматах, но, разумеется, никто этой неоднозначностью не пользовался.
Хех, даже не знал про вертикальную рокировку))
Была еще история о том, как шахматист на турнире сделал длинную рокировку при стоящем на своей исходной позиции ферзевом коне.
Когда ошеломленный соперник остановил часы и позвал судью, нарушитель предъявил тому последний «Шахматный кодекс», где черным по белому было написано «Ни одна фигура, кроме коня и ладьи при рокировке, не может перепрыгивать через другие фигуры.».
Судья, впрочем, принял решение быть верным духу, а не букве, и новатор был вынужден делать ход королем.
(Да, очевидно, в правилах рокировки не было указано требование отсутствия фигур между королем и ладьей.)
Когда ошеломленный соперник остановил часы и позвал судью, нарушитель предъявил тому последний «Шахматный кодекс», где черным по белому было написано «Ни одна фигура, кроме коня и ладьи при рокировке, не может перепрыгивать через другие фигуры.».
Судья, впрочем, принял решение быть верным духу, а не букве, и новатор был вынужден делать ход королем.
(Да, очевидно, в правилах рокировки не было указано требование отсутствия фигур между королем и ладьей.)
Поглядите книжку Корнилов «Программирование шахмат и других логических задач». Правда, там не всё есть. Впрочем, кое-что, чего там нет, я в своей статье расписал.
Для ладьи также будем генерить ходы в диапазоне 8 клеток, но с помощью метода generateDiagonalTurns()
Для слона все же
Вы бы прежде чем писать, все же ознакомились бы с теорией игры. Королева это вам не слон плюс ладья, а 9 пунктов. Король между прочим тоже не бесконечность, а 4 пункта (да да, в эндшпиле он очень даже фигура). Это материальная оценка. Плюс есть оценка позиции. Вам уже написали про мобильность. Если закрытая позиция конь больше слона, в открытой наоборот. И т.д. и т.п.
Ах да, и еще «Прежде всего я установил несколько бесплатных и условно-бесплатных игр» — не занимайтесь ерундой, идите на chess.com. Там и уроки есть, и про фигуры объясняется ;)
Ах да, и еще «Прежде всего я установил несколько бесплатных и условно-бесплатных игр» — не занимайтесь ерундой, идите на chess.com. Там и уроки есть, и про фигуры объясняется ;)
1) chess.com bad, lichess good
2) материальная оценка не является объективной истинной. Stockfish использует PawnValueMg = 126, KnightValueMg = 781,
BishopValueMg = 825, RookValueMg = 1276,
QueenValueMg = 2538 (https://github.com/official-stockfish/Stockfish/blob/master/src/types.h#L182) как базу. И очень успешно использует, не знаю зачем автор условно бесплатные программы.
Возможно в статье это не совсем очевидно отражено, поэтому скажу ещё раз. Сначала мне просто захотелось поиграть в шахматы, а уже затем захотелось самому посмотреть, как можно реализовать простой движок. Если бы я изначально задавался целью написать полноценный движок, то да, я бы глубоко погружался в тему и начинал с изучения существующих аналогов.
Хорошая статья, понятно что правила в шахматах не так просты, чтобы их с наскоку реализовать. Но её ценность не в полноте, а в том что это хороший старт, например для учебных целей.
Лично я её так воспринимаю, а не как исчерпывающий движок.
Лично я её так воспринимаю, а не как исчерпывающий движок.
Про некоторые правила вы не обмолвились.
На счёт рокоровки и взятия на проходе уже писали.
Есть ещё про 3 повторяющиеся позиции (плюс там тоже есть свои хитрости с рокировкой) и про 50 ходов без взятия фигур, тогда можно объявить ничью.
И ещё:
Поле НА которое фигура совершает ход, а поле с которого пишется иногда, если есть неопределённость (2 одинаковые фигуры могут сходить на одно поле).
Кстати, важный момент по поводу тестирования, можно найти кучу тестов с начальной позицией шахмат и количеством разрешённых ходов в ней — прогнать такие тесты самый хороший вариант чтобы проверить правильность реализации правил. Там и рокировка и взятие на проходе и ещё куча всяких вариантов будет заметна.
На счёт рокоровки и взятия на проходе уже писали.
Есть ещё про 3 повторяющиеся позиции (плюс там тоже есть свои хитрости с рокировкой) и про 50 ходов без взятия фигур, тогда можно объявить ничью.
И ещё:
Сперва пишется первая буква, обозначающая фигуру (для пешек букву не используем). Затем поле, с которого фигура совершает ход.
Поле НА которое фигура совершает ход, а поле с которого пишется иногда, если есть неопределённость (2 одинаковые фигуры могут сходить на одно поле).
Кстати, важный момент по поводу тестирования, можно найти кучу тестов с начальной позицией шахмат и количеством разрешённых ходов в ней — прогнать такие тесты самый хороший вариант чтобы проверить правильность реализации правил. Там и рокировка и взятие на проходе и ещё куча всяких вариантов будет заметна.
50 ходов без взятия фигур в плане реализации это совсем несложно, поэтому для статьи не принципиально. Я сосредоточился на основных правилах. Если бы я в одной статье рассказал про все особые случаи, статья получилась бы огромной (она и так не самая маленькая).
По поводу нотации для записи ходов я сознательно выбрал более многословную запись, чтобы её легче было объяснить людям, которые вообще не знакомы с шахматными нотациями.
Про тесты интересная мысль, как и предыдущие. Спасибо, я принял к сведению! Возможно потом доработаю движок с учётом ваших предложений.
По поводу нотации для записи ходов я сознательно выбрал более многословную запись, чтобы её легче было объяснить людям, которые вообще не знакомы с шахматными нотациями.
Про тесты интересная мысль, как и предыдущие. Спасибо, я принял к сведению! Возможно потом доработаю движок с учётом ваших предложений.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Как желание поиграть в шахматы превратилось в написание своего движка. История и реализация