ДЕЛАЕМ СВОИ ШРИФТЫ

При работе с текстами обычно используют встроенный в компьютер шрифт, а в игровых программах с целью улучшения дизайна его, как правило, заменяют каким-либо другим. На новый шрифт часто приходится отводить большой объем оперативной памяти, которой всегда не хватает в маломощном компьютере. Замена только одного из встроенных шрифтов (кириллицы или латиницы) хотя и экономит память, но зачастую проблем не решает.

Ниже приводятся разработанные мною алгоритмы и экономные программы для замены встроенного шрифта. Программы написаны на Бейсике для БК 0010-01. Алгоритмы же могут быть использованы и при работе на других языках, и для других компьютеров.

Все предлагаемые программы работают по одному принципу. Сначала курсор устанавливают в ту точку экрана, в которую должна быть выведена буква. Затем какой-либо переменной присваивают значение, равное абсолютному адресу этой точки, выводят в неё нужную букву и обращаются к подпрограмме замены шрифта.

При написании подпрограмм учитывалось, что в стандартном шрифте БК под символ отводится десять графических строк, из них девять - непосредственно под букву, а десятая - подрежим подчёркивания символов.

Приведённые ниже подпрограммы 1-3 замены встроенного шрифта могут быть включены, например, в основную программу, также приведённую ниже.

ВИДЫ ШРИФТОВ

НАКЛОННЫЙ ВПРАВО - КУРСИВ (ITALIC). Для создания этого шрифта необходимо верхнюю треть изображения буквы стандартного шрифта сдвинуть на одну точку вправо, а нижнюю треть - на одну точку влево. Этот сдвиг осуществляется подпрограммой 1 после вывода буквы.

В строке 1000 подпрограммы 1 (как и в подпрограммах 2 и 3) задаётся число циклов 10, так как на букву отводится десять строк изображения. Для большего быстродействия вместо числа 10 указывается восьмеричное число &O1100, но так как шаг цикла равен 64, то число циклов и будет равно 10. Для осуществления сдвига верхней и нижней третей изображения буквы в строке 1010 проверяется выполнение следующего условия: если значение переменной QQ% больше &0500, то происходит сдвиг шестой и последующих строк изображения буквы влево, а если QQ% меньше &O300, то управление передаётся строке 1040. В строках 1040-1070 реализуется сдвиг вправо.

Для работы этой подпрограммы необходимо в основной программе в переменную Р% занести абсолютный адрес первого (верхнего) машинного слова из описания буквы и по этому адресу вывести букву.

Обращение к подпрограмме осуществляется оператором GOSUB n, где n - номер первой строки подпрограммы. Например, для вывода буквы "А" в точку с координатами (3,7) требуется следующая основная программа:

10 ? CHR$(140)CHR$(140);
20 ? АТ(3,7):
30 Р%=PEEK(&O160)
40 ? "А";
50 GOSUB 1000
60 END

Далее следует текст подпрограммы 1

ПОДПРОГРАММА 1

1000 FOR QQ%=0% ТО &O1100 STEP 64%
1010 IF QQ%>&O500 THEN POKE P%+QQ%,PEEK(P%+QQ%)\4% ELSE IF QQ%<&O300 THEN GOSUB 1040
1020 NEXT QQ%
1030 RETURN
1040 Q2%=PEEK(P%+QQ%)
1050 POKE P%+QQ%,(Q2% AND &O17777)*4%
1060 IF (Q2% AND &O20000)<>0% THEN OUT P%+QQ%,&O100000,1%
1070 RETURN

 

НАКЛОННЫЙ ВЛЕВО (BACKSLANT). Для наклона шрифта влево надо заменить строку 1010 подпрограммы 1 на следующую:

1010 IF QQ%<&O300 THEN POKE P%+QQ%,PEEK(P%+OQ%)\4% ELSE IF QQ%>&O500 THEN GOSUB 1040

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

ЖИРНЫЙ (BOLD). При формировании этого шрифта на экран выводится два изображения одной и той же буквы, смещённых на одну точку по горизонтали относительно друг друга. Делается это с помощью подпрограммы 2, где в строках 1010-1030 осуществляются сдвиг изображения буквы вправо и наложение (операция OR) получившегося изображения на предыдущее.

ПОДПРОГРАММА 2

1000 FOR QQ%=0% ТО &O1100 STEP 64%
1010 Q2%=PEEK(P%+QQ%)
1020 OUT P%+QQ%,(Q2% AND &O17777)*4%,1%
1030 IF (Q2% AND &O20000)<>0% THEN OUT P%+QQ%,&O100000,1%
1040 NEXT QQ%
1050 RETURN

Можно сформировать так называемый компьютерный шрифт, в котором буквы утолщены только в нижней части. При этом необходимо в подпрограмме 2 заменить строку 1000 на следующую:

1000 FOR QQ%=&O500 ТО &O1100 STEP 64%

Основная программа для вывода жирных шрифтов аналогична приведённой выше.

КОНТУРНЫЙ (OUTLINE). Для создания этого шрифта используется сложный алгоритм. Изображение буквы стандартного шрифта сначала помещают в ту точку, в которой оно в дальнейшем должно находиться. Затем его временно перемещают на любое другое свободное место и вновь считывают это изображение, возвращая его с некоторым сдвигом на прежнее место. Этот сдвиг осуществляется наложением (операция OR) со смещением изображения стандартного шрифта на точку вверх, вниз, вправо, влево. После этого из полученного рисунка вырезают изображение буквы стандартного шрифта.

Шрифт формируется с помощью подпрограммы 3. В первом цикле (строки 1000-1020) осуществляется построчный перенос изображения буквы, выведенной основной программой, в левый верхний угол экрана.

В следующем цикле (строки 1030-1090) изображение перенесённой буквы сдвигается влево (строка 1040), вверх (строка 1050), вниз (строка 1060), вправо (строки 1070 и 1080), а затем перемещается на прежнее место.

В третьем цикле (строки 1100-1120) из полученного изображения удаляется изображение буквы стандартного шрифта.

Обращение к этой подпрограмме происходит так же, как и к двум предыдущим. Однако в основной программе не должны использоваться первые 10 строк экрана. Кроме того, учитывая, что получаемый шрифт может занимать до 12 точек по высоте, необходимо выводить получаемый текст через строку.

ПОДПРОГРАММА 3

1000 FOR QQ%=0% ТО &O1100 STEP 64%
1010 POKE &O40000+OQ%,PEEK(P%+OQ%)
1020 NEXT QQ%
1030 FOR QQ%=0% TO &O1100 STEP 64%
1040 OUT P%+QQ%+64%,PEEK(&O40000+QQ%)\4%,1%
1050 OUT P%+QQ%,PEEK(&O40000+QQ%),1%
1060 OUT P%+QQ%+128%,PEEK(&O40000+QQ%),1%
1070 OUT P%+QQ%+64%,INP(&O40000+QQ%,&O17777)*4%,1%
1080 IF (PEEK(&O40000+QQ%) AND &O20000)<>0% THEN OUT P%+QQ%+64%,&O100000,1%
1090 NEXT QQ%
1100 FOR QQ%=0% TO &O1100 STEP 64%
1110 OUT P%+QQ%+64%,PEEK(&O40000+QQ%),0%
1120 NEXT QQ%
1130 RETURN

ОСНОВНАЯ ПРОГРАММА ДЛЯ ВЫВОДА ШРИФТОВ НА ЭКРАН

Программа работает только при красном цвете текста, чёрном цвете экрана и в режиме 32 символа в строке. Строкой 10 устанавливается чёрный цвет курсора и экрана; 20 - компьютер переключается в режим 32 символа в строке; 30 - убирается служебная строка, восстанавливается изображение на экране (левому верхнему байту экрана будет соответствовать адрес &O40000) и устанавливается красный цвет курсора; 60 - указывается высота выводимого шрифта (10 точек для подпрограмм 1-2 и 12 точек для подпрограммы 3); 70 - происходит считывание текста из операторов DATA; 80 - контролируется конец текста; 90 - подсчитываются координаты центра строки символов, находящихся в переменной А$; 100-160 - из переменной А$ текст переносится в строку экрана, номер которой указан в переменной Y%; 2000-2030 - располагается подпрограмма раскраски символа.

ОСНОВНАЯ ПРОГРАММА

10 COLOR 4,4
20 IF INP(&O40,255%)=0% THEN ? CHR$(155);
30 ? CHR$(158)CHR$(140)CHR$(140)CHR$(145);
40 C1%=&HAAAA
50 C2%=&HFFFF
60 H%=N%*64%-64%
70 READ A$,Y%
80 IF A$="END" THEN 80
90 X%=14%-LEN(A$)\2%
100 FOR A%=1% TO LEN(A$)
110 ? AT(X%+A%,Y%);
120 P%=PEEK(&0160)
130 ?MID$(A$,A%,1%);
140 GOSUB 1000
150 GOSUB 2000
160 NEXT A%
170 GOTO 70
1000 RETURN
2000 FOR QQ%=0% TO H% STEP 64%
2010 IF QQ%<(H%\2%) THEN POKE P%+QQ%,PEEK(P%+QQ%) AND C1% ELSE POKE P%+ QQ%,PEEK(P%+QQ%) AND C2%
2020 NEXT QQ%
2030 RETURN
3000 DATA "ЭТОТ ШРИФТ",1
3010 DATA "ПОМОЖЕТ",3
3020 DATA "ВАМ",5
3030 DATA "УКРАСИТЬ ПРОГРАММУ",10
3040 DATA "END",-1

В программе использованы следующие переменные:

С1% - цвет верхней половины текста; С2% - цвет нижней половины текста; Н% - высота текста; А$ - строка символов, считанная из оператора DATA; Y% - номер строки экрана, в которую был выведен или выводится текст; Х% - координата центра для текста, находящегося в переменной А$; А% - номер буквы, выводимой из переменной А$; Р% - абсолютный адрес верхнего слова, выводимого символа; QQ% - переменная для организации циклов.

Описанные шрифты были использованы мной в программах игр BOBI, ВОВI 2, ALIENS, STAR BANDIT, SHERIF AND BANDIT, MAD GHOST.

Владислав Юров


 

БЫТОВОЙ НЕЙРОКОМПЬЮТЕР «ЭМБРИОН»

Нейрокомпьютер - удивительный объект, над созданием которого десятки лет работает огромная армия учёных, технологов, инженеров, математиков во многих странах мира. Задача создания нейрокомпьютера особенно сложна потому, что в ней переплетены фундаментальные

проблемы из многих областей науки и техники - нейрофизиологии, психологии, квантовой физики, вычислительной техники, общей теории поля, биоэнергетики и др. На эту научную проблему тратятся огромные ресурсы. Только в Японии на восьмилетнюю (1989 - 1997 гт.) программу "Нейрокомпьютер" по разработке компьютера шестого поколения выделено 231 млн. дол. Для создания нейрокомпьютера объединились крупнейшие фирмы Японии: Фудзицу, Хитачи, Тосиба, Мицубиси денки, Оки денки.

К 1997 г. нейрокомпьютер должен уметь говорить, иметь эмоции, обладать ощущениями, уметь делать выводы и накапливать опыт. В США программа Пентагона "Стратегическая компьютерная инициатива" преследует цель создания нового поколения компьютеров, обладающих определёнными человеческими качествами: здравым смыслом, специальными знаниями, умением видеть, слышать и говорить. Стоимость этой программы в 1984 - 1988 гг. составила 571 млн. дол., а в ближайшие годы превысит 1 млрд. дол.

ЗАНЯТИЕ 2

Надеюсь, вы успешно запустили программу "Эмбрион" (см. "Байтик", 1991, № 2, с.26), провели опыты, предложенные на первом занятии, "почувствовали" работу бытового нейрокомпьютера (БНК) "Эмбрион" в динамике, и мы можем приступить к анализу программы.

Анализ программы "Эмбрион"

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

  1. Создаётся совокупность триггеров размером n*(m + 1). Здесь n - число столбцов в сенсорной матрице (СМ), т.е. разрядность БНК (n = 3), m + 1 - число строк СМ (n = 3) плюс ещё одна строка, соответствующая регистру Р внутреннего состояния. Каждый триггер может устанавливаться в состояние "1" или "0" подачей сигнала "УСТАНОВКА" или "СБРОС" на соответствующий вход триггера.
  2. В каждый такт работы сети могут взаимодействовать только два триггера: один (обозначим его Si) из СМ, другой (обозначим его Рi) из регистра Р. Пары триггеров (Si,Pi), где i = 1,..., n, образуют элементы нейронной сети. Взаимодействие между триггерами в каждом элементе задастся оператором G (см. рисунок), который выполняет две функции: определяет состояния триггеров Si и Pi и управляет состоянием триггера Pi.

    Из рисунка видно, что в зависимости от исходных состояний триггеров Si и Pi можно выделить четыре типа элементов нейронной сети - 1, 2, 3, 4. В частности, если эти состояния одинаковы, то под действием оператора G состояние триггера Pi не меняется (элементы типа 1 и 4), а если они разные, то триггер Pi меняет своё состояние на противоположное (элементы типа 2 и 3). Иначе говоря, происходит "уравновешивание внутреннего состояния Р с состоянием внешней среды" (по Павлову)[1].

    Элементы типов 1 и 4 назовём пассивными, а элементы типов 2 и 3 – активными. Обозначим число элементов типа 1 через c, типа 2 - через d, типа 3 - через e. типа 4 - через g. Очевидно, что общее число элементов c+d+e+g не превышает разрядности БНК, т.е. n. Число активных элементов J = d + е называется невязкой. Оно характеризует степень неуравновешенности внешней и внутренней среды БНК.

  3. Регистры (строки) СМ подключаются к регистру Р поочерёдно. Выбор пары взаимодействующих триггеров (Si,Pi) осуществляет блок выдвижения гипотез (БВГ) случайным образом с вероятностью 1/n.
  4. Триггеры СМ и регистра Р взаимодействуют многократно. Исходное состояние при этом всякий раз одно и то же.

Перейдём теперь непосредственно к разбору программы. Но прежде отметим её особенность, состоящую в наличии трёх вложенных друг в друга циклов: в первом внутреннем цикле осуществляется просмотр отдельной j-й строки СМ в течение времени осмотра, определяемого величиной Uj; во втором, внешнем, - поочерёдный просмотр всех m строк СМ (от j = 1 до j = m); в третьем - возбуждение нейронной сети в течение заданного "времени жизни" Т (см. "Байтик", №2).

Итак, в строках 1.03 - 2.03 задаются образ на сенсорной матрице, значение NS и исходное состояние триггеров P1, Р2, Р3 регистра Р.

В строке 3.03 задастся гипотеза восприятия U = U1, U2, U3, которая вместе с NS определяет время жизни Т нейронной сети, причём значения U1, U2, U3 определяют время просмотра отдельных строк СМ, т.е. объем переносимой из них в регистр Р информации.

В строке 4.04 вводятся две группы переменных - K1, К2, К3 и X1, Х2, Х3, которым присваиваются соответственно значения Uj и Рi.

В строках 4.10 - 4.90 организован цикл К1-кратного сканирования первой строки СМ и переноса се содержимого в регистр Р с преобразованием в соответствии с оператором G, который в программе задаётся в виде формулы

Xi := (Pi + Si) - 1 * Pi,

где все переменные логические (:= знак присвоения). Датчиком псевдослучайных чисел (функция FRAN() в строке 4.20) генерируется число в интервале [0 - 1.0] и его значение присваивается переменной L.

Затем в зависимости от значения этого числа выполняются следующие действия:

После каждого импульса сканирования, поступающего из БВГ, состояние счётчика цикла К1 уменьшается на единицу (строка 4.80). После завершения цикла по К1 в строке 5.02 определяется номер канала (т.е. номер возбуждённого мотонейрона Y второго слоя сети), равный числу "возбуждённых" (находящихся в состоянии "1") триггеров регистра Р.

 

Рис. 1. Типы элементов нейронной сети: тёмный кружок - триггер в состоянии ”1"; светлый кружок - триггер в состоянии "0”; пунктирная линия - опрос триггеров Si и Pi; тонкая линия - управление триггерами Pi; жирная линия - изменение состояния триггера Pi

В строках 5.10 и 7.10 начинаются циклы по К2 и К3 соответственно, в которых в регистр Р передаётся информация из строк 2 и 3 СМ. Эти циклы аналогичны циклу по К1. По завершении этих циклов определяются номера мотонейронов Y2 и Y3 второго слоя нейронной сети.

Строкой 9.40 заканчивается первый из NS проходов по внешнему циклу возбуждения сети. При этом число Y3 представляет собой статистическую характеристику всей информации, перенесённой из СМ в регистр Р под воздействием кода U в БВГ.

Затем в строке 9.50 значение Y3 передаётся в часть программы, начинающуюся строкой 10.02 и обеспечивающую индикацию импульсной активности мотонейронов. Эта часть программы организована в виде счётчика-накопителя импульсов, формируемых при NS-кратном сканировании образа на СМ. Она выводит на экран номера мотонейронов (0, 1, 2, 3) и степень возбуждения каждого из них, задаваемую десятичным числом (SY, SJ, SC, SU) рядом с линией следующего вида - - - - -.

Если Y3-1 < 0, то переменная SY (строки 10.20, 1025) принимает значение 1 и на экране справа от обозначения мотонейрона 0 выводится знак и число "1" (строка 10.30).

Если Y3-1 = 0, то аналогичные данные выводятся рядом с обозначением мотонейрона 1 (строки 10.40, 10.45).

Если Y3-1 > 0, то после сравнения Y3 с числом 2 (строка 10.50) аналогичные данные выводятся рядом с обозначением мотонейронов 1, 2 или 3.

В строке 9.60 проверяется условие NS = 0 и, если оно выполняется, то на печать выводятся (строка 9.70) исходные данные.

Фрагмент программы, содержащий строки 9.71 - 9.76, также обеспечивает графическое отображение реакции мотонейронов, но в другой форме; об этом мы поговорим на одном из следующих занятий.

Альфа-ритм и его наблюдение

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

Для этого воспользуемся введённым ранее параметром J (невязка), который и характеризует динамику активности сети в течение её "времени жизни". Итак, добавим в программу "Эмбрион", во-первых, строку 2.04 для определения числа единиц в регистре Р (оно нужно для вычисления J)

2.04 S Р = P1 + Р2 + P3

а, во-вторых, подпрограмму вывода на печать альфа-ритма:

20.10 X FT(1,0,20); X FV(l,512,20);
20.15 S J = 0
20.20 S J = FABS(Y3-P)
20.25 S U = U1+U2+U3
20.30 S B = 512/(NS*U)
20.40 S X = X+(B*U-1)
20.50 F I = 1,1,5*J
20.60 X FT(1,X,20); X FV(1,X,20- J); R

Несколько слов об этой подпрограмме. В строке 20.10 проводится ось абсцисс. После каждой реализации возбуждения нейронной сети определяется абсолютная величина невязки по формуле J = Y3 - Р (первоначально J = 0). В строках 20.25 - 20.40 проводится масштабирование изображения альфа-ритма, а в строках 20.50 и 20.60 - формирование его фактической амплитуды и позиции на оси абсцисс. Переход к подпрограмме осуществляется по команде

10.10 D 20; G 9.6

Обратите внимание: на изображении альфа-ритма хорошо видны три цикла в работе БНК.

Владимир Цыганков



[1] Павлов Иван Петрович (1849-1936) русский физиолог, создатель учения о высшей нервной деятельности.

Performed by © gid, 2012-2022.