01.01. СЕРДЖО ЛЕОНЕ, ЭННИО МОРРИКОНЕ...

Перейти вниз

01.01. СЕРДЖО ЛЕОНЕ, ЭННИО МОРРИКОНЕ...

Сообщение автор Gudleifr в Вт Ноя 28, 2017 10:16 am

ТОМ I. МАШИНА ИГРАЕТ С ЧЕЛОВЕКОМ
О том, что может компьютер добавить к обычным играм в солдатики.

ГЛАВА ПЕРВАЯ. СЕРДЖО ЛЕОНЕ, ЭННИО МОРРИКОНЕ...
Стрельба "по-книжному"

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

В те же годы, когда компьютерные игры только начинались, проблема была еще страшнее. Как заставить ЭВМ реагировать на действие игрока немедленно? Вовремя выстрелить в появившегося на экране врага или даже просто заставить бегущую по экрану фигурку подпрыгнуть? Ведь, игры начали программировать еще тогда, когда и экрана-то у компьютеров не было - играли с телетайпа (это такая пишущая машинка для компьютера).
***

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



HIGN HOON  

...
ТЫ ВЫНУЖДЕН ВЫЯСНИТЬ ОТНОШЕНИЯ С ЧЕРНЫМ БАРТОМ - ОДНИМ ИЗ САМЫХ ОПАСНЫХ
БАНДИТОВ К ЗАПАДУ ОТ АЛЛЕГАНСКИХ ГОР.
ВЫЙДЯ ИЗ ПЫЛЬНОГО ПЕРУЛКА НА ЕЩЕ БОЛЕЕ ПЫЛЬНУЮ ГЛАВНУЮ УЛИЦУ ДОДЖ-СИТИ,
ТЫ ВИДИШЬ ЧЕРНОГО БАРТА, ВЫХОДЯЩЕГО ИЗ САЛУНА В СОТНЕ МЕТРОВ ВПЕРЕДИ.
ПО УГОВОРУ У ВАС ПО ЧЕТЫРЕ ПАТРОНА В БАРАБАНАХ ВАШИХ ШЕСТИЗАРЯДНЫХ ПУШЕК.
СТРЕЛЯЕТЕ ВЫ ПРИМЕРНО ОДИНАКОВО. В НАЧАЛЕ ВАШЕЙ ПРОГУЛКИ НИ ОДИН НЕ МОЖЕТ
ПОПАСТЬ В ДРУГОГО, КОГДА СОЙДЕТЕСЬ ВПЛОТНУЮ - НИ ОДИН НЕ ПРОМАХНЕТСЯ.
ЧЕМ БЛИЖЕ ВЫ СОЙДЕТЕСЬ, ТЕМ БОЛЬШЕ ТВОИ И ЕГО ШАНСЫ ПОПАСТЬ.
...
ТВОИ ВОЗМОЖНЫЕ ДЕЙСТВИЯ:

1. ПОДОЙТИ
2. СТОЯТЬ
3. СТРЕЛЯТЬ
4. СПРЯТАТЬСЯ ЗА ЛОШАДИНУЮ ПОИЛКУ
5. ОТСТУПИТЬ
6. РАЗВЕРНУТЬСЯ И БЕЖАТЬ

Листинг программы - JPG/RAR, 0.95Мб.

(Если вы не знали и забыли BASIC, то можете освежить свою память, забежав вперед и сходить по ссылке, приведенной ниже - в абзаце про СОВСЕМ МАЛЕНЬКИЕ BASIC-МАШИНКИ ИГР - ТЕМА #60, АБЗАЦ #635).
***

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

Рассматривая же саму BASIC-программу этой игры, мы видим многие черты, свойственные игровым программам тех времен (1970).

- Небрежное форматирование. Авторы жутко экономят на пробелах, из-за чего программа становиться очень плохо читаемой. От этой привычки BASIC- и FORTRAN-программисты отказались только с появлением синтаксических компиляторов и полноценных экранных редакторов.
- Приходилось применять даже в простейших программах технические трюки. Например, здесь - случайная прокрутка генератора случайных чисел.
- Выдача диплома. Распечатка красивой картинки (пусть и чисто текстовой) в награду за победу (или в виде издевательства). Выдача (иногда и на принтер) чека на круглую сумму, космического офицерского диплома или, наоборот, изображения надгробия производило достаточно сильное впечатление.
- Самое главное - игра самая простенькая, а играть очень интересно.

Бросаются в глаза и ошибки (всех 4-х групп, "не мешающих" программе работать):

- Недоработки - присутствует правка листинга ручкой (т.е. удаление заглушки - строки 1560); недостижима строка 1870 - сообщение о промахе последним патроном; а, заодно, и 1800-1810 - видимо, дублирование сообщений о промахе Барта в случае бегства игрока.
- Безвредная - дублирование строки 1420.
- Редкоуловимые - числа-то не совсем случайные, и возможно подобрать стартовое "счастливое" число, быстро приводящее к победе; расстояние между дуэлянтами может стать нулевым/отрицательным.
- Явные - число оставшихся патронов после выстрела Барта выводится на экран далеко не всегда; вместо проверки, спрятался ли игрок за корытом, в 1300 проверяется случайное число (проверка всегда неудачна); в случае бегства отсутствует случайный фактор; Барт может идти со скоростью больше 10.

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

КАК ОНО УСТРОЕНО

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

Однако, такая простая структура в природе обычно не встречается: программисты (точнее, программирующие пользователи) обожают превращать свои программы в лабиринты, блуждать по которым столь же интересно, как и играть в саму игру.
Этакая сложная система состояний с замысловатыми переходами между ними. Ни дать, ни взять - книга-игра.
***

ОСНОВНЫЕ ОПЕРАТОРЫ

- Случайный выбор:

СЛУЧАЙ(ПОРОГ, УСПЕХ)

где ПОРОГ - пороговое значение случайной величины (равномерно распределенной на отрезке [0,1) ), УСПЕХ - идентификатор (строка в программе) состояния, куда надо идти, если ПОРОГ превышен. Здесь и далее везде подразумеваются безвозвратные переходы. На BASIC это выглядит примерно так:

750W=RND(-1)*10
760IFW>X/10THEN820[/code]

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

- Более скучный случай выбора - когда вместо проверки случайной величины, берется значение какой либо переменной или числа, введенного игроком. Назовем его:

ПЕРЕХОД(ВЫРАЖЕНИЕ, ЗНАЧЕНИЕ1, ВЫБОР1, ЗНАЧЕНИЕ2, ВЫБОР2,.. ЗНАЧЕНИЕN, ВЫБОРN).

Например:

770IFC=2THEN1820
780IFC=3THEN1840

Для случая, если ВЫРАЖЕНИЕ может принимать несколько подряд идущих ЗНАЧЕНИЙ, начиная с единицы, в BASIC придумана специальная кострукция "перейти по метке, номер такой-то из списка" - ON GOTO, и, даже, "перейти к процедуре..." - ON GOSUB.

- Т.к. игра практически текстовая, важным является оператор выдачи сообщения:

ВЫДАЧА(СООБЩЕНИЕ, ВОЗВРАТ)

где ВОЗВРАТ - состояние в которое надо перейти после вывода сообщения. Например:

1820PRINT"GRAZED BART IN THE RIGHT ARM"
1830GOTO1040

Важнейшие случаи - там, где ВОЗВРАТ осуществляется в главные точки цикла управления: соответственно назовем их КОНЕЦ (2080), ХОД-ИГРОКА (550), ХОД-БАРТА (1040). Я буду заменять этими словами слово ВЫДАЧА.

***

Теперь вся программа целиком.
Начальные установки:

110 ВЫВЕСТИ ЗАГОЛОВОК
150 ЕСЛИ НАДО, ВЫВЕСТИ ВВОДНЫЙ КУСОК (см.выше про пыльный Додж-Сити), ИНАЧЕ - 460
300 ЗАЩИТА ОТ ДУРАКА (если человек прочел введение, но отказался читать инструкции то - 1370)
1370 КОНЕЦ("НОВИЧОК.")
330 ВЫВЕСТИ ИНСТРУКЦИЮ (какая цифра какому действий соответствует, см. выше)
460 ИНИЦИАЛИЗАЦИЯ ДАТЧИКА СЛУЧАЙНЫХ ЧИСЕЛ
540 РАССТОЯНИЕ = 100

Ход игрока:

550 ВВЕСТИ КОМАНДУ (1-6 - см. выше, при других вариантах - 1340)
1340 ХОД-ИГРОКА("НЕ СОБЛЮДАЕШЬ ИНСТРУКЦИИ - ПОМРЕШЬ МОЛОДЫМ!")
610 ПЕРЕХОД(КОМАНДА, ПОДОЙТИ, 620, СТОЯТЬ, 1390, СТРЕЛЯТЬ, 690, ПРЯТАТЬСЯ, 1410, ОТСТУПАТЬ, 1510, БЕЖАТЬ, 1610)

Игрок решил подойти к Барту:

620 ВВЕСТИ КОЛИЧЕСТВО ШАГОВ
630 ПЕРЕХОД(ЧИСЛО-ШАГОВ, меньше 0, 2000, больше 10, 1980)
1980 ВЫДАЧА("НИКТО НЕ МОЖЕТ ХОДИТЬ ТАК ВЫСТРО", 620)
2000 ВЫДАЧА("НИКАКИХ ОТРИЦАТЕЛЬНЫХ ЧИСЕЛ!", 620)
660 РАССТОЯНИЕ = РАССТОЯНИЕ - ЧИСЛО-ШАГОВ
670 ХОД-БАРТА("ОСТАЛОСЬ $ЧИСЛО-ШАГОВ$")

Игрок решил стрелять:

690 ВЫСТРЕЛЫ-ИГРОКА = ВЫСТРЕЛЫ-ИГРОКА + 1
700 ПЕРЕХОД(ВЫСТРЕЛЫ-ИГРОКА, не больше 4, 750)
710 ХОД-БАРТА("ДОВЫПЕНДРИВАЛСЯ, ПАТРОНОВ-ТО БОЛЬШЕ НЕТ."
"БАРТ ТЕПЕРЬ ПОДОЖДЕТ, ПОКА ТЫ НЕ ПОДОЙДЕШЬ ПОБЛИЖЕ."
"НАДО СРОЧНО СДЕЛАТЬ ЧТО-ТО УМНОЕ (НАПРИМЕР, УБЕЖАТЬ)")
750 СЛУЧАЙ(РАССТОЯНИЕ/100, 820)
770 ПЕРЕХОД(ВЫСТРЕЛЫ-ИГРОКА, 2, 1820, 3, 1840)
1820 ХОД-БАРТА("ТЫ ЗАЦЕПИЛ ПРАВУЮ РУКУ БАРТА")
1840 ХОД-БАРТА("ТЫ ЛЕГКО РАНИЛ БАРТА В ЛЕВОЕ ПЛЕЧО")
790 "ПРОМАХ"
800 ПЕРЕХОД(ВЫСТРЕЛЫ-ИГРОКА, 4, 710)
1460 ПЕРЕХОД(ВЫСТРЕЛЫ-БАРТА, больше 4, 1050)
1470 ХОД-БАРТА("У ТЕБЯ $4 - ВЫСТРЕЛЫ-ИГРОКА$ ПАТРОНОВ"
"У БАРТА - $4 - ВЫСТРЕЛЫ-БАРТА$")

Игрок стоит:

1390 ХОД-БАРТА("ТЫ - ПРЕКРАСНАЯ НЕПОДВИЖНАЯ МИШЕНЬ")

Игрок прячется:

1410 УКРЫТИЕ = УКРЫТИЕ + 1
1420 ПЕРЕХОД(УКРЫТИЕ, больше 3, 2060)
2060 ХОД-ИГРОКА("ПОИЛОК БОЛЬШЕ НЕТ")
1440 ХОД-БАРТА("НЕПЛОХОЙ МАНЕВР, БАРТ К ЭТОМУ НЕ ГОТОВ")

Игрок отступает:

1510 "БАРТ СОГЛАШАЕТСЯ НЕ СТРЕЛЯТЬ В ТЕБЯ,"
"ЕСЛИ ПРОВАЛИШЬ ИЗ ГОРОДА НАВСЕГДА."
"СОГЛАСЕН?"
1540 ПЕРЕХОД(ОТВЕТ, согласен, 1570, не согласен, 1590)
1590 КОНЕЦ("МУДРОЕ РЕШЕНИЕ")
1570 ХОД-ИГРОКА("ПРОДОЛЖИМ!")

Игрок бежит:

1610 ВВЕСТИ ДАЛЬНОСТЬ ОТСТУПЛЕНИЯ
1630 ПЕРЕХОД(ответ, меньше 50, 1670)
1640 КОНЕЦ("ТЫ БЕЖАЛ ТАК БЫСТРО, ЧТО СОБАКИ ОТСТАВАЛИ...")
1670 ПЕРЕХОД(ВЫСТРЕЛЫ-БАРТА, не меньше 4, 1770)
1770 КОНЕЦ("К СЧАСТЬЮ, У БАРТА КОНЧИЛИСЬ ПАТРОНЫ."
"ОН МОЖЕТ ТОЛЬКО КИНУТЬ ТЕБЕ ВСЛЕД СВОЮ ПУШКУ")
1680 "БАРТ СТРЕЛЯЕТ $4 - ВЫСТРЕЛЫ-БАРТА$ РАЗ..."
1690 ПЕРЕХОД(ВЫСТРЕЛЫ-БАРТА, меньше 3, 1730)
1700 КОНЕЦ("ТЫ ПОЛУЧИЛ ТО, ЧТО ЗАСЛУЖИЛ - ПУЛЮ В ЗАД")
1730 КОНЕЦ("БАРТ ТАК РАЗВОРОТИЛ ТВОЙ ЗАД"
"ЧТО ПОКОИТЬСЯ В МИРЕ БУДЕТ ТРУДНО")

Ход Барта:

1040 ПЕРЕХОД(РАССТОЯНИЕ, меньше 10, 1120)
1050 СЛУЧАЙ(0.5, 1120)
1070 ЧИСЛО-ШАГОВ = INT($2 + ЭТО-ЖЕ-СЛУЧАЙНОЕ-ЧИСЛО * 9) (Барт идет вперед)
1090 РАССТОЯНИЕ = РАССТОЯНИЕ - ЧИСЛО-ШАГОВ
1080 ХОД-ИГРОКА("ЧЕРНЫЙ БАРТ ПРОШЕЛ $ЧИСЛО-ШАГОВ$ ШАГОВ."
"МЕЖДУ ВАМИ ОСТАЛОСЬ $РАССТОЯНИЕ$ ШАГОВ")
1120 ВЫСТРЕЛЫ-БАРТА = ВЫСТРЕЛЫ-БАРТА + 1
1130 ПЕРЕХОД(ВЫСТРЕЛЫ-ИГРОКА, больше 4, 1070) (если у тебя больше нет патронов)
1140 ПЕРЕХОД(ВЫСТРЕЛЫ-БАРТА, не больше 4, 1200, 5, 1180, больше 6, 2020, иначе, 1070)
1180 ВЫДАЧА("ЭТО ТВОЙ ШАНС, У НЕГО КОНЧИЛИСЬ ПАТРОНЫ", 1070)
2020 КОНЕЦ("БАРТ СМЫВАЕТСЯ РАНЬШЕ,"
"ЧЕМ ТЫ УСПЕВАШЬ ПЕРЕЗАРЯДИТЬ ОРУЖИЕ."
"НЕ СОМНЕВАЙСЯ, БОЛЬШЕ ОН В ТВОЕМ ГОРОДЕ НЕ ПОКАЖЕТСЯ")
(здесь хитрость - Барт "стреляет" пустым револьвером, пока не запсихует)
1200 "БАРТ СТРЕЛЯЕТ . . . . . ."
1220 СЛУЧАЙ(РАССТОЯНИЕ/100, 1300)
1230 "И ПРОМАХИВАЕТСЯ..."
1240 ПЕРЕХОД(ВЫСТРЕЛЫ-БАРТА, 2, 1890, 3, 1940, больше 4, 1070, 4, 1960)
1890 ХОД-ИГРОКА("СЛЕГКА ЗАДЕВ ВАШУ ПРАВУЮ ГОЛЕНЬ")
1940 ХОД-ИГРОКА("ОЦАРАПАВ ВАМ СКУЛУ")
1960 ХОД-ИГРОКА("НАВЕРНОЕ, ДЕРНУЛ СПУСКОВОЙ КРЮЧОК")
1280 ХОД-ИГРОКА("ТЕБЕ ПОВЕЗЛО ПУЛЯ ПРОСВИСТЕЛА НАД УХОМ"
"У ТЕБЯ $4 - ВЫСТРЕЛЫ-ИГРОКА$ ПАТРОНОВ"
"У БАРТА - $4 - ВЫСТРЕЛЫ-БАРТА$")
1300 СЛУЧАЙ(равно 4, 1910) (sic!)
1910 ХОД-ИГРОКА("ЭТА УЛОВКА СПАСЛА ВАМ ЖИЗНЬ."
"ПУЛЯ БАРТА УДАРИЛАСЬ О ПОИЛКУ")
1310 КОНЕЦ("ПУЛЯ БАРТА ПРОБИЛА ТВОЕ СЕРДЦЕ"
"И ТЫ ТКНУЛСЯ НОСОМ В ЗЕМЛЮ")

Победа:

820 "ТЫ ВЛЕПИЛ БАРТУ ПРЯМО МЕЖДУ ГЛАЗ"
850 "КАК МЭР ДОДЖ-СИТИ, Я ПОЗДРАВЛЯЮ ВАС"
"БЛАГОДАРЮ ОТ ЛИЦА ВСЕХ ЖИТЕЛЕЙ"
"И ВРУЧАЮ ЧЕК НА $20,000"
890 ПЕЧАТАЕТСЯ "ВСАМДЕЛИШНЫЙ" ЧЕК, ЖАЛКО, НЕ НА ПРИНТЕРЕ
1020 КОНЕЦ("НЕ ТРАТЬ ВСЕ В ОДНОМ МЕСТЕ!")

***

Конечно, выкладывать эту программу в таком виде (старый BASIC и странный псевдокод) достаточно бесполезно. Если бы игрок имел гарантии работоспособности программы, то он, может, ее бы и ввел... чтобы убедиться, что, зная, в чем суть, играть не очень-то и интересно. Весь интерес - в издевательстве над программой, чтобы учесть коровьи лепешки, количество выпитого персонажами, их лексикон и все, что придет в голову.
Настоящая же задача - разработка стратегии поведения и углубление в дифференциальные уравнения "дуэльной модели". Ведь она, в отличие от "стрелялок от первого лица" - глубоко реалистичная.


Последний раз редактировалось: Gudleifr (Ср Дек 06, 2017 2:39 pm), всего редактировалось 6 раз(а)
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: 01.01. СЕРДЖО ЛЕОНЕ, ЭННИО МОРРИКОНЕ...

Сообщение автор Gudleifr в Вт Ноя 28, 2017 10:47 am

ШЕРИФ НЕРВНИЧАЕТ

...
СЦЕНАРИЙ #1. РЕВОЛЬВЕР В ПРАВОЙ РУКЕ, ДЕНЬГИ В ЛЕВОЙ РУКЕ, СТАКАН НА СТОЛЕ,
БУТЫЛКА НА СТОЛЕ, КОБУРА НА ГРАБИТЕЛЕ, РЕВОЛЬВЕР ШЕРИФА В ПРАВОЙ РУКЕ ШЕРИФА,
КОБУРА ШЕРИФА НА ШЕРИФЕ.
ГРАБИТЕЛЬ: (ГРАБИТЕЛЬ ЗА ОКНОМ.) ИДЕТ К ДВЕРИ; ОТКРЫВАЕТ ДВЕРЬ; ВХОДИТ;
ЗАКРЫВАЕТ ДВЕРЬ; ИДЕТ В УГОЛ; КЛАДЕТ В УГЛУ ДЕНЬГИ; ИДЕТ К СТОЛУ; КЛАДЕТ
РЕВОЛЬВЕР НА СТОЛ; СИДИТ И ЕРЗАЕТ; СИДИТ ЗА СТОЛОМ; БЕРЕТ СТАКАН ПРАВОЙ РУКОЙ
(ПУСТОЙ); СТАВИТ СТАКАН НА СТОЛ; БЕРЕТ БУТЫЛКУ ПРАВОЙ РУКОЙ; НАЛИВАЕТ; СТАВИТ
БУТЫЛКУ НА СТОЛ; БЕРЕТ СТАКАН ПРАВОЙ РУКОЙ; ПЬЕТ ИЗ СТАКАНА; СТАВИТ СТАКАН НА
СТОЛ; БЕРЕТ БУТЫЛКУ ПРАВОЙ РУКОЙ; СИДИТ ЗА СТОЛОМ; СИДИТ ЗА СТОЛОМ; ИДЕТ В
УГОЛ; ИДЕТ К ОКНУ; ИДЕТ К СТОЛУ; СТАВИТ БУТЫЛКУ НА СТОЛ; СИДИТ И ЕРЗАЕТ; СИДИТ
ЗА СТОЛОМ; СИДИТ И ЕРЗАЕТ; ИДЕТ К ОКНУ; ИДЕТ К СТОЛУ; ПОДЫМАЕТ СТАКАН ПРАВОЙ
РУКОЙ.
ШЕРИФ: (ШЕРИФ ЗА ОКНОМ.) ВИДИТ ГРАБИТЕЛЯ (ГРАБИТЕЛЬ ВИДИТ ШЕРИФА); ИДЕТ К
ДВЕРИ.
ГРАБИТЕЛЬ: СТАВИТ СТАКАН НА СТОЛ; БЕРЕТ РЕВОЛЬВЕР ПРАВОЙ РУКОЙ; ПРОВЕРЯЕТ
РЕВОЛЬВЕР.
ШЕРИФ: ЖДЕТ; ОТКРЫВАЕТ ДВЕРИ; ВИДИТ ГРАБИТЕЛЯ (ГРАБИТЕЛЬ ВИДИТ ШЕРИФА);
ВХОДИТ.
ГРАБИТЕЛЬ: ИДЕТ К ОКНУ; ЦЕЛИТСЯ; СТРЕЛЯЕТ; ШЕРИФ ЛЕГКО РАНЕН.
ШЕРИФ: ИДЕТ К ОКНУ; ЦЕЛИТСЯ; СТРЕЛЯЕТ; ПРОМАХНУЛСЯ; ИДЕТ К ДВЕРИ; ИДЕТ К ОКНУ.
ГРАБИТЕЛЬ: ИДЕТ К ДВЕРИ; ЦЕЛИТСЯ; ЦЕЛИТСЯ.
ШЕРИФ: ЦЕЛИТСЯ; СТРЕЛЯЕТ; ПРОМАХНУЛСЯ.
ГРАБИТЕЛЬ: СТРЕЛЯЕТ; ШЕРИФ ЛЕГКО РАНЕН.
ШЕРИФ: ИДЕТ К ДВЕРИ; ЦЕЛИТСЯ; СТРЕЛЯЕТ; ПРОМАХНУЛСЯ; ВЫХОДИТ; ЦЕЛИТСЯ.
ГРАБИТЕЛЬ: ЦЕЛИТСЯ; СТРЕЛЯЕТ; ПРОМАХНУЛСЯ; ЦЕЛИТСЯ; СТРЕЛЯЕТ; ПРОМАХНУЛСЯ.
ШЕРИФ: СТРЕЛЯЕТ; ПРОМАХНУЛСЯ; ИДЕТ К ОКНУ; ЦЕЛИТСЯ; СТРЕЛЯЕТ; ПРОМАХНУЛСЯ.
ГРАБИТЕЛЬ: ЦЕЛИТСЯ; СТРЕЛЯЕТ; ПРОМАХНУЛСЯ; ЦЕЛИТСЯ; СТРЕЛЯЕТ; ПРОМАХНУЛСЯ;
ЦЕЛИТСЯ; СТРЕЛЯЕТ; ШЕРИФ ЛЕГКО РАНЕН.
ШЕРИФ: ЦЕЛИТСЯ; СТРЕЛЯЕТ; ПОПАДАЕТ В ГРАБИТЕЛЯ.
ГРАБИТЕЛЬ: РОНЯЕТ РЕВОЛЬВЕР; ГРАБИТЕЛЬ УМИРАЕТ.
ШЕРИФ: КЛАДЕТ РЕВОЛЬВЕР В КОБУРУ; ИДЕТ К СТОЛУ; БЕРЕТ СТАКАН ПРАВОЙ РУКОЙ
(ПУСТОЙ); БЕРЕТ СТАКАН ИЗ ПРАВОЙ РУКИ В ЛЕВУЮ РУКУ; БЕРЕТ БУТЫЛКУ ПРАВОЙ РУКОЙ;
НАЛИВАЕТ; СТАВИТ БУТЫЛКУ НА СТОЛ; БЕРЕТ СТАКАН ИЗ ЛЕВОЙ РУКИ В ПРАВУЮ РУКУ;
ПЬЕТ ИЗ СТАКАНА; БЕРЕТ СІАКАН ИЗ ПРАВОЙ РУКИ В ЛЕВУЮ РУКУ; БЕРЕТ БУТЫЛКУ ПРАВОЙ
РУКОЙ; НАЛИВАЕТ; СТАВИТ БУТЫЛКУ НА СТОЛ; БЕРЕТ СТАКАН ИЗ ЛЕВОЙ РУКИ В ПРАВУЮ
РУКУ; ПЬЕТ ИЗ СТАКАНА; СТАВИТ СТАКАН НА СТОЛ; ИДЕТ В УГОЛ; БЕРЕТ ДЕНЬГИ ПРАВОЙ
РУКОЙ; ИДЕТ К ДВЕРИ; ВЫХОДИТ; ЗАКРЫВАЕТ ДВЕРЬ. ЗАНАВЕС.

Так во втором томе "Искусства программирования" Д.Кнут представил результат работы программы написания сценариев вестернов SAGA II (Mассаччусетский Технологический, 1960). И предложил сделать получше в качестве упражнения. Причем, подчеркнул, что подобным машинным текстам перед экранизацией требуется значительная режиссерская правка.
***

Вместо игрока, отвечающего за поведение одного персонажа HIGN HOON (а, опосредованно - обоих), программа честно использовала только генераторы случайных чисел (играла сама с собой).
Логическую часть SAGA можно примерно оценить по TV-презентации : AVI, 32.3Мб.


Кружочки с числами - это ПЕРЕКЛЮЧАТЕЛИ (места случайных действий).

Очевидно, что тут все те же, рассмотренные выше, СЛУЧАИ, ВЫБОРЫ и ВЫДАЧИ. Разница только в том, что вместо фиксированных ПОРОГОВ был использован их расчет на основании текущих значений переменных состояния.

Переменных состояния всего 16 (конечно, для описания действия используются и другие переменные, но на расчет вероятностей влияют только эти):

#Чему соответствуетЗначение если...
... да... нет
1шериф видит грабителя+10-10
2грабитель видит шерифа+10-10
3шериф прибыл+100
4грабитель целится+100
5шериф ранен+100
6грабитель ранен+100
7шериф поражен+100
8грабитель поражен+100
9опьянение бандитасначала - 0, +10 за каждый стакан, +20 за глоток из бутылки
10очередность+10 за каждое действие бандита, -10 за каждое действие шерифа
11последняя пуля грабителя+100
12последняя пуля шерифа+100
13дверь открыта+100
14шериф в комнате+100
15грабитель в комнате+100
16стакан полон+100
Формула работы ПЕРЕКЛЮЧАТЕЛЯ (под номером n):

P(n,k) = a(n,k,0) + SUM(j:1..16)(a(n,k,j)*b(j))

Т.е. вероятность (P) исхода равна (на самом деле, ее еще нужно отнормировать) взвешенной сумме переменных состояния b.

ПРИМЕР:
Пусть ПЕРЕКЛЮЧАТЕЛЬ #26 имеет три исхода (показаны только ненулевые коэффициенты):

1. шериф поражает бандита (a(26,1,0) = 10, a(26,1,l2) = 30)
2. ранит (a(26,2,0) = 60, a(26,2,5) = 1)
3. промахивается (a(26,3,0) = 110, a(26,3,1) = -10, a(26,3,5) = 3)

Переменная 1 (см.выше) равна +10, если шериф видит грабителя, иначе - -10. Переменная 5 - 0, если шериф не был ранен, и +10, если был. Переменная 12 - +10, если у шерифа остался последний патрон, иначе - 0.
Тогда, если у шерифа еще много патронов, он видит грабителя и не был ранен, имеем

P(26,1) = 10 + 30 * 0 = 10;
P(26,2) = 60 + 1 * 0 = 60;
P(26,3) = 110 - 10 * 10 + 3 * 0 = 10.

Т.е. вероятность ранить грабителя в 6 раз больше чем убить или промахнуться.
А, если бы шериф был ранен, то получилось бы:

P(26,1) = 10 + 30 * 0 = 10;
P(26,2) = 60 + 1 * 10 = 70;
P(26,3) = 110 - 10 * 10 + 3 * 10 = 40.
***

Очевидно, что выражение "программа пишет сценарий" в данном случае сильно преувеличено. Ведь, все блок-схемы и матрицы коэффициентов должны быть созданы заранее. Причем, практически вручную! Т.е., по сути, получение "неожиданного", не просчитанного ранее и не отлаженного до последней запятой сценария не более вероятно, чем то, что первая же мутация генотипа окажется для биологического организма исключительно полезной.
Нужно вводить "естественный отбор" и/или "обучение". Т.е. игра состоит не в чтении получившихся сценариев, а в подборе коэффициентов для получения чего-то интересного (для этого в SAGA II была введена специальна программа отладки).


Последний раз редактировалось: Gudleifr (Ср Дек 06, 2017 2:42 pm), всего редактировалось 2 раз(а)
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: 01.01. СЕРДЖО ЛЕОНЕ, ЭННИО МОРРИКОНЕ...

Сообщение автор Gudleifr в Вт Ноя 28, 2017 10:52 am

ОБОБЩЕННАЯ СХЕМА КОМПЬЮТЕРНОЙ ИГРЫ



Очевидно, все начинается с Идеи игры, которую автор перерабатывает в Сюжет и Правила. Правила делятся на строго-Логические (алгоритмы) и разного рода Оценочные (эвристики, экспертные системы, фреймы). Дыры в правилах затыкаются разного рода Случайными переходами. Сама игра - управляемый Правилами коммутатор - выбирает и настраивает Машины игры, которые и играют с Игроком. Части Машин выбрал условно (этот список - от Подстройки до Исключений я применял при анализе книг-игр - ТЕМА #20, АБЗАЦ #79).
***

Первые шесть глав этих заметок будут посвящены, в основном, отдельным Машинам игр.


Последний раз редактировалось: Gudleifr (Ср Дек 06, 2017 2:43 pm), всего редактировалось 1 раз(а)
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: 01.01. СЕРДЖО ЛЕОНЕ, ЭННИО МОРРИКОНЕ...

Сообщение автор Gudleifr в Вт Ноя 28, 2017 12:48 pm

ОРЕГОНСКАЯ ТРОПА

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

Эта игра выдержала бешеное количество реинкарнаций, привлекая американцев своим "историческим реализмом" (они даже ее включали в курс истории), а всех остальных - фэнтезийностью. Для меня она встала рядом с просмотренной в раннем детстве французской экранизацией "Прерии" Фенимора Купера - непонятно, что герои делают, но, видно, что это им очень сильно надо, раз они так переживают...
***

В чем суть? Задача игрока преодолеть некий маршрут (т.е. довести некий счетчик пройденного расстояния до какого-то значения). При этом он должен заранее побеспокоиться о припасах на дорогу (которыми он будет оплачивать увеличение счетчика расстояния).
Эта игра - одна из предтеч горячо мною нелюбимых "стратегий" (и настольных, и компьютерных), предлагающих перед началом "приключения" купить себе "армию" на некоторое количество "денег". Причем, не дается никаких указаний на соображения, которыми надо руководствоваться при распределении выделенной суммы по конкретным статьям расходов.
С другой стороны, игра кажется менее экономической, чем популярные в те времена симуляторы управления королевства, т.к. там ресурсы не только тратились, но и производились - эмулировался полный цикл воспроизводства. Но... Потеряли в формулах - компенсировали разнообразием видов ресурсов.
Листинг версии "Westward Ho! 1847 (c) David H. Ahl, 1986" - TXT, 0.02Мб.
***

Чтобы как-то замаскировать простую сущность игры: наблюдение за монотонным убыванием значений переменных, подверженных, правда, случайным флуктуациям, в игру были добавлены аркадные моменты: стрельба (по индейцам, бандитам и зверям) и переправа через реку (предок игр - "скроллеров"). В зависимости от способностей компьютеров, для которых переписывалась игра, от чисто вычислительных до вполне себе игровых автоматов.
Например, в той FORTRAN-версии, которую видел я, стрельба выглядела как набивание на клавиатуре случайной 4-х буквенной комбинации. Компьютер же замерял затраченное на это время (и конечно проверял правильность набора).
В версии для программируемых калькуляторов нужно было безошибочно воспроизвести мелькнувшее на экране 6-значное число.
В рассматриваемой версии (первые три строчки - запрос в начале игры навыка стрельбы, следующие две - заполнение массива "стрелятельных" слов, оставшиеся - собственно подпрограмма ВЫСТРЕЛ):

930 PRINT : PRINT "Please rank your shooting (typing) ability as follows :"
940 PRINT " (1) Ace marksman (2) Good shot (3) Fair to middlin'"
950 PRINT " (4) Need more practice (5) Shaky knees"
960 INPUT "How do you rank yourself";DR
970 IF DR > 1 AND DR < 6 THEN RETURN
980 PRINT "Please enter 1, 2, 3, 4, or 5." : GOTO 960
...
3440 FOR I = 1 TO 8 : READ S$(I) : NEXT I
3450 DATA "POW", "BANG", "BLAM", "WHOP", "pow", "bang", "blam", "whop"
...
3880 RN = 1 + INT(4 * RND(1))
3890 S1 = 60 * VAL(MID$(TIME$, 4, 2)) + VAL(RIGHT$(TIME$, 2))
3900 PRINT "Type " S$(RN); : INPUT X$
3910 IF S$(RN)<>X$ AND S$(RN + 4)<>X$ THEN PRINT "Nope. Try again. "; : GOTO 3900
3920 S2 = 60 * VAL(MID$(TIME$, 4, 2)) + VAL(RIGHT$(TIME$, 2))
3930 BR = S2 - S1 - DR - 1 : RETURN

Здесь задача упрощена - всего 4 слова, которые игрок рано или поздно выучит. По два варианта написания для того, чтобы не думать, в каком регистре набивать. Результат выстрела (BR, запомним на будущее) - число секунд, ушедших на набивание слова (S2 - S1), минус 1, минус коэффициент косорукости (DR). Причем, последний вводится самим игроком и никак не портит его налоговую историю (никто не узнает, что вы проходили на легком уровне). Самое же хитрое: получившийся результат - BR - часто еще и сравнивается со случайной величиной.

1230 M = M - 45 : GOSUB 3870 : IF BR <= 1 THEN 1270
1240 IF 100 * RND(1) < 13 * BR THEN 1290
1250 PRINT "Nice shot... right on target... good eatin' tonight!"

Здесь мы видим неудобство BASIC. Стрельба "размазана" по программе: в одном месте - параметры, в другом - данные, в третьем - сама процедура. Проследить взаимосвязь можно только по именам переменных.
Как исправить ситуацию? Во-первых, не надо, умничать. Т.к. "стрелятельные" слова используются только в одном месте, то массив совсем не нужен, можно обойтись обычным выбором. Не говоря уже о том, что если сделать слово честно случайным, его и нельзя будет создать заранее.
Во-вторых, надо тщательнее комментировать блоки общих данных (к которым в данном случае относятся DR и BR).
И, конечно, чем больше в программе будет мест ввода параметров, тем больше будет этих петель: "Ввели фигню. Выберите из допустимого".
Кстати "замер времени" в другом месте программы проходит по-другому:

170 PRINT "Press any key when you're ready to go" : RN = -32768!
180 WHILE LEN(INKEY$) = 0 : RN = RN + 1 : WEND
190 WHILE RN > 32767 : RN = RN - 65535! : WEND : RANDOMIZE RN : CLS

Здесь случайная задержка служит для получения случайного числа для инициализации датчика случайных чисел. Игрок даже не знает, что время, ушедшее на нажатие клавиши "Продолжить...", кому-то надо.
***

С точки зрения программирования все совсем скучно: сначала блок закупки, потом циклическое повторение конструкции из трех видов блоков: постоянных, случайных-важных и случайных-прочих. Есть еще (глубоко спрятанный) четвертый вид блоков - разруливающих, куда игрок попадает из остальных, попав в типовую ситуацию: стрельба, болезнь, смерть, по сути, реализующих набор операторов-ВЫДАЧ.
Постоянные блоки обеспечивали монотонное уменьшение ресурсов (и монотонное увеличение счетчика пройденного расстояния) и принятие игроком кое-каких организационных решений (торговля, охота, лечение, питание).
Случайные-важные посвящены неким важным событиям, которые, может, не всегда случаются, но требуют больших кусков кода и обдумывания игроком. Речь обычно идет о Теории Игр в чистом виде - игрок выбирает стратегию, а природа - свою (случайным образом). В итоге - решение игрока может быть удачным или не очень. Результат обычно, все равно, "размазывается" путем добавления случайных чисел. К таким блокам относятся налеты бандитов, преодоление серьезных препятствий, болезни.
Случайные-прочие обычно все сводятся в один большой блок. В нем с игроком происходят мелкие (не)приятности: встречи, изменения погоды, находки и потери.
Никаких сложных логических вычислений в игре нет (немножко в случайных-важных блоках), так что, программа не особо чувствительна к небольшим изменениям данных и коэффициентов.
Встречаются иногда нестандартные распределения вероятностей (опять в случайно-важных блоках) - чтобы сделать их более вероятными на определенных участках пути (для "реализма").
Тексты настолько маловысокохудожественны, что возникает желание, вообще, выкинуть большую часть событий, заменив на "увеличить/уменьшить на случайное число случайно выбранный параметр".
Вообще же, "первопроходчество по-американски" - по вполне цивилизованной стране (денег бы только хватило) - вызывает сомнения в удачности выбора его в качестве темы игры.
***

Элемент "симулятора проедания припасов" используется во многих более интересных играх - STAR TREK (про него поговорим в седьмой главе) или, даже VOYAGE OF THE B.S.M. PANDORA (ТЕМА #25, АБЗАЦ #93), но здесь кроме него почти ничего и нет.
Может ли подобная модель служить генератором неожиданностей для ролевой игры в солдатики? Или она - как раз то, что должно быть выброшено из игры, чтобы осталось только "Приключение"?
***

Внимательнее посмотрим на виды припасов.
Кроме фургона в этой версии игрок имел:

- волов (переменная A). Покупались раз и навсегда, по ходу игры медленно, но верно теряли товарный вид (болели, надрывались). От них зависело расстояние, пройденное за один ход;
- продовольствие (переменная F). Покупалось сразу и по дороге - в фортах, пополнялось охотой. В зависимости от нормы потребления, установленной игроком (понятно, в пределах запаса), болезни были легче или тяжелее;
- патроны (переменная B). Покупались сразу и по дороге. Расходовались в схватках и на охоте;
- одежда (переменная C). Покупалась сразу и по дороге. Нормально не расходовалась. Разные погодные катаклизмы требовали наличия некоторого (случайного) количества;
- прочие запасы (переменная R). Покупались сразу и по дороге. Нормально не расходовались. Но разные мелкие неприятности постоянно требовали их тратить (как, впрочем, и другие перечисленные запасы).

Все меряется в долларах, кроме патронов, те сразу пересчитывались в штуки - 50 на доллар. Запас долларов - переменная T.
Когда у игрока кончались запасы какого-либо вида, он либо сразу помирал при очередном требовании затрат, либо получал "рану/болезнь", которую можно было вылечить тратой денег (доктору), либо можно было успеть пополнить запасы покупкой (в фортах все в полтора раза дороже), либо каким-либо другим (случайным) способом, например, охотой или удачной встречей.
Сложность игры могла регулироваться, например, выбором игроком навыка стрельбы, или количеством стартовой суммы денег. В некоторых версиях от выбора игроком "профессии" немного менялись коэффициенты в формулах расходования ресурсов.
Большинство происшествий переводится в игре на язык уменьшения этих ресурсов, т.о. если бы я был до конца последовательным, то пришлось ввести обобщенный оператор ВЫДАЧА:

ВЫДАЧА(СООБЩЕНИЕ, A-, F-, B-, C-, R-, T-, ВОЗВРАТ)

за которым пристроить пару-другую операторов

ИСКЛЮЧЕНИЕ(РЕСУРС, ПРЕДЕЛ, СИТУАЦИЯ)

Т.е. когда в результате ВЫДАЧИ происходит выход какого-либо РЕСУРСА за ПРЕДЕЛ, то вместо ВОЗВРАТА управление передается на СИТУАЦИЮ. Правда, при этом возникает вопрос, когда происходит переход, до или после изменения остальных ресурсов, но для данной игры это значения не имеет - подумаешь, еще одна случайная потеря.
***

Простые программистские хитрости:

- Для того, чтобы быстро выбрать одно из случайно-прочих событий, их вероятности отнормировали (чтобы общая сумма была равна единице), и каждой отвели соответствующий отрезок на участке от 0 до 1. После этого достаточно было получить случайную величину и проверить, на какой отрезок она попала.

ВЫБОР(СЛУЧАЙНОЕ ВЕЩЕСТВЕННОЕ ЧИСЛО 0-100,
0..6,   1880,  6..11, 1910, 11..13, 1940, 13..15, 1980,
15..17, 2010, 17..22, 2040, 22..32, 2080, 32..35, 2180,
35..37, 2290, 37..42, 2320, 42..44, 2350, 44..54, 2410,
54..64, 2440, 64..69, 2530, 69..95, 2560, 95..100, 2610)

Реализованы это так (первые две строчки - заполнение массива вероятностей в начале программы):

3710 FOR I = 1 TO 15 : READ EP(I) : NEXT : RETURN
3720 DATA 6, 11, 13, 15, 17, 22, 32, 35, 37, 42, 44, 54, 64, 69, 95
...
1810 RN = 100 * RND(1)
1820 FOR I = 1 TO 15
1830 IF RN > EP(I) THEN NEXT I : I = 16
1840 IF I > 8 THEN 1860
1850 ON I GOTO 1880, 1910, 1940, 1980, 2010, 2040, 2080, 2180
1860 ON I - 8 GOTO 2290, 2320, 2350, 2410, 2440, 2530, 2560, 2610

Здесь видно, как можно было в BASIC организовать цикл с двумя выходами (строка 1830).

- В начале хода выдается текущее пройденное расстояние (переменная M), затем сразу считается расстояние для следующего хода. Остальные блоки хода не только меняют размеры запасов, но и изменяет расстояние. Конечно, обычно, неприятности его уменьшают, но возможно и увеличение (например, при бегстве от бандитов, ценой порчи волов).

 60 M = INT(M) : MA = M
 370 IF MP = 1 THEN PRINT "Total mileage to date is 950." : MP = 0 : GOTO 400
 380 PRINT "Total mileage to date is" INT(M + .5)
 390 M = M + 200 + (A - 110) / 2.5 + 10 * RND(1)
 400 ...

Здесь приведен код начала хода: сначала выводится старое M, затем считается новое, затем, в течение хода над новым M можно всячески издеваться. Это позволяет делать некоторое подобие отката вычислений до того, как результат уже принят.
Кроме того здесь можно видеть кусок обработки "Южного прохода" - нетривиальной замены M исключительным значением (950). В таких "заплатках" надо быть очень осторожным: т.к. состояние игрока описывается многими переменными, надо следить, чтобы не повредить не одну из них (здесь мы надеемся, что процедура, установившая MP в 1, сделала все сама и сделала правильно).

Другая заплатка - применение переменной MA (старый M) - на случай, если игра на этом ходу закончится. Там происходит, как раз, честный откат:

3200 ML = (2040 - MA) / (M - MA) : F = F + (1 - ML) * (8 + 5 * E) : GOSUB 3830
...
3230 D = INT(14 * (J + ML)) : DM = INT(D / 30.5) : DD = INT(D - 30.5 * DM)

Корректировка данных из учета того, что мы прошли больше, чем надо (M > 2400), и надо откатиться назад - до точной позиции финиша.

- В отличие от "Лунолета" (ТЕМА #43, АБЗАЦ #431) или других рассмотренных здесь моделей, счет времени ведется не от события к событию, а фиксированными отрезками по две недели. Чтобы разнообразить путешествие, географические пункты, отмечающие расстояние, расположены очень неравномерно. Создается иллюзия "рваного времени" - на цифирь расстояния игрок обращает внимания меньше, чем на "географию", и для него факт достижения нового участка становится неожиданным. Кроме того, список пунктов в разных играх немного отличается (некоторые проскакиваются незаметно), создавая у игрока иллюзию "разного прохождения".

3460 FOR I = 1 TO 20 : READ DA$(I) : NEXT I : RETURN
3470 DATA "March 29", "April 12", "April 26", "May 10", "May 24", "June 7", "June 21"
3480 DATA "July 5", "July 19", "August 2", "August 16", "August 31", "September 13"
3490 DATA "September 27", "October 11", "October 25", "November 8", "November 22"
3500 DATA "December 6", "December 20"
...
3530 FOR I = 1 TO 15 : READ MP(I), PL$(I) : NEXT I : RETURN
3540 DATA 5, "on the high prairie."
3550 DATA 200, "near Independence Crossing on the Big Blue River."
3560 DATA 350, "following the Platte River."
3570 DATA 450, "near Fort Kearney."
3580 DATA 600, "following the North Platte River."
3590 DATA 750, "within sight of Chimney Rock."
3600 DATA 850, "near Fort Laramie."
3610 DATA 1000, "close upon Independence Rock."
3620 DATA 1050, "in the Big Horn Mountains."
3630 DATA 1150, "following the Green River."
3640 DATA 1250, "not too far from Fort Hall."
3650 DATA 1400, "following the Snake River."
3660 DATA 1550, "not far from Fort Boise."
3670 DATA 1850, "in the Blue Mountains."
3680 DATA 2040, "following the Columbia River."
...
270 J = J + 1
280 IF J > 20 THEN 3080
290 PRINT : PRINT "Monday, " DA$(J) ", 1847. You are ";
300 FOR I = 1 TO 15 : IF M > MP(I) THEN NEXT I ELSE PRINT PL$(I)

Опять, первые два фрагмента - заполнение массивов (заодно мы видим, как хранить в BASIC записи - в виде параллельных массивов (MP и PL$)). Метод, как видим, почти ничего не весит (кроме самих массивов). Его можно применять для моделирования самых разных нелинейных функций.

- Большое количество ресурсов маскирует тот факт, что последний вид - "прочие запасы" - отвечает за все: и за оказание первой помощи, и за ремонт фургона, и за починку одежды, что крайне нереалистично.

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

1010 IF INT(J / 2)<>J / 2 THEN 1060
1020 INPUT "Want to (1) stop at next fort, (2) hunt, or (3) push on";X
1030 IF X < 1 OR X > 3 THEN PRINT "Enter a 1, 2, or 3 please." : GOTO 1020
1040 IF X = 3 THEN RETURN ELSE ON X GOSUB 1100, 1200
1050 IF KQ = 1 THEN 1020 ELSE RETURN
1060 INPUT "Would you like to (1) hunt or (2) continue on";X
1070 IF X < 1 OR X > 2 THEN PRINT "Enter a 1 or 2 please." : GOTO 1060
1080 IF X = 2 THEN RETURN ELSE GOSUB 1200 : RETURN

Здесь объединен в одном диалоге выбор между остановкой и продолжением движения (постоянный блок). Кроме того, охота возможна каждый ход, а форт встречается только раз в два хода. Причем, как-то неочевидно (ошибочно?) используется переменная возможности повтора KQ.

- Гордостью авторов является разруливающий блок "Вы умерли":

3000 PRINT "You run out of food and starve to death." : GOTO 3110
3010 T = 0 : PRINT "You need a doctor badly, but can't afford one." : GOTO 3030
3020 PRINT "You have run out of all medical supplies."
3030 PRINT : PRINT "The wilderness is unforgiving and you die of ";
3040 IF KH = 1 THEN PRINT "your injuries." : GOTO 3060
3050 PRINT "pneumonia."
3060 PRINT "Your family tries to push on, but finds the going too rough";
3070 PRINT " without you." : GOTO 3110
3080 PRINT "Your oxen are worn out and can't go another step. You try pushing"
3090 PRINT "ahead on foot, but it is snowing heavily and everyone is exhausted."
3100 PRINT : GOSUB 3740 : PRINT "You stumble and can't get up...."
3110 PRINT : GOSUB 3740 : PRINT "Some travelers find the bodies of you and your"
3120 PRINT "family the following spring. They give you a decent"
3130 PRINT "burial and notify your next of kin." : PRINT
3140 D = INT(14 * (J + ML)) : DM = INT(D / 30.5) : DD = INT(D - 30.5 * DM)
3150 PRINT "At the time of your unfortunate demise, you had been on the trail"
3160 PRINT "for" DM "months and" DD "days and had covered" INT(M + 70) " miles."
3170 PRINT " You had a few supplies left :" : GOSUB 3350 : PRINT : GOTO 3310

являющийся почти полноценным генератором сообщений, способным собирать текстовые сообщения из отдельных кусков. Чтобы получить конкретный "вид смерти" нужно войти в него по нужному адресу (см. далее СМЕРТЬ). (Код по адресу 3740 - просто пауза).

Программа уже доросла то тех размеров, когда "для структурности" пришлось оформить блоки в виде отдельных процедур. Однако, заплатки и вставки в избытке.
Можно заметить и разницу в написании схожих операторов из-за размера операндов, например, условный оператор может быть намного компактнее, если строки, которые в нем печатаются, короткие. Например:

760 INPUT "How much do you want to spend on food";F : F = INT(F)
770 IF F > 13 THEN 790 ELSE PRINT "That won't even get you to the Kansas River";
780 PRINT " - better spend a bit more." : GOTO 760
...
800 INPUT "How much do you want to spend on ammunition";B : B = INT(B)
810 IF B < 2 THEN PRINT "Better take a bit just for protection." : GOTO 800

Видно, что части THEN и ELSE "поменялись местами".
***

Программа (я пометил переменные, влияющие на выполнение блоков вопросительными знаками, уменьшающиеся/увеличивающиеся - плюсами/минусами; просто вопросительный знак - учет мнения игрока, перед переменной - установка игроком переменной):

100 ВЫВЕСТИ ЗАГОЛОВОК
130 (ИНИЦИАЛИЗАЦИЯ)
3430 МАССИВЫ СТРЕЛЯТЕЛЬНЫЕ СЛОВА И ДАТЫ
3530 МАССИВЫ МЕСТ
3700 МАССИВ ВЕРОЯТНОСТЕЙ СОБЫТИЙ
170 ИНИЦИАЛИЗАЦИЯ ДАТЧИКА СЛУЧАЙНЫХ ЧИСЕЛ
490 ВЫВЕСТИ ИНСТРУКЦИИ
690 ЗАКУПКА ИМУЩЕСТВА НА $350 (?А 100..150, ?F 14.., ?B 2.., ?C 24.., ?R 5.., T-)
920 ЗАПРОС НАВЫКА СТРЕЛЬБЫ ИГРОКА(?DR)
3830 ФАНФАРЫ
260 (ОСНОВНОЙ ЦИКЛ)
3190 ПОБЕДА(M?)
270 ДАТА И МЕСТО(J+)
310 ПРЕДУПРЕЖДЕНИЕ(F?)
320 ДОКТОР(KS?, KH?, T-)
- 3010 СМЕРТЬ(T?)
360 РАССТОЯНИЕ(MP?, A?, M+)
3350 ВЫВЕСТИ СВОДКУ
1000 ОСТАНОВКА(J?, ?)
- 1100 ФОРТ(F+, B+, C+, R+, T-)
- 1200 ОХОТА(B-, M-, F+)
- - 3870 ВЫСТРЕЛ
1310 ЕДА(?E, F-)
- 3000 СМЕРТЬ(F?)
1390 БАНДИТЫ
1800 СЛУЧАЙНОСТИ
2640 ГОРЫ(M?)
ВОЗВРАТ В НАЧАЛО ЦИКЛА

Случайные-важные блоки - БАНДИТЫ и ГОРЫ, случайные-прочие - СЛУЧАЙНОСТИ, остальные - постоянные. Впрочем, ГОРЫ больше похожи на еще один блок случайных-прочих, только там вместо таблицы случайностей куча IF.
***

БАНДИТЫ:

1400 ВЕРОЯТНОСТЬ ВСТРЕЧИ(M?)
1410 НАСТРОЕНИЕ БАНДИТОВ
1420 ВЫБОР СТРАТЕГИИ(?)
1460 СМЕНА НАСТРОЕНИЯ
1470 ВЫБОР(НАСТРОЕНИЕ, ВРАГИ, 1480, ДРУЗЬЯ, 1680)
- 1480 ВЫБОР(СТРАТЕГИЯ, 1, 1510, 2, 1540, 3, 1610, 4, 1650)
- - 1510 БЕГСТВО(M+, R-, B-, A-)
- - 1540 АТАКА(B-, KH+)
- - - 3870 ВЫСТРЕЛ
- - - 3110 СМЕРТЬ(B?)
- - 1610 ИНГОРИРОВАНИЕ(B-, R-)
- - 1650 ОБОРОНА(B-, M-, KH+)
- - - 3870 ВЫСТРЕЛ
- - - 3110 СМЕРТЬ(B?)
- 1680 ВЫБОР(СТРАТЕГИЯ, 1, 1680, 2, 1690, 4, 1700)
- - 1680 БЕГСТВО(M+, A-)
- - 1690 АТАКА(M-, B-)
- - 1700 ОБОРОНА(M-)

СЛУЧАЙНОСТИ (вероятности смотри выше):

1880 ПОЛОМКА ФУРГОНА(M-, R-)
1910 ВОЛ ОХРОМЕЛ(M-, A-)
1940 ДОЧКА СЛОМАЛА РУКУ(M-, R-)
1980 ВОЛ ОТВЯЗАЛСЯ(M-)
2010 СЫН ПОТЕРЯЛСЯ(M-)
2040 ПОИСК ВОДЫ(M-)
2080 ВЫБОР(M, РАВНИНА, 2090, ГОРЫ, 2130)
- 2090 ДОЖДЬ(M-, R-, B-, F-)
- 2130 СНЕГ(C?)
- - 2880 БОЛЕЗНЬ(E?, R-, KS+, M-)
- - - 3020 СМЕРТЬ(R?)
2180 БАНДИТЫ(B-, T-, KH+, A-, R-)
- 3870 ВЫСТРЕЛ
2290 ПОЖАР(M-, F-, B-, R-)
2320 ТУМАН(M-)
2350 УКУС ЗМЕИ(B-, R-)
- 3060 СМЕРТЬ(R?)
2410 КРУШЕНИЕ НА ПЕРЕПРАВЕ(M-, F-, C-)
2440 НАПАДЕНИЕ ВОЛКОВ(B-, C-, F-)
- 3870 ВЫСТРЕЛ
- 3030 СМЕРТЬ(B?)
2530 ЛИВЕНЬ(M-, B-, R-)
2560 КУШАТЬ ХОЧЕТСЯ(E?)
- 2880 БОЛЕЗНЬ(E?, R-, KS+, M-)
- - 3020 СМЕРТЬ(R?)
2610 ИНДЕЙЦЫ(F+)

ГОРЫ:

2650 ЮЖНЫЙ ПРОХОД(M?)
2680 ЗАБЛУДИЛИСЬ(M-)
2700 КРУШЕНИЕ(M-, B-, R-)
2730 ТРУДНАЯ ДОРОГА(M-)
2750 ВСЕ-ТАКИ ЮЖНЫЙ ПРОХОД(?M, MP+)
2840 СНЕГ(C?)
- 2880 БОЛЕЗНЬ(E?, R-, KS+, M-)
- - 3020 СМЕРТЬ(R?)

Конечно, в блоках можно выделить некоторые адреса, служащие "точками сбора" разруливающих блоков для операторов ВЫДАЧА/ИСКЛЮЧЕНИЕ, но это подразумевает более глубокий анализ, чем мне кажется необходимым для этой игрушки.


Последний раз редактировалось: Gudleifr (Ср Дек 06, 2017 2:48 pm), всего редактировалось 3 раз(а)
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: 01.01. СЕРДЖО ЛЕОНЕ, ЭННИО МОРРИКОНЕ...

Сообщение автор Gudleifr в Вт Ноя 28, 2017 1:04 pm

B-1 NUCLEAR BOMBER

Это промежуточная игра между "ТРОПОЙ" и тем же "Лунолетом". Меньше внимания уделяется "окружающему миру" и больше - возможностям игрока. Если хотите, игрок перестает быть человеком, сидящим перед ЭВМ, и как бы вживается в некую виртуальную сущность, ощущая свойства и возможности, например, самолета, как свои собственные.
Цикл программы (листинг - TXT, 0.01Мб) уже строится вокруг приема команд игрока, без размазывания диалогов по всей программе.
***

География игры, в отличие от "ТРОПЫ", стала полностью двумерной, хотя принцип неравномерного размещения объектов сохранился. Массивы мест выглядят здесь так:

5 N0=10:N1=20:N2=N0+N1
...
40 FOR I=1 TO N2:READ N$(I),T(I,1),T(I,2):NEXT
45 N$(0)="THULE AFB":T(0,1)=0:T(0,2)=0
50 DATA ARKHANGELSK,8261,5922,ASTRAKHAN',8631,7947,KIYEV,7391,7467
55 DATA LENINGRAD,7661,6427,MOSKVA,7956,6937,MURMANSK,8056,5452
60 DATA SEVASTO POL,7506,8152,SVERDLOVSK,9311,6682,VOLGOGRAD,8331,7692
65 DATA YEREVAN,8381,8657
70 DATA DUBOVKA,8350,7650,KHAR'KOV,8850,7450,KONOSHA,8153,6325
75 DATA LIPETSK,8100,7210,OCHAMCHIRA,8060,8400,ODESSA,7230,8050
80 DATA ONEGA,8147,5976,PECHENGA,7976,5410,PINSK,7115,7235
82 DATA PODOL'SK,7900,7010,PSKOV,7475,6780,ROSTO V,7990,8010
84 DATA SARPA,8515,7930,SYKTYVKAR,8825,6200,TALLINN,7060,6415
86 DATA TBILISI,8415,8435,UKHTA,8960,5925,VINNITSA,7200,7585,VYBORG,7575,6300
90 DATA YARAN'SK,8575,6740

Налицо чуть ли не структуризация данных: нулевая позиция - база, 1-10 - цель, 11-30 - ПВО. В дальнейшем увидим: в двумерном массиве T записываются не только координаты объектов, но их состояние - T(I,3).
Но нам важнее другое - поле игры получается не плоское-ровное, а, опять, географически-сложное.
Если будете реализовывать, не забудьте заменить советские города на американские. Бомбить США удобно через полюс или при помощи летающей лодки, базирующейся в Тихом океане.
***

В дополнение к массиву мест и переменным игрока введен еще отдельный массив радиолокационных контактов (перехватчиков), они же истребители (MIG) и ракеты (SAM). Массив C(10,2) двумерный: в первом "столбце" - номера целей, во втором - время до перехвата. Номера 1-10 зарезервированы для ракет, остальные - для истребителей.
У бомбардировщика есть бомбы, которые он должен применить по случайно выбранному в начале игры объекту (F9), но в случае форс-мажора - по любому объекту (не по ПВО!). И есть ракеты, которыми можно отстреливаться от перехватчиков и поражать ПВО. Кроме того, от перехватчиков можно пытаться уклониться или ставить помехи.
Для красоты используется массив со словами "MIG" и "SAM", но это для BASIC уже избыточная "структурность". И, когда дело доходит до дела, и у игрока спрашивают, по какому перехватчику он стреляет, ответ сравнивается с обычными текстовыми константами (строка 830), а затем игнорируется (различаются только перехватчики и ПВО).
Т.о. мы видим два метода дополнительной типизации элементов массивов: в массиве N номер элемента уже сам обозначает тип (0 - база, 1..N0 - объект, N0..N2 - ПВО), а в С тип элемента прописан в самом элементе C(I,1). Учитывая, что массив C постоянно просматривается с начала до конца, первый способ гораздо "бейсиковее".
***

Рудиментом от процедуры стрельбы "ТРОПЫ" служит процедура ввода пароля, на этот раз чисто случайного:

140 ... F$="":FOR I=1 TO 5
150 F$=F$+CHR$(INT(RND(.01)*26)+65):NEXT ...
...
192 PRINT "YOUR FAIL SAFE CODE IS ";F$;".":PRINT
...
391 INPUT "FAIL SAFE CODE";A$:IF A$=F$ THEN F9=1

***

Еще один блок, практически целиком унаследованный от "ТРОПЫ" - разруливание ситуации "игрок помер" (тут же - "игрок победил"). Строки 1470-1580.
Как и в "ТРОПЕ", этот блок завершается предложением сыграть еще раз, отправив игрока снова в начало программы. Здесь мы стоим у истоков одного из самых некрасивых решений в истории программирования (не только игр): "убить все и начать заново" вместо "привести в исходное состояние". В современных играх ожидание "общей очистки/общей загрузки" занимает уже почти минуты.
Казалось бы, так трудно, выводя статистику по игре, попутно очищать эти переменные? Зачем, ведь, их так мало? И вот, наш инициирующий блок разделен на две части: строки 5-90 описывают массивы и загружают константы (это больше делать не надо), а строки 100-280 устанавливают начальные значения переменных. По ошибке несколько констант, например, A9 и строки массива M$, попали во вторую часть и перезагружаются (след каких-то заплаток)?
Как бы тони было, мы видим, что возврат к 100 означает начало новой игры, а к 290 - начало следующего хода игры. К сожалению, мы также видим, что какой-то достаточно сложный блок тоже желает сам на себя сослаться (1020), придется разбираться.
***

В игре появилась дополнительная штука - калькулятор географии. Специальный набор блоков обеспечивает необходимый набор операций, которые сама игра считает элементарными. База объектов проста и мала, поэтому калькулятор написан на BASIC, но еще чуть-чуть и пришлось бы вставлять коды... (Как в TANCTICS - ТЕМА #41).
Калькулятор объектов выполняет следующие команды:

- Направление на объект NN:

1600 DX=X-T(NN,1):DY=Y-T(NN,2)
1610 IF DY=0 THEN AN=90-180*(DX>0):RETURN
1620 AN=ATN(-DX/DY)*180/3.1415-180*(DY<0)+360*(DX>0)*(DY>0):RETURN

- Расстояние до объекта NN:

1710 RA=SQR((X-T(NN,1))^2+(Y-T(NN,2))^2):RETURN

- Номер объекта по первым двум буквам имени имени A$:

1760 NN=-1:FOR L=0 TO N2:IF A$=LEFT$(N$(L),2) THEN NN=L
1770 NEXT:RETURN

И чуть более сложная команда:

- Ближайший не уничтоженный объект на нашем пути:

610 I=0:J=10000:FOR NN=NO+1 TO N2:GOSUB 1710:IF RA>J THEN 640
620 IF T(NN,3)=2 THEN 640
630 GOSUB 1600:IF ABS(C-AN)>45 AND ABS(C-AN)<315 THEN 640
631 J=RA:I=NN
640 NEXT:NN=I:IF NN>0 THEN 580

Здесь, кстати, ошибка (или заплатка). Переменной NO не существует (всегда 0). Видимо, подразумевался перебор только узлов ПВО (начиная с N0+1).

Дя перехватчиков такого калькулятора не предусмотрено (они слишком просты), хотя в строках 670-690 лежит маленькая (здесь же применяемая) подпрограммка для вывода информации о контактах.
***

Вернемся к самой главной части программы - вводу команд пользователя. Ранее мы видели ввод различных параметров по мере надобности ("ОРЕГОНСКАЯ ТРОПА") или ввод всех параметров за раз ("Лунолет"). Здесь же мы вводим не только то, что хотим (как в "HIGN HOON"), но, и, практически, тогда, когда хотим, т.к. ситуация между командами меняется достаточно плавно.

30 FOR I=1 TO 12:READ C$(I):NEXT
35 DATA AU,EC,EV,PH,NA,AL,CO,ST,RA,SE,AR,BO
...
290 PRINT CHR$(27)+CHR$(41):GOSUB 670 PRINT :INPUT"COMMAND";A$:IF LEN(A$)<2 THEN 310
294 PRINT CHR$(27)+CHR$(40)
295 CM=0
300 FOR I=1 TO 12:IF LEFT$(A$,2)=C$(I) THEN CM=I
305 NEXT:IF CM>0 THEN 350
310 PRINT "LEGAL COMMANDS ARE:":PRINT "CO  TO  CHANGE COURSE"
311 PRINT "AL  TO  CHANGE ALTITUDE":PRINT "ST  TO  GET A STATUS REPORT"
312 PRINT "RA  TO  GET A RADAR REPORT":PRINT "NA  TO  GET NAVIGATION DATA "
313 PRINT "SE  TO  SEARCH FOR  A DEFENSE COMPLEX"
314 PRINT "AU  TO  HAVE AU TO PILOT FLY PLANE"
315 PRINT "EV  TO  CONDUCT EVASIVE ACTION"
316 PRINT "EC  TO  USE ECM"
317 PRINT "PH  TO  LAUNCH PHOENIX MISSILE"
318 PRINT "AR  TO  ARM BOMB"
319 PRINT "BO  TO  DROP BOMB":T0=T+3+INT(5*RND(0)):GOTO 1020
350 ON  CM GOTO 430,970,740,820,560,360,380,700,650,610,390,470

Т.е.

ВЫБОР(КОМАНДА, AU, 430, EC, 970, EV, 740, PH, 820,
NA, 560, AL, 360, CO, 380, ST, 700, RA, 650,
SE, 610, AR, 390, BO, 470)

Неприятность, поджидающая на этом пути - чувствительность игры к регистру клавиатуры. Вроде, мелочь, но здорово затрудняющая игроку знакомство с игрой.
По окончанию каждой команды происходит приращение счетчика времени (обычно, T0). Так, например, в строке 319 ("Введена неправильная команда") стоит T0=T+3+INT(5*RND(0)).
По сути, наш несчастный оператор ВЫДАЧА получает дополнительный параметр - "добавить время". Многие команды используют "стандартный добавлятор времени" - строку 370.

370 T0=T+13+INT(15*RND(0)):GOTO 1020

Другие, предпочитают увеличивать T0 по-своему, затем - опять на 1020. А команда установки таймера вместо T0 устанавливает T2, что не мешает опять же послать нас на 1020.
***

Остается рассмотреть сами команды и одну "мелочь".

AL(360) - установить новую высоту, в допустимых пределах. Здесь, как и в следующей команде, идет речь не о непосредственном изменении высоты (A), а о требовании ее изменения (A1). Далее - 370.
CO(380) - установить новый курс. Опять не C, а C1. И 370.
AR(390) - активировать бомбы (F9=1). Проверяется, может, они уже сброшены (F9=2)? Для активации требуется ввод пароля (F$). В любом случае - на 370.
AU(430) - включить автопилот. Тут достаточно интересный фрагмент (слишком сложный для такой простой программы):

430 PRINT "TIME FOR  AUTO PILOT (S,M,H)? ";:A$=" "
431 B$=INKEY$:IF B$="" THEN 431
432 PRINT B$;:IF ASC(B$)=13 THEN 439
433 IF ASC(B$)<>20 THEN A$=A$+B$:GOTO 431
434 IF ((ASC(B$)=20)AND(LEN(A$)>1)) THEN A$=LEFT$(A$,LEN(A$)-1)
435 GOTO 431
439 A$=A$+" ":I=0:J=0:K=0
440 IF A$=" " THEN 460
441 I=VAL(A$):GOSUB 1650:IF A$=" " THEN 460
450 J=VAL(A$):GOSUB 1650:IF A$=" " THEN 460
455 K=VAL(A$)
460 I=-I*(I>0):J=-J*(J>0):K=-K*(K>0):T2=T+I+60*J+3600*K:GOTO 1020
...
1650 IF LEFT$(A$,1)="," THEN 1670
1660 A$=RIGHT$(A$,LEN(A$)-1):IF LEN(A$)>1 THEN 1650
1665 A$="  "
1670 A$=RIGHT$(A$,LEN(A$)-1):RETURN

Т.е. используется конечный автомат, распознающий значение времени в формате (S,M,H), считывая его литера за литерой.
Замечаем, что вместо T0 мы почему-то устанавливаем T2. И на 1020.

BO(470) - сброс бомб. Проверяется, может, они уже сброшены (F9=2) или не активированы (F9=0). Требуется ввод названия места и проверяется есть ли такой объект (не ПВО). Проверяется не слишком ли далеко цель (до 250км). Еще раз запрашивается подтверждение. Если хоть что-то не так - 370.
Пауза. Сообщение: "цель уничтожена". Далее - корректировка параметров (L9, T8, S, A0, F9). T0=T+3+INT(5*RND(0)) и на 1020.
NA(560) - запросить курс на место. Ввести имя объекта/ПВО. Выдать примерный курс и дальность. T0=T+40+INT(41*RND(0)), на 1020.
SE(610) - найти ближайший объект/ПВО (по курсу). (См. выше). Процедура вывода и приращения T0 - из предыдущей команды.
RA(650) - радар. Проверяет список контактов, выводя номера контактов и время до перехвата. T0=T+5+INT(RND(0)*11), на 1020.
ST(700) - статус. Выводятся курс (C), скорость (S), высота (A), топливо (F). Почему-то не выводятся координаты (X и Y). Если главная цель еще не поражена, выводится ее название. Выводится число оставшихся ракет (P). T0=T+20+INT(RND(0)*21).
EV(740) - противозенитный маневр. Параметры A и C изменяются достаточно замысловато. Причем, изменяются сразу (а не как в командах AL и CO). Если есть контакты, часть из них отказывается от атаки (пропадает). В процессе исполнения команды есть шанс разбиться (A<0). T0=T+10+INT(21*RND(0)) и 1020.
PH(820) - пуск ракет. Есть ли еще ракеты? По кому (перехватчику или ПВО)? Хватит ли дальности (по ПВО - 200км, по перехватчику - 10с)? Узел или ближайший контакт (без разницы МиГ или ракета) уничтожается. При стрельбе по ракете (не по истребителю) есть шанс промахнуться. Одна ракета тратится (P=P-1). T0=T+3+INT(5*RND(0)) и 1020.
EC(970) - радиоэлектронная борьба. Некоторые контакты самоликвидируются. Тратится немножко специального ресурса (E) от которого зависит вероятность успешности этой операции. T0=T+3+INT(5*RND(0)) и 1020

Остается "мелочь" - что происходит после того, как команда исполнена, переменная T0 или T2 установлена и мы перешли на 1020.
***

Посмотрев на этот кусок, мы видим, что основная его задача - пропуск времени до ближайшего события. Это то, чего нам так не хватает во всех играх в солдатики! Обеспечить географическую или еще какую неожиданность все-таки можно, как и ввести параметры фишки/солдатика. А, вот заранее посчитать, когда на поле боя что-либо случится, на это не способен ни один варгейм. Приходится делить (квантовать) время на маленькие отрезки и по прошествии каждого считать, что произошло. Именно поэтому все, кроме варгеймеров, считают эти игры такими нудными.
Самое же скучное, что в современных компьютерных играх этого механизма тоже нет. Они тоже занимаются честным квантованием... Так какой от них прок? Двигать солдатиков я и сам могу.
***

Из других характерных черт блока 1020, разрушающих нашу счастливую "бейсиковость", сразу можно отметить использование нескольких дополнительных переменных, которые в программе не использовались. Более того, этот блок частично заражает этой "болезнью" и следующий за ним блок концовок.
Причина в том, что для описания состояния (игровой позиции) уже недостаточно просто параметров и просто позиции в программе. Нужны еще переменные, запоминающие, через какие точки программа проходила ранее (старые состояния). Например, в переменной R9 запоминается, от чего умер экипаж нашего славного бомбардировщика, чтобы при формировании финального текста десятком строк далее вставить нужные слова.
Конечно, такие "логические" переменные встречались и в "ТРОПЕ" - ранение, болезнь, "южный проход". Но там они, все-таки, рассматривались как параметры нашего персонажа, были осмысленными, здесь же они представляют сугубо временное храшилище данных, порожденное избыточной сложностью одного блока.
***

Как же считается время следующего события? К сожалению, игра показывает пример, как этого не делать. Слишком много ошибок.
Во-первых, устанавливается ключ I9, означающий, что из всех событий ранее всего случится исполнение команды игрока (которое запланировано на T0). Если же ранее произойдет другое событие, то блок 1020 будет исполнен еще один раз, т.е. будет исполняться пока команда игрока не будет исполнена. Если команды не было (AU за команду не считается), то следующим событием считается ближайшее (не считая прошедших) из перехвата ближайшим перехватчиком, 10 секунд до перехвата ближайшим перехватчиком, конца работы автопилота, 301 секунда от текущего момента.
Во-вторых, считается, насколько, за момент до ближайшего события, могут быть исполнены команды смены высоты и курса. Т.к. предыдущий блок не работает в случае ввода этих команд, то, очевидно, они будут исполнены целиком.
В-третьих, учитывается изменение координат и топлива (конец топлива означает крушение). После этого момент времени считается наступившим и блок расчета времени плавно переходит в очередной блок случайных и неслучайных неприятностей.
***

Если за прошедшее время случился перехват, объявляется воздушный ядерный взрыв, случайным образом изменяется высота, скорость и топливо. Есть и небольшой шанс погибнуть.
Если до перехвата остается не больше 10с, выводится сообщение (пора пускать ракету).
Аналогично сообщается о попадании объекта в радиус поражения бомб, а ПВО - в радиус поражения ракет.
С близких баз ПВО стартуют перехватчики (наблюдается ненужный всплеск тригонометрических вычислений для расчета времени перехвата).
Напоследок проверяется не подлетел ли бомбардировщик к собственной базе (если топлива немного не хватает, не страшно, заправщик успевает).
***

Формулы приводить не буду. Ибо а) они очевидны, б) все цифры, как и в "ТРОПЕ" взяты с потолка.


Последний раз редактировалось: Gudleifr (Ср Дек 06, 2017 2:52 pm), всего редактировалось 1 раз(а)
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: 01.01. СЕРДЖО ЛЕОНЕ, ЭННИО МОРРИКОНЕ...

Сообщение автор Gudleifr в Вт Ноя 28, 2017 1:05 pm

Уже в последей игре есть средство организовать опрос действий пользователя в реальном режиме:

431 B$=INKEY$:IF B$="" THEN 431

Никто не мешает программе, не обнаружив нажатия клавиши, не зацикливаться, а продолжать что-то делать, время от времени проверяя, не созрел ли игрок для какого-либо действия.
Может показаться, что современные "бейсики" ушли далеко вперед, предлагая программисту не заморачиваться ожиданием события, а реагировать на нажатие клавиш/кнопок "немедленно" ("засыпая", когда делать нечего). Это - неправда, "сон" в системной очереди практически ничем не отличается от "ручного ожидания" (даже, если программист этого не знает). Важно запомнить, что, в принципе, программа не должна особо зависеть от того, как в Операционной Системе реализуется работа в реальном времени.
***

Ну, да ладно, прежде чем решить, разрешить ли игроку перемещаться в игровой вселенной, или, наоборот, вращать ее вокруг него, еще немного поговорим о том, как эту вселенную сделать.
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: 01.01. СЕРДЖО ЛЕОНЕ, ЭННИО МОРРИКОНЕ...

Сообщение автор Gudleifr в Вт Ноя 28, 2017 1:10 pm

ЕЩЕ ПРО BASIC (И НЕМНОГО - ПРО FORTH, КОТОРЫЙ ПОЯВИТЬСЯ ПОЗДНЕЕ)

Все, конечно, помнят цитируемое по поводу и без высказывание Дейкстры о вредоносном влиянии BASIC на начинающих программистов. Все знают и политкорректное объяснение: BASIC не является языком структурного программирования.
Так почему же на BASIC написано (или, на худой конец, переписано), пожалуй, больше "классических программ", чем на всех остальных языках вместе взятых?
Ответ на оба вопроса может быть только один: если у нас есть BASIC, программист нам больше не нужен. Любой физик или лирик может написать то, что ему надо. Как правильно сказали Microsoft про свой Visual Basic: "Есть идея - есть программа!".
Т.е. BASIC - это окончательное решение для конкретной машины, простой язык для доступа ко всем, необходимым для дела, ее возможностям. Язык, не требующий умения программировать. Я неоднократно наблюдал, как пользователи делали на BASIC такие вещи, которые "нормальному программисту" сразу и в голову не придут.
***

BASIC - МАШИННО-ОРИЕНТИРОВАННЫЙ ЯЗЫК
На первый взгляд - наоборот. Какой же он машинно-зависимый, если на всех машинах он выглядит практически одинаково? Даже машинно-зависимые операции записываются одними и теми же параметрами: рисование на экране, проигрывание музыки, ввод/вывод в порты, обращение к памяти машины... Вот-вот, дело, как раз, в двух последних. Любая интересная программа на BASIC содержит в себе столько обращений к специфическим для машины портам, специфическим адресам памяти, вызовов машинных кодов, что перенос самой BASIC-программы с одной машины на другую практически бесполезен. Проще написать заново.
С другой стороны, по мере развития информатики, понятие "машина" изменяется. Например, VBA (Visual Basic for Applications) работает не на голом железе, а на "машине MS Excell". Точно так же обеспечивая простой доступ ко всем ее возможностям (необходимым для работы).
***

BASIC ДЛЯ ПРОГРАММИСТОВ
Не знаю, как другие, но я испытываю к BASIC-программам очень теплые чувства. По двум причинам:
1. Мне интересны простые решения, позволяющие делать сложные вещи, и устройство систем, позволяющих такие решения.
2. Мне интересны сложные решения, в которых можно разобраться, потому что есть исходные тексты.
Я уже писал, что склонен считать, что идеально удобный программно-аппаратной комплекс (или АРМ - Автоматизированное Рабочее Место) состоит из частей:
1. Универсальная ЭВМ.
2. Набор "виртуальных драйверов", превращающих ЭВМ в специализированный калькулятор.
3. Программа игры на языке программирования калькулятора, близком к человеческому.
4. Набор "канцелярских принадлежностей" и "органайзеров", ориентированных на ручные операции.
BASIC - это способ достичь этого простейшим способом. Причем "современность" и "привлекательность" определяются только выбором "Универсальной ЭВМ" и совсем не лимитируются "убожеством BASIC".
Но, если BASIC - окончательное решение, то зачем нам FORTH? Очень просто: FORTH - средство написания BASIC-ов. Т.е. еще более окончательное (точнее, краеугольное) решение.
***

ГРАНИЦЫ BASIC
В чем же отличие BASIC от других проблемно-ориентированных языков? Например, от языка Foxbase+, тоже умеющего работать с экраном и подключать к программе машинные коды. Или от языка написания игр-квестов компании Sierra? Очевидный ответ - отличаются "машины", которые на этих языках программируются. Но, ведь считаем же мы BASIC-ом язык написания макросов в MS Word...
Главное отличие в другом: BASIC - язык действия, а не описаний/размышлений. Каждый его оператор говорит: "Сделай!" - а не требует "понимания в текущем контексте". Язык Foxbase+ больше следит за правильностью регистраций данных, а языки Sierra могут что-то сделать только путем манипуляций со свойствами объектов.
Языку действия методы ООП противопоказаны. Поэтому, кстати, исходники на BASIC гораздо легче понять и применить, чем исходники на Java. (Вы уже, наверное, заметили, к чему я веду: FORTH-то тоже - язык действия). Языку действия не нужна никакая структурность.

Позвольте, но, ведь, начиная с MS Visual Basic, он тоже стал объектно-ориентированным... Да. Во-первых, сама "универсальная ЭВМ" стала объектно-ориентированной (см. Win-API: все эти суб-/супер-классирования классов окон). А, во-вторых, избыточная объектно-ориентированность привела к тому, что BASIC перестал быть языком пользователя. И, хотя, BASIC по-прежнему остается самым родным средством программирования IBM PC, сама IBM PC все более превращается в игрушку, запрограммированную где-то-там, не у нас, специально подготовленными людьми.
***

BASIC-БОЛЕЗНИ FORTH
FORTH всегда был средством создания языков. Т.е. в идеале он должен сам через себя полностью самоопределяться. Однако, бесконечные рекурсии и рефлексии здесь невозможны, с чего-то надо начать. И за исходные были приняты BASIC-соглашения: работа ведется в консоли, одинаково хорошо/плохо инкапсулирующей интерфейсные свойства ОС; операции работы с файлами/потоками сделаны так же; даже более-машинно-зависимые процедуры, например, опрос клавиатуры, цельнотянуты из BASIC. И дело не в том, что подобные действия названы теми же словами, а в том, что они прицеплены не к тому месту FORTH-системы, излишне ее тормозят и усложняют.
Проблема "курицы и яйца": BASIC-процедуры есть простейший путь реализации FORTH или BASIC-процедуры, это то, что FORTH должен "стандартно реализовывать", должна быть безусловно решена в пользу первой альтернативы. BASIC, написанный на FORTH, не обязан быть синтаксически подобен тому самому классическому, для 8-битных компьютеров.
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: 01.01. СЕРДЖО ЛЕОНЕ, ЭННИО МОРРИКОНЕ...

Сообщение автор Gudleifr в Вт Ноя 28, 2017 1:24 pm

СОВСЕМ МАЛЕНЬКИЕ BASIC-МАШИНКИ ИГР

Прежде чем перейти к программам, построенным для реализации каких-то игр, посмотрим на игры, естественно порождаемые программами. Как писано в книжках, которые я собрался цитировать, компьютер умеет:
- запрашивать данные;
- сохранять данные;
- генерировать случайные числа;
- вычислять;
- принимать решения, сравнивая данные разными способами;
- сообщать результаты вычислений, решения, сохраненные данные;
- делать точно то, что вы ему приказали, даже если это глупо;
- не умеет делать то, что вы ему не приказывали.

Может ли это само по себе быть игрой? Оказывается, может, надо только придумать подходящий антураж - TXT, 0.06Мб).
***

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

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

Ф.Херберт, Дюна/Мессия Дюны (перевод П.А.Вязникова):
"Халлек обернулся, увидел салют и ответил кивком. Показал на спарринг-манекен.
- А теперь займемся твоей координацией. Покажи, как ты справляешься с этой зловредной штукой. Я буду управлять ею отсюда - здесь мне будет лучше видно. И предупреждаю - сегодня я применю новые контрудары. Враг тебя об этом предупреждать не станет.
Пауль приподнялся на носках, чтобы расслабить мускулы. Он вдруг со всей серьезностью понял, что его жизнь начала резко меняться. Он подошел к тренажеру, ткнул острием рапиры выключатель на груди куклы и почувствовал, как силовое поле оттолкнуло клинок.
- Ан гард!- скомандовал Халлек, и манекен начал атаку.
Пауль включил щит, парировал и контратаковал.
Халлек, управляя куклой, внимательно следил за ним. Его сознание словно разделилось: одна часть напряженно контролировала ход поединка, а другая блуждала где-то вдалеке.
"Я - словно хорошо сформированное садовником плодовое дерево. Дерево, полное хорошо развитых способностей и чувств, и все они привиты на меня - все они вызревали для кого-то другого..."
Почему-то он вспомнил свою младшую сестру - ее миниатюрное, напоминающее о сказочных эльфах лицо ясно встало перед его глазами. Но сестра давно была мертва - умерла в солдатском борделе у Харконненов. Она любила анютины глазки... или маргаритки? Он уже не помнил. И то, что он не мог вспомнить этого, огорчило его.
Пауль отбил медленный рубящий удар куклы и с левой руки провел антре-тиссе.
"Вот ловкий чертенок!- подумал Халлек, теперь полностью поглощенный ловкими движениями Пауля.- Он тренировался самостоятельно. Это не похоже на стиль Дункана, и уж определенно не то, чему учил его я!"

Вступив в тренировочный зал, Алия мельком заметила собственное многоликое отражение в хрустальных призмах. Тренировочный манеж. Длинный меч дожидался ее на подставке напротив спарринг-манекена. Алия подумала: придется сегодня попотеть, потрудиться до изнеможения... чтобы утомилась плоть и очистился ум.
Меч привычно лег в ее руку. Левой рукой она выхватила крис из висевших на груди ножен, и, держа его наизготовку, кончиком меча нажала на кнопку включения. Немедленно ожившее поле щита спарринг-манекена медленно и твердо отодвинуло ее руку.
Засверкали призмы, спарринг-манекен скользнул влево.
Меч Алие следовал за ним; девушке часто казалось, что манекен живет собственной жизнью. Но это были всего лишь сервомоторы и сложные контуры, умело отвлекающие глаза от опасности, чтобы обмануть и тем самым научить. Сложная машина копировала ее собственные реакции, как анти-я; двигалась, отвечая ее движениям, мерцала светом на призмах, нападала и защищалась.
Из призм навстречу ей разом ударили отражения мечей, но только один был настоящим; она отразила удар и, преодолевая сопротивление щита, кончиком меча коснулась спарринг-манекена. Ожил огонек маркера, замерцали огни в призмах... лишь еще более отвлекая внимание.
Машина уже атаковала с новой скоростью - чуть побыстрее, чем прежде.
Она отразила удар, и дерзко шагнув в опасную зону, поразила устройство ножом.
В глубине призм засветилось уже два огонька.
Автомат задвигался быстрее, выдвинулся вперед, словно притянутый движениями ее тела и кончика меча.
Атака - удар - контрудар.
Атака - удар - контрудар.
Загорелось уже четыре маркера, машина становилась опаснее, с каждым огоньком труднее было понять, где находится истинный клинок.
Пять огней.
На обнаженном теле ее сверкали бисеринки пота. Она существовала теперь во Вселенной, границами были ее собственный меч, меч мишени, ее босые ноги, переступающие по полу фехтовального зала... Нервы и мышцы - движения против движения.
Атака - удар - контрудар.
Шесть огней... семь.
Восемь!
Она никогда еще не отваживалась на спарринг на этом уровне.
Внутри ее тела забившийся в угол разум скулил и молил прекратить безрассудство. Машина вместе со всеми ее призмами и мишенью не ведает осторожности... она не думает, она не испытывает угрызений совести. И клинок в ней самый настоящий... иначе в тренировке нет смысла. Его острие способно и ранить, и убивать. Лучшие фехтовальщики Империи прекращали схватку при семи огоньках.
Девять!
Высший восторг охватил Алию. Атакующий нож и спарринг-манекен мелькали перед глазами, сливаясь в мерцающий морок. Собственный меч словно ожил в руке. Она превратилась в антимашину. Не она орудовала клинком - меч властвовал над всем ее телом.
Десять!
Одиннадцать!

М.Гарднер, Математические головоломки и развлечения:
... Особый раздел в коллекции Граймза занимают около 200 замечательных головоломок, изобретенных и сконструированных Л.Д.Уитткером, ветеринаром из Фармвиля, штат Виргиния. Все они искусно вырезаны из драгоценных пород дерева (Уитткер вытачивает их в мастерской, устроенной в подвале его дома), многие из них очень сложны и дьявольски остроумны. Как правило, головоломка имеет вид коробочки с отверстием в крышке. Бросив туда стальной шарик, вы должны выкатить его через другое отверстие в боковой стенке. Над коробочкой разрешается производить любые манипуляции, не ломая и ие открывая ее. Разумеется, одними лишь постукиваниями по коробочке мы не сможем заставить шарик прокатиться по всем внутренним ходам и выйти наружу. Некоторые препятствия на своем пути он сможет преодолеть лишь в том случае, если мы догадаемся определенным образом встряхнуть коробочку. Другие барьеры с его пути можно убрать, если воспользоваться магнитом или подуть в специальную дырочку. Внутренние магниты размещены так, что они притягивают к себе шарик, удерживая его. Вы ничего не подозреваете об этом, потому что внутри коробки специально для того, чтобы ввести вас в заблуждение, положены "подставные" шарики, которые и будут греметь при встряхивании головоломки. Снаружи коробочки могут быть колесики, рычажки и кнопки самого различного вида. Манипулируя определенным образом некоторыми из них, вы можете помочь шарику выбраться наружу; некоторые же из них сделаны лишь для того, чтобы обмануть вас. Иногда для того, чтобы протолкнуть шарик через очередное препятствие, нужно ткнуть булавкой в незаметную на первый взгляд дырочку.
Несколько лет назад Граймз и Уитткер заключили между собой соглашение, по которому Граймз через определенный промежуток времени регулярно должен получать от Уитткера новую головоломку. Если Граймз успеет разгадать ее в течение месяца, то он вправе оставить новинку у себя безвозмездно; в противном случае он должен купить ее. Иногда стороны, не довольствуясь условиями соглашения, заключали еще и азартные пари. Как-то раз Граймз почти год безуспешно бился над разгадкой головоломки Уитткера, но все его усилия так и не привели к успеху. С помощью маленького компаса Граймз установил расположение внутренних магнитов, а изогнутыми проволочками обследовал все отверстия. Выходное отверстие было закрыто пробкой, которую нужно было протолкнуть внутрь, но что-то удерживало ее: по-видимому, расположенные внутри стальные шарики. Граймз догадался, что, наклонив определенным образом коробку, он сумеет выкатить шарики из-под пробки, но все его попытки оканчивались неудачей. В конце концов он просветил устройство рентгеновскими лучами (рис. 175) и решил головоломку. На рентгенограмме обнаружилась одна большая полость, в которую нужно было загнать пятый шарик. Когда все пять шариков заняли свои места, пробка поддалась.


Рис.175. Чтобы разгадать одну из головоломок (на снимке - слева), Граймзу пришлось просветить ее рентгеновскими лучами.

Остальное было уже не так трудно, хотя один раз для выполнения сложного маневра потребовалось 3 руки: надавливая правой и левой рукой на определенные места футляра, нужно было еще поднять рычажок, удерживаемый сильной пружиной. Граймзу удалось проделать и этот трюк, привязав к рычажку нить, другой конец которой был прикреплен к его ноге!
***

Может, использовать не компьютер, а некое простейшее устройство - ящичек-брелок с 4-7 цветными лампочками, кнопочками и бибикалкой на 7 нот (понятно, с настроечными колесиками на задней крышке) - этакий игровой эквивалент - кубика, пушки и/или приборчика проверки реакции? Кстати, в советское время чертежи подобных девайсов широко тиражировались. Но не прижились (не успели?).

Как ограничить необходимый компьютерный минимум? Для каких игр против компьютера достаточно "электронного кубика", а для каких необходим "игральный автомат".
Я вижу два условия для "кубиковых" игр:
1. честность игрока
2. немультимедийность

И единственный дополнительный "кубик" который потребуется - простейший проверятель реакции - дура о двух лампочках (готовность, успех), и трех настраиваемых таймерах с настраиваемым случайным разбросом (на-старт, игра, показ-результата). Остальные "аттракционы" доступны настольным играм и без компьютера.

1. Проверятели остальных физических и умственных кондиций вполне доступны в домашних условиях (конечно, если игрок честен).
2. Различного рода гомеостаты вполне реализуются средствами тех же книг-игр.
3. "Туман войны" книгами-играми и колодами карт тоже вполне реализуем.
4. Сложные вычислители? Тут надо разграничить: вычисления сложные и вычисления нудные. Сложные, как в книге-игре "Лунолет", вполне реализуемы при помощи таблиц/номограмм. С нудными, например, как в игре ROBOTS (отличается от приведенного в сборнике ICEBERG, тем, что кораблей врага много и, сталкиваясь, они образуют новые айсберги) бороться труднее. Однако, видимо предел сложности игры выше предела ее нудности (играют же люди в варгеймы на сотню жетонов).
5. "Выбиратели стратегий" тоже реализуются без проблем.

Т.о. мы видим, что в нише "создания кубиков" программисту практически нечего делать.
Однако, открывается другая ниша - изготовления гомеостатов и номограммок. И здесь все наши "увеличители энтропии" и ее "уменьшители", "машины Теории Игр" и прочие "демоны" вполне востребованы. Во сколько раз игра станет сложнее, если скорость игрока уменьшить? Напрямую не скажешь. Но если и "скорость" и "сложность" были изначально рассчитаны как ф-ии от неких параметров "всеобщей модели игры", то ответ можно вполне прикинуть. Вспоминается, как дизайнер "Golden Axe" долго и путано объяснял прихождение в свою гениальную голову гениальной мысли о том, что в виду удлинения удара игрока за счет меча пришлось увеличить размер противников... Спросил бы программиста...

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

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: 01.01. СЕРДЖО ЛЕОНЕ, ЭННИО МОРРИКОНЕ...

Сообщение автор Спонсируемый контент


Спонсируемый контент


Вернуться к началу Перейти вниз

Вернуться к началу


 
Права доступа к этому форуму:
Вы не можете отвечать на сообщения