Dagaz: Пинки здравому смыслу (часть 1)
Важной частью работы над универсальной игровой системой является систематизация правил. За тысячи лет своего развития, человечество придумало невероятное количество настольных игр. Их правила, по большей части, похожи, но некоторые могут поставить разработчика в тупик. Эти правила столь же важны, как и все остальные. Здесь не действует принцип Парето — либо мы реализуем игру полностью, на все 100%, либо… это будет совсем другая игра. В процессе работы над проектом Dagaz, я решил составить свой рейтинг правил, наиболее неожиданных или неудобных для разработчика. Встречайте… 10. Странные ходыШахматы — это, пожалуй, первая игра, про которую мы вспоминаем говоря о настольных играх, но они далеко не сразу обрели знакомые нам черты. В Шатрандже, их непосредственном предшественнике, ферзь был самой слабой фигурой! Он ходил всего на одно поле, по любой из диагоналей. Слон также не был дальнобойным, но умел перепрыгивать через фигуры. Пешка, дойдя до последней горизонтали превращалась лишь в ферзя (а не в любую фигуру на выбор, как сейчас). Ладья ходила по привычным нам правилам, но её ещё требовалось вывести на «оперативный простор». В целом, игра получалась весьма неторопливой, но это компенсировалось наличием огромного количества табий — начальных позиций, с которых игроки, по договорённости, могли начинать игру.Первый пинок По всей видимости, не зная о табиях, жители Эфиопии решили по своему преодолеть медлительность Шатранджа. В их варианте этой игры, первые ходы, выполнялись игроками независимо друг от друга (кто сколько успел). Лишь после первого взятия, устанавливалось нормальное чередование ходов. Этот удар по здравому смыслу выступает сегодня вне конкурса, поскольку я просто не представляю себе как реализовать подобное требование в универсальной игровой системе. Кстати говоря, подобная игра «на скорость» весьма характерна для жителей африканского континента и встречается не только при игре в шахматы. Конь — ещё одна фигура, практически не претерпевшая изменений со времён Чатуранги. Он разучился перепрыгивать фигуры (как свои так и противника) в Сянцы и Чанги, а в Сёги умеет двигаться только вперёд (что, по своему, многое говорит о менталитете японцев), но эта фигура, по-прежнему, остаётся самой узнаваемой во всех играх шахматного семейства. Именно на основе коня были впервые «сконструированы» новые типы фигур, таких как канцлер и архиепископ. Впоследствии, поток подобных химер стал столь интенсивным, что потребовалась специальная система классификации для вновь изобретённых фигур, но не конь, на мой взгляд, является самой странной фигурой.Пешка — единственная фигура в Шахматах, взятия которой отличаются от обычного хода. Привычный нам «шахматный» принцип (фигура, выполняющая взятие, устанавливается на место взятой фигуры), пока, остаётся неизменным, но ходит пешка на одно поле вперёд, а бьёт по диагонали. Это самая малая проблема для разработчика, неприятности начинаются дальше.
С целью максимально быстрого захвата центра доски, пешкам было дано право двойного хода из начальной позиции (в некоторых вариантах шахмат, с досками большего размера, пешка прыгает ещё дальше). Поскольку такой прыжок позволял прорвать пешечный строй противника, как следствие, появилось правило «взятия на проходе», и вот это уже форменное безобразие. Шахматный принцип здесь нарушается. Атакуется не то поле, на котором стоит вражеская фигура, а поле, через которое она прошла. Более того, выполнить такой ход можно только на следующем ходу после «прыжка» пешкой противника. Посмотрим, как это отразилось на разработчиках:
En-Passant (ZoG) (define En-Passant ( $1 (verify enemy?) (verify last-to?) (verify (piece? Pawn)) capture n to n (verify last-from?) add ) ) выглядит несколько сложнее обычного взятия: (define Pawn-capture ( $1 (verify enemy?) (Pawn-add) ) ) Шаманство с перемещениями — малая часть проблемы. Разработчикам ZoG пришлось ввести в ядро новый предикат last-from?, выполняющий проверку того факта, что предыдущий ход (противника) выполнялся с текущего поля. Такое решение сложно расценить иначе чем поспешный и не очень удачный «костыль». Оно не универсально и не работает в более сложных случаях. Например, в четырёхсторонних шахматах, правило взятия на проходе может быть применено лишь к игроку, сидящему напротив, но предыдущий ход выполняется не им, а игроком, сидящим сбоку, в результате чего last-from? не работает! Пришлось подумать о более универсальном решении: En-Passant (Dagaz) (define pawn-jump (check (not is-moved?)) (set! turn-jumped turn-number) (check-source Pawn) (check n) (check is-empty?) (check n) (check is-empty?) (drop-pieces current-pieces) add-move )
(define (en-passant piece-type direction) (check-source piece-type) (check direction) (check is-enemy?) (check (<= 1 (- turn-number turn-jumped))) capture (check n) (check is-empty?) (drop-pieces current-pieces) add-move ) Если вы думаете, что «взятием на проходе» странности привычных нам Шахмат ограничиваются, подумайте ещё раз. В Шахматах есть ход, во время которого двигается сразу несколько фигур! Да, это рокировка. Она тоже появилась не сразу и не на пустом месте. С историей вопроса можно ознакомится в этой замечательной статье. Идея — одним ходом спрятать короля в «крепость» и, заодно, ввести в бой тяжёлую фигуру прекрасна, но страдают опять разработчики:Рокировка (ZoG) (define O-O ( (verify never-moved?) e ; KB1 (verify empty?) e ; KN1 (verify empty?) cascade e ; KR1 (verify (and friend? (piece? Rook) never-moved?) ) from back ; K1 ; Save expensive not-attacked?s for last (verify not-attacked?) e ; KB1 (verify not-attacked?) to (set-attribute never-moved? false) ; We could check if KN1 is attacked too, but this isn't ; really necessary since Zillions doesn't allow any moves ; into check e ; KN1 (set-attribute never-moved? false) add ) ) И это только короткая! Длинную я приводить не стал, из соображений гуманности. Я благодарен небу и всему цивилизованному шахматному сообществу, за то, что, до сегодняшнего дня, не сохранилась «свободная рокировка», столь любимая, в своё время, итальянцами. Специально для этого хода, разработчикам пришлось ввести в ядро ZoG команду cascade, позволяющую вовлечь в выполнение хода несколько фигур. Здесь, я ничего плохого не скажу, хорошее универсальное решение, но себя я решил вообще не ограничивать глупыми условностями. Рокировка начинается с перемещения короля, но кто сказал, что ходить должна всего одна фигура?Рокировка (Dagaz) (define O-O (check (not is-moved?)) (check not-attacked?) (take-piece-to-head current-pieces) (check w) (check is-empty?) (check (not-attacked? King)) (check w) (check is-empty?) (check (not-attacked? King)) (drop-pieces current-pieces) (check w) (check (not is-moved?)) (set! is-moved? true) (take-piece-to-head current-pieces) e e (drop-pieces current-pieces) add-move ) Возможность выполнения рокировки связана с выполнением ряда интересных условий. Так рокировка невозможна, если:король или ладья уже ходили в партии король находится под шахом король в результате рокировки попадает под шах поле, через которое должен пройти король, атаковано фигурой противника между королём и ладьёй, в сторону которую переставляется король, находятся другие фигуры Проверка последнего условия выполняется тривиально. Для того, чтобы проверять первое условие, в ZoG были введены атрибуты фигур (очень полезная возможность, правда я считаю, что было бы ещё полезнее, если бы атрибуты могли хранить не только булевские значения). Что касается остального — то это тема для отдельного и очень серьёзного разговора в одном из следующих разделов.Как можно видеть, в реализации классических Шахмат, есть над чем поломать голову, но настоящее веселье начинается в шахматах не классических. Что будет, если собрать вместе Шахматы, Хнефатафл, Шашки, Фанорону, добавить одну уникальную, ни на что не похожую фигуру, тщательно перемешать, но не взбалтывать? Не знаю как у вас, а у Роберта Эббота, в 1962 году, получилась Ультима.
В этой игре всё непривычно. Пожалуй, только король продолжает придерживаться шахматных принципов. Вот здесь можно посмотреть иллюстрированное руководство правил, по которым ходят фигуры. Для разработчика, в этом празднике жизни, важнее всего то, что, в этой игре, чаще всего, атакуется совсем не то поле, на которое ходит фигура, а иногда даже несколько полей сразу. Этот факт имеет далеко идущие последствия, но это вновь тема для разговора в одном из последующих разделов. Другим примером подобной «проблемной» игры является Ритмомахия.