Поиграть в игры, конечно! Играли же древние люди на калькуляторах МК-61/52, которые лишь немногим нагляднее.
Угадай число
Начал я с игры, где компьютер с помощью половинного деления должен найти загаданное игроком целое число от 0 до 100.
Свою догадку компьютер записывает в регистр A, а затем останавливается.
Значения всех регистров можно увидеть благодаря светодиодам, встроенным в реле:
Теперь игрок должен изменить код программы в ПЗУ, заменив константу, загружаемую в регистр D. Если там не 0, это значит, что предположение больше загаданного числа. Иначе — меньше. После этого нужно нажать кнопку «продолжить работу». Проверив регистр 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), а также добавить-таки устройство ввода в виде матрицы из тумблеров. Может тогда получится сделать хотя бы крестики-нолики.
Комментарии (16)
Wizard_of_light
26.12.2018 12:33Играли же древние люди на калькуляторах МК-61/52, которые лишь немногим нагляднее
Да вы что, МК-61/52 самый игровой. Там был почти джойстик — переключатель «радианы/грады/градусы»! И в процессе выполнения программы промежуточные результаты выполнения на экране отображались. В «посадку на Луну» можно было почти в реальном времени играть :)
dolovar
26.12.2018 12:47Предполагаю, что в заголовке не хватает слова «привычный» — игры на компьютере без привычных устройств ввода-вывода.
Говоря о компьютерных играх, под привычными мы подразумеваем динамики, микрофон, экран, тач-панель, клавиатуру, мышь, джойстик, браслет, принтер…
Светодиоды и тумблеры можно назвать непривычными, да, но с натяжкой.
(задумался об игре «посадка на Луну с терменвоксом»)Dovgaluk Автор
26.12.2018 12:54Дело в том, что эти тумблеры в каком-то смысле устройства ввода, но их состояние напрямую процессор узнать не может. Только косвенно.
То есть работа с ними отличается от обычного «читаем порт/ячейку памяти».dolovar
27.12.2018 11:56Насколько я понял, здесь сочетание нескольких разных моментов.
Первый — разворот позиций, в «угадай число» игроком является компьютер, а человек является ведущим игры.
Второй — игра «с непрямым контролем», компьютер оценивает косвенные признаки и пытается управлять ходом игры посредством подачи сигналов на светодиоды, а не пытается самостоятельно тумблеры переключать или иным способом модифицировать логику своей программы.
Третий — «вычисления в памяти», то есть компьютер не оценивает что-либо, а напрямую своей структурой участвует в ходе игры.
Третьего я до конца не понял, но чувствую пересечение с книгой «Радость познания» Ричарда Фейнмана, где он упоминает возможности ухода от архитектуры фон Неймана в сторону обратимых машин, а также со вчерашней статьей о "8-битном аналоговом чипе памяти".
В любом случае, удачи. Уважаю тех, чьи хобби связаны с попытками создать новое.
alexhott
26.12.2018 13:58Я бы даже постеснялся назвать это компьютером.
Автору конечно плюсы и респект.
vadimbn
26.12.2018 21:45Во времена советского союза была детская вычислительная машина — ДВМ. К ней шла вполне внушительная инструкция с играми. «Программировалась» она перемычками и штекерами, после чего двигались вправо-влево планочки, от их положения зависело какие лампочки загорятся на панели.
По сравнению с этим девайсом программируемые микрокалькуляторы выглядели суперкомпьютерами. И ведь играли же… Но даже там все же есть «устройства ввода-вывода».Dovgaluk Автор
27.12.2018 09:01У меня есть детская логическая машина.
Тоже штекерами «программируется».vadimbn
27.12.2018 14:43Да, это практически одно и то же, только в другом, более компактном исполнении. Та, кстати, тоже «логическая машина». И вся соль в инструкции. БОльшая часть «программы» закладывается прямо в мозг :).
tendium
28.12.2018 00:33О, с МК-52 начался мой путь в мир программирования. Я с ним реально засыпал. :) А было мне, чтоб не соврать, лет 10… Разумеется, это были сильно примитивные вещи, но циклы, условия, переходы я отлично усвоил благодаря данному программируемому калькулятору. Аж ностальгия хлынула.
maximw
Так светодиоды и есть устройство вывода, а тумблеры — ввода. Я почему-то подумал что тут речь пойдет об игре, что-то типа Life. Где компьютер играет сам с собой или вообще нет игроков.
Dovgaluk Автор
Life бы хотелось написать, но там без ОЗУ никак не обойтись.
maximw
Это да, я только к заголовку придираюсь.