and
+is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
+
+# Please also look if there are files or directories which have a
+# different copyright/license attached and list them here.
diff --git a/debian/cron.d.ex b/debian/cron.d.ex
new file mode 100644
index 0000000..c3bc3de
--- /dev/null
+++ b/debian/cron.d.ex
@@ -0,0 +1,4 @@
+#
+# Regular cron jobs for the instead package
+#
+0 4 * * * root [ -x /usr/bin/instead_maintenance ] && /usr/bin/instead_maintenance
diff --git a/debian/docs b/debian/docs
new file mode 100644
index 0000000..f3d4ef2
--- /dev/null
+++ b/debian/docs
@@ -0,0 +1,2 @@
+readme.txt
+readme.txt
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..b1f4b47
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,100 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+
+
+
+
+configure: configure-stamp
+configure-stamp:
+ dh_testdir
+ # Add here commands to configure the package.
+
+ touch configure-stamp
+
+
+build: build-stamp
+
+build-stamp: configure-stamp
+ dh_testdir
+
+ # Add here commands to compile the package.
+ rm -rf Rules.make
+ ln -s Rules.make.system Rules.make
+ $(MAKE) DESTDIR=/usr BIN=/usr/games STEADPATH=/usr/share/games/stead
+ rm -rf Rules.make
+ #docbook-to-man debian/instead.sgml > instead.1
+ touch $@
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp configure-stamp
+
+ # Add here commands to clean up after the build process.
+ rm -rf Rules.make
+ ln -s Rules.make.system Rules.make
+ $(MAKE) clean
+ rm -rf Rules.make
+ ln -s Rules.make.standalone Rules.make
+
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ # Add here commands to install the package into debian/instead.
+ rm -rf Rules.make
+ ln -s Rules.make.system Rules.make
+ $(MAKE) install DESTDIR=$(CURDIR)/debian/instead/usr STEADPATH=$(CURDIR)/debian/instead/usr/share/games/stead BIN=$(CURDIR)/debian/instead/usr/games ICONPATH=$(CURDIR)/debian/instead/usr/share/pixmaps
+ rm -rf Rules.make
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installchangelogs
+ dh_installdocs
+ dh_installexamples
+# dh_install
+# dh_installmenu
+# dh_installdebconf
+# dh_installlogrotate
+# dh_installemacsen
+# dh_installpam
+# dh_installmime
+# dh_python
+# dh_installinit
+# dh_installcron
+# dh_installinfo
+ dh_installman
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+# dh_perl
+# dh_makeshlibs
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/desktop/Makefile b/desktop/Makefile
new file mode 100644
index 0000000..454c754
--- /dev/null
+++ b/desktop/Makefile
@@ -0,0 +1,14 @@
+include ../Rules.make
+clean:
+ rm -rf instead.desktop
+
+all: instead.desktop
+
+instead.desktop: instead.desktop.in
+ cat instead.desktop.in | sed -e "s|@BIN|$(BIN)|g" > instead.desktop
+
+install:
+ install -d -m 0755 $(DESTDIR)/share/applications
+ install -m 0644 instead.desktop $(DESTDIR)/share/applications/instead.desktop
+ install -m 0644 instead.desktop $(DESTDIR)/share/applications/instead.desktop
+
diff --git a/desktop/Makefile.windows b/desktop/Makefile.windows
new file mode 100644
index 0000000..263836e
--- /dev/null
+++ b/desktop/Makefile.windows
@@ -0,0 +1,3 @@
+clean:
+all:
+install:
diff --git a/desktop/instead.desktop.in b/desktop/instead.desktop.in
new file mode 100644
index 0000000..482ce9c
--- /dev/null
+++ b/desktop/instead.desktop.in
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Encoding=UTF-8
+Version=0.8.5
+Type=Application
+Name=INSTEAD
+Name[ru]=INSTEAD
+Comment=Siple Text Adventures Interpretor
+Comment[ru]=Интерпретатор простых приключений
+Exec=@BIN/sdl-instead
+Icon=sdl_instead.png
+Terminal=false
+Categories=Game;LogicGame;
+
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..5725b45
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,7 @@
+include ../Rules.make
+clean:
+all:
+install:
+ install -d -m0755 $(DESTDIR)/share/doc/instead
+ install -m0644 *.jpg *.html *.txt $(DESTDIR)/share/doc/instead
+
diff --git a/doc/Makefile.windows b/doc/Makefile.windows
new file mode 100644
index 0000000..5838a1a
--- /dev/null
+++ b/doc/Makefile.windows
@@ -0,0 +1,8 @@
+clean:
+all:
+install:
+ if not exist ..\bin\doc mkdir ..\bin\doc
+ copy /Y *.txt ..\bin\doc
+ copy /Y *.png ..\bin\doc
+ copy /Y *.html ..\bin\doc
+ copy /Y *.jpg ..\bin\doc
diff --git a/doc/index.html b/doc/index.html
index 4b5e1a1..e25e6b3 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -4,7 +4,7 @@
[ Что это такое? ] [ Скриншоты ] [ Скачать ]
-INSTEAD 0.7 -- интерпретатор простых текстовых приключений для Unix
+INSTEAD 0.8 -- интерпретатор простых текстовых приключений для Unix
Интерпретатор STEAD (Simply Text Adventure) позволяет проигрывать игры, которые по жанру являются
смесью визуальной новеллы, текстового квеста и классических квестов 90-х. Особенности STEAD игры:
@@ -15,8 +15,7 @@
поддержка тем для графического интерпретатора -- конкретная игра может менять вид интерфейса;
переносимость (изначально написана для Linux, зависит от SDL и lua).
-На данный момент автором STEAD написана одна игра: 'Возвращение Квантового Кота', которая входит в состав архива с исходным кодом.
-Игра содержит около 70 сцен, графику и oldschool треки.
+В архив с интерпретатором входит игра: 'Возвращение Квантового Кота'. Игра содержит около 70 сцен, графику и oldschool треки.
Работа графического интерпретатора.
@@ -31,7 +30,7 @@
-Скачать текущую версию можно здесь: http://sites.google.com/site/sdlinstead/
+Скачать текущую версию и другие игры для INSTEAD можно здесь: http://instead.googlecode.com/
[ Что это такое? ] [ Скриншоты ] [ Скачать ]
diff --git a/doc/writing_games.txt b/doc/writing_games.txt
new file mode 100644
index 0000000..fcffce1
--- /dev/null
+++ b/doc/writing_games.txt
@@ -0,0 +1,964 @@
+== 0. Общие сведения ==
+
+Код игр для STEAD пишется на lua (5.1), поэтому, знание этого языка полезно, хотя и не необходимо. Код движка на lua занимает всего ~900 строк и лучшей документацией, конечно, является изучение его кода.
+
+Главное окно игры содержит информацию о статической и динамической части сцены, активные события и картинку сцены с возможными переходами в другие сцены (в графическом интерпретаторе).
+
+Динамическая часть сцены составлена из описаний объектов сцены, она отображается всегда.
+
+Статическая часть сцены отображается только один раз, при показе сцены, или при повторении команды look (в графическом интерпретаторе -- клик на названии сцены).
+
+Игроку доступны объекты доступные на любой сцене -- инвентарь. Игрок может взаимодействовать с объектами инвентаря и действовать объектами инвентаря на другие объекты сцены или инвентаря.
+
+Следует отметить, что понятие инвентаря является условным. Например, в "инвентаре" могут находиться такие объекты как "открыть", "осмотреть", "использовать" и т.д.
+
+Действиями игрока могут быть:
+
+ * осмотр сцены;
+ * действие на объект сцены;
+ * действие на объект инвентаря;
+ * действие объектом инвентаря на объект сцены;
+ * действие объектом инвентаря на объект инвентаря;
+ * переход в другую сцену;
+
+Игра представляет из себя каталог, в котором должен находиться скрипт main.lua. Другие ресурсы игры (скрипты на lua, графика и музыка) должны находиться в рамках этого каталога. Все ссылки на ресурсы делаются относительно текущего каталога -- каталога игры.
+
+В начале файла main.lua может быть определен заголовок, состоящий из тегов. Теги должны начинаться с символов '--': комментарий с точки зрения lua. На данный момент существует один тег: $Name:, который должен содержать название игры в кодировке UTF8. Пример использования тега:
+{{{
+-- $Name: Самая интересная игра!$
+}}}
+
+Графический интерпретатор ищет доступные игры в каталоге games. Unix версия интерпретатора кроме этого каталога просматривает также игры в каталоге ~/.instead/games.
+
+== 1. Сцена ==
+
+Сцена -- это единица игры, в рамках которой игрок может изучать все объекты сцены и взаимодействовать с ними. В игре должна быть хотя бы одна сцена с именем main.
+{{{
+main = room {
+ nam = 'главная комната',
+ dsc = 'Вы в большой комнате.',
+};
+}}}
+Запись означает создание объекта main типа room. У каждого объекта игры есть атрибуты и обработчики. Например, атрибут nam (имя) является необходимым для любого объекта.
+
+Атрибут nam для сцены это то, что будет заголовком сцены при ее отображении. Имя сцены также используется для ее идентификации при переходах.
+
+Атрибут dsc это описание статической части сцены, которое выводится один раз при входе в сцену или явном выполнении команды look.
+
+Внимание!!! Если для вашего творческого замысла необходимо, чтобы описание статической части сцены выводилось каждый раз, вы можете определить для своей игры параметр forcedsc (в начале игры).
+{{{
+game.forcedsc = true;
+}}}
+Или, аналогично, задать атрибут forcedsc для конкретных сцен.
+
+Для длинных описаний удобно использовать запись вида:
+
+{{{dsc = [[ Очень длинное описание... ]],}}}
+
+При этом переводы строк игнорируются. Если вы хотите, чтобы в выводе описания сцены присутствовали абзацы -- используйте символ ^.
+
+{{{
+dsc = [[ Первый абзац. ^^
+Второй Абзац.^^
+
+Третий абзац.^
+На новой строке.]],
+}}}
+== 2. Объекты ==
+
+Объекты -- это единицы сцены, с которыми взаимодействует игрок.
+{{{
+tabl = obj {
+ nam = 'стол',
+ dsc = 'В комнате стоит {стол}.',
+ act = 'Гм... Просто стол...',
+};
+}}}
+Имя объекта nam используется при попадании его в инвентарь а также в текстовом интерпретаторе для адресации объекта.
+
+dsc -- описатель объекта. Он будет выведен в динамической части сцены. Фигурными скобками отображается фрагмент текста, который будет являться ссылкой в графическом интерпретаторе.
+
+act -- это обработчик, который вызывается при действии пользователя (действие на объект сцены). Его задача -- возвращение строки текста, которая станет частью событий сцены.
+
+ВНИМАНИЕ: в пространстве имен lua уже существуют некоторые объекты (таблицы), например: table, io, string... Будьте внимательны, при создании объекта. Например, в приведенном примере используется tabl, а не table.
+
+== 3. Добавляем объекты в сцену ==
+
+Ссылкой на объект называется текстовая строка, содержащая имя объекта при его создании. Например: 'tabl' -- ссылка на объект tabl.
+
+Для того, чтобы поместить в сцену объекты, нужно определить массив obj, состоящий из ссылок на объекты:
+{{{
+main = room {
+ nam = 'главная комната',
+ dsc = 'Вы в большой комнате.',
+ obj = { 'tabl' },
+};
+}}}
+Теперь, при отображении сцены мы увидим объект стол в динамической части.
+
+== 4. Объекты связанные с объектами ==
+
+Объекты тоже могут содержать атрибут obj. При этом, список будет последовательно разворачиваться. Например, поместим на стол яблоко.
+{{{
+apple = obj {
+ nam = 'яблоко',
+ dsc = 'На столе лежит {яблоко}.',
+ act = 'Взять что-ли?',
+};
+
+tabl = obj {
+ nam = 'стол',
+ dsc = 'В комнате стоит {стол}.',
+ act = 'Гм... Просто стол...',
+ obj = { 'apple' },
+};
+}}}
+При этом, в описании сцены мы увидим описание объектов стол и яблоко, так как apple -- связанный с tabl объект.
+
+
+== 5. Атрибуты и обработчики как функции ==
+
+Большинство атрибутов и обработчиков могут быть также функциями. Так, например:
+{{{
+nam = function()
+ return 'яблоко';
+end,
+}}}
+Это синоним записи: nam = 'яблоко';
+
+Функции сильно расширяют возможности STEAD, например:
+{{{
+apple = obj {
+ nam = 'яблоко',
+ dsc = function(s)
+ if not s._seen then
+ return 'На столе {что-то} лежит.';
+ else
+ return 'На столе лежит {яблоко}.';
+ end
+ end,
+ act = function(s)
+ if s._seen then
+ return 'Это яблоко!';
+ else
+ s._seen = true;
+ return 'Гм... Это же яблоко!';
+ end
+ end,
+};
+}}}
+Если атрибут или обработчик оформлен как функция, то обычно первый аргумент функции (s) сам объект. В данном примере, при показе сцены будет в динамической части сцены будет текст: 'На столе что-то лежит'. При взаимодействии с 'что-то', переменная `_seen` объекта apple будет установлена в true и мы увидим, что это было яблоко.
+
+Зная lua, можно упростить запись:
+{{{
+function sw(v, a, b)
+ if v then
+ return a;
+ end
+ return b
+end
+
+apple = obj {
+ nam = function(s)
+ return sw(not s._seen, 'нечто','яблоко');
+ end,
+ dsc = function(s)
+ return sw(not s._seen,'На столе {что-то} лежит.', 'На столе лежит {яблоко}.');
+ end,
+ act = function(s)
+ if s._seen then
+ return 'Это яблоко!';
+ else
+ s._seen = true;
+ return 'Гм... Это же яблоко!';
+ end
+ end,
+};
+}}}
+И в дальнейшем всегда использовать функцию sw (или какую-либо другую, вспомогательную функцию).
+
+Запись `s._seen` означает, что переменная `_seen` размещена в объекте s (то-есть apple). Подчеркивание означает, что эта переменная попадет в файл сохранения игры. Начиная с версии интерпретатора 0.7.7 в файл сохранения игры попадают также переменные, название которых начинается с большой буквы.
+
+Внимание!!! Переменные в любом случае не записываются в файл сохранения, если они не размещены в одном из перечисленных типов объектов: комната, объект, игра, игрок.
+
+== 6. Инвентарь ==
+
+Простейший вариант сделать объект, который можно брать -- определить обработчик tak.
+
+Например:
+{{{
+apple = obj {
+ nam = 'яблоко',
+ dsc = 'На столе лежит {яблоко}.',
+ inv = function()
+ inv():del('apple');
+ return 'Я съел яблоко.';
+ end,
+ tak = 'Вы взяли яблоко.',
+};
+}}}
+При этом, при действии игрока на объект яблоко -- яблоко будет убрано из сцены и добавлено в инвентарь. При действии игрока на инвентарь -- вызывается обработчик inv.
+
+В нашем примере -- при действии игроком на яблоко в инвентаре - яблоко будет съедено.
+
+== 7. Переходы между сценами ==
+
+Для перехода между сценами используется атрибут сцены -- список way.
+{{{
+room2 = room {
+ nam = 'зал',
+ dsc = 'Вы в огромном зале.',
+ way = { 'main' },
+};
+
+
+main = room {
+ nam = 'главная комната',
+ dsc = 'Вы в большой комнате.',
+ obj = { 'tabl' },
+ way = { 'room2' },
+};
+}}}
+При этом, вы сможете переходить между сценами main и room2. Как вы помните, nam может быть функцией, и вы можете генерировать имена сцен на лету, например, если вы хотите, чтобы игрок не знал название сцены, пока не попал на нее.
+
+При переходе между сценами движок вызывает обработчик exit из текущей сцены и enter в той сцены, куда идет игрок. Например:
+{{{
+room2 = room {
+ enter = 'Вы заходите в зал.',
+ nam = 'зал',
+ dsc = 'Вы в огромном зале.',
+ way = { 'main' },
+ exit = 'Вы выходите из зала.',
+};
+}}}
+
+exit и enter могут быть функциями. Тогда первый параметр это (как всегда) сам объект, а второй это ссылка на комнату куда игрок хочет идти (для exit) или из которой уходит (для enter). Например:
+{{{
+room2 = room {
+ enter = function(s, f)
+ if f == 'main' then
+ return 'Вы пришли из комнаты.';
+ end
+ end,
+ nam = 'зал',
+ dsc = 'Вы в огромном зале.',
+ way = { 'main' },
+ exit = function(s, t)
+ if t == 'main' then
+ return 'Я не хочу назад!', false
+ end
+ end,
+};
+}}}
+Как видим, обработчики могут возвращать два значения: строку и статус. В нашем примере функция exit вернет false, если игрок попытается уйти из зала в main комнату. false означает, что переход не будет выполнен. Такая же логика работает и для enter. Кроме того, она работает и для обработчика tak.
+
+== 8. Действие объектов друг на друга ==
+
+Игрок может действовать объектом инвентаря на другие объекты. При этом вызывается обработчик use у объекта которым действуют и used -- на которого действуют.
+
+Например:
+{{{
+knife = obj {
+ nam = 'нож',
+ dsc = 'На столе лежит {нож}',
+ inv = 'Острый!',
+ tak = 'Я взял нож!',
+ use = 'Вы пытаетесь использовать нож.',
+};
+
+tabl = obj {
+ nam = 'стол',
+ dsc = 'В комнате стоит {стол}.',
+ act = 'Гм... Просто стол...',
+ obj = { 'apple', 'knife' },
+ used = 'Вы пытаетесь сделать что-то со столом...',
+};
+}}}
+Если игрок возьмет нож и использует его на стол -- то увидит текст обработчиков use и used. use и used могут быть функциями. Тогда первый параметр это сам объект,
+а второй -- ссылка на объект на который направлено действие в случае use и объект, которым действие осуществляется в случае used.
+
+use может вернуть статус false, в этом случае обработчик used не вызовется (если он вообще был). Статус обработчика used -- игнорируется.
+
+Пример:
+{{{
+knife = obj {
+ nam = 'нож',
+ dsc = 'На столе лежит {нож}',
+ inv = 'Острый!',
+ tak = 'Я взял нож!',
+ use = function(s, w)
+ if w ~= 'tabl'
+ return 'Не хочу это резать.', false
+ else
+ return 'Вы вырезаете на столе свои инициалы.';
+ end
+};
+}}}
+Нож можно использовать только на стол.
+
+== 9. Объект игрок ==
+
+Игрок в STEAD представлен объектом pl. Тип объекта -- player. В движке объект создается следующим образом:
+{{{
+pl = player {
+ nam = "Incognito",
+ where = 'main',
+ obj = { }
+};
+}}}
+Атрибут obj представляет собой инвентарь игрока.
+
+== 10. Объект game ==
+
+Игра также представлена объектом game с типом game. В движке он определяется следующим образом:
+{{{
+game = game {
+ nam = "INSTEAD -- Simple Text Adventure interpreter v"..version.." '2009 by Peter Kosyh",
+ dsc = [[
+Commands:^
+ look(or just enter), act (or just what), use [on what], go ,^
+ back, inv, way, obj, quit, save , load .]],
+ pl ='pl',
+ showlast = true,
+};
+}}}
+Как видим, объект хранит в себе указатель на текущего игрока ('pl') и некоторые параметры. Например, вы можете указать в начале своей игры кодировку текста следующим образом:
+{{{ game.codepage="UTF-8"; }}}
+
+Поддержка произвольных кодировок изначально присутствует в UNIX версии интерпретатора, в windows версии -- начиная с 0.7.7.
+
+Кроме того, объект game может содержать обработчики по умолчанию act, inv, use, которые будут вызваны, если в результате действий пользователя не будут найдены никакие другие обработчики. Например, вы можете написать в начале игры:
+{{{
+game.act = 'Не получается.';
+game.inv = 'Гм.. Странная штука..';
+game.use = 'Не сработает...';
+}}}
+
+== 11. Атрибуты - списки ==
+
+Атрибуты списки (такие как way или obj) позволяют работать с собой, таким образом позволяя реализовать динамически определяемые переходы между сценами, живые объекты и т.д.
+
+Методы списков: add, del, look, srch. Из них наиболее часто используемые: add и del.
+
+add - добавляет в список. del -- удаляет из него. srch -- выполняет поиск объекта. Следует отметить, что параметром del и srch может быть не только сам объект или идентификатор объекта, но и имя объекта.
+
+Начиная с версии 0.8 параметром add может быть сам объект. Кроме того, с этой версии добавляется необязательный второй параметр -- позиция в списке. Начиная с версии 0.8 вы можете также выполнять модификацию списка по индексу с помощью метода set. Например:
+{{{
+objs():set('knife',1);
+}}}
+
+Выше, вы уже видели пример со съеденным яблоком, там использовалась конструкция inv():del('apple');
+
+inv() -- это функция, которая возвращает список инвентаря. del после ':'-- метод, удаляющий элемент инвентаря.
+
+Аналогично, собственная реализация tak может быть такой:
+{{{
+knife = obj {
+ nam = 'нож',
+ dsc = 'На столе лежит {нож}',
+ inv = 'Острый!',
+ act = function(s)
+ objs():del('knife');
+ inv():add('knife');
+ end,
+};
+}}}
+
+Кроме добавления, удаления объектов из списков вы можете использовать выключение/включение объектов с помощью методов enable() и disable(). Например: knife:disable(). При этом объект knife пропадает из описания сцены, но в последствии может быть опять быть включен, с помощью knife:enable().
+
+== 12. Функции, которые возвращают объекты ==
+
+В STEAD определены некоторые функции, которые возвращают наиболее часто используемые объекты. Например:
+ * inv() возвращает список инвентаря;
+ * objs() возвращает список объектов текущей сцены; (начиная с 0.8.5 -- необязательный параметр -- сцена, для которой возвращается список);
+ * ways() возвращает список возможных переходов из текущей сцены; (начиная с 0.8.5 -- необязательный параметр -- сцена, для которой возвращается список);
+ * me() возвращает объект-игрок;
+ * here() возвращает объект текущую сцену; (начиная с 0.8.5 -- еще одна функция where() -- возвращает текущую сцену как строку-имя объекта, а не сам объект)
+ * from() возвращает объект прошлой сцены;
+
+Комбинируя эти функции с методами add, del можно динамически менять сцену, например:
+{{{
+ways:add('nexroom'); -- добавить переход на новую сцену;
+}}}
+{{{
+objs():add('chair'); -- добавить объект в текущую сцену;
+}}}
+
+Еще одна функция, которая получает объект по ссылке:
+ref().
+
+Например, мы можем добавить объект в локацию 'home' следующим образом:
+{{{
+ref('home').obj:add('chair');
+}}}
+
+Впрочем, следующая более простая запись тоже является корректной:
+{{{
+home.obj:add('chair');
+}}}
+
+Или, для версии >=0.8.5:
+{{{
+objs('home'):add('chair');
+}}}
+или, наконец:
+{{{
+put('chair', 'home');
+}}}
+
+Начиная с 0.8.5 -- deref(o), возвращает ссылку-строку для объекта;
+
+== 13. Некоторые вспомогательные функци. ==
+
+В STEAD определены некоторые высокоуровневые функции, которые могут оказаться полезными при написании игры.
+
+have() -- проверяет, есть ли объект в инвентаре. По имени объекта или по атрибуту nam объекта. Например:
+{{{
+...
+act = function(s)
+ if have('knfie') then
+ return 'Но у меня же есть нож!';
+ end
+end
+...
+}}}
+move(o, w) -- переносит объект из текущей сцены в другую:
+
+{{{ move('mycat','inmycar');}}}
+
+Если вы хотите перенести объект из произвольной сцены, вам придется удалить его из старой сцены с помощью метода del. Для создания сложно перемещающихся объектов, вам придется написать свой метод, который будет сохранять текущую позицию объекта в самом объекте и делать удаление объекта из старой сцены. Вы можете указать исходную позицию (комнату) объекта в качестве третьего параметра move.
+
+{{{ move('mycat','inmycar', 'forest'); }}}
+
+Начиная с версии 0.8 присутствует также функция movef, аналогичная move, но добавляющая объект в начало списка.
+
+seen(o) -- если объект присутствует в текущей сцене:
+{{{
+ if seen('mycat') then
+ move('mycat','inmycar');
+ end
+}}}
+drop(o) -- положить объект из инвентаря на сцену:
+
+ drop('knife');
+
+Начиная с версии 0.8 присутствует также функция dropf, аналогичная drop, но добавляющая объект в начало списка. Начиная с версии 0.8.5 второй необязательный параметр -- комната, куда помещается предмет. Кроме того, для версий >=0.8.5 доступна функция put, которая не удаляет предмет из инвентаря.
+
+
+take(o) -- взять объект.
+
+ take('knife');
+
+Начиная с версии 0.8.5 второй необязательный параметр -- комната, с которой берется предмет.
+
+taken(o) -- если объект взят -- вернет true (взят с помощью tak или take());
+
+rnd(m) -- случайное значение от 1 до m.
+
+goto(w) -- перейти в сцену w, при этом обработчику нужно вернуть возвращаемое значение goto, так как goto вернет описание новой сцены или сообщенмие о том, что переход невозможен, например:
+
+change_pl(p) -- переключиться на другого игрока (со своим инвентарем и позицией). При этом функция возвращает описание сцены нового игрока и это возвращаемое значение должно быть передано из обработчика (см. goto()).
+
+{{{
+mycar = obj {
+ nam = 'моя машина',
+ dsc = 'Перед хижиной стоит мой старенький {пикап} Toyota.',
+ act = function(s)
+ return goto('inmycar');
+ end
+};
+}}}
+
+back() -- goto в предыдущую сцену.
+
+time() -- возвращает текущее время игры. Время игры считается в активных действиях.
+
+cat(...) -- возвращает строку -- склейку строк-аргументов. Если первый аргумент nil, то функция возвращает nil.
+
+par(...) -- возвращает строку -- склейку строк-аргументов, разбитых строкой-первым параметром.
+
+== 14. Диалоги ==
+
+Диалоги это сцены, содержащие объекты -- фразы. Например, простейший диалог может выглядеть следующим образом.
+{{{
+povardlg = dlg {
+ nam = 'на кухне',
+ dsc = 'Передо мной полное лицо женщины - повара в белом колпаке и усталым взглядом...',
+ obj = {
+ [1] = phr('Мне вот-этих зелененьких... Ага -- и бобов!', 'На здоровье!'),
+ [2] = phr('Картошку с салом, пожалуйста!', 'Приятного аппетита!'),
+ [3] = phr('Две порции чесночного супа!!!', 'Прекрасный выбор!'),
+ [4] = phr('Мне что-нибудь легонькое, у меня язва...', 'Овсянка!'),
+ },
+};
+}}}
+phr -- создание фразы. Фраза содержит вопрос, ответ и реакцию (реакция в данном примере отсутствует). Когда игрок выбирает одну из фраз, фраза отключается. Когда все фразы отключатся диалог заканчивается. Реакция -- это строка кода на lua который выполнится после отключения фразы. Например:
+{{{
+food = obj {
+ nam = 'еда',
+ inv = function (s)
+ inv():del('food');
+ return 'Я ем.';
+ end
+};
+
+gotfood = function(w)
+ inv():add('food');
+ food._num = w;
+ return back();
+end
+
+povardlg = dlg {
+ nam = 'на кухне',
+ dsc = 'Передо мной полное лицо женщины - повара в белом колпаке и усталым взглядом...',
+ obj = {
+ [1] = phr('Мне вот-этих зелененьких... Ага -- и бобов!', 'На здоровье!', [[pon(1); return gotfood(1);]]),
+ [2] = phr('Картошку с салом, пожалуйста!', 'Приятного аппетита!', [[pon(2); return gotfood(2);]]),
+ [3] = phr('Две порции чесночного супа!!!', 'Прекрасный выбор!', [[pon(3);return gotfood(3);]]),
+ [4] = phr('Мне что-нибудь легонькое, у меня язва...', 'Овсянка!', [[pon(4); return gotfood(4);]]),
+ },
+};
+}}}
+В данном примере, игрок выбирает еду. Получае ее (запомнив выбор в переменной food._num) и возвращается обратно (в ту сцену откуда попал в диалог).
+
+В реакции может быть любой lua код, но в STEAD определены наиболее часто используемые функции:
+
+pon(n..) -- включить фразы диалога с номерами n... (в нашем примере -- чтобы игрок мог повторно взять еду того-же вида).
+poff(n...) -- выключить фразы диалога с номерами n...
+prem(n...) -- удалить (заблокировать) фразы диалога с номерами n... (удаление означает невозможность включения фраз. pon(n..) не приведет к включению фраз).
+
+Переход в диалог осуществляется как переход на сцену:
+{{{
+povar = obj {
+ nam = 'повар',
+ dsc = 'Я вижу {повара}.',
+ act = function()
+ return goto('povardlg');
+ end,
+};
+}}}
+Вы можете переходить из одного диалога в другой диалог -- организовывая иерархические диалоги.
+
+Также, вы можете прятать некоторые фразы при инициализации диалога и показывать их при некоторых условиях.
+{{{
+facectrl = dlg {
+ nam = 'фэйсконтроль',
+ dsc = 'Я вижу перед собой неприятное лицо полного охранника.',
+ obj = {
+ [1] = phr('Я пришел послушать лекцию Белина...',
+ '-- Я не знаю кто вы -- ухмыляется охранник -- но мне велели пускать сюда только приличных людей.',
+ [[pon(2);]]),
+ [2] = _phr('У меня есть приглашение!',
+ '-- А мне плевать! Посмотри на себя в зеркало!!! Ты пришел слушать самого Белина -- правую руку самого... -- охранник почтительно помолчал -- Так что пошел вон..', [[pon(3,4)]]),
+ [3] = _phr('Сейчас я дам тебе по роже!', '-- Ну все... Мощные руки выталкивают меня в коридор...',
+ [[poff(4)]]),
+ [4] = _phr('Ты, кабан! Я же тебе сказал -- у меня есть приглашение!',
+ '-- Чтоооооо? Глаза охранника наливаются кровью... Мощный пинок отправляет меня в коридор...',
+ [[poff(3)]]),
+ },
+ exit = function(s,w)
+ s:pon(1);
+ end,
+};
+}}}
+
+`_phr` -- создает выключенную фразу, которую можно включить. Данный пример показывает также возможность использования методов pon, poff, prem для диалога (см. exit).
+
+Вы можете включать/выключать фразы не только текущего, но и произвольного диалога, с помощью методов объекта диалог pon/poff. Например: shopman:pon(5);
+
+== 15. Облегченные объекты ==
+
+Иногда, сцену нудно наполнить декорациями, которые обладают ограниченной функциональностью, но делают игру разнообразней. Для этого можно использовать облегченный объект. Например:
+{{{
+sside = room {
+ nam = 'южная сторона',
+ dsc = [[Я нахожусь у южной стены здания института. ]],
+ act = function(s, w)
+ if w == 1 then
+ ways():add('stolcorridor');
+ return "Я подошел к подъезду. На двери подъезда надпись -- 'Столовая'. Хм -- зайти внутрь?";
+ end
+ if w == 2 then
+ return 'Те, кто выходят, выглядят более довольными...';
+ end
+ end,
+ obj = { vobj(1, "подъезд", "У восточного угла находится небольшой {подъезд}."),
+ vobj(2, "люди", "Время от времени дверь подъезда хлопает впуская и выпуская {людей}.")},
+};
+}}}
+Как видим, vobj позволяет сделать легкую версию статического объекта, с которым тем не менее можно взаимодействовать (за счет определения обработчика act в сцене и анализа ключа объекта). vobj также вызывает метод used, при этом в качестве третьего параметра передается объект, воздействующий на виртуальный объект.
+
+Синтаксис vobj: vobj(ключ, имя, описатель); где ключ -- это цифра, которая будет передана обработчикам act/used сцены как второй параметр.
+
+Существует модификация объекта vobj -- vway. vway реализует ссылку.
+Синтаксис vway: vway(имя, описатель, сцена назначения); например:
+
+{{{
+ obj = { vway("дальше", "Нажмите {здесь}.", 'nextroom') }
+}}}
+
+Вы можете динамически заполнять сцену объектами vobj или vway с помощью методов add и del. Например:
+
+{{{
+ home.objs:add(vway("next", "{Дальше}.", 'next_room');
+-- some code here
+ home.objs:del("next");
+}}}
+
+Определена также упрощенная сцена vroom.
+Синтаксис: vroom(имя перехода, сцена назначения). Например:
+
+{{{
+ home.objs:add(vroom("идти на запад", 'mountains');
+}}}
+
+== 16. Динамические события ==
+
+Вы можете определять обработчики, которые выполняются каждый раз, когда время игры увеличивается на 1. Например:
+{{{
+mycat = obj {
+ nam = 'Барсик',
+ lf = {
+ [1] = 'Барсик шевелится у меня за пазухой.',
+ [2] = 'Барсик выглядывает из за пазухи.',
+ [3] = 'Барсик мурлычит у меня за пазухой.',
+ [4] = 'Барсик дрожит у меня за пазухой.',
+ [5] = 'Я чувствую тепло Барсика у себя за пазухой.',
+ [6] = 'Барсик высовывает голову из за пазухи и осматривает местность.',
+ },
+ life = function(s)
+ local r = rnd(6);
+ if r > 2 then
+ return;
+ end
+ r = rnd(6);
+ return s.lf[r];
+ end,
+....
+
+profdlg2 = dlg {
+ nam = 'Белин',
+ dsc = 'Белин бледен. Он смотрит на дробовик рассеянным взглядом.',
+ obj = {
+ [1] = phr('Я пришел за своим котом.',
+ 'Я выхватываю Барсика из руки Белина и засовываю себе за пазуху.',
+ [[inv():add('mycat'); lifeon('mycat')]]),
+....
+}}}
+Любой объект или сцена могут иметь свой обработчик life, который вызывается каждый раз при смене текущего времени игры, если объект или сцена были добавлены в список живых объектов с помощью lifeon. Не забывайте удалять живые объекты из списка с помощью lifeoff, когда они больше не нужны. Это можно сделать, например, в обработчике exit, или любым другим способом.
+
+== 17. Графика и музыка ==
+
+Графический интерпретатор анализирует атрибут сцены pic, и воспринимает его как путь к картинке, например:
+
+{{{
+home = room {
+ pic = 'gfx/home.png',
+ nam = 'дома',
+ dsc = 'Я у себя дома',
+};
+}}}
+
+Конечно, pic может быть функцией, расширяя возможности разработчика.
+Если в текущей сцене не определен атрибут pic, то берется атрибут game.pic. Если не определен и он, то картинка не отображается.
+
+Интерпретатор проигрывает в цикле текущую музыку, которая задается с помощью функции:
+set_music(имя музыкального файла).
+
+Например:
+{{{
+street = room {
+ pic = 'gfx/street.png',
+ enter = function()
+ set_music('mus/rain.ogg');
+ end,
+ nam = 'на улице',
+ dsc = 'На улице идет дождь.',
+};
+}}}
+
+get_music() возвращает текущее имя трека.
+
+Начиная с версии 0.7.7 в функцию set_music() можно передавать второй параметр -- количество проигрываний. Получить текущий счетчик можно с помощью get_music_loop. 0 - означает вечный цикл. 1..n -- количество проигрываний. -1 -- проигрывание текущего трека закончено.
+
+== 18. Полезные советы ==
+=== Статус игрока ===
+Код движка расположен в файле stead.lua. В своей игре вы можете переопределять любую функцию или объект lua, добиваясь того, что нужно для вашего творческого замысла. Кроме того, полезно знать особенности работы движка. Например, ниже представлена реализация статуса игрока в виде текста, который появляется в инвентаре, но не может быть выбран.
+
+{{{
+pl.Life = 10;
+pl.Power = 10;
+
+status = obj {
+ nam = 'Жизнь: '..pl.Life..',Сила: '..pl.Power,
+};
+inv():add('status');
+status.object_type = nil
+}}}
+
+=== goto из обработчика exit ==
+
+Если вы выполните goto из обработчика exit, то получите переполнение стека, так как goto снова и снова будет вызывать метод exit. Вы можете избавиться от этого, если вставите проверку, разрушающую рекурсию. Например:
+{{{
+exit = function(s, t)
+ if t == 'dialog' then return; end
+ return goto('dialog');
+}}}
+
+Вы можете также делать goto из обработчиков enter.
+
+=== Динамически создаваемые ссылки. ==
+Динамически создаваемые ссылки могут быть реализованы разным способом. Ниже приводится пример, основанный на использовании объектов vway. Для добавления ссылки можно использовать запись:
+{{{
+home.obj:add(vway('Дорога', 'Я заметил {дорогу}, ведущую в лес...', 'forest'));
+}}}
+Для удаления ссылки можно использовать метод del.
+{{{
+home.obj:del('Дорога');
+}}}
+Для определения наличия ссылки в сцене -- метод srch.
+{{{
+if not home.obj:srch('Дорога') then
+ home.obj:add(vway('Дорога', 'Я заметил {дорогу}, ведущую в лес...', 'forest'));
+end
+}}}
+Динамические ссылки удобно создавать в обработчике enter, или по мере необходимости в любом месте кода игры. Если ссылки создаются в текущей сцене, то последний пример можно упростить:
+{{{
+if not seen('Дорога') then
+ objs():add(vway('Дорога', 'Я заметил {дорогу}, ведущую в лес...', 'forest'));
+end
+}}}
+Кроме того, вы можете просто включать и выключать ссылки с помощью enable(), disable(), например:
+{{{
+ objs()[1]:disable();
+}}}
+
+Вы можете создавать выключенные vobj и vway следующим образом:
+{{{
+ obj = {vway('Дорога', 'Я заметил {дорогу}, ведущую в лес...', 'forest'):disable()},
+}}}
+И затем включать их по индексу в массиве obj:
+{{{
+ objs()[1]:enable();
+}}}
+
+=== Компиляция игр ===
+Если вы не хотите показывать исходный код своих игр, вы можете откомпилировать исходный код компилятором luac. Правда, при этом главный файл main.lua желательно оставлять текстовым, так его заголовок сканируется интерпретатором при выборе игры. Таким образом схема выглядит следующим образом (game.lua -- скомпилированный lua код):
+
+main.lua
+{{{
+-- $Name: Моя закрытая игра!$
+dofile("game.lua");
+}}}
+
+Кроме того, компиляция игр может быть использована для поиска ошибок в коде.
+
+=== Переключение между игроками ===
+Вы можете создать игру с несколькими персонажами и время от времени переключаться между ними (см. switch_pl). Но вы можете также использовать этот трюк для того, что бы иметь возможность переключаться между разными типами инвентаря.
+
+=== Использование первого параметра обработчика ===
+Пример кода.
+{{{
+knife = obj {
+ nam = 'камень',
+ dsc = 'На краю лежит {камень}.',
+ act = function()
+ objs():del('knife');
+ return 'Я толкнул камень, он сорвался и улетел вниз...';
+ end
+}}}
+
+Обработчик act мог бы выглядеть проще:
+{{{
+ act = function(s)
+ objs():del(s);
+ return 'Я толкнул камень, он сорвался и улетел вниз...';
+ end
+}}}
+=== Использование set_music ===
+Вы можете использовать set_music для проигрывания звуков, задавая второй параметр -- счетчик циклов проигрывания звукового файла.
+
+Вы можете написать для игры свой проигрыватель музыки, создав его на основе живого объекта, например:
+{{{
+-- играет треки в случайном порядке, начиная со 2-го
+tracks = {"mus/astro2.mod", "mus/aws_chas.xm", "mus/dmageofd.xm", "mus/doomsday.s3m"}
+mplayer = obj {
+ nam = 'плеер',
+ life = function(s)
+ local n = get_music();
+ local v = get_music_loop();
+ if not n or not v then
+ set_music(tracks[2], 1);
+ elseif v == -1 then
+ local n = get_music();
+ while get_music() == n do
+ n = tracks[rnd(4)]
+ end
+ set_music(n, 1);
+ end
+ end,
+};
+lifeon('mplayer');
+}}}
+
+Вы можете использовать функции get_music_loop и get_music, для того, чтобы запоминать прошлую мелодию, и потом восстанавливать ее, например:
+
+{{{
+function save_music(s)
+ s.OldMusic = get_music();
+ s.OldMusicLoop = get_music_loop();
+end
+
+function restore_music(s)
+ set_music(s.OldMusic, s.OldMusicLoop);
+end
+
+-- ....
+enter = function(s)
+ save_music(s);
+end,
+exit = function(s)
+ restore_music(s);
+end,
+-- ....
+
+}}}
+
+Начиная с версии 0.8.5 функции save_music и restore_music уже присутствуют в библиотеке.
+
+=== Живые объекты ===
+Если вашему герою нужен друг, одним из способов может стать метод life этого персонажа, который всегда переносит объект в локацию игрока:
+{{{
+horse = obj {
+ nam = 'лощадь',
+ dsc = 'Рядом со мной стоит {лошадь}.',
+ life = function(s)
+ if not seen('horse') then
+ move('horse', here(), s.__where);
+ s.__where = pl.where;
+ end
+ end,
+};
+lifeon('horse');
+}}}
+
+=== Отладка ===
+Для того, чтобы во время ошибки увидеть стек вызовов функций lua, вы можете запустить sdl-instead с параметром -debug. При этом в windows версии интерпретатора будет создана консоль отладки.
+
+Вы можете отлаживать свою игру вообще без instead. Например, вы можете создать следующий файл game.lua:
+{{{
+dofile("/usr/share/games/stead/stead.lua"); -- путь к stead.lua
+dofile("main.lua"); -- ваша игра
+game:ini();
+iface:shell();
+}}}
+И запустите игру в lua: lua game.lua.
+При этом игра будет работать в примитивном shell окружении. Полезные команды: ls, go, act, use....
+
+== 19. Темы для sdl-instead ==
+
+Графический интерпретатор поддерживает механизм тем. Тема представляет из себя каталог, с файлом theme.ini внутри.
+
+Тема, которая является минимально необходимой -- это тема default. Эта тема всегда загружается первой. Все остальные темы наследуются от нее и могут частично или полностью заменять ее параметры. Выбор темы осуществляется пользователем через меню настроек, однако конкретная игра может содержать собственную тему и таким образом влиять на свой внешний вид. В этом случае в каталоге с игрой должен находиться свой файл theme.ini. Тем не-менее пользователь свободен отключить данный механизм, при этом интерпретатор будет предупреждать о нарушении творческого замысла автора игры.
+
+Синтаксис theme.ini очень прост.
+
+<параметр> = <значение>
+
+или
+
+; комментарий
+
+Значения могут быть следующих типов: строка, цвет, число.
+
+Цвет задается в форме #rgb, где r g и b компоненты цвета в шестнадцатеричном виде. Кроме того некоторые основные цвета распознаются по своим именам. Например: yellowgreen, или violet.
+
+Параметры могут принимать значения:
+
+scr.w = ширина игрового пространства в пикселях (число)
+
+scr.h = высота игрового пространства в пикселях (число)
+
+scr.col.bg = цвет фона
+
+scr.gfx.bg = путь к картинке фонового изображения (строка)
+
+scr.gfx.use = путь к картинке-индикатору режима использования (строка)
+
+scr.gfx.pad = размер отступов к скролл-барам и краям меню (число)
+
+scr.gfx.x, scr.gfx.y, scr.gfx.w, scr.gfx.h = координаты, ширина и высота окна изображений. Области в которой располагается картинка сцены. Интерпретация зависит от режима расположения (числа)
+
+win.gfx.h - синоним scr.gfx.h (для совместимости)
+
+scr.gfx.mode = режим расположения (строка fixed, embedded или float). Задает режим изображения. embedded -- картинка является частью содержимого главного окна, параметры win.x, win.y, win.w игнорируются. float -- картинка расположена по указанным координатам (win.x, win.y) и масштабируется к размеру win.w x win.h если превышает его. fixed -- картинка является частью сцены как в режиме embedded, но не скроллируется вместе с текстом а расположена непосредственно над ним.
+
+win.x, win.y, win.w, win.h = координаты, ширина и высота главного окна. Области в которой располагается описание сцены (числа)
+
+win.fnt.name = путь к файлу-шрифту (строка)
+
+win.fnt.size = размер шрифта главного окна (размер)
+
+win.gfx.up, win.gfx.down = пути к файлам-изображениям скорллеров вверх/вниз для главного окна (строка)
+
+win.col.fg = цвет текста главного окна (цвет)
+
+win.col.link = цвет ссылок главного окна (цвет)
+
+win.col.alink = цвет активных ссылок главного окна (цвет)
+
+inv.x, inv.y, inv.w, inv.h = координаты, высота и ширина области инвентаря. (числа)
+
+inv.mode = строка режима инвентаря (horizontal или vertical). В горизонтальном режиме инвентаря в одной строке могут быть несколько предметов. В вертикальном режиме, в каждой строке инвентаря содержится только один предмет. (число)
+
+inv.col.fg = цвет текста инвентаря (цвет)
+
+inv.col.link = цвет ссылок инвентаря (цвет)
+
+inv.col.alink = цвет активных ссылок инвентаря (цвет)
+
+inv.fnt.name = путь к файлу-шрифту инвентаря (строка)
+
+inv.fnt.size = размер шрифта инвентаря (размер)
+
+inv.gfx.up, inv.gfx.down = пути к файлам-изображениям скорллеров вверх/вниз для инвентаря (строка)
+
+menu.col.bg = фон меню (цвет)
+
+menu.col.fg = цвет текста меню (цвет)
+
+menu.col.link = цвет ссылок меню (цвет)
+
+menu.col.alink = цвет активных ссылок меню (цвет)
+
+menu.col.alpha = прозрачность меню 0-255 (число)
+
+menu.col.border = цвет бордюра меню (цвет)
+
+menu.bw = толщина бордюра меню (число)
+
+menu.fnt.name = путь к файлу-шрифту меню (строка)
+
+menu.fnt.size = размер шрифта меню (размер)
+
+menu.gfx.button = путь к файлу изображению значка меню (строка)
+
+menu.button.x, menu.button.y = координаты кнопки меню (числа)
+
+snd.click = путь к звуковому файлу щелчка (строка)
+
+include = имя темы (последний компонент в пути каталога) (строка)
+
+Кроме того, заголовок темы может включать в себя комментарии с тегами. На данный момент существует только один тег: $Name:, содержащий UTF-8 строку с именем темы. Например:
+{{{
+; $Name:Новая тема$
+; модификация темы book
+include = book
+scr.gfx.h = 500
+}}}
+
+Интерпретатор выполняет поиск тем в каталоге themes. Unix версия кроме этого каталога, просматривает также каталог ~/.instead/themes/
+
+
+TODO
+Полный список объектов и методов.
diff --git a/games/Makefile b/games/Makefile
index 3a7e598..28b1e40 100644
--- a/games/Makefile
+++ b/games/Makefile
@@ -5,6 +5,6 @@ install:
for f in *; do \
if [ ! -d $$f ]; then continue; fi;\
install -d -m0755 $(GAMESPATH)/$$f;\
- tar -c -C $$f . | tar -x -C $(GAMESPATH)/$$f;\
+ tar --exclude=".svn" -c -C $$f . | tar -x -C $(GAMESPATH)/$$f;\
done
clean:
diff --git a/games/Makefile.windows b/games/Makefile.windows
new file mode 100644
index 0000000..5fa58a5
--- /dev/null
+++ b/games/Makefile.windows
@@ -0,0 +1,11 @@
+all:
+install:
+ if not exist ..\bin\games\cat mkdir ..\bin\games\cat
+ copy cat ..\bin\games\cat
+ if not exist ..\bin\games\cat\gfx mkdir ..\bin\games\cat\gfx
+ copy cat\gfx ..\bin\games\cat\gfx
+ if not exist ..\bin\games\cat\mus mkdir ..\bin\games\cat\mus
+ copy cat\mus ..\bin\games\cat\mus
+ if not exist ..\bin\games\tutorial mkdir ..\bin\games\tutorial
+ copy tutorial ..\bin\games\tutorial
+clean:
diff --git a/games/cat/ep1.lua b/games/cat/ep1.lua
index bb1b2b6..f85ca7b 100644
--- a/games/cat/ep1.lua
+++ b/games/cat/ep1.lua
@@ -2,11 +2,11 @@ mywear = obj {
nam = 'ватник',
dsc = function(s)
if here() == stolcorridor then
- local st='';
+ local st='.';
if not have('gun') then
- st = 'Под которым спрятан дробовик.';
+ st = ', под которым спрятан дробовик.';
end
- return 'А еще на вешалке висит мой {ватник}.'..st;
+ return 'А еще на вешалке висит мой {ватник}'..st;
else
return 'На гвоздике, вбитом в сосновую дверь, висит {ватник}.';
end
@@ -109,7 +109,7 @@ gun = obj {
return 'Я попытался спрятать дробовик в одежду, но он слишком длинный.'
else
s._hidden = true;
- return 'Теперь я могу спрятать обрез в одежде!.';
+ return 'Теперь я могу спрятать обрез в одежде!';
end
end
end
@@ -374,7 +374,7 @@ home = room {
if seen(mycat) then
move('mycat','forest');
return [[
-Когда я выходил из хижины Барсик внезапно проснулся и бросился мне под ноги.
+Когда я выходил из хижины, Барсик внезапно проснулся и бросился мне под ноги.
Я погладил его за ушами -- Значит едем вместе?
]]
end
@@ -562,7 +562,7 @@ shop = room {
village.obj:del('truck');
village.obj:del('mycat');
return [[
-Когда я заходил в магазин я чуть не с толкнулся с неприятным типом в сером пальто и
+Когда я заходил в магазин, я чуть не с толкнулся с неприятным типом в сером пальто и
шляпе с длинными полями... Он извинился каким-то шипящим голосом и сделал вид, что приподнимает шляпу... Из под
ее полей блеснули белые зубы... Дойдя до прилавка я услышал звук запускающегося двигателя.]];
end
@@ -730,8 +730,8 @@ guarddlg = dlg {
[2] = phr('Я забыл свой пропуск -- можно мне зайти?','-- Нет...', 'poff(1); pon(3);'),
[3] = _phr('Вы знаете Белина? У него мой кот -- мне нужно его забрать...', '-- Нет пропуска?', 'pon(4)'),
[4] = _phr('Я просто пришел забрать своего кота! Дайте телефон Белина.',
-[[Глаза охранника меняют свой цвет. Уголки губ поднимаются наверх -- вот что, господин хороший -- я так понял,
-пропуска у вас нет, идите-ка отсюда пока можете...]], 'pon(5, 6)'),
+[[Глаза охранника меняют свой цвет. Уголки губ поднимаются наверх -- вот что, господин хороший, -- я так понял,
+пропуска у вас нет, идите-ка отсюда, пока можете...]], 'pon(5, 6)'),
[5] = _phr('Ну все, щас я дам по твоей роже...', 'Рука охранника тянется к автомату. ', 'poff(6); return guardreact();'),
[6] = _phr('Ладно, я пошел...', '-- Не спеши - охранник уже не скрывает свою ухмылку - ты мне не нравишься...','poff(5); return guardreact()'),
[7] = _phr('Щас я вас всех перестреляю из своего дробовика...', 'На этот раз охранник даже не отвечает. Его налитые кровью глаза красноречивей всяких слов.','return guardreact()'),
@@ -740,7 +740,7 @@ guarddlg = dlg {
guard = obj {
nam = 'охрана',
dsc = [[
-В будке сидит {охрана}. Кажется она вооружена автоматами калашникова.
+В будке сидит {охрана}. Кажется, она вооружена автоматами калашникова.
]],
act = function(s)
return goto('guarddlg');
@@ -762,13 +762,13 @@ inst = room {
учреждение. Позади территории института находятся железнодорожные пути. ]],
act = function(s, w)
if w == 1 then
- return 'Высота стены около 5 метров. Но этого мало -- сверху проходит колючая проволока -- думаю она под напряжением...';
+ return 'Высота стены около 5 метров. Но этого мало -- сверху проходит колючая проволока -- думаю, она под напряжением...';
end
if w == 2 then
return 'Нет, Владимир был прав... Это какой-то военный штаб...';
end
if w == 3 then
- return 'Да -- это похоже тот самый фургон, в котором человек в сером пальто увез моего Барсика.';
+ return 'Да -- это, похоже, тот самый фургон, в котором человек в сером пальто увез моего Барсика.';
end
end,
used = function(s, w, b)
@@ -889,7 +889,7 @@ backwall = room {
if f == 'inmycar' then
return 'Отлично... Кажется удалось добраться незамеченным...'..' '..st;
end
- return 'Плутая по снежному полю я добрался до задней стены.'..' '..st;
+ return 'Плутая по снежному полю, я добрался до задней стены.'..' '..st;
end,
nam = 'восточная стена института',
dsc = 'Я нахожусь у задней стороны института.',
diff --git a/games/cat/ep2.lua b/games/cat/ep2.lua
index 5c74461..0e20683 100644
--- a/games/cat/ep2.lua
+++ b/games/cat/ep2.lua
@@ -76,8 +76,8 @@ alienwear = obj {
'Холодновато, но стильно!',
'Очень красиво смотрится на фоне снега!',
'Длиннополое пальто -- это ретро!',
- 'Я терминатор!',
- 'Я пацифист!',
+ 'Я -- терминатор!',
+ 'Я -- пацифист!',
'Пиджачок сидит на мне как влитой!',
'Рокн рол мертв, а я еше нет!',
'Когда-то я занимался альпинизмом!',
@@ -88,7 +88,7 @@ alienwear = obj {
inv = function(s)
if s._num == 7 and not have('card') then
inv():add('card');
- return 'Немного покопавшись в карманах косухи я нашел карточку.';
+ return 'Немного покопавшись в карманах косухи, я нашел карточку.';
end
return s.xinv[s._num];
end,
@@ -99,7 +99,7 @@ garderob = obj {
dsc = 'На правой стороне коридора висят {вешалки} с одеждой.',
act = function(s, w)
if have('mywear') or have('alienwear') then
- return 'Здесь много людей, я не думаю что я смогу сделать это незаметно.';
+ return 'Здесь много людей, я не думаю, что я смогу сделать это незаметно.';
elseif tonumber(w) and tonumber(w) > 0 and tonumber(w) <= 8 then
if not me()._walked then
return 'Это будет слишком заметно...';
@@ -143,7 +143,7 @@ garderob = obj {
portrait = obj {
nam = 'портреты',
dsc = 'По стенам развешены большие {портреты} в деревянных рамах.',
- act = 'Гм... На портретах одно и тоже лицо! Улыбающееся холодной улыбкой лицо человека лет сорока с холодным взглядом.',
+ act = 'Гм... На портретах одно и тоже лицо! Улыбающееся холодной улыбкой лицо человека, лет сорока, с пустым, ничего не выражающим взглядом.',
};
salo = obj {
@@ -286,15 +286,15 @@ kitchendlg = dlg {
[3] = _phr('Хм... Из отдела искривления пространства...', '-- Старье!', [[pon(6);poff(4,5)]]),
[4] = _phr('Ааа... Отдел квантовых скачков..', '-- Хм? Не слышал о таком.', [[pon(6);poff(3,5)]]),
- [5] = _phr('ЭЭэ... Отдел изучения квазипространства!', '-- Ого! Прикольно!', [[pon(6);poff(3,4)]]),
+ [5] = _phr('Эээ... Отдел изучения квазипространства!', '-- Ого! Прикольно!', [[pon(6);poff(3,4)]]),
[6] = _phr('Хм... ', '-- А у тебя какой уровень секретности?', [[pon(7,8)]]),
[7] = _phr('Супер секретно!', '-- Ух ты! ... ', [[poff(8); pon(9)]]),
[8] = _phr('Анонимный.', '-- Да? Не слышал о таком, наверное это более секретный уровень, чем мой...',
[[poff(7); pon(9)]]),
[9] = _phr('Мэээ...', '-- Меня зовут Илья... Просто Илья -- тянет худую руку парень -- а тебя как?', [[pon(10, 11, 12)]]),
[10] = _phr('Пп.. Пк... Пупкин... Василий Пупкин.', '-- Редкая фамилия!', [[poff(11,12); pon(13)]]),
- [11] = _phr('Сережка.', '-- Дай пятерню братан!', [[poff(10,12); pon(13)]]),
- [12] = _phr('Гоша...', '-- Ну, будем знакомы Гошка!', [[poff(10,11); pon(13)]]),
+ [11] = _phr('Сережка.', '-- Дай пятерню, братан!', [[poff(10,12); pon(13)]]),
+ [12] = _phr('Гоша...', '-- Ну, будем знакомы, Гошка!', [[poff(10,11); pon(13)]]),
[13] = _phr('Кхмм...',
[[-- Какой ты странный... Но это не важно. Мы все здесь -- Илья сделал выразительное лицо -... Мне тут поручили
распространить приглашения на закрытую лекцию Белина... Только для друзей... Ты мне нравишься, да и по уровню
@@ -405,7 +405,7 @@ sside = room {
end,
way = {'eside','wside'},
obj = { vobj(1, "подъезд", "У восточного угла находится небольшой {подъезд}."),
- vobj(2, "люди", "Время от времени дверь подъезда хлопает впуская и выпуская {людей}.")},
+ vobj(2, "люди", "Время от времени дверь подъезда хлопает, впуская и выпуская {людей}.")},
exit = function(s, t)
if t == 'eside' then
return 'Если я пойду туда, я попаду в зону видимости пулеметных вышек.', false
@@ -420,7 +420,7 @@ nside = room {
way = {'eside','wside' },
act = function(s, w)
if w == 1 then
- return 'Да -- водосточная труба... Довольно крепкая. Но вряд-ли я смогу взобраться по ней наверх.';
+ return 'Да -- водосточная труба... Довольно крепкая. Но вряд ли я смогу взобраться по ней наверх.';
end
end,
obj = { vobj(1, 'труба', 'Водосточная {труба} проходит по восточному углу здания.')},
@@ -434,7 +434,7 @@ wside = room {
way = {'entrance', 'nside','sside' },
act = function(s, w)
if w == 1 then
- return 'Тот самый фургон с которого все началось...';
+ return 'Тот самый фургон, с которого все началось...';
end
if w == 5 then
return 'Она начинается слишком высоко, к тому-же снизу она закрыта на замок. Возможно, это будет кому-то полезно при пожаре, хотя я лично сомневаюсь...'
@@ -535,7 +535,7 @@ entrance = room {
way = { 'wside' },
enter = function(s, f)
if have('gun') and f == 'wside' and not gun._hidden then
- return 'Мне кажется там внутри возникнет множество вопросов по-поводу моего дробовика... Я должен его как-то спрятать.', false
+ return 'Мне кажется, там внутри возникнет множество вопросов по-поводу моего дробовика... Я должен его как-то спрятать.', false
end
end,
exit = function(s, t)
@@ -744,7 +744,7 @@ stol = obj {
if w == 'vent' or w == 'resh' then
inv():del('stol');
stoly._moved = true;
- return 'Напрягая свои силы я сдвигаю один из столов в центр комнаты.';
+ return 'Напрягая свои силы, я сдвигаю один из столов в центр комнаты.';
end
end
};
@@ -782,7 +782,7 @@ eroom = room {
dsc = [[Я нахожусь в небольшой комнате с бежевыми стенами.]],
enter = function(s, f)
if f == 'cor3' then
- return [[Открыв дверь я заглядываю внутрь комнаты. Ухх... Пусто! Можно осмотреться...]];
+ return [[Открыв дверь, я заглядываю внутрь комнаты. Ухх... Пусто! Можно осмотреться...]];
end
if f == 'toilet' then
return 'Ну что же... Я поднимаю железную решетку в полу туалета и лезу в темноту... Через несколько минут я уже спрыгиваю из вентиляционного отверстия на стол, и спускаюсь на пол.';
@@ -872,7 +872,7 @@ switch = obj {
if not cor3._locked then
return [[Я перевожу выключатель в позицию <<выключено>> и иду вдоль стен, когда
одна из дверей за мной вдруг открывается и старческий голос звучит на весь коридор -- Безобразие!!! Включите обратно!!! --
-мне приходиться вернуться к выключателю и перевести его в позицию <<включено>>.]];
+мне приходится вернуться к выключателю и перевести его в позицию <<включено>>.]];
end
vent._off = true;
return 'Выключаю!';
@@ -890,7 +890,7 @@ cor3 = room {
dsc = 'Длинный коридор идет до самой стены здания. На потолке тускло горят лампы дневного света. На полу постелена зеленая ковровая дорожка.',
act = function(s, w)
if w == 1 then
- return 'Я подхожу к одной из дверей и заглядываю в окошко-иллюминатор... Люди в белых костюмах, словно пчелы снуют у причудливых аппаратов. -- Наверное это лаборатории -- догадываюсь я.';
+ return 'Я подхожу к одной из дверей и заглядываю в окошко-иллюминатор... Люди в белых костюмах, словно пчелы, снуют у причудливых аппаратов. -- Наверное, это лаборатории -- догадываюсь я.';
end
if not tonumber(w) then
return nil, false
@@ -906,7 +906,7 @@ cor3 = room {
return goto('room3x');
end
if w == 7 then
- return 'Окно выходит на южную сторону... Темно -- ничего не видно кроме снежинок, ударяющихся о стекло...';
+ return 'Окно выходит на южную сторону... Темно -- ничего не видно, кроме снежинок, ударяющихся о стекло...';
end
if w == 8 then
return 'Зайти?';
@@ -967,7 +967,7 @@ umyvalnik = obj {
me()._mylo = false;
return 'Я смываю мыло со своего лица...';
end
- return 'Я пью хлорированную воду жадными глотками... Да -- это не та вода из ручья которую я пью в лесу...';
+ return 'Я пью хлорированную воду жадными глотками... Да -- это не та вода из ручья, которую я пью в лесу...';
end,
used = function(s, w)
if w == 'mylo' then
@@ -1016,7 +1016,7 @@ floor3 = room {
end
if w == 2 then
if not s._unlocked then
- return 'Металл обитый кожей. Дверь снабжена считывателем электронных карт. Надпись на двери: <<Уровень:3 Категория:Прикладная физика>>';
+ return 'Металл обитый кожей. Дверь снабжена считывателем электронных карт. Надпись на двери: <<Уровень:3 Категория: Прикладная физика>>';
end
return goto('cor3');
end
@@ -1369,13 +1369,13 @@ hall41 = room {
pic = 'gfx/hall1.png',
act = function(s, w)
if w == 1 then
- return 'Глядя в ночную темноту я с тоской вспоминаю Барсика...';
+ return 'Глядя в ночную темноту, я с тоской вспоминаю Барсика...';
end
if w == 2 then
return 'Примерно такие были у нас в институте, когда я... Ладно...';
end
if w == 3 then
- return 'Все, что я мог бы вспомнить я благополучно забыл.';
+ return 'Все, что я мог бы вспомнить, я благополучно забыл.';
end
end,
obj = {
@@ -1404,7 +1404,7 @@ cor4 = room {
return 'Я тоскливо гляжу в ночную тьму... Я понимаю -- что очень устал... Но я должен идти...';
end
if w == 12 then
- return 'Эта дверь, как и многие здесь, снабжена считывателем смарткарт. На нем горит красная лампочка.';
+ return 'Эта дверь, как и многие здесь, снабжена считывателем смарт-карт. На нем горит красная лампочка.';
end
if tonumber(w) >=5 and tonumber(w) <=9 then
room4x._num = w - 4;
@@ -1517,7 +1517,7 @@ floor5 = room {
vobj(4, 'информация', 'Я вижу две двери, ведущие в южный и северный коридоры. На южной {двери} написано: <<уровень 5, категория: информация>>.'),
vobj(5, 'красная дверь', 'На северной {двери} нет надписей. Это массивная дверь, обитая красной кожей.'),
- vobj(6, 'охранник', 'Между проходами в коридоры установлен стол, за котором сидит {охранник},');
+ vobj(6, 'охранник', 'Между проходами в коридоры установлен стол, за которым сидит {охранник},');
},
way = { 'lift' },
};
diff --git a/games/cat/ep3.lua b/games/cat/ep3.lua
index 4a01b11..ffe7855 100644
--- a/games/cat/ep3.lua
+++ b/games/cat/ep3.lua
@@ -17,7 +17,7 @@ lection = room {
Согласно квантовой механике, если над ядром не производится наблюдения, то его состояние описывается суперпозицией (смешением) двух состояний — распавшегося ядра и нераспавшегося ядра, следовательно, кот, сидящий в ящике, и жив, и мёртв одновременно. -- Белин повышает голос. -- можно сказать, что это просто игры разума, отвлеченная лирика, но я покажу и докажу, что это не совсем так... ^^
--- Итак, если ящик открыть, то экспериментатор обязан увидеть только какое-нибудь одно конкретное состояние — <<ядро распалось, кот мёртв>> или <<ядро не распалось, кот жив>>. Сам Шредингер думал, что его парадокс доказывает несостоятельность квантовой механики, но мы то с вами знаем, что квантовая механика и есть истинное представление о нашем мире -- снова повышает тон голоса Белин -- и вот независимо друг от друга, что доказывает отчасти истинность предположения -- Ганс Моравек в 1987 и Бруно Маршал в 1988 рассмотрели ситуацию с точки зрения самого кота!^^
+-- Итак, если ящик открыть, то экспериментатор обязан увидеть только какое-нибудь одно конкретное состояние — <<ядро распалось, кот мёртв>> или <<ядро не распалось, кот жив>>. Сам Шредингер думал, что его парадокс доказывает несостоятельность квантовой механики, но мы то с вами знаем, что квантовая механика и есть истинное представление о нашем мире -- снова повышает тон голоса Белин -- и вот, независимо друг от друга, что доказывает отчасти истинность предположения -- Ганс Моравек в 1987 и Бруно Маршал в 1988 рассмотрели ситуацию с точки зрения самого кота!^^
-- Если верна многомировая интерпретация Эверетта, то в результате каждого проведенного эксперимента с котом вселенная расщепляется на две вселенных, в одной из которых кот остается жив, а в другой погибает. В мирах, где кот умирает, он перестает существовать. Напротив, с точки зрения неумершего кота, эксперимент будет продолжаться, не приводя к исчезновению кота. Это происходит потому, что в любом ответвлении кот способен наблюдать результат эксперимента лишь в том мире, в котором он выживает. И если многомировая интерпретация верна, то кот может заметить, что он никогда не погибнет в ходе эксперимента... -- Белин замолкает и осматривает зал... ^^
@@ -27,7 +27,7 @@ lection = room {
Мы все с вами тяжело работали этот год, под четким руководством... -- тут Белин бросил взгляд в сторону портретов -- и должен вам сказать, что информации в нашем информационном центре -- Белин посмотрел в потолок -- достаточно, чтобы доказать, я повторяю, научно доказать теоретически и экспериментально истинность многомировой интерпретации... -- Но что это значит для нас? -- Вы не можете этого видеть, но -- Белин смотрит на часы -- уже через несколько минут состав с ураном прибывает к задним воротам института... Урана хватит для того, чтобы обеспечить каждого из вас ядерной бомбой. Так как вы скоро убедитесь в том, что квантовое бессмертие это реальность, то каждый из нас сможет стать непобедимым террористом!!! Вселенная расщепится на множество миров, в каждом из который Вы -- палец Белина указывает в зал -- будете его диктатором и господином!!! -- Белин почти кричал...^^
-Зал не выдержал и взревел. Люди вставали и хлопали... Их глаза горели каким-то бешеным огнем... О Боже, подумал я -- это какое-то наваждение... Мои ноги не слушались меня -- я сидел на своем месте и не мог пошевелиться...^^
+Зал не выдержал и взревел. Люди вставали и хлопали... Их глаза горели каким-то бешеным огнем... О Боже, -- подумал я -- это какое-то наваждение... Мои ноги не слушались меня -- я сидел на своем месте и не мог пошевелиться...^^
Но я отвлекся -- говорит Белин -- продолжим наш опыт. С этими словами он достал из под стола живой комочек... Это был мой Барсик... -- Сейчас я помещу эту кошку в ящик и мы с вами... -- красная пелена застилает мои глаза...
]],
@@ -65,14 +65,14 @@ lection = room {
end
end,
obj = {
- vobj(1, 'дальше', '{Дальше}'),
+ vobj(1, 'дальше', '{Дальше}.'),
};
};
profdlg = dlg {
nam = '!!!',
pic = 'gfx/me.png',
- dsc = 'Я собираюсь с силами встаю и во всю глотку кричу...',
+ dsc = 'Я собираюсь с силами, встаю и во всю глотку кричу...',
obj = {
[1] = phr('Это кот, а не кошка!',
'-- Рука Белина останавливается -- его взгляд фокусируется на мне -- он узнает меня!! -- Охрана -- в зале посторонний!!! Убе... Уберите его!!! -- кричит он..',
@@ -105,7 +105,7 @@ gdlg1 = dlg {
[1] = phr('Положи свое ружье прикладом вперед на стол и толкни его сюда..',
'Охранник неуверенно смотрит на меня..',
[[pon(2)]]),
- [2] = _phr('Я сказал на стол ружье!!! -- я посильнее надавливаю стволами на Белина -- он близок к обмороку.', 'Охранник оторожно кладет помповое ружье на стол и толкает его ко мне... -- я быстро забираю ружье. Теперь в левой руке у меня обрез, в правом -- помповое ружье.',
+ [2] = _phr('Я сказал на стол ружье!!! -- я посильнее надавливаю стволами на Белина -- он близок к обмороку.', 'Охранник осторожно кладет помповое ружье на стол и толкает его ко мне... -- я быстро забираю ружье. Теперь в левой руке у меня обрез, в правом -- помповое ружье.',
[[pon(3); inv():add('shotgun')]]),
[3] = phr('Не нравилось тебе мое лицо да?? Дааа???',
'Охранник молчит, на его лбу выступает пот...',
@@ -177,7 +177,7 @@ professor = obj {
s._gun = true;
objs():add('guardian');
gun._hidden = false;
- return 'Я достаю обрез из-под одежды и, перепрыгивая через стол, бросаюсь к Белину.';
+ return 'Я достаю обрез из-под одежды и, перепрыгивая через стол, бросаюсь к Белину.';
end
end,
};
@@ -316,7 +316,7 @@ lest = obj {
s._seen = true;
return 'Это же пожарная лестница!!!';
end
- return 'Прыгать лили нет? Вот в чем вопрос...';
+ return 'Прыгать или нет? Вот в чем вопрос...';
end,
};
@@ -328,7 +328,7 @@ window = room {
return 'в окно';
end,
pic = 'gfx/fromwin1.png',
- enter = "Это безумие, но все-же я бросаюсь к окну... За спиной я слышу рев толпы...";
+ enter = "Это безумие, но все же я бросаюсь к окну... За спиной я слышу рев толпы...";
dsc = 'Я стою на подоконнике и всматриваюсь в ночную пустоту.',
obj = {
'lest',
@@ -378,7 +378,7 @@ up = room {
s._num = s._num + 1;
if s._num == 2 then
lifeon('ladder');
- return 'Внезапно ночную тьму разрезает луч прожектора и тишину нарушает вой сирены... Похоже, внизу меня заметили...', false;
+ return 'Внезапно, ночную тьму разрезает луч прожектора и тишину нарушает вой сирены... Похоже, внизу меня заметили...', false;
end
if s._num > 4 then
ladder.way:del('up');
@@ -489,7 +489,7 @@ fire = obj {
return 'Я кидаю бумажку на горящий ковер...';
end
kover._fire = true;
- return 'Я кладу бумагу на ковер... Волоски ковра вспыхивают... Похоже начинается пожар..';
+ return 'Я кладу бумагу на ковер... Волоски ковра вспыхивают... Похоже, начинается пожар..';
end
};
@@ -701,7 +701,7 @@ escape2 = room {
enter = function(s, f)
if f == 'room5' then
lifeon('escape2');
- return 'В бессилии я бью прикладом в ненавистную дверь. И вдруг, через несколько секунд слышу, как кто-то подходит к двери с внешней стороны... Это охранник!!! Писк срабатывания считывателя и вот дверь открывается. Охранник пятится -- ему в грудь упирается ствол помпового ружья. Мы выходим на площадку пятого этажа.';
+ return 'В бессилии я бью прикладом в ненавистную дверь. И вдруг, через несколько секунд слышу, как кто-то подходит к двери с внешней стороны... Это охранник!!! Писк срабатывания считывателя -- и вот, дверь открывается. Охранник пятится -- ему в грудь упирается ствол помпового ружья. Мы выходим на площадку пятого этажа.';
end
if f == 'krysha' then
lifeon('escape2');
@@ -710,7 +710,7 @@ escape2 = room {
life = function(s)
s._timer = s._timer + 1;
if s._timer == 3 then
- return 'Внезапно на этаже раздается звук сирены. -- Внимание!!! На пятом этаже лицо с нулевым уровнем допуска. Повторяю... -- льется голос из невидимых динамиков.';
+ return 'Внезапно, на этаже раздается звук сирены. -- Внимание!!! На пятом этаже лицо с нулевым уровнем допуска. Повторяю... -- льется голос из невидимых динамиков.';
end
if s._timer > 3 then
return '-- На пятом этаже лицо с нулевым уровнем доступа!!! -- от воя сирены меня начинает мутить.';
@@ -756,7 +756,7 @@ escape2 = room {
return 'Там пламя!', false
end
if t == 'lift' then
- return 'Я вижу что лампочки вызова всех лифтов горят. Скорее всего это означает, что сюда поднимается охрана... Надо спешить!', false;
+ return 'Я вижу, что лампочки вызова всех лифтов горят. Скорее всего это означает, что сюда поднимается охрана... Надо спешить!', false;
end
if t == 'krysha' then
lifeoff('escape2');
@@ -809,7 +809,7 @@ hall5 = room {
return 'Я провожу ладонью по скользкой поверхности одной из колонн... Мрамор!';
end
if w == 3 then
- return 'Но уж эта то люстра точно из горного хрусталя.';
+ return 'Но уж эта-то люстра точно из горного хрусталя.';
end
if w == 4 then
return 'Темно... Хотя... Что это? Мне кажется, что у задней стороны института стоит поезд.';
@@ -845,7 +845,7 @@ hall5 = room {
vobj(5,'западные окна', 'Разбитое {окно} находится слева от меня.'),
vobj(6,'небольшая дверь', 'В конце зала, в его северной части, я вижу небольшую деревянную {дверь}.'),
vobj(7,'входная дверь', 'За моей спиной входная {дверь}.'),
- vobj(8,'картины', 'По стенам развешены {картины} в красивых рамах.'),
+ vobj(8,'картины', 'По стенам развешаны {картины} в красивых рамах.'),
vobj(9,'диваны', 'У стен расставлены мягкие {диваны}.'),
},
way = { 'krysha' },
@@ -893,9 +893,9 @@ gudlg = dlg {
enter = function(s)
lifeoff('mycat');
inv():del('shotgun');
- return [[Странно... Дверь не закрыта... Я осторожно открываю дверь и вхожу в комнату.^^Внезапно я обнаруживаю, что на меня смотрит дуло револьвера. -- Браво, браво, браво -- говорит мне человек в кресле, владелец револьвера. -- Я уже заждался. Тот самый лесник? Ну что же, подождем охрану. А пока -- брось ружье на пол. Мне ничего не остается, как сделать то - что он сказал.]];
+ return [[Странно... Дверь не закрыта... Я осторожно открываю дверь и вхожу в комнату.^^Внезапно я обнаруживаю, что на меня смотрит дуло револьвера. -- Браво, браво, браво -- говорит мне человек в кресле, владелец револьвера. -- Я уже заждался. Тот самый лесник? Ну что же, подождем охрану. А пока -- брось ружье на пол. Мне ничего не остается, как сделать то, что он сказал.]];
end,
- dsc = [[Передо мной то самое лицо. Лицо с портретов, которые увешивают почти все комнаты этого здания. Лицо спокойное, ничего не выражающее. Слабая улыбка на губах. Надо тянуть время... И я спрашиваю у него:]],
+ dsc = [[Передо мной то самое лицо. Лицо с портретов, которыми увешаны почти все комнаты этого здания. Лицо спокойное, ничего не выражающее. Слабая улыбка на губах. Надо тянуть время... И я спрашиваю у него:]],
obj = {
[1] = phr('Может, поговорим?',
'Гм... Ну о чем нам говорить? О чем мне говорить с лесником?', [[pon(2)]]),
@@ -909,10 +909,10 @@ gudlg = dlg {
[5] = _phr('Ложь!',
'А что если? Представь, что если?... Ты же хакер да? Любишь продумывать все заранее...',
[[pon(6);poff(9)]]),
- [6] = _phr('Нет! Это не может быть правдой! Если это правда -- рано или поздно мир будет обречен! Тоггда...',
+ [6] = _phr('Нет! Это не может быть правдой! Если это правда -- рано или поздно мир будет обречен! Тогда...',
'-- Да, ты правильно понял... Тогда есть только ТЫ!!! Послушай себя -- кто дал тебе этот ответ? Не его ли ты жаждешь? Не его ли жаждет твое Я? -- Я проваливаюсь в его бездонный взгляд.', [[pon(7)]]),
[7] = _phr('Если... Если... То зачем?',
- '-- Правильно... Правильно -- вкрадчиво говорит мне человек с портрета... Новая волна страха оглушает меня я падаю на колени... Сердце бешено стучит и вылетает из груди...',
+ '-- Правильно... Правильно -- вкрадчиво говорит мне человек с портрета... Новая волна страха оглушает меня, я падаю на колени... Сердце бешено стучит и вылетает из груди...',
[[pon(8)]]),
[8] = _phr('Не могу... Нет...',
'-- И если все так, то тебе нечего бояться -- мурлычет он. -- Сердце бьется еще сильнее. И наконец, моя грудь взрывается, мягкий комочек шерсти отталкивается от нее лапами и летит в лицо человеку с портрета. Раздается выстрел, резкая боль в левом плече отрезвляет меня, я вскакиваю на ноги и бросаюсь вперед...',[[return goto('escape3')]]),
@@ -1056,7 +1056,7 @@ escape3 = room {
dsc = [[Я нахожусь в небольшой, но уютной комнате. Посреди стоит стол. Рядом опрокинуто кресло. Из небольшой люстры равномерно льется свет. Два небольших книжных шкафа стоят у стен.]],
obj = {
vobj(1, 'человек', 'На полу, прислонившись к столу, сидит {человек} с портретов. Струйка крови стекает с его губ -- он стонет.'),
- vobj(2, 'картины', 'По стенам развешены {картины}.'),
+ vobj(2, 'картины', 'По стенам развешаны {картины}.'),
vobj(3, 'дверь', 'За моей спиной {дверь}.'),
'revol',
'shkaf',
@@ -1095,7 +1095,7 @@ nwall = room {
way = {'eside2','wside' },
act = function(s, w)
if w == 1 then
- return 'Да -- водосточная труба... Довольно крепкая. Но вряд-ли я смогу взобраться по ней наверх.';
+ return 'Да -- водосточная труба... Довольно крепкая. Но вряд ли я смогу взобраться по ней наверх.';
end
end,
enter = function(s, f)
diff --git a/games/cat/main.lua b/games/cat/main.lua
index 3007888..9c07b63 100644
--- a/games/cat/main.lua
+++ b/games/cat/main.lua
@@ -1,3 +1,4 @@
+-- $Name:Возвращение квантового кота$
game.codepage="UTF-8";
game.act = 'Не получается.';
game.inv = 'Гм.. Странная штука..';
@@ -30,7 +31,7 @@ main = room {
начать все по-порядку...^^
В тот холодный февральский день я как всегда собрался ехать в поселок...]],
-obj = { vobj(1,'Дальше','{Дальше}') },
+obj = { vobj(1,'Дальше','{Дальше}.') },
act = function()
return goto('home');
end,
diff --git a/games/tutorial/main.lua b/games/tutorial/main.lua
index 6a3c8d5..aa9052f 100644
--- a/games/tutorial/main.lua
+++ b/games/tutorial/main.lua
@@ -1,10 +1,17 @@
+-- $Name:Обучение
game.codepage="UTF-8"
+game.act = 'Не получается.';
+game.inv = 'Гм.. Не то..';
+game.use = 'Не сработает...';
game.dsc = [[Команды:^
look(или просто ввод), act <на что> (или просто на что), use <что> [на что], go <куда>,^
back, inv, way, obj, quit, save , load . Работает автодополнение по табуляции.^^]];
+game.pic = 'stead.png';
+
+set_music('ramparts.mod');
main = room {
- nam = 'туториал',
+ nam = 'Обучение',
act = function()
return goto('r1');
end,
@@ -12,7 +19,7 @@ main = room {
Каждая сцена игры представляет собой описание статической и динамической части.^^
Динамическая часть сцены состоит из объектов, персонажей и т.д. С динамической частью
-игрок может взаимодействовать с помощью мыши, с помощью нажатий на подсвеченные ссылки.^^
+игрок может взаимодействовать с помощью мыши, нажимая на подсвеченные ссылки.^^
В данной сцене единственным объектом является объект "Дальше" -- который вы видите внизу текста.
Итак, для продолжения обучения вы можете нажать на "Дальше".
@@ -69,7 +76,7 @@ r1 = room {
};
r2 = room {
- nam = 'урок 2',
+ nam = 'Урок 2',
enter = function()
lifeon('r2');
end,
@@ -112,7 +119,7 @@ vasa = obj {
}
r3 = room {
- nam = 'урок 3',
+ nam = 'Урок 3',
enter = function()
lifeon('r3');
end,
@@ -131,7 +138,7 @@ r3 = room {
};
r4 = room {
- nam = 'урок 4',
+ nam = 'Урок 4',
enter = function()
apple._knife = false;
lifeon('r4');
@@ -148,7 +155,7 @@ r4 = room {
};
r5 = room {
- nam = 'урок 5',
+ nam = 'Урок 5',
dsc = [[Хорошо. Изучаем переходы. Идите на урок 6. Для этого нажмите мышью на соответствующую ссылку.]],
exit = function(s, t)
if t ~= 'r6' then
@@ -159,7 +166,7 @@ r5 = room {
};
r6 = room {
- nam = 'урок 6',
+ nam = 'Урок 6',
dsc = [[Идите на последний урок.]],
exit = function(s, t)
if t ~= 'theend' then
@@ -170,9 +177,19 @@ r6 = room {
};
theend = room {
- nam = 'последний урок',
+ nam = 'Последний урок',
dsc = [[Вы можете сохранять игру, выбрать другую игру или выполнять иные действия с помощью меню.
Для вызова меню нажмите клавишу esc или нажмите мышью на символ меню (справа снизу).
-Теперь вы готовы к игре. Удачи!!!]],
+Теперь вы готовы к игре. Удачи!!!^^
+В обучении использован трек:^Ramparts by Scorpion]],
+ obj = { vway('клавиши', 'Посмотреть {список клавиш}.', 'help')},
};
+help = room {
+ nam = 'Список клавиш',
+ dsc = [[
+esc - меню^
+alt-q - выход^
+alt-enter - полный экран/окно^
+Вверх/Вниз, Пробел/Backspace, PgUp/PgDn - прокрутка главного окна.]],
+};
diff --git a/games/tutorial/ramparts.mod b/games/tutorial/ramparts.mod
new file mode 100644
index 0000000000000000000000000000000000000000..623dc7a3d175ed0fe5b19865acf15565a91981fa
GIT binary patch
literal 22664
zcmeHv4RBM}weCKWuw`r+*(TUya4i08Y77`cpfNOd2ni38Kyo2@PzHi)oZ=*4is8~^
z!j*1wr-b*?o8)F*(@9`L+XLF_LPSWHdGGsQ+>OwwjkswGG>9>$dMS{pb}FA+Lk95u|W!t=aLC38W1#
zHP*d?Kah1nV`ok6PSe&p(+dqdOj~y~*4I`Nk`KD+pxd~!?u8fXwwX-Z>T4TbuBmT?
z?+J5?R5NB$jfPB(HCr1i{=V)-lW8Fx6AeqFVoaOC%C(@yxarLM8g^m5JS#)lu4V@BzYnpYv9Ii{UE8tVZiULxMjb+rwzfMk13
zVQgdE^i-qjrv
zL7u^MP5m}`bw%A2mC*xc^bb`hWHL)a)l_qc3Llig8T*KPm_rmqvXjE62fS7X2Q-G?l?v7m&ux
z>Oz!Xk;WvsB1KMGsJ<*`R;TKd74
z{zd*v{zvOe_=#v=;=jg{f*<&QXZ$cf1wT`rieHf59={~N9e%W@#*g#W_$B`me%Zf>
zUy@7srLlxxvQO~?|2461i9a?9|DI9!sr(N3Mfq*lab`2mFeB6RjU=eTrXYAMtA}8?ORC)cC>G?eW9>4v9~Q
zpQ(oYsrawRzaGEn@3#2CUWdd_#4pX4@GJHO{3-qczgn)=$9j$U)%Gd=7~oIgKVrWF
z{utmF`A6~Z0sIpGVEr|+{5JRnf49fK2k@)-5B4xV3ZFpzSL}=U)&3E`%0I=g(x>=U
z_9^~DU_XWb-+=!R;1~Hv@vjE_68{jtEWZtY!QbuiuLk@o{)0V?Pr)zS7xAn852X4h
zEwFz^=`*5z@)J0}yOst7en5YKW8gUK&%Cj6DpT-1D|_w{+-5DUzsy{
z{=rfDe>NVaKU&^3O8?Ksqx8G>D6vTU8-8-{x|e~wG6Tu~rHA^ZhqD}N06YUoz7OL{
z;68F1o&j`$ysM0!{j?5rfxN2_=cD`zX##l@=;M6=)`=#NH=#bgt_b=ksC`BMl4uX~
z&7g0tRODvRHy29&W&1)+QtZqA#rS0ZVtlfHDL%lL8Xwj;@SlPoo&lud7vsNM@WV5J
zyBL2?9G(H(b@;~zB>t16Wg&0``eo!V^8f9HWMCTf2h#o*fZrB>dW;{^#5(}V}2mM+u|4VhxJ{?N7o1I
zAK*U-`EP;s+XM0z(SM6-{hOu{auD;0^F{eV@JD-n&~KR!@sC=6z$53sYbn^jB-oeq
zTTY1faDBi(;z$3I+>HATaAAB&^gn9-57PNm&KSUd3&cauA1Qu}7cbOb*@5~g_Ca4>
zfAG&3K)xEzztxsyq-z?CQBM6YBLiT60OO(fK@NBZ3UNN#2RX#AtUuLP&Oelc{$7X=
z>;pbQe=o*I^RMVja`a2rNA!_0jF9{=xV
z{<$v-RjOG0g^%%{vVu{%KsMNgPQ+I&{y%FsRn&D|65RB#s4JgEBt4w
z(Z9lfW)J#T@xL1MRs3i6fPM?|i|+r0OkB{H_^+`D`V#*&hmh|I|22hJ4`lqynAM=K
z;vcOyD*iL8!M~dSv>u>7^}mcXfxepmd%?e&|5#s9U*i8>h+oZrbEo3GF=)+eWL;PL%yl)MRVLq8Jh_MdQG3YnJ^Rpv6#ra>O-$ec2M&E?zE7}*&
z4CuhU`2Q6!c
zLVP%1dd)2Phfk^gN#{T9f6xlf2RZG3a6a0@vBEDphW#t-CsD5M|LFV^;{Bqee@Wtp
zU=R7PKEG-Iqw-JfTIL;nqY$MsjQA6L<)c
z|I29qi~C2_e+l~s#I!#I|8JF1`vm(x%!TKV3gqpDw!o@TppVh;r1u}R{~4He6W+f=eH8fz{9+6W|L}f@F{tVv
zeLkY%Ki3-wy@kM?Q&V*N$?
zLi}R=1N*2i*(XqsFn+oI)BOehvHv?_S&q+tRQ=C#`g})u{ufV_1e=MhYQtH1r
zmhmqqSfAj2R_s3nIqh%g`M;dt{h89AfE?y4^&iF%kJ>+;4@&<9a?r>AUBEBs)BcU(
zm-Q9@g1(4A$6xgMTy1<>wE;C$${(3CLCWQ{|vf{27uh+-?3(r4B$whrt{!{HM{^j^n;#2$s
z-v#_sj?Vye@E7&(U3YZ`TA=@Lf&C}F|49P>Tjc!?&wuB`{Tn`iqW6CbDgO@w-}bD5
zw88U%GMRf{tM^-INBc#Sk^HH=#S|Cf1$(tt;2jn
z|0Lyq9qL2>g!8GKF@XO8dHvVX`VIg7485a1jUWE~xY&PzeTcsa*N6IFNAaV+aQ_SQ
zA%3ba_!s*>*}vHTDgK52Ps+b4e!)LJpTYPg`;vZ&f7SZaeoMXn*pI36kNuW9|1B`4
z#62i~XB~AL{G0)bk1ZH}(4C`l#2RJ`ceBQT(6}^Y7%J_N#LKh573Br||-Q>3pMj
zeqsHR`7hN^fx&C-9^&(`0`ZD$ZHs!M2
zua<6DH)-%AwY0FPZc6#lUBsHw|Tvu9qx4TUC-7>^XBpn$Uc{FFbb2f)#6p3C}Kl;C}rrd)pVy
z)Wz?Pow???RWa`ei!qau4f^?KS-=@7X&g29V@g_KLwu*}AHU=Eot%rx-z9{EV^N^-5%~
zmX?%y9?U3t&Ah108zzGn*Ox7tkXFB9QC00D>quF)uDfy9&W4w^)NWkA_Sx0XtX%Qf
zBh{4)ADlaD=8Wl6O+|(I6O5K`y7s^D$}2m!Z{1P{MxJ|a^{OXUEPJeaab@L#d2?r#
zmz9)EF}?c@CjQa$Du(>ptGgSwZ>@i!_W6zL)~$JF<;o|PKenX$;l&WpoI6-}eeb?~
zZ@%+xc#i`6wH@1D+)}$~;}6$9x8~`UD_1=JNY&y+4=s3b-h=b!R#fzSt+Ai|eBb|m
z^X+&4ylC@Yf$5I`W63&CSR8*Hkuty1TJ)$M%M;FV%0^yzz(6J^Re6Cn3VeA6p7B
zE;=XLd>yR(;+=PYwI7T${r(R}|MmE%pPxK^_WZ?5?QK`Db$0dGw<{*`yFIV|bmz{7
z7wc+jo?rjNwGi(!Pp?|}mVynu2}Z?(xpq5Jo513MT;JKXyL*I4?d_n{BhIoj~+dK{L_;sPn|w}?)>G;
zZS5V`ySln>^!8cNiPPmC_Ii9iUoaR7g(F-f5=$oewXcAa9Sz%Fe4(yp(*{iYGpo=8
zq-V*J>Z)o;e`V#u1@q_4t(a3@I(_=oDU(e_6DJlH@UIX4=A%Q0A!DB$
zJq9^D*?RuWnR90^UbuMaa$DQgj?U}XySsaOdU|j4+pIRbeb6<8p*Y=cx7Y3Su`C-}
zx(;?Q<_^|mDQx4a#gz{&Sb*ydF3V?>m6psXn^{&my=1xx9T!Xhzs78XAuBsmuTM`;
zOVe^k4t;#M>EouRBcH(H|10GAvlAyzwzQmTZG~7aT)1%Q(&a1d9apbjy>_j$v#aYm
zWCdcnaih1luit954cZ0=9S+CPkjv?E4SQx)E_!I;Lkkzp2h?+B&6-&@LjXPnkQYJ#
z`4jHT%gebhCnv{f$bu^)L!Xh37lfkI>NFaLVTcAe&NDpWNdnS5_=it~z)qZOIoW#p
z%-M72&tHNiYHM$Ypt`$yx^8r1I98j@YPZ2at}kgJYFy4D-aC9`r#Gk
zLg6qMj^snE3ozD-3XF9|X-P@R)TxsvPc{`7!BR~snoPsap8#PSjoI0dI!IntW+wd6
zLk2S;?lg!S{)5mp_zNlEFR!8DC*gY@t|a}ENF-vBE9cLhzku7Ttpk>~tGm1RM(>Tj
zKFB1damYD@Q4hNzTCWFV_Q4;P^#=mD@q$9kxcws0csvo0$75hM4oSibypSYDz%vB0
z$Y?YgUCCVBe6z~SXI0E9D}|+)K6UC8(`5L)7DYux#efhN1y?1%5cgzWPHry1ge%*S
zZ7?F%Yyg^>m1RWCxJv11IuS7}m{zCLX@yGz_%#}?7Z!qU3tWalJHl}yC|n5y2GQN=
z%5{hNuwHA-c4crn-s9=?oE|1T=bjMCA|Wnp=fk9z=t5ae(r@Pn^Ami?PcDasGrTAdGCQ=?mJ
z=@W#n1M=|N6WCZ2A1-&)d#X_WS!UoEUWG7Clrxwepdg<(t;7UA2B?`Qx(|EaN$nObgor
zpF6vc9&g_N%Mado=lAcOv0m&upOA!^nsIS+s+PN>Ap79J2Ua7a
zBqx31bP^(@&ueS5pKZV1A9Qs)+b&+}y3lRE?(Fd=aI7z}d$a(!fE|yIA!_f%%4+p)hKOBpP_%wzjH1V+8I1S7hlJKEm!0&Mndp!Pt-xmvce5{l8`vYt!6p1i#Fss+4!|!>@%E?G4
zoVTyHv%Lehlhx_r;z@>Qk|ddoL9+M+#HiEi8EqmKg}k}25plVEPOuA&Y9t2j4V=^Q
zcq9x`FZ?VVhT}ZWCAdgD9P$VK!!FQqIXzx~G!l(Pxv)Rt4|B12BoX5^JpA4%jV>8a
zLh1tHAS`nTps|6FXL#7{a)Fa@lxMVQ>Du(nG`$WQl4Kk@1V{~^46$C{u*(hzy{ymc
z1uuO!0DznIg%UiY&&bNm&|((@3jv)DpWhz@tZ{InC23k{0<~HOzJ-P`8Ht2_UN?3Wb~`jp{eAs?
z)}diH_`%HT()5Ph+}!-a`*Mtcg-ON&en^U=A9|8r8yJV>1#-H50qo(Uu>^#pg)YvJ
z3++x8fG5dF!0+|5Ug%VYVEYW>*~H<)C!yaq5Zi8!Pw0KFYFrMTCiHT8NS|A7GPZ>T2mSQPIo
z7}!71oNKhncm((W-5+ceKkP`a+vD}QJsvg)%`2oY0i7QgiAM2z>@yQ!0yP4D7Me%*
zFl>wf>@AoO4nf&Xd9XFkpZc)yW_F5rrXkR&p3oJ{nxURBJu`GeE&mUA8mE?%c*`S}}SjmL&N&o$XW!WiR@y9&V
zZJiW4MNV}T?k$g6btVo7m#X?Hzd`SWv)X_|9
zd7<8F%yqG*Q>OMR+id>ds|I-9cok0b2-jY4s-oS*mbaR&k&1s``oXIIJJD1Os92MA
z25BdJ2OsG%?K6@Nh73=#(Og7f&8sAaT$`v@q
z`i);29c)2I_{;HwosA0IX~M>4bQ42xp9f
z6VC`q_+vJ9fz?<%Fo!Vtx&&`xvuqPdC`!1*mpabIhpb@7qxsVm8%x+UPr;3R8$VF&
z4rdJ!K5Hl+?DKv&VT|m!n|yFAr{f6!jmT-Z+r&8pjci8SCaFndD2OHQi(IkA&D{gbffs1U<~dp%jR4>7fK{
z6K`Ogw&*B)B*q$PRI2B*sJWP3YNi@Bw+#B^Xb^SDen8!x~{a88kSvtZ5_|=WazH)3Fi4
z>0NwiB$9qJ#<1F;W(1DCP}(hC7mjC+B*t*s7$1TEq9c)L@>YbNbx{%-VQxZ~q6uh1
ziEwfx6yZoPHWGm|1niAyxde$PF#~*jghb;B{uUpDvp)cZQp3lB8ZJIE0u2qv2h+ky
zf5M*(kHn)9E&-=mbR@wgMq<&(NFp*O#xo;QC6FHPOJk`%2tUV)ftU2tZ~OU2xKc}u
zGD5p4?())0G&uN?>V-{;^WQc#IUI$Bf2VqZ
zlcK)isiz7GoX+NyH%4j;$B(;Q6DBN6d4r_3@aUuC$GhEMq`Xm5>z_H}@#N(#PI<$m
z*8l$Zb8@`i3m3i~K~vM^%Pea&&YSo32%da$_U!EJn>RZ;j;UTrDgHnEth4jxO@pDV
z?9oTp%kQWp|Ia>KRaH`wnHdcB^qe_!M1E%_={Gl@Ki}6E4v!r>Wy*pDD^{!(Ut$UR
z&px|!=>rekf4^RT>z3W#*7n60&CLpm-~H~`u`_3`U2`~Y-KwaVH}3~OSWMq>;a<4Y
M-n{)T6!znP0u&>+*#H0l
literal 0
HcmV?d00001
diff --git a/games/tutorial/stead.png b/games/tutorial/stead.png
new file mode 100644
index 0000000000000000000000000000000000000000..526195aff32fef17ff408f290d9ab3f132a052e3
GIT binary patch
literal 14611
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
dZ9nh=kDMqXM)s$9Y}^nU??xZwZ*
literal 0
HcmV?d00001
diff --git a/icon/Makefile b/icon/Makefile
new file mode 100644
index 0000000..dcdf8b7
--- /dev/null
+++ b/icon/Makefile
@@ -0,0 +1,7 @@
+include ../Rules.make
+clean:
+all:
+install:
+ install -d -m0755 $(ICONPATH)
+ install -m0644 sdl_instead.png $(ICONPATH)
+
diff --git a/icon/Makefile.windows b/icon/Makefile.windows
new file mode 100644
index 0000000..8d27c9c
--- /dev/null
+++ b/icon/Makefile.windows
@@ -0,0 +1,5 @@
+clean:
+all:
+install:
+ if not exist ..\bin\icon mkdir ..\bin\icon
+ copy sdl_instead.png ..\bin\icon
diff --git a/icon/book16x16.ico b/icon/book16x16.ico
new file mode 100644
index 0000000000000000000000000000000000000000..ccde08f7fdcd2bd7bc5de4c94584c51da8b125bb
GIT binary patch
literal 1150
zcmZ{j3rtgI6vsb`F~&zgf?M`*!x=Y?8$-6Z1avBqi4SyI6=iB*ozTt|u<{T#sMwBI
zfsu%?QCx{IDA{bmqA41IN-YJ-#8*|Sh|+D~oXD7IZE62IH`|gWhI8|~-?{&D{<)9u
zT*iFp@b_nQ4r0P-jJ?1ZTTGBd%0D_SQ-u!|W)K0ytHh!?vuCV0UYvHRNGj3?&YhD$
z+D>9Sv5{Cw1QQF1mk7qDA3MO9D2lTAOJ1A1$=I%baKq`vok?JD@Ml-5aBDl&X%~(X}
zd=+{5L^#2=@xM`LNR3FyFT_}PA#kM#?#l`|EO~JC9tF&qxZaWmnYs$n&K{h(YeQwF
z+)CCE&c8KRUR_~(4L`q=pzj2~z|Ht1d>Qh@
zs|U&I%lRp|{o5WNALEv_T!X^=1o@Z7@P(=kJ3bYXFBuEoO~=0C8YI?tA@X3MoBEFs
zvj}egUrCf5YpTEbr>mgZ@|eUD!P+2eYR;FCwpg)ZQygM5@{oPb=6EM6MxWC);awgh
zK2JVwW_;K3V}(t({`f7qsOq$C81BS^D$|-+(NAeLt-qIB9(g3+pYv``%Jrl-nx9g?
zS!x*Zei)yjr+hjwO_(h&Yx~9Np?qnH#?YzIb`BJ`^bRR|?ZZ4CFIw3@=6QSNNB3l{
zx5pLcM{bF_`)Y*X@E+>tg11Y2xXAQy(nWcM^1|hN>thAY+Y%48$r{dIBrUAo_6*C{
z@oQ)K2L$g-FN}#6AC2UU|HT{ch3{w`g-21Vxqa0Im)1Hmthc+I<@!Fm|GXE~&2~(N
ztXjwY1KhWIEp|RiY&<>1yvrjac={k^@GG1O5_P$W5
zyK~C!ao6|QMjB1lhlWv)M|ScwH)o5cH2$yPG8v&FeHCLSVo1u^GcfiyK5oFv
literal 0
HcmV?d00001
diff --git a/icon/sdl_instead.ico b/icon/sdl_instead.ico
new file mode 100644
index 0000000000000000000000000000000000000000..22265463e42c7dad02f79efd7c47ddeb8e2c1ca8
GIT binary patch
literal 2462
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