Старый добрый Морской бой, с произвольным количеством однопалубных кораблей.
Как обычно, подбить все корабли первым. Вы играете против ПМК.
Квадратное поле 10 x 10 (0…9 x 0…9), стрельба по очереди, первым начинает ПМК. Что считать координатой X, а что Y решайте сами, главное, чтобы быть в этом последовательными.
Перед первым запуском пару констант в регистры:
Регистр | Значение |
---|---|
Ra | 33333331, признак победы ПМК. |
Rb | -8CEC6-L-. (ВСЁСБИЛИ). Признак поражения ПМК. Вводиться как 3, 3, 1, 3, 9, 5, 4, 5, КИНВ, /-/, ВП, 7, x→Пb. |
Rс | Случайное число. Можно оставить пустым. |
Начало игры: вводим количество кораблей у каждого (от 1 до 99) В/О С/П.
ПМК располагает свои корабли и отвечает координатами удара (двузначное число, если ведущий ноль, то однозначное). Если ПМК попал, то вводите любое отрицательное число и С/П, тогда ПМК сделает ещё ход. Если он промазал, то вводите свои координаты удара и С/П.
При попадании ПМК выдаст отрицательное число (его абсолютное значение – количество оставшихся у ПМК кораблей), иначе выдаст свой ход.
Если вы ввели отрицательное число (сбили), и это уже последний ваш корабль, то ПМК выдаст признак его победы 33333331. Если, наоборот, вы сбили все его корабли, то выдаст "-ВCЁСБИЛИ"( -8CEC6-L- ).
Для новой игры: новое количество кораблей В/О, С/П и далее как описано.
# | | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 |
---|---|---|---|---|---|---|---|---|---|---|
00 | | БП | 50 | Fx<0 | 89 | FL0 | 68 | П→xa | В/О | 4 | ПП |
10 | | 76 | П→xd | + | x→Пe | <-> | 7 | ПП | 76 | F10x | <-> |
20 | | 8 | ÷ | /-/ | ВП | F1/x | К[x] | − | КП→xe | К∧ | К{x} |
30 | | В/О | П→xc | 7 | × | Fπ | + | К{x} | x→Пc | ПП | 71 |
40 | | КППb | Кx=0a | F↻ | КП→xe | К⊕ | Кx→Пe | + | КЗН | x→Пd | В/О |
50 | | К[x] | x→П0 | FLg | 9 | x→Пd | Кx→Пd | 1 | − | Fx=0 | 54 |
60 | | П→x0 | x→П1 | F10x | КППa | FL1 | 63 | П→x0 | x→П1 | 5 | x→Пd |
70 | | КППa | П→xc | ВП | 2 | К[x] | В/О | 3E | FВx | <-> | FВx |
80 | | ÷ | К[x] | В↑ | F↻ | × | 1 | − | − | В/О | F10x |
90 | | FВx | К[x] | КППb | Fx≠0 | 68 | ПП | 42 | П→x1 | FL1 | 87 |
A0 | | П→xb | В/О |
R0 | Количество кораблей у игрока. |
---|---|
R1 | Количество кораблей у ПМК. |
R2…R5 | Местоположение кораблей ПМК в битовом представлении. |
R6…R9 | Местоположение выстреловПМК в битовом представлении. |
Ra | 33333331, признак победы ПМК. А также адрес процедуры поиска свободного бита через генератор случайных чисел. |
Rb | -8CEC6-L-. (ВСЁСБИЛИ). Признак поражения ПМК. Также адрес процедуры (BA = 08) преобразование целого числа (0…9) из регистра X в номер регистра (в Re) для определения бита для тестирования. |
Rc | Случайное число. |
Rd | Число 1 или 5 – базовый адрес битовой карты, используемый процедурой генерации или проверки битов. |
Re | Текущий регистр для проверки/установки бита. |
Основная идея программы: запомнить два поля (в битовом представлении)
10 x 10. Затем на одном, вначале пустом, расставить корабли (поставить биты).
А на другом (тоже пустом) расставлять
свои ходы. При этом
главное проверить, а не стоит ли там ещё корабль (установлен бит).
Теперь технические детали. Для операций с битами используются шестнадцатеричные операции. Т. к. одна шестнадцатеричная цифра может представлять 4 бита, то 7 цифр (максимум в шестнадцатеричных операциях) 7 × 4 = 28. А в 4 регистрах 28 × 4 = 112, т. е. более, чем сто. Таким образом для хранения одного поля в битовом представлении достаточно 4-х регистров памяти. Теперь по используемым процедурам:
Aв регистре X, и
Bв регистре Y. На выходе
Amod
B+ 1 в X, и [
A/
B] в Y.
Плюс одиндля удобства следующих операций. Используется только стек. Единственная деталь: вместо − и 1, + используется 1, −, −. Это связано с оптимизацией (пояснение ниже).
хитрая, то нужно сначала выполнить X2-влияющую команду (см. недокументированные возможности). В данном случае /-/. И кстати, −0 переходит в −1 даже в ручном режиме, хотя при этом возле нуля минус не отображается. Поэтому в конце с большим числом делается не плюс, а минус. Поясню, что для функции Fxy пришлось бы ещё прибавлять малую величину и делать К[x], т. к. даже 22 вычисляется неточно. Здесь получается на одну команду длиннее, но намного быстрее (и запутаннее от подглядывания). Потом через Re поднимается существующая битовая маска, делается тест и в конце 0 или не ноль. Важно, что в регистре Y остаётся число с номером бита. Ещё важная особенность – расстановка битов по регистрам делается
хитро, что даже видя число из регистра, трудно понять, что и где.
занято, то повтор, если нет, используется сохранённые ею значения Re и RY для установки бита, зачистки стека от битов (операция + и КЗН, та же защита от подглядывания), заодно сохраняя в Rd смещение 1, т. к. регистры R2…R5 используются для хранения кораблей ПМК (R6…R9 – выстрелов ПМК), и обычно первым делом проверяются в начале хода.
отрубаниедробной части, сохранение количества кораблей в R0, затем проверка на то, что больше нуля (FLg для ≤0 выдаст ошибку). Затем девятка с уменьшением (9…2) последовательно записывается в регистры R9…R2. Сделано так вот почему: для очистки обоих битовых карт (первый разряд в битовых операциях не участвует), заодно в конце операции в Rd будет 1. Затем копирование в R1 количества кораблей, заодно проверяя верхнюю границу (для x≥100 F10x выдаст ошибку). Затем очень короткий (по длине, но не по времени) цикл по вызову процедуры 3 (расстановка всех кораблей), восстановление в R1 числа кораблей. Далее R0 будет показывать оставшееся количество кораблей у игрока, R1 – у ПМК. Потом сразу идёт процедура…
нестреляноеполе, и последний удачный результат извлекает из регистра случайного числа, возвращаясь на адрес 01 (команда С/П). Обратите внимание, что хвост этой операции используется в процедуре 3.
всё, то извлекается Ra и возврат на остановку. Если нет, то далее на адрес хода ПМК. Если это ход игрока, то с адреса 89 сначала делается проверка на ≤99 (через F10x), затем берётся целая часть (такой порядок, чтобы в случае ЕГГ0Г можно было продолжить, как раз остановка будет на команде К[x]). Вызов процедуры 2, и если игрок не попал, то снова уход на выстрел ПМК (адрес 68), а если попал, то вызов хвоста процедуры установки бита (вот зачем была операция XOR, а не OR, чтобы стереть бит), используя те же данные из Re и RY. Извлечение значения оставшихся кораблей, проверка на всё ли подбили. Тут главное, это переход, на 87, если не всё. После вызова процедуры 2 в RX останется (уже в RY, после П→x1) единица, а странно сделанное окончание процедуры 1 вычтет её и вернёт на начало. Т. е. в итоге отобразиться
−число оставшихся кораблей ПМК.