0.8.5 version

This commit is contained in:
p.kosyh 2009-08-26 05:25:53 +00:00
parent 6f6094c7f3
commit e8c753c50a
75 changed files with 6674 additions and 1144 deletions

View File

@ -1,4 +1,5 @@
SUBDIRS = src/instead src/sdl-instead stead games themes
#SUBDIRS = src/sdl-instead stead games themes icon desktop doc
SUBDIRS = src/sdl-instead stead games themes icon desktop doc
all:
@for dir in $(SUBDIRS); do \

18
Makefile.windows Normal file
View File

@ -0,0 +1,18 @@
MAKE=mingw32-make
all:
$(MAKE) -C src\sdl-instead all
$(MAKE) -C themes -f Makefile.windows all
clean:
$(MAKE) -C src\sdl-instead clean
install: all
if not exist bin mkdir bin
copy src\sdl-instead\sdl-instead.exe bin
$(MAKE) -C themes -f Makefile.windows install
$(MAKE) -C games -f Makefile.windows install
$(MAKE) -C stead -f Makefile.windows install
$(MAKE) -C icon -f Makefile.windows install
$(MAKE) -C doc -f Makefile.windows install

View File

@ -1 +1 @@
Rules.make.system
Rules.make.standalone

View File

@ -1,23 +1,29 @@
VERSION := \"0.7\"
VERSION := \"0.8.5\"
DESTDIR=
BIN=
STEADPATH=./stead
THEMESPATH=./themes
GAMESPATH=./games
ICONPATH=./icon
LUA_CFLAGS=$(shell pkg-config --cflags lua5.1)
LUA_LFLAGS=$(shell pkg-config --libs lua5.1)
# for arch linux use this
# for arch linux (may be others) use this
#
#LUA_CFLAGS=$(shell pkg-config --cflags lua)
#LUA_LFLAGS=$(shell pkg-config --libs lua)
# LUA_CFLAGS=$(shell pkg-config --cflags lua)
# LUA_LFLAGS=$(shell pkg-config --libs lua)
#
SDL_CFLAGS=$(shell sdl-config --cflags)
SDL_LFLAGS=$(shell sdl-config --libs) -lSDL_ttf -lSDL_mixer -lSDL_image
CFLAGS += -g -Wall -DHAVE_ICONV -DRUSSIAN
CFLAGS += -g -Wall -D_HAVE_ICONV -DRUSSIAN
INSTALLD=echo
INSTALL=echo
EXE=
PLATFORM=unix.c
RESOURCES=

View File

@ -1,10 +1,11 @@
VERSION := \"0.7.4\"
VERSION := \"0.8.5\"
DESTDIR=/usr/local
BIN=$(DESTDIR)/bin
BIN=$(DESTDIR)/bin/
STEADPATH=$(DESTDIR)/share/stead
THEMESPATH=$(DESTDIR)/share/stead/themes
GAMESPATH=$(DESTDIR)/share/stead/games
THEMESPATH=$(STEADPATH)/themes
GAMESPATH=$(STEADPATH)/games
ICONPATH=$(DESTDIR)/share/pixmaps
LUA_CFLAGS=$(shell pkg-config --cflags lua5.1)
LUA_LFLAGS=$(shell pkg-config --libs lua5.1)
@ -18,6 +19,11 @@ LUA_LFLAGS=$(shell pkg-config --libs lua5.1)
SDL_CFLAGS=$(shell sdl-config --cflags)
SDL_LFLAGS=$(shell sdl-config --libs) -lSDL_ttf -lSDL_mixer -lSDL_image
CFLAGS += -Wall -DHAVE_ICONV -DRUSSIAN
CFLAGS += -Wall -D_HAVE_ICONV -DRUSSIAN
INSTALLD=install -d -m 0775
INSTALL=install -m 0775
EXE=
PLATFORM=unix.c
RESOURCES=

30
Rules.windows Normal file
View File

@ -0,0 +1,30 @@
VERSION := \"0.8.5\"
DESTDIR=
BIN=..\..\bin\\
STEADPATH=./stead
THEMESPATH=./themes/
GAMESPATH=./games
ICONPATH=./icon
LUA_CFLAGS=
LUA_LFLAGS=-llua5.1
SDL_CFLAGS=-IC:\MinGW\include\SDL
SDL_LFLAGS=-lSDL -lSDLmain -lSDL_ttf -lSDL_mixer -lSDL_image
CFLAGS += -Wall -DRUSSIAN -mwindows -D_HAVE_ICONV
LDFLAGS += -liconv
CC=gcc
RM=del
EXE=.exe
INSTALLD=echo mkdir
INSTALL=copy
PLATFORM=windows.c
RESOURCES=resources.o
resources.o: resources.rc
windres -i resources.rc -o resources.o

1
configure.bat Normal file
View File

@ -0,0 +1 @@
copy Rules.windows Rules.make

6
debian/README.Debian vendored Normal file
View File

@ -0,0 +1,6 @@
instead for Debian
------------------
<possible notes regarding this package - if none, delete this file>
-- Peter Kosyh <peter@localhost> Thu, 21 May 2009 11:40:29 +0400

99
debian/changelog vendored Normal file
View File

@ -0,0 +1,99 @@
instead (0.8.5) unstable; urgency=low
* possible segfaults in timer functions.
* ways, objs, drop, take - extra parameters
* put - function
* set_music fixes
-- Peter Kosyh <p.kosyh@gmail.com> Thu, 24 Aug 2009 08:32:00 +0400
instead (0.8.4) unstable; urgency=low
* bug in savevar
* bug in long strings
-- Peter Kosyh <p.kosyh@gmail.com> Thu, 20 Aug 2009 14:09:14 +0400
instead (0.8.3) unstable; urgency=low
* sge forgotten
* set_music with loop argument bug
-- Peter Kosyh <p.kosyh@gmail.com> Wed, 19 Aug 2009 14:09:14 +0400
instead (0.8.2) unstable; urgency=low
* gfx_load_img
-- Peter Kosyh <p.kosyh@gmail.com> Sat, 15 Aug 2009 14:09:14 +0400
instead (0.8) unstable; urgency=low
* key_name attribute!!!!
* do_ini
* version in stead.lua
* opairs!!!
* vroom fix
* typos
* backtrace
* list_set
-- Peter Kosyh <p.kosyh@gmail.com> Fri, 07 Aug 2009 14:09:14 +0400
instead (0.7.7-4) unstable; urgency=low
* Fixes :)
-- Peter Kosyh <p.kosyh@gmail.com> Wed, 05 Aug 2009 17:26:55 +0400
instead (0.7.7) unstable; urgency=low
* typos in games
* local games now can be placed in ~/.instead/games
* console version disabled by default
* -- $Name: tag -- full name of games, not only dirname
* fix of link color for title/ways
* bug in text layout logic (last period in line)
* embedded mode (picture and ways inside text!!!)
* float mode (for books)
* faster text renderer (x2-x5 times)
* free motion mode of scrolling
* click sound support in themes (in default theme too)
* new options (click sound, music)
* default theme changes
* fullscreen with Alt-Enter
* options -alsa, -fullscreen, -window
* now italic font used for events
* 48000Hz added in sound preferences
* now scroll position is saved in embedded mode
* themes support, one new theme added
* vway and vroom added
* updated tutorial
* set_music now take an loop parameter
* autosave is now default
* now vars saved if they begins from uppercase letter (undescore too);
* save slots !!!
* a lot of bugs fixed (memory leaks, SDL cavities.. )
-- Peter Kosyh <p.kosyh@gmail.com> Thu, 30 Jul 2009 18:12:19 +0400
instead (0.7.6-1) unstable; urgency=low
* debian file fixes
-- Peter Kosyh <p.kosyh@gmail.com> Fri, 29 May 2009 14:17:01 +0400
instead (0.7.6) unstable; urgency=low
* Keyboard scrolling
* Font scaling
* inv.horiz option
-- Peter Kosyh <p.kosyh@gmail.com> Mon, 25 May 2009 10:58:29 +0400
instead (0.7.5) unstable; urgency=low
* Initial release
-- Peter Kosyh <p.kosyh@gmail.com> Thu, 21 May 2009 11:40:29 +0400

21
debian/changelog.txt vendored Normal file
View File

@ -0,0 +1,21 @@
* опечатки
* 3 режима размещения картинки (в том числе и встроенный в текст)
* механизм выбора тем представлен в меню и настройках
* режим свободного скроллинга (таскание мышкой)
* ускорение отрисовки текста (x4-x5 раз)
* слоты для загрузки/сохранения игр
* звук на реакцию движка
* выделение наклонным шрифтом событий сцены
* изменена тема по умолчанию (картинка теперь не мешает тексту, так как скроллируется с ним),
* добавлена тема 'Книга' -- оптимальная для книг-игр с вертикальными картинками
* позиция скроллирования не сбрасывается при реакции движка
* фильтр событий мыши (случайные двойные клики и т.д.)
* полноэкранный режим по Alt-Enter
* другие улучшения интерфейса
* обновлена документация (новые объекты, расширения движка)
* игры и темы кроме системного каталога ищутся также в ~/.instead/games ~/.instead/themes (unix версия)
* консольная версия не входит в поставку по умолчанию
* параметры командной строки: -alsa, -fullscreen, -window
* исправлено множество ошибок

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
7

14
debian/control vendored Normal file
View File

@ -0,0 +1,14 @@
Source: instead
Section: games
Priority: optional
Maintainer: Peter Kosyh <p.kosyh@gmail.com>
Build-Depends: debhelper (>= 7), pkg-config, liblua5.1-dev, libsdl1.2-dev, libsdl-ttf2.0-dev, libsdl-image1.2-dev, libsdl-mixer1.2-dev, libreadline5-dev
Standards-Version: 3.7.3
Homepage: http://instead.googlecode.com
Package: instead
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: instead, simply text adventures/visual novels engine and game.
Visual novell/text quest-like game in russian with engine.

24
debian/copyright vendored Normal file
View File

@ -0,0 +1,24 @@
This package was debianized by Peter Kosyh <peter@localhost> on
Thu, 21 May 2009 11:40:29 +0400.
It was downloaded from <url://example.com>
Upstream Author(s):
<put author's name and email here>
<likewise for another author>
Copyright:
<Copyright (C) YYYY Name OfAuthor>
<likewise for another author>
License:
<Put the license of the package here indented by 4 spaces>
The Debian packaging is (C) 2009, Peter Kosyh <peter@localhost> 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.

4
debian/cron.d.ex vendored Normal file
View File

@ -0,0 +1,4 @@
#
# Regular cron jobs for the instead package
#
0 4 * * * root [ -x /usr/bin/instead_maintenance ] && /usr/bin/instead_maintenance

2
debian/docs vendored Normal file
View File

@ -0,0 +1,2 @@
readme.txt
readme.txt

100
debian/rules vendored Executable file
View File

@ -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

14
desktop/Makefile Normal file
View File

@ -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

3
desktop/Makefile.windows Normal file
View File

@ -0,0 +1,3 @@
clean:
all:
install:

View File

@ -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;

7
doc/Makefile Normal file
View File

@ -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

8
doc/Makefile.windows Normal file
View File

@ -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

View File

@ -4,7 +4,7 @@
</head><body brgcolor="#d6e7c9" bgcolor="#ffffff">
<center>[ <a href="#info">Что это такое?</a> ] [ <a href="#screenshots">Скриншоты</a> ] [ <a href="#download"> Скачать </a> ]</center>
<hr>
<center><h2>INSTEAD 0.7 -- интерпретатор простых текстовых приключений для Unix</h2></center>
<center><h2>INSTEAD 0.8 -- интерпретатор простых текстовых приключений для Unix</h2></center>
<h1><a name="info">Что это такое?</a></h1>
<p align="justify">Интерпретатор STEAD (Simply Text Adventure) позволяет проигрывать игры, которые по жанру являются
смесью визуальной новеллы, текстового квеста и классических квестов 90-х. Особенности STEAD игры:</p>
@ -15,8 +15,7 @@
<li>поддержка тем для графического интерпретатора -- конкретная игра может менять вид интерфейса;
<li>переносимость (изначально написана для Linux, зависит от SDL и lua).
</ul>
<p align="justify">На данный момент автором STEAD написана одна игра: 'Возвращение Квантового Кота', которая входит в состав архива с исходным кодом.
Игра содержит около 70 сцен, графику и oldschool треки.</p>
<p align="justify">В архив с интерпретатором входит игра: 'Возвращение Квантового Кота'. Игра содержит около 70 сцен, графику и oldschool треки.</p>
<h1><a name="screenshots">Скриншоты</a></h1>
<p align = "justify">Работа графического интерпретатора.</p>
@ -31,7 +30,7 @@
<img src="6.png">
<h1><a name="download">Скачать</a></h1>
Скачать текущую версию можно здесь: <a href="http://sites.google.com/site/sdlinstead/">http://sites.google.com/site/sdlinstead/</a>
Скачать текущую версию и другие игры для INSTEAD можно здесь: <a href="http://instead.googlecode.com/">http://instead.googlecode.com/</a>
<hr>
<center>[ <a href="#info">Что это такое?</a> ] [ <a href="#screenshots">Скриншоты</a> ] [ <a href="#download"> Скачать </a> ]</center>

964
doc/writing_games.txt Normal file
View File

@ -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 <on what> (or just what), use <what> [on what], go <where>,^
back, inv, way, obj, quit, save <fname>, load <fname>.]],
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
Полный список объектов и методов.

View File

@ -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:

11
games/Makefile.windows Normal file
View File

@ -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:

View File

@ -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 = 'Я нахожусь у задней стороны института.',

View File

@ -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' },
};

View File

@ -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)

View File

@ -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,

View File

@ -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 <fname>, load <fname>. Работает автодополнение по табуляции.^^]];
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 - прокрутка главного окна.]],
};

BIN
games/tutorial/ramparts.mod Normal file

Binary file not shown.

BIN
games/tutorial/stead.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

7
icon/Makefile Normal file
View File

@ -0,0 +1,7 @@
include ../Rules.make
clean:
all:
install:
install -d -m0755 $(ICONPATH)
install -m0644 sdl_instead.png $(ICONPATH)

5
icon/Makefile.windows Normal file
View File

@ -0,0 +1,5 @@
clean:
all:
install:
if not exist ..\bin\icon mkdir ..\bin\icon
copy sdl_instead.png ..\bin\icon

BIN
icon/book16x16.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
icon/sdl_instead.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
icon/sdl_instead.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -1,19 +1,28 @@
Deps:
sdl, sdl-mixer, sdl-image, sdl-ttf, lua5.1
On debian systems:
apt-get install liblua5.1-dev libreadline-dev libsdl1.2-dev libsdl-ttf2.0-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libreadline5-dev
make
make install
sdl-instead
sdl, sdl-mixer, sdl-image, sdl-ttf, lua5.1
To run just from build dir use:
rm Rules.make
ln -s Rules.make.standalone Rules.make
make clean
make
./sdl-instead
rm -f Rules.make
ln -s Rules.make.standalone Rules.make
make clean
make
./sdl-instead
To install into system:
# as root
rm -f Rules.make
ln -s Rules.make.system Rules.make
make clean
make install
sdl-instead
On debian systems:
apt-get install liblua5.1-dev libreadline-dev libsdl1.2-dev libsdl-ttf2.0-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libreadline5-dev
building deb package:
build-essential
debuild

View File

@ -2,7 +2,7 @@
include ../../Rules.make
all: instead
instead: instead.c rline.c
$(CC) $(CFLAGS) -DSTEAD_PATH=\"${STEADPATH}/\" instead.c $(LUA_CFLAGS) rline.c $(LUA_LFLAGS) -lreadline -o instead
$(CC) $(CFLAGS) -DSTEAD_PATH=\"${STEADPATH}/\" instead.c $(LUA_CFLAGS) rline.c $(LUA_LFLAGS) -lncurses -lreadline -o instead
clean:
rm -rf *.o instead
install:

340
src/instead/copying Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -12,7 +12,7 @@
#include <termios.h>
#include <stdio.h>
#include <wchar.h>
#ifdef HAVE_ICONV
#ifdef _HAVE_ICONV
#include <langinfo.h>
#include <iconv.h>
#endif
@ -241,7 +241,7 @@ char **tquest_completion(char *text, int start, int end)
/* Tell the GNU Readline library how to complete. We want to try to complete
on command names if this is the first word in the line, or on filenames
if not. */
#ifdef HAVE_ICONV
#ifdef _HAVE_ICONV
static char curcp[64];
static char *fromcp;
#endif
@ -257,7 +257,7 @@ void initialize_readline(void)
rl_parse_and_bind(strdup("Control-g: 'go '"));
/* Tell the completer that we want a crack first. */
rl_attempted_completion_function = (CPPFunction *) tquest_completion;
#ifdef HAVE_ICONV
#ifdef _HAVE_ICONV
strncpy(curcp, nl_langinfo(CODESET), sizeof(curcp));
fromcp = getstring("return game.codepage;");
#endif
@ -292,7 +292,7 @@ char *string_fromwc(const wchar_t *str)
pstr[ wcstombs(pstr, str, mbs_size) ] = 0;
return pstr;
}
#ifdef HAVE_ICONV
#ifdef _HAVE_ICONV
#define CHAR_MAX_LEN 4
static char *decode(iconv_t hiconv, const char *s)
{

View File

@ -1,10 +1,11 @@
game.codepage="UTF-8"
game.err = "Ошибка!"
game.dsc = [[Команды:^
look(или просто ввод), act <на что> (или просто на что), use <что> [на что], go <куда>,^
back, inv, way, obj, quit, save <fname>, load <fname>. Работает автодополнение по табуляции.^^]];
main = room {
nam = 'туториал',
nam = 'Обучение',
act = function()
return goto('r1');
end,

View File

@ -1,27 +1,24 @@
include ../../Rules.make
CFLAGS += $(SDL_CFLAGS) $(LUA_CFLAGS) -DSTEAD_PATH=\"${STEADPATH}/\" -DGAMES_PATH=\"${GAMESPATH}/\" -DTHEMES_PATH=\"${THEMESPATH}/\" -DVERSION=$(VERSION)
CFLAGS += $(SDL_CFLAGS) $(LUA_CFLAGS) -DSTEAD_PATH=\"${STEADPATH}/\" -DGAMES_PATH=\"${GAMESPATH}/\" -DTHEMES_PATH=\"${THEMESPATH}/\" -DVERSION=$(VERSION) -DICON_PATH=\"${ICONPATH}/\"
LDFLAGS += $(SDL_LFLAGS) $(LUA_LFLAGS)
SRC := graphics.c input.c game.c main.c instead.c sound.c
SRC := graphics.c input.c game.c main.c instead.c sound.c SDL_rotozoom.c $(PLATFORM)
OBJ := $(patsubst %.c, %.o, $(SRC))
all: sdl-instead
PREFIX:=/usr/local
all: sdl-instead$(EXE)
$(OBJ): %.o : %.c gui.h
$(OBJ): %.o : %.c gui.h menu.h menu-en.h
$(CC) -c $(<) $(I) $(CFLAGS)
sdl-instead: $(OBJ)
sdl-instead$(EXE): $(OBJ) $(RESOURCES)
$(CC) $(CFLAGS) $(^) $(LDFLAGS) -o $(@)
# strip sdl-instead
install:
install -d -m 0755 $(BIN)
install -m 0755 sdl-instead $(BIN)/sdl-instead
$(INSTALLD) $(BIN)
$(INSTALL) sdl-instead$(EXE) $(BIN)/sdl-instead$(EXE)
clean:
rm -f *.o sdl-instead
$(RM) -f *.o sdl-instead$(EXE)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,117 @@
/*
SDL_rotozoom - rotozoomer
LGPL (c) A. Schiffler
*/
#ifndef _SDL_rotozoom_h
#define _SDL_rotozoom_h
#include <math.h>
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif
#ifndef M_PI
#define M_PI 3.141592654
#endif
#include "SDL.h"
/* ---- Defines */
#define SMOOTHING_OFF 0
#define SMOOTHING_ON 1
/* ---- Structures */
typedef struct tColorRGBA {
Uint8 r;
Uint8 g;
Uint8 b;
Uint8 a;
} tColorRGBA;
typedef struct tColorY {
Uint8 y;
} tColorY;
/* ---- Prototypes */
#define DLLINTERFACE
/*
rotozoomSurface()
Rotates and zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
'angle' is the rotation in degrees. 'zoom' a scaling factor. If 'smooth' is 1
then the destination 32bit surface is anti-aliased. If the surface is not 8bit
or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
*/
DLLINTERFACE SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth);
DLLINTERFACE SDL_Surface *rotozoomSurfaceXY
(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth);
/* Returns the size of the target surface for a rotozoomSurface() call */
DLLINTERFACE void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth,
int *dstheight);
DLLINTERFACE void rotozoomSurfaceSizeXY
(int width, int height, double angle, double zoomx, double zoomy,
int *dstwidth, int *dstheight);
/*
zoomSurface()
Zoomes a 32bit or 8bit 'src' surface to newly created 'dst' surface.
'zoomx' and 'zoomy' are scaling factors for width and height. If 'smooth' is 1
then the destination 32bit surface is anti-aliased. If the surface is not 8bit
or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
*/
DLLINTERFACE SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth);
/* Returns the size of the target surface for a zoomSurface() call */
DLLINTERFACE void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight);
/*
shrinkSurface()
Shrinks a 32bit or 8bit 'src' surface ti a newly created 'dst' surface.
'factorx' and 'factory' are the shrinking ratios (i.e. 2=1/2 the size,
3=1/3 the size, etc.) The destination surface is antialiased by averaging
the source box RGBA or Y information. If the surface is not 8bit
or 32bit RGBA/ABGR it will be converted into a 32bit RGBA format on the fly.
*/
DLLINTERFACE SDL_Surface *shrinkSurface(SDL_Surface * src, int factorx, int factory);
/*
Other functions
*/
DLLINTERFACE SDL_Surface* rotateSurface90Degrees(SDL_Surface* pSurf, int numClockwiseTurns);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
#endif
#endif /* _SDL_rotozoom_h */

340
src/sdl-instead/copying Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,50 @@
#ifndef __GAME_H__
#define __GAME_H__
#ifndef GAMES_PATH
#define GAMES_PATH "./games"
#endif
#define DEFAULT_THEME "default"
#ifndef THEMES_PATH
#define THEMES_PATH "./themes"
#endif
#define MAIN_FILE "main.lua"
#define THEME_FILE "theme.ini"
#define MENU_GAMES_MAX 8
#define MENU_THEMES_MAX 8
#define FONT_MIN_SZ 8
#define FONT_MAX_SZ 64
#define MAX_SAVE_SLOTS 6
extern char *game_local_games_path(void);
extern char *game_local_themes_path(void);
extern int cfg_load(void);
extern int cfg_save(void);
extern char *opt_game;
extern int nosound_sw;
extern int alsa_sw;
extern int fullscreen_sw;
extern int window_sw;
extern int opt_fs;
extern char *opt_theme;
extern char *curtheme;
extern int game_theme_select(const char *name);
extern int game_load_theme(const char *path);
extern int game_init(const char *game);
extern void game_done(void);
extern int game_loop(void);
extern int games_lookup(void);
extern int games_lookup(const char *path);
extern int themes_lookup(const char *path);
extern void game_err_msg(const char *s);
extern int game_error(const char *name);
#endif

View File

@ -2,7 +2,8 @@
#include <SDL_image.h>
#include <SDL_ttf.h>
#include <SDL_mutex.h>
#include <unistd.h> /* for usleep */
#include "SDL_rotozoom.h"
#include "input.h"
#include "graphics.h"
#include "math.h"
@ -352,35 +353,16 @@ img_t gfx_combine(img_t src, img_t dst)
return new;
}
img_t gfx_load_image(char *filename, int transparent)
img_t gfx_load_image(char *filename)
{
SDL_Surface *img, *img2;
SDL_Surface *img;
img = IMG_Load(filename);
if (!img) {
fprintf(stderr, "File not found: '%s'\n", filename);
return NULL;
}
if (transparent && transparent != 2) {
SDL_SetColorKey(img, SDL_RLEACCEL, img->format->colorkey);
return img;
}
// Create hardware surface
img2 = SDL_CreateRGBSurface(SDL_HWSURFACE | (transparent)?SDL_SRCCOLORKEY:0,
img->w, img->h, 16, 0xF800, 0x7E0, 0x1F, 0);
if (!img2) {
SDL_FreeSurface(img);
fprintf(stderr, "Error creating surface!\n");
return NULL;
}
if (transparent)
SDL_SetColorKey(img2, SDL_SRCCOLORKEY | SDL_RLEACCEL, 0xF81F);
SDL_SetAlpha(img2, 0, 0);
SDL_BlitSurface(img, NULL, img2, NULL);
SDL_FreeSurface(img);
return img2;
return img;
}
void gfx_draw_bg(img_t p, int x, int y, int width, int height)
@ -458,10 +440,38 @@ void gfx_clear(int x, int y, int w, int h)
int gfx_width;
int gfx_height;
int gfx_init(int width, int height, int fs)
int gfx_setmode(int w, int h, int fs)
{
gfx_width = width;
gfx_height = height;
gfx_width = w;
gfx_height = h;
screen = SDL_SetVideoMode(gfx_width, gfx_height, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | ( ( fs ) ? SDL_FULLSCREEN : 0 ) );
if (screen == NULL) {
fprintf(stderr, "Unable to set %dx%d video: %s\n", w, h, SDL_GetError());
return -1;
}
gfx_clear(0, 0, gfx_width, gfx_height);
return 0;
}
unsigned int timer_counter = 0;
SDL_TimerID timer_han = NULL;
static SDL_Surface *icon = NULL;
Uint32 counter_fn(Uint32 interval, void *p)
{
timer_counter ++;
return interval;
}
int gfx_init(void)
{
char title[4096];
strcpy( title, "INSTEAD SDL - " );
strcat( title, VERSION );
if (TTF_Init()) {
fprintf(stderr, "Can't init TTF subsystem.\n");
@ -469,21 +479,22 @@ int gfx_init(int width, int height, int fs)
}
// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO) < 0) {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER /*| SDL_INIT_AUDIO*/) < 0) {
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
return -1;
}
screen = SDL_SetVideoMode(gfx_width, gfx_height, 32, SDL_DOUBLEBUF | SDL_HWSURFACE | ((fs)?SDL_FULLSCREEN:0));
SDL_WM_SetCaption("IN S.T.E.A.D SDL - "VERSION, NULL);
// icon = IMG_Load( GAMEDATADIR"icon/lines.png" );
// if (icon) {
// SDL_WM_SetIcon( icon, NULL );
// }
if (screen == NULL) {
fprintf(stderr, "Unable to set 800x480 video: %s\n", SDL_GetError());
return -1;
SDL_WM_SetCaption( title, title );
#ifndef ICON_PATH
#define ICON_PATH "./icon"
#endif
icon = IMG_Load( ICON_PATH"/sdl_instead.png" );
if ( icon ) {
SDL_WM_SetIcon( icon, NULL );
}
gfx_clear(0, 0, gfx_width, gfx_height);
timer_han = SDL_AddTimer(100, counter_fn, NULL);
return 0;
}
void gfx_flip(void)
@ -516,339 +527,18 @@ void gfx_update(int x, int y, int w, int h) {
void gfx_done(void)
{
if (icon)
SDL_FreeSurface(icon);
if (timer_han)
SDL_RemoveTimer(timer_han);
timer_han = NULL;
TTF_Quit();
SDL_Quit();
}
/* code from sge */
#ifndef PI
#define PI 3.1414926535
#endif
void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
{
Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
/* Gack - slow, but endian correct */
*(pix+surface->format->Rshift/8) = color>>surface->format->Rshift;
*(pix+surface->format->Gshift/8) = color>>surface->format->Gshift;
*(pix+surface->format->Bshift/8) = color>>surface->format->Bshift;
*(pix+surface->format->Ashift/8) = color>>surface->format->Ashift;
}
void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
{
*((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
}
void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
{
switch ( dest->format->BytesPerPixel ) {
case 1:
*((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
break;
case 2:
*((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
break;
case 3:
_PutPixel24(dest,x,y,color);
break;
case 4:
*((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
break;
}
}
Uint32 sge_GetPixel(SDL_Surface *surface, Sint16 x, Sint16 y)
{
if(x<0 || x>=surface->w || y<0 || y>=surface->h)
return 0;
switch (surface->format->BytesPerPixel) {
case 1: { /* Assuming 8-bpp */
return *((Uint8 *)surface->pixels + y*surface->pitch + x);
}
break;
case 2: { /* Probably 15-bpp or 16-bpp */
return *((Uint16 *)surface->pixels + y*surface->pitch/2 + x);
}
break;
case 3: { /* Slow 24-bpp mode, usually not used */
Uint8 *pix;
int shift;
Uint32 color=0;
pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
shift = surface->format->Rshift;
color = *(pix+shift/8)<<shift;
shift = surface->format->Gshift;
color|= *(pix+shift/8)<<shift;
shift = surface->format->Bshift;
color|= *(pix+shift/8)<<shift;
shift = surface->format->Ashift;
color|= *(pix+shift/8)<<shift;
return color;
}
break;
case 4: { /* Probably 32-bpp */
return *((Uint32 *)surface->pixels + y*surface->pitch/4 + x);
}
break;
}
return 0;
}
/*
* Macro to get clipping
*/
#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) >= \
SDL_VERSIONNUM(1, 1, 5)
#define sge_clip_xmin(pnt) pnt->clip_rect.x
#define sge_clip_xmax(pnt) pnt->clip_rect.x + pnt->clip_rect.w-1
#define sge_clip_ymin(pnt) pnt->clip_rect.y
#define sge_clip_ymax(pnt) pnt->clip_rect.y + pnt->clip_rect.h-1
#else
#define sge_clip_xmin(pnt) pnt->clip_minx
#define sge_clip_xmax(pnt) pnt->clip_maxx
#define sge_clip_ymin(pnt) pnt->clip_miny
#define sge_clip_ymax(pnt) pnt->clip_maxy
#endif
#define SWAP(x,y,temp) temp=x;x=y;y=temp
//==================================================================================
// Helper function to sge_transform()
// Returns the bounding box
//==================================================================================
void _calcRect(SDL_Surface *src, SDL_Surface *dst, float theta, float xscale, float yscale, Uint16 px, Uint16 py, Uint16 qx, Uint16 qy, Sint16 *xmin, Sint16 *ymin, Sint16 *xmax, Sint16 *ymax)
{
int i;
Sint16 x, y, rx, ry;
Sint32 istx, ictx, isty, icty;
// Clip to src surface
Sint16 sxmin = sge_clip_xmin(src);
Sint16 sxmax = sge_clip_xmax(src);
Sint16 symin = sge_clip_ymin(src);
Sint16 symax = sge_clip_ymax(src);
Sint16 sx[]={sxmin, sxmax, sxmin, sxmax};
Sint16 sy[]={symin, symax, symax, symin};
// We don't really need fixed-point here
// but why not?
istx = (Sint32)((sin(theta)*xscale) * 8192.0); /* Inverse transform */
ictx = (Sint32)((cos(theta)*xscale) * 8192.2);
isty = (Sint32)((sin(theta)*yscale) * 8192.0);
icty = (Sint32)((cos(theta)*yscale) * 8192.2);
//Calculate the four corner points
for(i=0; i<4; i++){
rx = sx[i] - px;
ry = sy[i] - py;
x = (Sint16)(((ictx*rx - isty*ry) >> 13) + qx);
y = (Sint16)(((icty*ry + istx*rx) >> 13) + qy);
if(i==0){
*xmax = *xmin = x;
*ymax = *ymin = y;
}else{
if(x>*xmax)
*xmax=x;
else if(x<*xmin)
*xmin=x;
if(y>*ymax)
*ymax=y;
else if(y<*ymin)
*ymin=y;
}
}
//Better safe than sorry...
*xmin -= 1;
*ymin -= 1;
*xmax += 1;
*ymax += 1;
//Clip to dst surface
if( !dst )
return;
if( *xmin < sge_clip_xmin(dst) )
*xmin = sge_clip_xmin(dst);
if( *xmax > sge_clip_xmax(dst) )
*xmax = sge_clip_xmax(dst);
if( *ymin < sge_clip_ymin(dst) )
*ymin = sge_clip_ymin(dst);
if( *ymax > sge_clip_ymax(dst) )
*ymax = sge_clip_ymax(dst);
}
#define TRANSFORM_GENERIC_AA \
Uint8 R, G, B, A, R1, G1, B1, A1=0, R2, G2, B2, A2=0, R3, G3, B3, A3=0, R4, G4, B4, A4=0; \
Sint32 wx, wy, p1, p2, p3, p4;\
\
Sint32 const one = 2048; /* 1 in Fixed-point */ \
Sint32 const two = 2*2048; /* 2 in Fixed-point */ \
\
for (y=ymin; y<ymax; y++){ \
dy = y - qy; \
\
sx = (Sint32)(ctdx + stx*dy + mx); /* Compute source anchor points */ \
sy = (Sint32)(cty*dy - stdx + my); \
\
for (x=xmin; x<xmax; x++){ \
rx=(Sint16)(sx >> 13); /* Convert from fixed-point */ \
ry=(Sint16)(sy >> 13); \
\
/* Make sure the source pixel is actually in the source image. */ \
if( (rx>=sxmin) && (rx+1<=sxmax) && (ry>=symin) && (ry+1<=symax) ){ \
wx = (sx & 0x00001FFF) >> 2; /* (float(x) - int(x)) / 4 */ \
wy = (sy & 0x00001FFF) >> 2;\
\
p4 = wx+wy;\
p3 = one-wx+wy;\
p2 = wx+one-wy;\
p1 = two-wx-wy;\
\
SDL_GetRGBA(sge_GetPixel(src,rx, ry), src->format, &R1, &G1, &B1, &A1);\
SDL_GetRGBA(sge_GetPixel(src,rx+1,ry), src->format, &R2, &G2, &B2, &A2);\
SDL_GetRGBA(sge_GetPixel(src,rx, ry+1), src->format, &R3, &G3, &B3, &A3);\
SDL_GetRGBA(sge_GetPixel(src,rx+1,ry+1), src->format, &R4, &G4, &B4, &A4);\
\
/* Calculate the average */\
R = (p1*R1 + p2*R2 + p3*R3 + p4*R4)>>13;\
G = (p1*G1 + p2*G2 + p3*G3 + p4*G4)>>13;\
B = (p1*B1 + p2*B2 + p3*B3 + p4*B4)>>13;\
A = (p1*A1 + p2*A2 + p3*A3 + p4*A4)>>13;\
\
_PutPixelX(dst,x,y,SDL_MapRGBA(dst->format, R, G, B, A)); \
\
} \
sx += ctx; /* Incremental transformations */ \
sy -= sty; \
} \
}
Uint8 _sge_lock=1;
SDL_Rect sge_transformAA(SDL_Surface *src, SDL_Surface *dst, float angle, float xscale, float yscale ,Uint16 px, Uint16 py, Uint16 qx, Uint16 qy, Uint8 flags)
{
Sint32 dy, sx, sy;
Sint16 x, y, rx, ry;
SDL_Rect r;
r.x = r.y = r.w = r.h = 0;
float theta = (float)(angle*PI/180.0); /* Convert to radians. */
// Here we use 18.13 fixed point integer math
// Sint32 should have 31 usable bits and one for sign
// 2^13 = 8192
// Check scales
Sint32 maxint = (Sint32)(pow(2, sizeof(Sint32)*8 - 1 - 13)); // 2^(31-13)
if( xscale == 0 || yscale == 0)
return r;
if( 8192.0/xscale > maxint )
xscale = (float)(8192.0/maxint);
else if( 8192.0/xscale < -maxint )
xscale = (float)(-8192.0/maxint);
if( 8192.0/yscale > maxint )
yscale = (float)(8192.0/maxint);
else if( 8192.0/yscale < -maxint )
yscale = (float)(-8192.0/maxint);
// Fixed-point equivalents
Sint32 const stx = (Sint32)((sin(theta)/xscale) * 8192.0);
Sint32 const ctx = (Sint32)((cos(theta)/xscale) * 8192.0);
Sint32 const sty = (Sint32)((sin(theta)/yscale) * 8192.0);
Sint32 const cty = (Sint32)((cos(theta)/yscale) * 8192.0);
Sint32 const mx = (Sint32)(px*8192.0);
Sint32 const my = (Sint32)(py*8192.0);
// Compute a bounding rectangle
Sint16 xmin=0, xmax=dst->w, ymin=0, ymax=dst->h;
_calcRect(src, dst, theta, xscale, yscale, px, py, qx, qy, &xmin,&ymin, &xmax,&ymax);
// Clip to src surface
Sint16 sxmin = sge_clip_xmin(src);
Sint16 sxmax = sge_clip_xmax(src);
Sint16 symin = sge_clip_ymin(src);
Sint16 symax = sge_clip_ymax(src);
// Some terms in the transform are constant
Sint32 const dx = xmin - qx;
Sint32 const ctdx = ctx*dx;
Sint32 const stdx = sty*dx;
// Lock surfaces... hopfully less than two needs locking!
if ( SDL_MUSTLOCK(src) && _sge_lock )
if ( SDL_LockSurface(src) < 0 )
return r;
if ( SDL_MUSTLOCK(dst) && _sge_lock ){
if ( SDL_LockSurface(dst) < 0 ){
if ( SDL_MUSTLOCK(src) && _sge_lock )
SDL_UnlockSurface(src);
return r;
}
}
TRANSFORM_GENERIC_AA
// Unlock surfaces
if ( SDL_MUSTLOCK(src) && _sge_lock )
SDL_UnlockSurface(src);
if ( SDL_MUSTLOCK(dst) && _sge_lock )
SDL_UnlockSurface(dst);
//Return the bounding rectangle
r.x=xmin; r.y=ymin; r.w=xmax-xmin; r.h=ymax-ymin;
return r;
}
SDL_Rect sge_transform(SDL_Surface *src, SDL_Surface *dst, float angle, float xscale, float yscale, Uint16 px, Uint16 py, Uint16 qx, Uint16 qy, Uint8 flags)
{
return sge_transformAA(src, dst, angle, xscale, yscale, px, py, qx, qy, flags);
}
SDL_Surface *sge_transform_surface(SDL_Surface *src, Uint32 bcol, float angle, float xscale, float yscale, Uint8 flags)
{
float theta = (float)(angle*PI/180.0); /* Convert to radians. */
// Compute a bounding rectangle
Sint16 xmin=0, xmax=0, ymin=0, ymax=0;
_calcRect(src, NULL, theta, xscale, yscale, 0, 0, 0, 0, &xmin,&ymin, &xmax,&ymax);
Sint16 w = xmax-xmin+1;
Sint16 h = ymax-ymin+1;
Sint16 qx = -xmin;
Sint16 qy = -ymin;
SDL_Surface *dest;
dest = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask);
if(!dest)
return NULL;
// sge_ClearSurface(dest,bcol); //Set background color
sge_transform(src, dest, angle, xscale, yscale, 0, 0, qx, qy, flags);
return dest;
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER);
}
img_t gfx_scale(img_t src, float xscale, float yscale)
{
return (img_t)sge_transform_surface((SDL_Surface *)src, 0, 0, xscale, yscale, 0);
return (img_t)zoomSurface((SDL_Surface *)src, xscale, yscale, 1);
}
fnt_t fnt_load(const char *fname, int size)
@ -897,6 +587,7 @@ struct word {
struct word *next; /* in line */
struct line *line;
struct xref *xref;
SDL_Surface *prerend;
};
struct word *word_new(const char *str)
@ -914,6 +605,7 @@ struct word *word_new(const char *str)
w->style = 0;
w->img = NULL;
w->unbrake = 0;
w->prerend = NULL;
return w;
}
@ -925,6 +617,9 @@ void word_free(struct word *word)
// gfx_free_image(word->img);
if (word->word)
free(word->word);
if (word->prerend)
SDL_FreeSurface(word->prerend);
word->prerend = NULL;
free(word);
}
@ -1172,8 +867,8 @@ void layout_add_line(struct layout *layout, struct line *line)
{
struct line *l = layout->lines;
line->layout = layout;
if (line->w > layout->w)
layout->w = line->w;
// if (line->w > layout->w)
// layout->w = line->w;
if (!l) {
layout->lines = line;
line->prev = NULL;
@ -1186,6 +881,16 @@ void layout_add_line(struct layout *layout, struct line *line)
return;
}
struct image *_layout_lookup_image(struct layout *layout, const char *name)
{
struct image *g = layout->images;
for (g = layout->images; g; g = g->next) {
if (!strcmp(g->name, name))
return g;
}
return NULL;
}
void layout_add_image(struct layout *layout, struct image *image)
{
struct image *g = layout->images;
@ -1201,12 +906,8 @@ void layout_add_image(struct layout *layout, struct image *image)
img_t layout_lookup_image(struct layout *layout, char *name)
{
struct image *g = layout->images;
for (g = layout->images; g; g = g->next) {
if (!strcmp(g->name, name))
return g->image;
}
return NULL;
struct image *g = _layout_lookup_image(layout, name);
return (g)?g->image: NULL;
}
void layout_add_xref(struct layout *layout, struct xref *xref)
@ -1257,6 +958,11 @@ int txt_layout_add_img(layout_t lay, const char *name, img_t img)
{
struct layout *layout = (struct layout *)lay;
struct image *image;
image = _layout_lookup_image(layout, name);
if (image) { /* overwrite */
image->image = img;
return 0;
}
image = image_new(name, img);
if (!image)
return -1;
@ -1573,7 +1279,6 @@ void xref_update(xref_t pxref, int x, int y, clear_fn clear)
gfx_noclip();
}
void txt_layout_draw_ex(layout_t lay, struct line *line, int x, int y, int off, int height, clear_fn clear)
{
struct layout *layout = (struct layout*)lay;
@ -1618,11 +1323,15 @@ void txt_layout_draw_ex(layout_t lay, struct line *line, int x, int y, int off,
col = acol;
else
col = lcol;
s = TTF_RenderUTF8_Blended((TTF_Font *)(layout->fn),
word->word, col);
s = word->prerend;
if (!s) {
s = TTF_RenderUTF8_Blended((TTF_Font *)(layout->fn),
word->word, col);
word->prerend = s;
}
yy = (line->h - TTF_FontHeight((TTF_Font *)(layout->fn))) / 2; // TODO
gfx_draw(s, x + word->x, y + line->y + yy);
SDL_FreeSurface(s);
// SDL_FreeSurface(s);
}
}
// gfx_noclip();
@ -1693,33 +1402,67 @@ void txt_box_resize(textbox_t tbox, int w, int h)
void txt_box_size(textbox_t tbox, int *w, int *h)
{
struct textbox *box = (struct textbox *)tbox;
if (!tbox)
return;
if (w)
*w = box->w;
if (h)
*h = box->h;
}
void txt_box_scroll(textbox_t tbox, int disp)
void txt_box_scroll_next(textbox_t tbox, int disp)
{
int ld;
int off;
struct textbox *box = (struct textbox *)tbox;
struct line *line = box->line;
if (!line)
return;
ld = box->off - line->y + disp;
while (line && ld > line->h) {
ld -= line->h;
if (box->lay->h - box->off < box->h)
return;
off = box->lay->h - box->off - box->h;
if (disp > off)
disp = off;
off = box->off - line->y; /* offset from cur line */
off += disp; /* needed offset */
while (line->next && off > line->h) {
off -= line->h;
line = line->next;
}
if (line) {
box->line = line;
box->off = line->y + ld;
box->line = line;
box->off = line->y + off;
}
void txt_box_scroll_prev(textbox_t tbox, int disp)
{
int off;
struct textbox *box = (struct textbox *)tbox;
struct line *line = box->line;
if (!line)
return;
off = box->off - line->y; /* offset from cur line */
off -= disp; /* offset from current line */
while (line->prev && off < 0) {
line = line->prev;
off += line->h;
}
// line = line->next;
// if (line) {
// box->off += (line->y - box->off);
// box->line = line;
// }
box->line = line;
box->off = line->y + off;
if (box->off <0)
box->off = 0;
}
void txt_box_scroll(textbox_t tbox, int disp)
{
if (disp >0)
return txt_box_scroll_next(tbox, disp);
else if (disp <0)
return txt_box_scroll_prev(tbox, -disp);
}
void txt_box_next_line(textbox_t tbox)
@ -1885,6 +1628,9 @@ img_t get_img(struct layout *layout, char *p)
{
int len;
img_t img;
if (!p)
return NULL;
if (p[0] != '<' || p[1] != 'g' || p[2] != ':')
return NULL;
p += 3;
@ -1964,7 +1710,7 @@ int get_unbrakable_len(struct layout *layout, const char *ptr)
int w = 0;
int ww = 0;
char *p, *eptr;
while (*ptr) {
while (ptr && *ptr) {
int sp, sp2 = 0;
while(get_token(ptr, &eptr, NULL, &sp)) {
if (sp)
@ -1976,7 +1722,8 @@ int get_unbrakable_len(struct layout *layout, const char *ptr)
p = get_word(ptr, &eptr, &sp);
if (!p)
return w;
if (sp) {
if (sp || !*p) {
free(p);
return w;
}
@ -2002,7 +1749,7 @@ void _txt_layout_add(layout_t lay, char *txt)
int w, h, nl = 0;
int spw;
img_t img = NULL;
if (!layout)
if (!layout || !layout->fn)
return;
saved_style = TTF_GetFontStyle((TTF_Font *)(layout->fn));
@ -2041,18 +1788,20 @@ void _txt_layout_add(layout_t lay, char *txt)
sp = 1;
} else
p = get_word(ptr, &eptr, &sp);
if (!p)
break;
addlen = get_unbrakable_len(layout, eptr);
img = get_img(layout, p);
if (img) {
w = gfx_img_w(img);
h = gfx_img_h(img);
} else {
// fprintf(stderr,"AAA:'%s'\n", p);
TTF_SizeUTF8((TTF_Font *)(layout->fn), p, &w, &h);
}
nl = !*p;
if ((line->num && (line->w + ((line->w)?spw:0) + w + addlen) >= layout->w) || nl) {
// if ((line->num && (line->w + ((sp)?spw:0) + w) >= layout->w) || nl) {
if ((line->num && (line->w + ((sp && line->w)?spw:0) + w + addlen) > layout->w) || nl) {
struct line *ol = line;
if ((layout->h) && (line->y + line->h) >= layout->h)
break;
@ -2253,30 +2002,36 @@ void gfx_cursor(int *xp, int *yp, int *w, int *h)
#define ALPHA_STEPS 5
volatile int step_nr = -1;
SDL_mutex *sem;
static Uint32 update(Uint32 interval, void *aux)
static void update_gfx(void *aux)
{
img_t img = (img_t) aux;
if (step_nr == -1)
return;
gfx_set_alpha(img, (255 * (step_nr + 1)) / ALPHA_STEPS);
gfx_draw(img, 0, 0);
gfx_flip();
step_nr ++;
if (step_nr == ALPHA_STEPS) {
step_nr = -1;
return 0;
}
}
static Uint32 update(Uint32 interval, void *aux)
{
push_user_event(update_gfx, aux);
return interval;
}
extern void nsleep(int delay);
void gfx_change_screen(img_t src)
{
sem = SDL_CreateMutex();
struct inp_event ev;
memset(&ev, 0, sizeof(ev));
SDL_TimerID han;
step_nr = 0;
SDL_AddTimer(60, update, src);
while (step_nr != -1) {
usleep(100);
}
SDL_DestroyMutex(sem);
han = SDL_AddTimer(60, update, src);
while (input(&ev, 1) >=0 && step_nr != -1); /* just wait for change */
SDL_RemoveTimer(han);
}

View File

@ -36,7 +36,8 @@ extern void gfx_noclip(void);
extern void gfx_clip(int x, int y, int w, int h);
extern int gfx_width;
extern int gfx_height;
extern int gfx_init(int w, int h, int fs);
extern int gfx_init(void);
extern int gfx_setmode(int w, int h, int fs);
extern void gfx_update(int x, int y, int w, int h);
extern void gfx_done(void);
extern void gfx_clear(int x, int y, int w, int h);
@ -44,7 +45,7 @@ extern void gfx_draw(img_t pixmap, int x, int y);
extern void gfx_draw_wh(img_t p, int x, int y, int w, int h);
extern img_t gfx_grab_screen(int x, int y, int w, int h);
extern img_t gfx_new(int w, int h);
extern img_t gfx_load_image(char *filename, int transparent);
extern img_t gfx_load_image(char *filename);
extern void gfx_free_image(img_t pixmap);
extern int gfx_img_w(img_t pixmap);
extern int gfx_img_h(img_t pixmap);
@ -86,6 +87,7 @@ extern void txt_box_next(textbox_t tbox);
extern void txt_box_prev(textbox_t tbox);
extern void txt_box_next_line(textbox_t tbox);
extern void txt_box_prev_line(textbox_t tbox);
extern void txt_box_scroll(textbox_t tbox, int disp);
extern xref_t txt_box_xref(textbox_t tbox, int x, int y);
extern int txt_box_off(textbox_t tbox);
extern void txt_box_size(textbox_t tbox, int *w, int *h);

View File

@ -13,15 +13,18 @@ iface.xref = function(self, str, obj)\n\
if not o then\n\
o = ref(inv():srch(obj));\n\
end\n\
if not o or not o.id then\n\
if not isObject(o) or not o.id then\n\
return str;\n\
-- error ('Xref to nowhere:'..str);\n\
end\n\
return cat('<a:'..cmd..tostring(o.id)..'>',str,'</a>');\n\
return cat('<a:'..cmd..'0'..tostring(o.id)..'>',str,'</a>');\n\
end;\n\
iface.title = function(self, str)\n\
return nil\n\
end;\n\
iface.em = function(self, str)\n\
if str == nil then return nil; end; \n\
return cat('<i>',str,'</i>');\n\
end;\n\
\n\
iface.inv = function(self, str)\n\
if str then\n\

View File

@ -1,18 +1,56 @@
#include <SDL.h>
#include "input.h"
#include <strings.h>
#include <stdio.h>
void push_user_event(void (*p) (void*), void *data)
{
SDL_Event event;
SDL_UserEvent uevent;
uevent.type = SDL_USEREVENT;
uevent.code = 0;
event.type = SDL_USEREVENT;
uevent.data1 = p;
uevent.data2 = data;
event.user = uevent;
SDL_PushEvent(&event);
}
int input_init(void)
{
SDL_EnableKeyRepeat(500, 30);
return 0;
}
void input_clear(void)
{
SDL_Event event;
while (SDL_PollEvent(&event));
return;
}
int input(struct inp_event *inp, int wait)
{
int rc;
SDL_Event event;
if (wait)
SDL_Event peek;
memset(&event, 0, sizeof(event));
memset(&peek, 0, sizeof(peek));
if (wait) {
rc = SDL_WaitEvent(&event);
else
} else
rc = SDL_PollEvent(&event);
if (!rc)
return 0;
inp->sym = NULL;
inp->type = 0;
inp->count = 1;
switch(event.type){
case SDL_USEREVENT: {
void (*p) (void*) = event.user.data1;
p(event.user.data2);
return AGAIN;
}
case SDL_QUIT:
return -1;
case SDL_KEYDOWN: //A key has been pressed
@ -29,6 +67,10 @@ int input(struct inp_event *inp, int wait)
inp->type = MOUSE_MOTION;
inp->x = event.button.x;
inp->y = event.button.y;
while (SDL_PeepEvents(&peek, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEMOTION)) > 0) {
inp->x = peek.button.x;
inp->y = peek.button.y;
}
break;
case SDL_MOUSEBUTTONUP:
inp->type = MOUSE_UP;
@ -47,6 +89,16 @@ int input(struct inp_event *inp, int wait)
inp->type = MOUSE_WHEEL_UP;
else if (event.button.button == 5)
inp->type = MOUSE_WHEEL_DOWN;
while (SDL_PeepEvents(&peek, 1, SDL_GETEVENT, SDL_EVENTMASK (SDL_MOUSEBUTTONDOWN)) > 0) {
if (!((event.button.button == 4 &&
inp->type == MOUSE_WHEEL_UP) ||
(event.button.button == 5 &&
inp->type == MOUSE_WHEEL_DOWN)))
break;
inp->count ++;
}
break;
}
return 1;

View File

@ -8,15 +8,21 @@
#define MOUSE_WHEEL_UP 5
#define MOUSE_WHEEL_DOWN 6
#define MOUSE_MOTION 7
#define USER_EVENT 8
#define AGAIN 2
struct inp_event {
int type;
int code;
char *sym;
int x;
int y;
int count;
};
int input(struct inp_event *ev, int wait);
int input_init(void);
void input_clear(void);
void push_user_event(void (*p) (void*), void *data);
#endif

View File

@ -1,3 +1,7 @@
#ifndef STEAD_PATH
#define STEAD_PATH "./stead"
#endif
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
@ -5,39 +9,99 @@
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <libintl.h>
// #include <libintl.h>
#include <unistd.h>
#include "gui.h"
#ifdef HAVE_ICONV
#ifdef _HAVE_ICONV
#include <iconv.h>
#endif
#include "game.h"
/* the Lua interpreter */
char *fromgame(const char *s);
char *togame(const char *s);
lua_State *L = NULL;
static int report (lua_State *L, int status)
{
if (status && !lua_isnil(L, -1)) {
const char *msg = lua_tostring(L, -1);
if (msg == NULL)
msg = "(error object is not a string)";
fprintf(stderr,"Error: %s\n", msg);
game_err_msg(msg);
lua_pop(L, 1);
status = -1;
}
return status;
}
static int traceback (lua_State *L)
{
lua_getfield(L, LUA_GLOBALSINDEX, "debug");
if (!lua_istable(L, -1)) {
lua_pop(L, 1);
return 1;
}
lua_getfield(L, -1, "traceback");
if (!lua_isfunction(L, -1)) {
lua_pop(L, 2);
return 1;
}
lua_pushvalue(L, 1); /* pass error message */
lua_pushinteger(L, 2); /* skip this function and traceback */
lua_call(L, 2, 1); /* call debug.traceback */
return 1;
}
extern int debug_sw;
static int docall (lua_State *L)
{
int status;
int base = 0;
if (debug_sw) {
base = lua_gettop(L); /* function index */
lua_pushcfunction(L, traceback); /* push traceback function */
lua_insert(L, base); /* put it under chunk and args */
}
status = lua_pcall(L, 0, LUA_MULTRET, base);
if (debug_sw)
lua_remove(L, base); /* remove traceback function */
/* force a complete garbage collection in case of errors */
if (status != 0)
lua_gc(L, LUA_GCCOLLECT, 0);
return status;
}
static int dofile (lua_State *L, const char *name) {
int status = luaL_loadfile(L, name) || docall(L);
return report(L, status);
}
static int dostring (lua_State *L, const char *s) {
int status = luaL_loadstring(L, s) || docall(L);
return report(L, status);
}
char *getstring(char *cmd)
{
char *s;
if (!L)
return NULL;
if (luaL_dostring(L, cmd)) {
fprintf(stderr,"Error: %s\n", lua_tostring(L, -1));
exit(1);
}
if (dostring(L, cmd))
return NULL;
s = (char*)lua_tostring(L, -1);
if (s)
s = fromgame(s);
return s;
}
char *instead_eval(char *s)
{
char *p;
// s = togame(s);
p = getstring(s);
// free(s);
return p;
}
@ -62,20 +126,19 @@ int luacall(char *cmd)
int rc;
if (!L)
return -1;
if (luaL_dostring(L, cmd)) {
fprintf(stderr,"Error: %s\n", lua_tostring(L, -1));
exit(1);
if (dostring(L, cmd)) {
return -1;
}
rc = lua_tonumber(L, -1);
return rc;
}
#ifdef HAVE_ICONV
#ifdef _HAVE_ICONV
static char *curcp = "UTF-8";
static char *fromcp = NULL;
#endif
#ifdef HAVE_ICONV
#ifdef _HAVE_ICONV
#define CHAR_MAX_LEN 4
static char *decode(iconv_t hiconv, const char *s)
{
@ -162,11 +225,10 @@ char *togame(const char *s)
int instead_load(char *game)
{
if (luaL_loadfile(L, game) || lua_pcall(L, 0, 0, 0)) {
fprintf(stderr,"Error:%s\n", lua_tostring(L, -1));
if (dofile(L, game)) {
return -1;
}
#ifdef HAVE_ICONV
#ifdef _HAVE_ICONV
if (fromcp)
free(fromcp);
fromcp = getstring("return game.codepage;");
@ -181,34 +243,27 @@ int instead_init(void)
/* initialize Lua */
L = lua_open();
luaL_openlibs(L);
if (luaL_loadfile(L,STEAD_PATH"stead.lua") || lua_pcall(L, 0, 0, 0)) {
fprintf(stderr,"Error:%s\n", lua_tostring(L, -1));
if (dofile(L,STEAD_PATH"/stead.lua")) {
return -1;
}
if (luacall(instead_gui_lua)) {
fprintf(stderr,"Error while registering lua gui functions\n");
return -1;
}
#if 0
if (luaL_loadfile(L,"gui.lua") || lua_pcall(L, 0, 0, 0)) {
fprintf(stderr,"Error:%s\n", lua_tostring(L, -1));
return -1;
}
#endif
/* cleanup Lua */
return 0;
}
void instead_done(void)
{
#ifdef HAVE_ICONV
#ifdef _HAVE_ICONV
if (fromcp)
free(fromcp);
#endif
if (L)
lua_close(L);
L = NULL;
#ifdef _HAVE_ICONV
fromcp = NULL;
#endif
}

View File

@ -6,5 +6,6 @@ extern int instead_load(char *game);
extern void instead_done(void);
extern char *instead_cmd(char *s);
extern char *instead_eval(char *s);
char *fromgame(const char *s);
#endif

View File

@ -1,20 +1,65 @@
#include <unistd.h>
#include <stdlib.h>
#include "graphics.h"
#include "game.h"
#include <stdio.h>
#include <sys/fcntl.h>
#include <string.h>
extern int debug_init(void);
extern void debug_done(void);
int debug_sw = 0;
int main(int argc, char **argv)
{
if (games_lookup()) {
fprintf(stderr, "No games found.\n");
// exit(1);
int i;
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i],"-alsa"))
alsa_sw = 1;
else if (!strcmp(argv[i], "-nosound"))
nosound_sw = 1;
else if (!strcmp(argv[i], "-fullscreen"))
fullscreen_sw = 1;
else if (!strcmp(argv[i], "-window"))
window_sw = 1;
else if (!strcmp(argv[i], "-debug"))
debug_sw = 1;
}
if (debug_sw) {
debug_init();
}
if (game_init(NULL)) {
exit(1);
if (window_sw)
opt_fs = 0;
if (fullscreen_sw)
opt_fs = 1;
if (games_lookup(GAMES_PATH)) {
fprintf(stderr, "No games found.\n");
}
themes_lookup(THEMES_PATH);
themes_lookup(game_local_themes_path());
games_lookup(game_local_games_path());
cfg_load();
if (opt_theme)
game_theme_select(opt_theme);
if (!curtheme)
game_theme_select(DEFAULT_THEME);
if (game_init(opt_game)) {
game_error(opt_game);
}
game_loop();
cfg_save();
game_done();
if (debug_sw)
debug_done();
return 0;
}

103
src/sdl-instead/menu-en.h Normal file
View File

@ -0,0 +1,103 @@
#define UNKNOWN_ERROR "Unknown error."
#define ERROR_MENU "Error while loading game:\n\
'%s'\n\
\n\
<a:/select>Ok</a>"
#define WARNING_MENU "Error while processing game:\n\
'%s'\n\
\n\
<a:/resume>Ok</a>"
#define SAVE_SLOT_EMPTY "empty"
#define SELECT_LOAD_MENU "Load game\n\n"
#define AUTOSAVE_SLOT "Autosave"
#define BROKEN_SLOT "error"
#define SELECT_SAVE_MENU "Save game\n\n"
#define MAIN_MENU \
"<a:/resume>Resume game</a>\n\
<a:/select>Select game</a>\n\
<a:/themes>Select theme</a>\n\
<a:/new>Restart game</a>\n\
<a:/load_menu>Load game</a>\n\
<a:/save_menu>Save game</a>\n\
<a:/about>About</a>\n\
<a:/settings>Settings</a>\n\
<a:/ask_quit>Quit</a>"
#define ABOUT_MENU \
"Written by Peter Kosyh '2009\n\
Ported to Windows by Ilja Ryndin\n\
\n\
Homepage:\n\
<u>http://instead.googlecode.com</u>\n\
\n\
<a:/main>Back</a>"
#define BACK_MENU "<a:/main>Back</a>"
#define ON "on"
#define OFF "off"
#define SELECT_GAME_MENU "Select game to play\n\n"
#define SELECT_THEME_MENU "Select theme\n\n"
#define SETTINGS_MENU \
"Volume\n\
<a:/vol--><<</a><a:/vol-><</a> <a:/mtoggle>%d%%</a> <a:/vol+>></a><a:/vol++>>></a>\n\
\n\
Quality\n\
<a:/hz-><<</a> %dHz <a:/hz+>>></a>\n\
\n\
Music: <a:/music>%s</a>\n\
Click sound: <a:/click>%s</a>\n\
\n\
Full Screen: <a:/fs>%s</a>\n\
Font scaling: <a:/fs--><<</a>%d<a:/fs++>>></a>\n\
Refs highlighting: <a:/hl>%s</a>\n\
Motion mode: <a:/motion>%s</a>\n\
Mouse filter: <a:/filter>%s</a>\n\
\n\
Custom game themes: <a:/owntheme>%s</a>\n\
Аutosave: <a:/autosave>%s</a>\n\
\n\
<a:/main>Apply</a>"
#define OWN_THEME_MENU \
"Warning!!!\n\
\n\
Current game have custom theme.\n\
So, changes will be ignored.\n\
\n\
<i>You can disable custom themes\n\
in settings menu.</i>\n\
\n\
<a:/resume>Ok</a>"
#define CUSTOM_THEME_MENU \
"Warning!!!\n\
\n\
This game have custom theme, but custom theme setting is disabled. \
Game may look differ than author's design.\n\
\n\
<i>You can enable custom theme support in settings menu.</i>\n\
\n\
<a:/resume>Ok</a>"
#define QUIT_MENU \
"Really quit?\n\
\n\
<a:/quit>Yes</a> | <a:/main>No</a>"
#define SAVED_MENU \
"Current Game saved!\n\
\n\
<a:/main>Ok</a>"
#define NOGAMES_MENU \
"No games found. \n\
Please, put any game in the this directory:\n'%s'"
#define NOTHEMES_MENU \
"No themes found.\n\
Please, write any theme in this directory:\n'%s'"

105
src/sdl-instead/menu.h Normal file
View File

@ -0,0 +1,105 @@
#define UNKNOWN_ERROR "Неизвестная ошибка."
#define ERROR_MENU "Во время инициализации игры произошла ошибка:\n\
'%s'\n\
\n\
<a:/select>Да</a>"
#define WARNING_MENU "Во время работы игры произошла ошибка:\n\
'%s'\n\
\n\
<a:/resume>Да</a>"
#define SAVE_SLOT_EMPTY "пусто"
#define SELECT_LOAD_MENU "Загрузите игру\n\n"
#define AUTOSAVE_SLOT "Автосохранение"
#define BROKEN_SLOT "ошибка"
#define SELECT_SAVE_MENU "Сохраните игру\n\n"
#define MAIN_MENU \
"<a:/resume>Вернуться в игру</a>\n\
<a:/select>Выбор игры</a>\n\
<a:/themes>Выбор темы</a>\n\
<a:/new>Начать заново</a>\n\
<a:/load_menu>Загрузить игру</a>\n\
<a:/save_menu>Сохранить игру</a>\n\
<a:/about>Информация</a>\n\
<a:/settings>Настройки</a>\n\
<a:/ask_quit>Выход</a>"
#define ABOUT_MENU \
"INSTEAD SDL - "VERSION"\n\
\n\
Интерпретатор простых\n\
текстовых приключений.\n\
Косых П.А. '2009\n\
\n\
Версия для Windows\n\
Рындин И.В. '2009\n\
\n\
Сайт проекта:\n\
<u>http://instead.googlecode.com</u>\n\
\n\
<a:/main>Назад</a>"
#define BACK_MENU "<a:/main>Назад</a>"
#define ON "Да"
#define OFF "Нет"
#define SETTINGS_MENU \
"Громкость\n\
<a:/vol--><<</a><a:/vol-><</a> <a:/mtoggle>%d%%</a> <a:/vol+>></a><a:/vol++>>></a>\n\
\n\
Качество звука\n<a:/hz-><<</a> %dГц <a:/hz+>>></a>\n\
\n\
Музыка: <a:/music>%s</a>\n\
Звук щелчка: <a:/click>%s</a>\n\
\n\
Полный экран: <a:/fs>%s</a>\n\
Масштаб шрифта: <a:/fs--><<</a>%d<a:/fs++>>></a>\n\
Подсветка ссылок: <a:/hl>%s</a>\n\
Режим прокрутки: <a:/motion>%s</a>\n\
Фильтр мышки: <a:/filter>%s</a>\n\
\n\
Собственные темы игр: <a:/owntheme>%s</a>\n\
Автосохранение: <a:/autosave>%s</a>\n\
\n\
<a:/main>Применить</a>"
#define CUSTOM_THEME_MENU \
"Внимание!!!\n\
\n\
Игра содержит собственную тему, но поддержка собственных тем отключена в настройках. \
Игра может выглядеть не так, как задумывал ее автор.\n\
\n\
<i>Вы можете разрешить возможность переопределения тем в настройках.</i>\n\
\n\
<a:/resume>Да</a>"
#define OWN_THEME_MENU \
"Внимание!!!\n\
\n\
Выбранная игра переопределяет тему. Изменения не вступят в силу.\n\
\n\
<i>Вы можете запретить возможность переопределения тем в настройках.</i>\n\
\n\
<a:/resume>Да</a>"
#define QUIT_MENU \
"На самом деле выйти?\n\
\n\
<a:/quit>Да</a> | <a:/main>Нет</a>"
#define SELECT_GAME_MENU "Выбор игры\n\n"
#define SELECT_THEME_MENU "Выбор темы\n\n"
#define SAVED_MENU \
"Игра сохранена!\n\
\n\
<a:/main>Да</a>"
#define NOGAMES_MENU \
"Не найдена ни одна игра.\n\
Пожалуйста, скопируйте хотя бы одну игру в каталог:\n'%s'"
#define NOTHEMES_MENU \
"Не найдена ни одна тема.\n\
Пожалуйста, скопируйте хотя бы одну тему в каталог:\n'%s'"

View File

@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "../../icon/sdl_instead.ico"

View File

@ -1,4 +1,6 @@
#include "sound.h"
#include "input.h"
#include <SDL.h>
#include <SDL_mixer.h>
@ -15,67 +17,123 @@ int audio_buffers = 8192;
static Mix_Music *mus;
static char *next_mus = NULL;
static int next_fadein = 0;
static int next_loop = -1;
static SDL_TimerID timer_id = NULL;
static int sound_on = 0;
static void mus_callback(void *aux)
{
if (!timer_id)
return;
if (snd_playing_mus())
return;
if (mus)
snd_free_mus(mus);
mus = NULL;
if (next_mus) {
snd_play_mus(next_mus, next_fadein, next_loop);
free(next_mus);
next_mus = NULL;
}
SDL_RemoveTimer(timer_id);
timer_id = NULL;
}
static Uint32 callback(Uint32 interval, void *aux)
{
if (!snd_playing_mus()) {
if (mus)
snd_free_mus(mus);
mus = NULL;
if (next_mus) {
snd_play_mus(next_mus, next_fadein);
free(next_mus);
next_mus = NULL;
}
timer_id = NULL;
return 0;
}
return interval;
push_user_event(mus_callback, aux);
return interval;
}
int snd_hz(void)
{
int freq = 0;
Mix_QuerySpec(&freq, NULL, NULL);
if (sound_on)
Mix_QuerySpec(&freq, NULL, NULL);
return freq;
}
int alsa_sw = 0;
int nosound_sw = 0;
int snd_init(int hz)
{
if (nosound_sw)
return -1;
if (!hz)
hz = audio_rate;
else
audio_rate = hz;
audio_buffers = (audio_rate / 11025) * 2048;
if (!audio_buffers) /* wrong parameter? */
audio_buffers = 8192;
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
fprintf(stderr, "Unable to init audio!\n");
return -1;
}
if (alsa_sw) {
SDL_AudioInit("alsa");
}
if (Mix_OpenAudio(hz, audio_format, audio_channels, audio_buffers)) {
fprintf(stderr, "Unable to open audio!\n");
return -1;
}
sound_on = 1;
return 0;
}
int snd_volume_mus(int vol)
{
if (!sound_on)
return 0;
Mix_Volume(-1, vol);
return Mix_VolumeMusic(vol);
}
wav_t snd_load_wav(const char *fname)
{
if (!sound_on)
return NULL;
if (!fname)
return NULL;
return (wav_t)Mix_LoadWAV(fname);
}
void snd_free_wav(wav_t w)
{
if (!w)
return;
Mix_HaltChannel(-1);
Mix_FreeChunk((Mix_Chunk*)w);
}
Mix_Music *snd_load_mus(const char *fname)
{
Mix_Music *mus;
if (!sound_on)
return NULL;
mus = Mix_LoadMUS(fname);
return mus;
}
extern void game_music_finished(void);
int snd_play_mus(char *fname, int ms)
int snd_play_mus(char *fname, int ms, int loop)
{
if (!sound_on)
return 0;
if (snd_playing_mus()) {
if (next_mus) {
free(next_mus);
}
next_mus = strdup(fname);
next_fadein = ms;
next_loop = loop;
if (!timer_id)
timer_id = SDL_AddTimer(200, callback, NULL);
return 1;
@ -84,19 +142,27 @@ int snd_play_mus(char *fname, int ms)
snd_free_mus(mus);
mus = snd_load_mus(fname);
if (!mus)
if (!mus) {
fprintf(stderr,"Can't load '%s'.\n", fname);
return 0;
if (ms)
Mix_FadeInMusic((Mix_Music*)mus, -1, ms);
}
if (loop >= 0)
Mix_HookMusicFinished(game_music_finished);
else
Mix_PlayMusic((Mix_Music*)mus, -1);
snd_volume_mus(snd_volume_mus(-1)); // hack?
Mix_HookMusicFinished(NULL);
if (ms)
Mix_FadeInMusic((Mix_Music*)mus, loop, ms);
else
Mix_PlayMusic((Mix_Music*)mus, loop);
snd_volume_mus(snd_volume_mus(-1)); // SDL hack?
return 0;
}
void snd_stop_mus(int ms)
{
if (!sound_on)
return;
Mix_HookMusicFinished(NULL);
if (ms)
Mix_FadeOutMusic(ms);
else
@ -105,6 +171,8 @@ void snd_stop_mus(int ms)
int snd_playing_mus(void)
{
if (!sound_on)
return 0;
if (Mix_PlayingMusic() | Mix_FadingMusic())
return 1;
return 0;
@ -112,15 +180,29 @@ int snd_playing_mus(void)
void snd_free_mus(mus_t mus)
{
if (!sound_on)
return;
Mix_HaltMusic();
Mix_FreeMusic((Mix_Music*) mus);
}
void snd_play(void *chunk)
{
if (!sound_on)
return;
if (!chunk)
return;
Mix_PlayChannel(-1, (Mix_Chunk*)chunk, 0);
}
void snd_done(void)
{
Mix_HaltMusic();
if (!sound_on)
return;
if (timer_id)
SDL_RemoveTimer(timer_id);
Mix_HaltChannel(-1);
Mix_HaltMusic();
timer_id = NULL;
if (mus)
Mix_FreeMusic((Mix_Music*) mus);
@ -129,5 +211,5 @@ void snd_done(void)
free(next_mus);
next_mus = NULL;
Mix_CloseAudio();
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}

View File

@ -8,12 +8,18 @@
#define SND_BOOM 4
#define SND_FADEOUT 5
#define SND_PAINT 6
typedef void* wav_t;
typedef void* mus_t;
//extern mus_t snd_load_mus(const char *path);
extern void snd_free_mus(mus_t mus);
extern int snd_init(int hz);
extern int snd_hz(void);
extern int snd_play_mus(char *music, int ms);
extern void snd_play(wav_t chunk);
extern void snd_free_wav(wav_t chunk);
extern wav_t snd_load_wav(const char *fname);
extern int snd_play_mus(char *music, int ms, int loop);
extern int snd_playing_mus();
extern void snd_stop_mus(int ms);
extern int snd_volume_mus(int vol);

91
src/sdl-instead/unix.c Normal file
View File

@ -0,0 +1,91 @@
#include <limits.h>
#include <pwd.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <sys/fcntl.h>
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
extern char *curgame;
extern char *curgame_dir;
static char save_path[PATH_MAX];
static char local_games_path[PATH_MAX];
static char local_themes_path[PATH_MAX];
void nsleep(int u)
{
usleep(u);
}
char *game_local_games_path(void)
{
struct passwd *pw;
pw = getpwuid(getuid());
if (!pw)
return NULL;
snprintf(local_games_path, sizeof(local_games_path) - 1 , "%s/.instead/games/", pw->pw_dir);
return local_games_path;
}
char *game_local_themes_path(void)
{
struct passwd *pw;
pw = getpwuid(getuid());
if (!pw)
return NULL;
snprintf(local_themes_path, sizeof(local_themes_path) - 1 , "%s/.instead/themes/", pw->pw_dir);
return local_themes_path;
}
char *game_cfg_path(void)
{
struct passwd *pw;
pw = getpwuid(getuid());
if (!pw)
return NULL;
snprintf(save_path, sizeof(save_path) - 1 , "%s/.insteadrc", pw->pw_dir);
return save_path;
}
char *game_save_path(int cr, int nr)
{
struct passwd *pw;
if (!curgame)
return NULL;
pw = getpwuid(getuid());
if (!pw)
return NULL;
snprintf(save_path, sizeof(save_path) - 1 , "%s/.instead/", pw->pw_dir);
if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST)
return NULL;
snprintf(save_path, sizeof(save_path) - 1 , "%s/.instead/saves", pw->pw_dir);
if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST)
return NULL;
snprintf(save_path, sizeof(save_path) - 1, "%s/.instead/saves/%s/", pw->pw_dir, curgame_dir);
if (cr && mkdir(save_path, S_IRWXU) && errno != EEXIST)
return NULL;
if (nr)
snprintf(save_path, sizeof(save_path) - 1, "%s/.instead/saves/%s/save%d", pw->pw_dir, curgame_dir, nr);
else
snprintf(save_path, sizeof(save_path) - 1, "%s/.instead/saves/%s/autosave", pw->pw_dir, curgame_dir);
return save_path;
}
int debug_init(void)
{
return 0;
}
void debug_done()
{
}

89
src/sdl-instead/windows.c Normal file
View File

@ -0,0 +1,89 @@
#include <windows.h>
#include <shlobj.h>
#include <limits.h>
#include <sys/types.h>
#include <dir.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
extern char *curgame;
extern char *curgame_dir;
static char save_path[PATH_MAX];
void nsleep(int u)
{
Sleep(u);
}
char *game_local_games_path(void)
{
return NULL; /* TODO ? */
}
char *game_local_themes_path(void)
{
return NULL; /* TODO ? */
}
extern void unix_path(char *);
char *app_dir( void )
{
static char appdir[PATH_MAX];
SHGetFolderPath( NULL,
CSIDL_FLAG_CREATE | CSIDL_LOCAL_APPDATA,
NULL,
0,
(LPTSTR)appdir );
unix_path(appdir);
return appdir;
}
char *game_cfg_path( void )
{
snprintf(save_path, sizeof(save_path) - 1 , "%s\\insteadrc", app_dir());
return save_path;
}
char *game_save_path( int cr, int nr )
{
char appdir[PATH_MAX];
strcpy( appdir, app_dir() );
snprintf(save_path, sizeof(save_path) - 1 , "%s/instead", appdir);
if (cr && mkdir(save_path) && errno != EEXIST)
return NULL;
snprintf(save_path, sizeof(save_path) - 1 , "%s/instead/saves", appdir);
if (cr && mkdir(save_path) && errno != EEXIST)
return NULL;
snprintf(save_path, sizeof(save_path) - 1, "%s/instead/saves/%s", appdir, curgame_dir);
if (cr && mkdir(save_path) && errno != EEXIST)
return NULL;
if (nr)
snprintf(save_path, sizeof(save_path) - 1, "%s/instead/saves/%s/save%d", appdir, curgame_dir, nr);
else
snprintf(save_path, sizeof(save_path) - 1, "%s/instead/saves/%s/autosave", appdir, curgame_dir);
return save_path;
}
int debug_init(void)
{
if (!AllocConsole())
return -1;
SetConsoleTitle("Debug");
freopen("CON", "w", stdout); //Map stdout
freopen("CON", "w", stderr); //Map stderr
return 0;
}
void debug_done()
{
FreeConsole();
}

6
stead/Makefile.windows Normal file
View File

@ -0,0 +1,6 @@
clean:
all: stead.lua
install:
if not exist ..\bin\stead mkdir ..\bin\stead
copy stead.lua ..\bin\stead

340
stead/copying Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,6 @@ install:
for f in *; do \
if [ ! -d $$f ]; then continue; fi;\
install -d -m0755 $(THEMESPATH)/$$f;\
tar -c -C $$f . | tar -x -C $(THEMESPATH)/$$f;\
tar --exclude=".svn" -c -C $$f . | tar -x -C $(THEMESPATH)/$$f;\
done

7
themes/Makefile.windows Normal file
View File

@ -0,0 +1,7 @@
include ../Rules.make
clean:
all:
install:
for /D %%f in (*) do ( if not exist "..\bin\themes\%%f" mkdir "..\bin\themes\%%f" )
for /D %%f in (*) do ( copy /Y %%f ..\bin\themes\%%f )

BIN
themes/book/book.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 KiB

33
themes/book/theme.ini Normal file
View File

@ -0,0 +1,33 @@
; $Name:Книга (800x600)$
scr.w = 800
scr.h = 600
scr.gfx.bg = book.png
scr.col.bg = white
scr.gfx.x = 18
scr.gfx.y = 36
scr.gfx.w = 344
scr.gfx.h = 410
scr.gfx.mode = float
win.x = 400
win.y = 18
win.w = 350
win.h = 550
win.col.fg = #000000
win.col.link = #a02c00
win.col.alink = #606060
menu.button.y = 576
inv.x = 30
inv.y = 460
inv.w = 320
inv.h = 100
inv.col.fg = #000000
inv.col.link = #902c00
inv.col.alink = #606060
inv.mode = horizontal

View File

@ -0,0 +1,8 @@
; $Name: Стандартная (800x600)$
scr.w = 800
scr.h = 600
win.h = 568
inv.h = 568
scr.gfx.h = -1
menu.button.y = 576

BIN
themes/default/click.ogg Normal file

Binary file not shown.

BIN
themes/default/click.wav Normal file

Binary file not shown.

View File

@ -1,9 +1,12 @@
; $Name: Стандартная (800x480)$
scr.w = 800
scr.h = 480
scr.gfx.bg = bg.png
scr.col.bg = white
scr.gfx.use = use.png
scr.gfx.pad = 16
scr.gfx.mode = embedded
win.gfx.h = -1 ;unlim
win.x = 48
win.y = 8
@ -11,12 +14,11 @@ win.w = 500
win.h = 448
win.fnt.name = sans.ttf
win.fnt.size = 16
win.gfx.h = 200
win.gfx.up = aup.png
win.gfx.down = adown.png
win.col.fg = #000000
win.col.link = #0000FF
win.col.alink = #FF0000
win.col.fg = black
win.col.link = #b02c00
win.col.alink = #606060
inv.x = 620
inv.y = 8
@ -26,19 +28,22 @@ inv.fnt.name = sans.ttf
inv.fnt.size = 16
inv.gfx.up = aup.png
inv.gfx.down = adown.png
inv.col.fg = #FFFFFF
inv.col.fg = #CCCCCC
inv.col.link = #CCCCCC
inv.col.alink = goldenrod
inv.mode = vertical
menu.col.bg = #FFFFFF
menu.col.fg = #000000
menu.col.link = #0000FF
menu.col.alink = #FF0000
menu.col.alpha = 180
menu.col.border = #000000
menu.col.bg = white
menu.col.fg = black
menu.col.link = blue
menu.col.alink = red
menu.col.alpha = 220
menu.col.border = black
menu.bw = 1
menu.fnt.name = sans.ttf
menu.fnt.size = 15
menu.gfx.button = menu.png
menu.buttonx = 776
menu.buttony = 456
menu.button.x = 776
menu.button.y = 456
snd.click = click.wav ; click.ogg

View File

@ -0,0 +1,7 @@
; $Name:Старая (800x480)
win.col.fg = black
win.col.link = blue
win.col.alink = red
scr.gfx.mode = fixed
scr.gfx.h = 200