Простые окончания в шахматах. ПМК ставит мат королём и ладьёй одинокому королю.
Исходно вариант программы, которая ставит мат, была предложена в журнале
Техника молодёжи
№9 за 1987 год.
Представленная версия программы – модификация, которая проверяет дополнительные условия до начала игры.
Игра по правилам шахмат. За белых, имеющих ладью и конечно короля, играет ПМК. За чёрных королём - игрок. Программа просто демонстрирует, как ставится мат с помощью ладьи.
В отличие от настоящих шахмат, использующих для обозначения вертикалей латинские буквы, здесь используются цифры:
| 8 | 18 | 28 | 38 | 48 | 58 | 68 | 78 | 88 |
|---|---|---|---|---|---|---|---|---|
| 7 | 17 | 27 | 37 | 47 | 57 | 67 | 77 | 87 |
| 6 | 16 | 26 | 36 | 46 | 56 | 66 | 76 | 86 |
| 5 | 15 | 25 | 35 | 45 | 55 | 65 | 75 | 85 |
| 4 | 14 | 24 | 34 | 44 | 54 | 64 | 74 | 84 |
| 3 | 13 | 23 | 33 | 43 | 53 | 63 | 73 | 83 |
| 2 | 12 | 22 | 32 | 42 | 52 | 62 | 72 | 82 |
| 1 | 11 | 21 | 31 | 41 | 51 | 61 | 71 | 81 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
Как и в классических обозначениях, первый знак – вертикаль. В дальнейшем будем обозначать это координата X, а номер горизонтали - координата Y.
Дело в том, что мощности
ПМК не хватит на перерасчёт координат для произвольного положения,
поэтому условие 1:
король белых должен быть ниже чёрного, причём минимум через одну горизонталь.
Если это не так, то поверните доску на 90 градусов. Если по-прежнему не так, то ещё раз. С учётом симметрии условие выполнится.
Более того, в алгоритме, используемом ПМК, король не защищает свою ладью. С учётом этого условие 2: ладья в самом начале не должна стоять на соседних вертикалях с королём черных.
Такое ограничение связано с тем, что в этом случае король чёрных может прорваться ниже и тем самым нарушить условие 1. В исходной версии программы такой прорыв проверялся позднее и снова предлагалось перевернуть доску. Посчитав это неудобным, игра то уже началась, условие проверяется до начала.
Кстати, вариант, когда ладья стоит на одной вертикали с чёрным королём не запрещён. Это возможно, не нарушая правила шахмат, когда король белых закрывает чёрного от шаха по той же вертикали.
Перед первым запуском несколько констант в регистры:
| Регистр | Значение |
|---|---|
| R7 | 36 |
| R8 | 3 |
| R9 | 9------0. Признак неверного начального положения: необходимо повернуть доску на 90 градусов. Формирование: 66555555. , КИНВ, К{x}, ВП, 8. |
| Ra | 10 |
| Re | 98 |
Если используется образ, загруженный в эмулятор, то они уже введены.
Затем традиционное В/0 и С/П. На экране отобразится единица – признак готовности.
Далее вводим координаты белого короля (x, y) в регистры R3, R4. Затем координаты белой ладьи в R5, R6. И вместо отдельного ввода координат чёрного короля делаем ход.
Для скорости ввода ход чёрного короля указываем одним двузначным числом XY, затем С/П. Варианты ответов ПМК:
Обозначения используется те же, что в оригинале, кроме признака неверного хода.
ПМК не проверяет:
Приведём для удобства в одном месте описание всех регистров:
| Регистр | Значение |
|---|---|
| R0 | Признак начала игры. Первый раз сюда заносится единица. Если первоначальная проверка положения прошла успешно, то будет не единица. |
| R1 | Координата X чёрного короля. |
| R2 | Координата Y чёрного короля. |
| R3 | Координата X белого короля. |
| R4 | Координата Y белого короля. |
| R5 | Координата X белой ладьи. |
| R6 | Координата Y белой ладьи. |
| R7 | 36. Адрес кода отхода ладьёй (MoveRook). |
| R8 | 3, адрес начала хода (ввод). |
| R9 | 9------0. Признак неверного начального положения, и адрес (A0) функции формирования хода ладьи (PrintRook). |
| Ra | 10. |
| Rb | Не используется в программе. |
| Rc | Рабочий. Хранит число вертикалей между белыми фигурами. Проверяется только на ноль. |
| Rd | Рабочий. Хранит число вертикалей между чёрным королём и белым минус 2. При нулевом значении короли расположены через одну горизонталь. |
| Re | 98. Адрес вывода неверного положения (PrintErr). |
Чтобы провести дополнительные проверки, т.е. добавить дополнительные команды, исключены, по сравнению с оригиналом, вертикальные манёвры ладьи. Мат можно поставить и без этого.
Алгоритм описан на псевдокоде, похожем на JavaScript.
Start:
R0 = 1 // Установить признак начала игры
Input:
stopAndWaitRx()
R1 = Math.floor(RX/10)
R2 = RX - (R1 * 10)
Rd = R2 - R4 - 2
if (Rd < 0) { // Короли слишком близко по вертикали
continue PrintErr
}
Rc = R5 - R3 // Если 0, то белые фигуры на одной вертикали
RX = 1 - Math.abs(R5 - R1); // Удаленность ладьи и чёрного короля в вертикалях
// RX == 1 - на одной вертикали
// RX == 0 - на соседних, ладья не сможет отрезать черного короля
// RX <= -1 - далеко
if (R0 == 1) // Если начало игры {
if (RX >= 0) { // Если ладья и черный король на одной или соседних вертикалях
if (Rc != 0) { // Если белые фигуры не на одной вертикали
continue PrintErr
}
R0 = RX // Сбросить признак начала игры (R0 = 0)
MoveRook: // Отход ладьёй. В другую половину от чёрного короля 1..4 -> 7, 5..8 -> 1
RX = Math.floor(R1 / 5)
if (RX == 0) {
RX = 7
} // Или остаётся RX = 1
RY = R5
R5 = RX
if ((RX - RY) == 0) { Если ладья тут и стояла, сдвигаем её правее
R5++
}
RX = PrintRook(R6)
continue Input
}
}
R0 = RX // Сбросить признак начала игры (R0 <= 0)
if (RX == 0) { // Если ладья и черный король на соседних вертикалях
continue MoveRook // Отходим ладьёй
}
RX1 = R2 - 1 // Сохраняем значение на горизонталь ниже чёрного короля
if ((-R6 + RX1) != 0) { // Если ладья не на горизонталь ниже черного короля, т.е. не отрезает его
if (Rc == 0) { // Если белый король и ладья на одной вертикали, то король мешает своей ладье
continue MoveRook // Поэтому сначала отходим ладьёй
} else {
PrintRook(RX1) // Отрезаем чёрного короля
continue Input
}
} else { // Если ладья уже отрезает черного короля
if (Rd != 0) { // Если белый король слишком низко
R4++ // Поднимаем белого короля
PrintKing: // Вывод координат белого короля
RX = R3 + R4/10
continue Input
} else { // Белый король уже через одну горизонталь от черного
RX = R1 - R3
if (RX == 0) { // Короли напротив друг друга
RX = 10 ** PrintRook(R2) // Делаем шах
continue Input
} else { // Не напротив и RX != 0
RY = RX
if (Math.log10(Math.abs(RX)) == 0) { // Если короли на соседних вертикалях (RX == ±1)
continue MoveRook // Отходим ладьёй - выжидательный ход
} else {
R3 = R3 + sign(RY) // Продвигаем по горизонтали белого короля к чёрному
continue PrintKing
}
}
}
}
PrintRook: // RX - новое положение ладьи по вертикали
R6 = RX
RX = R5 * 10 + R6
return
PrintErr:
RX = R9
continue Input
| # | | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 |
|---|---|---|---|---|---|---|---|---|---|---|
| 00 | | В/О | 1 | x→П0 | С/П | В↑ | П→xa | ÷ | К[x] | x→П1 | П→xa |
| 10 | | × | − | x→П2 | П→x4 | − | 2 | − | x→Пd | Кx≥0e | П→x5 |
| 20 | | П→x3 | − | x→Пc | 1 | П→x5 | П→x1 | − | К∣x∣ | − | FL0 |
| 30 | | 53 | Fx≥0 | 53 | П→xc | Кx=0e | x→П0 | П→x1 | 5 | ÷ | К[x] |
| 40 | | Fx=0 | 43 | 7 | П→x5 | <-> | x→П5 | − | Fx=0 | 50 | КП→x5 |
| 50 | | П→x6 | КПП9 | КБП8 | x→П0 | Кx≠07 | П→x6 | /-/ | П→x2 | 1 | − |
| 60 | | + | Fx≠0 | 68 | П→xc | Кx≠07 | FВx | КПП9 | КБП8 | П→xd | Fx≠0 |
| 70 | | 78 | КП→x4 | П→x3 | П→x4 | П→xa | ÷ | + | КБП8 | П→x1 | П→x3 |
| 80 | | − | Fx≠0 | 94 | В↑ | К∣x∣ | FLg | Кx≠07 | <-> | КЗН | П→x3 |
| 90 | | + | x→П3 | БП | 73 | П→x2 | КПП9 | F10x | КБП8 | П→x9 | КБП8 |
| A0 | | x→П6 | П→x5 | П→xa | × | + | |||||
Программа один в один выполняет шаги по указанному выше алгоритму. С учётом того, что никаких сложностей (в отличие от оригинала) не производится, то можно легко понять реализацию.
Единственное пояснение: команда В/О перенесена из конца в начало,
чтобы обезопасить
ввод единицы. Иначе, если до нажатия С/П
были введены какие-то цифры, то ввод продолжится и единица не получится.