Что можно сделать с компьютером на электромагнитных реле у которого нет никаких устройств ввода, а из устройств вывода — только дамп восьми регистров?
Поиграть в игры, конечно! Играли же древние люди на калькуляторах МК-61/52, которые лишь немногим нагляднее.
Начал я с игры, где компьютер с помощью половинного деления должен найти загаданное игроком целое число от 0 до 100.
Свою догадку компьютер записывает в регистр A, а затем останавливается.
Значения всех регистров можно увидеть благодаря светодиодам, встроенным в реле:
Теперь игрок должен изменить код программы в ПЗУ, заменив константу, загружаемую в регистр D. Если там не 0, это значит, что предположение больше загаданного числа. Иначе — меньше. После этого нужно нажать кнопку «продолжить работу». Проверив регистр D, компьютер использует прежнее предположение как верхний или нижний предел в следующей попытке.
Недостаток первой программы в том, что ей неудобно пользоваться. Это можно понять, посмотрев на фотографию ПЗУ — не очень-то легко переключать такие маленькие тумблеры, играя в игру (а ведь при этом надо ещё и следить, чтобы программу случайно не испортить).
Поэтому я придумал другой вариант ввода. Для отладки рядом с каждым регистром предусмотрен тумблер для сброса его значения. Его переключать намного удобнее, чем менять ПЗУ.
Теперь компьютер заранее заносит единицу в регистр D, а игрок либо сбрасывает его (если догадка меньше, чем задуманное число), либо оставляет как есть (если догадка больше).
Другая классическая игра, которую часто реализуют начинающие программисты — игра Баше.
В ней два игрока из кучки, содержащей первоначально N предметов, по очереди берут не менее одного и не более М предметов. Проигравшим считается тот, кому нечего брать.
В моём варианте игра идёт с компьютером. Изначально в кучке 21 предмет (например, 21 спичка). Игроки берут от 1 до 3 спичек в свой ход, а выигрывает тот, кто берёт последнюю спичку.
В игре есть выигрышная стратегия для первого игрока — всегда оставлять число спичек, которое кратно четырём. Так как 0 тоже кратно четырём, то второй игрок привести игру в эту позицию не сможет, а значит проиграет.
Компьютер ходит вторым, оставляя шанс человекам, но ошибок он не делает. И если игрок не будет следовать выигрышной стратегии, то это сделает компьютер.
В первой версии использовался тот же подход, что и для «угадай число» — в свой ход нужно было закодировать число спичек внутри одной из инструкций. Даже можно было считерить и взять все спички сразу, а компьютер ничего не заметит.
Но потом я переписал и эту программу тоже. Теперь в три регистра (B, C, D) компьютер заносит по 1, а игрок должен сбросить 0, 1 или 2 из них. Оставшиеся единицы — это те спички, которые он берёт. Читерить тоже можно, если сбросить все три регистра (как будто не берёшь ничего).
Конечно программа получилось несколько длиннее, но зато пользоваться ей значительно удобнее.
Дальше я планирую допаять ПЗУ (сейчас есть только 32 слова из возможных 64), а также добавить-таки устройство ввода в виде матрицы из тумблеров. Может тогда получится сделать хотя бы крестики-нолики.
Поиграть в игры, конечно! Играли же древние люди на калькуляторах МК-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), а также добавить-таки устройство ввода в виде матрицы из тумблеров. Может тогда получится сделать хотя бы крестики-нолики.