Хабрахабр

Как написать игру для компьютера, в котором нет устройств ввода и вывода

Что можно сделать с компьютером на электромагнитных реле у которого нет никаких устройств ввода, а из устройств вывода — только дамп восьми регистров?

Играли же древние люди на калькуляторах МК-61/52, которые лишь немногим нагляднее. Поиграть в игры, конечно!

Угадай число

Начал я с игры, где компьютер с помощью половинного деления должен найти загаданное игроком целое число от 0 до 100.

Свою догадку компьютер записывает в регистр A, а затем останавливается.

Значения всех регистров можно увидеть благодаря светодиодам, встроенным в реле:

Если там не 0, это значит, что предположение больше загаданного числа. Теперь игрок должен изменить код программы в ПЗУ, заменив константу, загружаемую в регистр D. После этого нужно нажать кнопку «продолжить работу». Иначе — меньше. Проверив регистр D, компьютер использует прежнее предположение как верхний или нижний предел в следующей попытке.

Первая версия программы

MOVI B, 1 ; 00: 10000001 00000001 MOVI C, 101 ; 01: 10000010 01100101 Loop: ADD A, B, C ; 02: 01001000 00011010 SHR A, A ; 03: 01111000 00001100 HALT ; 04: 00010000 00000000 MOVI D, guess ; 05: 10000011 iiiiiiii OR F, D, D ; 06: 01101000 00110011 JMP NZ, Greater ; 07: 11100111 00001010 MOV B, A ; 08: 00011001 00000000 JMP Loop ; 09: 10000111 00000010 Greater: MOV C, A ; 0a: 00011010 00000000 JMP Loop ; 0b: 10000111 00000010

Это можно понять, посмотрев на фотографию ПЗУ — не очень-то легко переключать такие маленькие тумблеры, играя в игру (а ведь при этом надо ещё и следить, чтобы программу случайно не испортить). Недостаток первой программы в том, что ей неудобно пользоваться.

Для отладки рядом с каждым регистром предусмотрен тумблер для сброса его значения. Поэтому я придумал другой вариант ввода. Его переключать намного удобнее, чем менять ПЗУ.

Теперь компьютер заранее заносит единицу в регистр D, а игрок либо сбрасывает его (если догадка меньше, чем задуманное число), либо оставляет как есть (если догадка больше).

Финальная версия программы

MOVI B, 1 ; 00: 10000001 00000001 MOVI C, 101 ; 01: 10000010 01100101 Loop: ADD A, B, C ; 02: 01001000 00011010 SHR A, A ; 03: 01111000 00001100 MOVI D, 1 ; 04: 10000011 00000001 HALT ; 05: 00010000 00000000 OR F, D, D ; 06: 01101000 00110011 JMP NZ, Greater ; 07: 11100111 00001010 MOV B, A ; 08: 00011001 00000000 JMP Loop ; 09: 10000111 00000010 Greater: MOV C, A ; 0a: 00011010 00000000 JMP Loop ; 0b: 10000111 00000010

Игра вычитания (игра Баше)

Другая классическая игра, которую часто реализуют начинающие программисты — игра Баше.
В ней два игрока из кучки, содержащей первоначально N предметов, по очереди берут не менее одного и не более М предметов. Проигравшим считается тот, кому нечего брать.

Изначально в кучке 21 предмет (например, 21 спичка). В моём варианте игра идёт с компьютером. Игроки берут от 1 до 3 спичек в свой ход, а выигрывает тот, кто берёт последнюю спичку.

Так как 0 тоже кратно четырём, то второй игрок привести игру в эту позицию не сможет, а значит проиграет. В игре есть выигрышная стратегия для первого игрока — всегда оставлять число спичек, которое кратно четырём.

И если игрок не будет следовать выигрышной стратегии, то это сделает компьютер. Компьютер ходит вторым, оставляя шанс человекам, но ошибок он не делает.

Первая версия программы

MOVI A, 21 ; 00: 10000000 00001101 Loop: HALT ; 01: 00010000 00000000 MOVI B, move ; 02: 10000001 000000mm SUB A, A, B ; 03: 01011000 00001001 AND C, A, 3 ; 04: 01100010 10001011 MOVI Z, C, 1 ; 05: 10010010 00000001 SUB A, A, C ; 06: 01011000 00001010 JMP Loop ; 07: 10000111 00000001

В первой версии использовался тот же подход, что и для «угадай число» — в свой ход нужно было закодировать число спичек внутри одной из инструкций. Даже можно было считерить и взять все спички сразу, а компьютер ничего не заметит.

Теперь в три регистра (B, C, D) компьютер заносит по 1, а игрок должен сбросить 0, 1 или 2 из них. Но потом я переписал и эту программу тоже. Читерить тоже можно, если сбросить все три регистра (как будто не берёшь ничего). Оставшиеся единицы — это те спички, которые он берёт.

Финальная версия программы

MOVI A, 21 ; 00: 10000000 00010101 Loop: MOVI B, 1 ; 01: 10000001 00000001 MOVI C, 1 ; 02: 10000010 00000001 MOVI D, 1 ; 03: 10000011 00000001 HALT ; 04: 00010000 00000000 SUB A, A, B ; 05: 01011000 00001001 SUB A, A, C ; 06: 01011000 00001010 SUB A, A, D ; 07: 01011000 00001011 AND C, A, 3 ; 08: 01100010 10001011 MOVI Z, C, 1 ; 09: 10010010 00000001 SUB A, A, C ; 0a: 01011000 00001010 JC Exit ; 0b: 10110111 00001101 JNZ Loop ; 0c: 11100111 00000001 Exit: HALT ; 0d: 00010000 00000000

Конечно программа получилось несколько длиннее, но зато пользоваться ей значительно удобнее.

Дальше я планирую допаять ПЗУ (сейчас есть только 32 слова из возможных 64), а также добавить-таки устройство ввода в виде матрицы из тумблеров. Может тогда получится сделать хотя бы крестики-нолики.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть