RedPower 2/Программирование

В модификации Red Power 2 существуют программируемые компьютеры. Они используют MineOS v1.2 и язык программирования FORTH.

Основная задача компьютера — это замена ваших редстоун цепей с применением логических элементов. Несмотря на это, компьютер остался собой и сохранил полную функциональность.

## Сборка

Компьютер в Red Power 2, состоит из четырех основных деталей-монитор, центральный процессор, дисковод, декодер IO, так же как дополнение существуют объединительная плата, на которую ставится 8K RAM модуль, служащий для расширения памяти компьютера, изначально у компьютера 600 байт памяти. Память напрямую влияет на количество программ, которые вы сможете использовать на компьютере. Части компьютера можно ставить как вплотную, так и раздельно, соединив их плоским кабелем. Важно! Объединительные платы надо ставить непосредственно за центральным процессором.

Немного о декодере IO, это устройство используется для перевода сигналов компьютера в сигналы красного камня, к нему сзади ставится связка проводов, на которую он и подает сигналы.

## Запуск

Что бы первый раз запустить компьютер, нам потребуется дискета с операционной системой — Загрузочный диск FORTH, ее необходимо вставить в дисковод, нажатием ПКМ. Затем, нажав ПКМ на центральный процессор, нажать на кнопку `Start`. Теперь нажмем ПКМ на монитор и, немного подождав, увидим надпись вида

"MineOS V1.2 Initialized 600 bytes free."

Всё, мы запустили компьютер и теперь можем приступить к его программированию.

## Программирование

### Элементарная часть

Основная идея программирования на языке FORTH — это интерпретация новому слову, какой-то последовательности уже известных команд.
Узнать, какие команды сейчас доступны для использования можно, введя "`WORDS`

" без кавычек. Завершение ввода любой команды производится нажатием `↵ Enter`.

Определение нового слова выполнятся вводом "`: *слово*`

", затем вводятся команды, примечание после ввода на этой команды каждая последующая строка будет начинаться так "`compile: `

", и завершается определение вводом "`;`

".
Пример определения слова Hi при вводе которого на экран будет выводится "Hello world"

```
>: Hi
```


```
compile: ." Hello world"
```


```
compile: ;
```


Внимание! compile: вводить не надо, оно автоматически появится у вас на экране, после ввода "`: Hi`

"

Теперь просто введя Hi на экран выведется "Hello world". В программе `." `

— это команда вывода строки, конец которой обозначается вторым символом `"`

.

Если теперь ввести "`WORDS`

", то мы увидим, что сразу после только что введенного WORDS идет наша команда Hi, т.е. мы определили новую команду для нашего компьютера и можем теперь ее использовать наравне с остальными.

Создадим еще одну программу.

```
>: five
```


```
compile: 2 3 + .
```


```
compile: ;
```


Теперь, введя five, на экране появится цифра 5. О команде "`2 3 + .`

", как только наш компьютер встречает ни с чем не связанное число, он помещает его в стек. Встретив "`+`

", компьютер сложит два значения лежащих на вершине стека, для любого другого знака арифметической операции он сделает тоже самое. Встретив "`.`

", компьютер выведет на экран число, лежащие в вершине стека.

Если нам больше не будет требоваться какая-либо команда и необходимо ее удалить, надо ввести "`FORGET *команда*`

", FORGET — стандартная команда, которая удаляет другие команды. Например, введя "`FORGET five`

", а затем WORDS, мы больше не увидим five в списке команд. Внимание! Будьте осторожны, удаляя команду, вы так же удаляете все команды, в которых она использовалась.
Перейдем к непосредственному взаимодействию с декодером IO.

Когда он устанавливается в мире, ему присваивается ID 3, его можно сменить отверткой. К компьютеру может быть подключено несколько декодеров, чтобы сменить декодер, на который посылается сигнал, необходимо ввести "`*ID декодера* IOXADDR !`

".

Для взаимодействия с декодером существуют 4 основных команды:

`IOX!`

— берет из стека значение и посылает на него сигнал. Если ввести
`1 IOX!`

— будет послан сигнал по белому проводу, т.к. он соответствует значению.

В RedPower 2 определено кодирование цветов по битам (значениям от 0 до 15 в соответствие с цветами), для определения можно пользоваться таблицей:

Col | Bit | Dec | Hex | Цвет |
---|---|---|---|---|

0 | 1 | 0х0001 | Белый / White | |

1 | 2 | 0х0002 | Оранжевый / Orange | |

2 | 4 | 0х0004 | Пурпурный / Magenta | |

3 | 8 | 0х0008 | Светло-синий / Light blue | |

4 | 16 | 0х0010 | Жёлтый / Yellow | |

5 | 32 | 0х0020 | Светло-зелёный / Lime | |

6 | 64 | 0х0040 | Розовый / Pink | |

7 | 128 | 0х0080 | Серый / Grey | |

8 | 256 | 0х0100 | Светло-серый / Light grey | |

9 | 512 | 0х0200 | Голубой / Cyan | |

10 | 1024 | 0х0400 | Фиолетовый / Purple | |

11 | 2048 | 0х0800 | Синий / Blue | |

12 | 4096 | 0х1000 | Коричневый / Brown | |

13 | 8192 | 0х2000 | Зелёный / Green | |

14 | 16384 | 0х4000 | Красный / Red | |

15 | 32768 | 0х8000 | Чёрный / Black |


Здесь Bit — это бит который соответствует проводу и Dec — значение, которое необходимо вводить перед IOX! для активации провода. Для активации сразу нескольких проводов надо ввести сумму значений Dec соответствующих проводов.

`IOX@`

— помещает в стек значение соответствующее включенным проводам. Если ввести `IOX@ .`

— на экран будет выведено значение соответствующее включенным проводам.

`IOXSET`

— берет из стека число и подает сигнал на провода соответствующие этому числу. Если ввести `4 IOXSET`

— к текущим сигналам прибавится сигнал на пурпурный провод.

`IOXRST`

— берет из стека число и убирает сигнал с провода соответствующие этому числу. Если ввести `4 IOXRST`

— из текущих сигналов уберется сигнал на пурпурный провод.

Это основные команды взаимодействия. Создадим простейшую команду, которая подаст сигнал на оранжевый провод на 10 тактов.

```
>: sign1
```


```
compile: 2 IOXSET
```


```
compile: 10 TICKS
```


```
compile: 2 IOXRST
```


```
compile: ;
```


Возможен иной вариант.

```
>: sign2
```


```
compile: 2 IOX!
```


```
compile: 10 TICKS
```


```
compile: 0 IOX!
```


```
compile: ;
```


Этого достаточно для простого управления различными системами: фермы, двери, лифты...

И последнее, допустим, есть компьютер, в котором мы создали множество команд и хотим их перенести на другой компьютер, для этого можно воспользоваться пустой дискетой, вставив ее в привод и введя команду `SAVE" *имя дискеты*"`

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

### Продвинутый уровень

Кроме команд взаимодействия с декодером есть множество других команд, которые можно использовать для усложнения и усовершенствования программ.

#### Переменные и константы

Переменную можно определить следующим образом "`VARIABLE *имя переменной*`

", изначально любая переменная имеет значение 0. Константу можно определить так "`*значение* CONSTANT *имя константы*`

", если не указать значение, оно возьмется из стека (по факту оно итак сначала помещается в стек а затем присваивается константе). Различие между переменной и константой в том, что значение переменной можно менять, а константы нет.

Для работы с переменной есть две операции `@`

— помещает в стек значение переменной, используется так "`*имя переменной* @ .`

" — выведет на экран значение переменной. Вторая это `!`

— присваивает переменной значение из стека, например "`*значение* *имя переменной* !`

" — задаст переменной заданное значение.

#### Массивы и строки

В языке FORTH нет явного способа задания массива, для этого используется создание константы большего размера чем обычно. Командой `*размер* ALLOT CONSTANT *название*`

создастся массив заданного размера, здесь `ALLOT`

— команда выделения указанного количества памяти. Чтобы получить нужный элемент массива, мы должны обратиться к памяти по адресу *начало массива*+i * *размер элемента*, i — номер нужного элемента.

Строки идентичны массивам, только каждый элемент — это символ, и строка всегда на один символ короче, чем создавалась, это связано с использованием особого символа — конец строки, он используется автоматически. Для строк определены следующие команды:

`TYPE`

— выводит строку на экран, используется — `*имя строки* TYPE`


`ACCEPT`

— используется для ввода строки, используется — `*имя строки* *размер строки* ACCEPT [нажмите `

`↵ Enter`] [Введите строку] [нажмите `↵ Enter`]

`STRLEN`

— возвращает в стек длину строки, используется - `*имя строки* STRLEN .`

— выведет на экран размер

`STRCMP`

— сравнивает две строки, вернет в стек 1, если равны, иначе 0, используется `*имя первой строки* *имя второй строки* STRCMP .`

— выведет 1 или 0

`ATOI`

— преобразует строку в число со знаком и помещает в стек, используется `*имя строки* ATOI`


`UATOI`

— преобразует строку в число без знака и помещает в стек

`UITOA`

— преобразует число в строку и возвращает адрес строки

`MOVE`

— копирует одну строку в другую, используется `*имя копируемой* *имя строки куда копируем* *размер строк* MOVE`


#### Логические операции

В основном это операции проверки на истинность, все логические операции возвращают TRUE(1) или FALSE(0).

`0=`

— сравнит значение из стека с 0, если оно 0, вернет в стек TRUE, иначе FALSE

`0<>`

— сравнит значение из стека с 0, если оно НЕ 0, вернет в стек TRUE, иначе FALSE

`0<`

— сравнит значение из стека с 0, если оно меньше 0, вернет в стек TRUE, иначе FALSE

`<>`

— сравнит два значения из стека, если они НЕ равны, вернет в стек TRUE, иначе FALSE

`<`

— сравнит два значения из стека, если первое меньше, вернет в стек TRUE, иначе FALSE

`>`

— сравнит два значения из стека, если первое больше, вернет в стек TRUE, иначе FALSE

`=<`

— сравнит два значения из стека, если первое меньше либо равно второму, вернет в стек TRUE, иначе FALSE

`>=`

— сравнит два значения из стека, если первое больше либо равно второму, вернет в стек TRUE, иначе FALSE

`=`

— сравнит два значения из стека, если первое равно второму, вернет в стек TRUE, иначе FALSE

`KEY?`

— возвращает TRUE, если была нажата клавиша.

#### Условия

Полезны, когда необходимо выполнить различные действия при разных значениях чего-либо (например переменной). Условие реализуется 2 основными командами и одной не обязательной. Первая команда — это `IF`

, она берет значение из стека, и если оно TRUE (логическая 1), начинает выполнять команды, при этом возможна дополнительная команда `ELSE`

, указывающая, что необходимо выполнить, если условие не верно. Общая структура такова

`IF (команды, если условие верно) ELSE (команды, если условие не верно) THEN`


`THEN`

— обозначает конец блока `IF`

. Внимание! `ELSE`

не обязателен, но `THEN`

обязателен после каждого `IF`

.

#### Циклы

Полезны, когда требуется повторить одни и те же команды несколько раз. В языке FORTH много различных циклов, по этому по порядку:

`DO (команды внутри цикла) LOOP`

— вытаскивает из стека два значения и работает, прибавляя ко второму по 1, пока числа не будут равны. Используется так `*до скольки* *от скольки* DO (команды в цикле) LOOP`

, например `5 0 DO ." Hello world" LOOP`

— выведет Hello world 5 раз.

Возможны варианты: вместо `DO`

использовать `?DO`

— тогда цикл не запустится, если значения равны, вместо `LOOP`

использовать `*значение* +LOOP`

— каждый раз прибавляет к счетчику не 1, а указанное значение.

Существует команда принудительного выхода из цикла `LEAVE`

.

Существуют 2 команды, что бы узнать значение счетчика цикла. `I`

— вернет значение текущего счетчика цикла `DO`

, `J`

— вернет значение счетчика цикла на уровень выше.

`BEGIN`

— общая команда для начала 3 разных циклов: `UNTIL`

, `REPEAT`

, `AGAIN`


`UNTIL`

— выйдет из цикла если логическое значение в стеке TRUE, иначе повторит цикл

`REPEAT`

— особая конструкция вида `BEGIN (команды 1) WHILE (команды 2) REPEAT`

, сначала выполняются команды 1, затем, если логическое значение в стеке TRUE, выполняются команды 2 и цикл повторяется, иначе выходит за `REPEAT`


`AGAIN`

— создает бесконечный цикл, выйти можно 3 командами `EXIT`

- выходит из текущей команды, `QUIT`

— завершение выполнения всех команд, `ABORT`

— то же, что и QUIT, только с очисткой стека.

#### Остальные различные команды

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

`PAGE`

— отчистит экран и поместит курсор в левый верхний угол.

`SCROLL`

— перемещает содержимое экрана на 1 строку вверх.

`AT-XY`

— возьмет из стека два значения и поместит туда курсор.

`CR`

— конец строки и переход на следующую.

`HEX`

— перейдет в 16-ричную систему счисления.

`DECIMAL`

— перейдет в 10-ричную систему счисления.

`TIMES`

— возьмет из стека значение и повторит следующую за собой команду это число раз.

`CELL`

— вернет размер ячейки памяти в байтах.

`NEGATE`

— возьмет из стека значение и поменяет ему знак.

`MAX`

или `MIN`

— возьмут из стека два значения и вернет наибольшее\наименьшее соответственно.