Форум TeamX
   Home   Members  
Pages: [1] |   Go Down
 
Author Topic: Placeholders  (Read 737 times)
KLIMaka
Пользователь
Posts: 72


Placeholders
« on: 22 November 2010, 00:08:05 »

Как-то захотелось мне реализовать такую вот штуку, как плейсхолдеры. Вроде разок такое предложение даже на NMA проскользнуло, но так и забылось. Ну и вот наконец общая концепция была реализована. Для понимания всего нижеследующего крайне важно понимание принципа работы скриптовой функции tokenize, так что не поленитесь и загляните в документацию по KA_SSL.

Итак, что такое плейсхолдеры? Будем понимать под ними некоторые зарезервированные слова в сообщениях, которые в момент вывода на экран будут заменятся на нечто иное, более соответствующее контексту. Т.е.  чтобы получить «Hello, Narg! How are you?» вместо такого кода

Code:
display_msg( message_str( NAME, 100) + obj_name(dude_obj) + message_str( NAME, 101));

{100}{}{Hello, }
{101}{}{! How are you?}

Хотелось бы писать нечто подобное:

Code:
Display_msg( parse(message_str(NAME,100)));

{100}{}{Привет, %dude_name%! Как дела?}

Этот магический %dude_name% и есть плейсхолдером, который заменяется на реальное имя ГГ. Самый большой интерес представляет функция parse, которая заменяет текст с плейсхолдерами на реальное сообщение.

Code:
// Здесь последовательно находятся все строки заключенные в % и %, и заменяются на их представление.
procedure parse( variable str )
begin
variable token,  rest, line, result;

line := tokenize(str, 0, '%');
result := line;

while  line != str do
begin
token := tokenize(str, line, '%');
line += "%" + token;
if token == “”
result += “%”;
else if token == “dude_name” then
result += obj_name(dude_obj);

rest := tokenize(str, line, '%');
line += "%" + rest;
result += rest;
end

return result;
end

Важным моментом здесь является выбор разделителя, для обозначения тела плейсхолдера. В данном случае я выбрал знак ‘%’. Это обозначает, что все строки, заключенные в пару разделителей будут распознаваться как плейсхолдеры, также это обозначает, что в теле плейсхолдера использование % недопустимо. Также сам символ % можно получить путем записи пары разделителей ( «95%%» будет интерпретировано как «95%» ), но все же такой вид нельзя применять внутри тела плейсхолдера.

Такая реализация несколько ограниченна, так как для каждого вида плейсхолдера нужен свой блок if-then, и при достаточном их количестве код функции распухнет до неприличных размеров.

Выходом может быть применение функций. Замечательной особенностью  SSL есть то, что функции могут вызываться не только через идентификатор ( call foo();  ), но и с использованием строкового представлении имени функции ( call “foo”(); ). Имея такую возможность функцию parse можно изменить таким образом:

Code:
//-----------------
line += "%" + token;
if token == “”
result += “%”;
//else if token == “dude_name” then
// result += obj_name(dude_obj);  это убираем
else
result += token(); //          а это добавляем
rest := tokenize(str, line, '%');
//-----------------

Теперь нужно только определить функции для всех плейсхолдеров.  Например так:

Code:
procedure dude_name()
begin
return obj_name( dude_obj );
end

procedure dude_money()
begin
return item_caps_total( dude_obj );
end

Теперь запросто можно написать:

Code:
display_msg( parse( “Ah, %dude_name%, only %dude_money% caps? Hm, not so much.” ));

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

Итак, поставим такую задачу: выводить для каждого криттера, к которому привязан данный скрипт, при наведении на него курсора, выводить «Это Наркоман, у которого 15 монет.»
Исходное сообщение может выглядеть так:
Code:
{100}{}{Это %name%, у которого %money% монет.}

Здесь присутствую два плейсхолдера, которые нетрудно определить, их реализацию я оставлю на самостоятельное рассмотрение.

Пока ничего нового, но что делать, если криттер женского пола? Нам нужно в зависимости от пола использовать либо «которого» либо «которой». Для этого можно применить более сложный плейсхолдер, который имеет аргументы, например так:

Code:
{100}{}{Это %name%, у котор%sex:ого|ой% %money% монет.}

Здесь я применяю плейсхолдер с аргументами %sex:ого|ой%, который в зависимости от пола объекта, к которому привязан данный скрипт заменяется либо на «ого» либо на «ой». Для обработки плейсхолдеров такого расширенного вида придется немного поменять функцию  parse. необходимо заменить вызов

Code:
result += token();

на

Code:
result += placeholder( token );

и определить функцию:

Code:
// Вызывает функцию обработчик с аргументами или без. Имя от аргументов отделяются ‘:’.
procedure placeholder( variable name )
begin
variable name1, args;
name1 := tokenize( name, 0, ':'); // получаем имя плейсхолдера
if name1 != name then             // если присутствуют аргументы
begin
args := tokenize( name, name1, ':' );
return name1(args);    // отделяем имя от аргументов и вызываем функцию с аргументами
end
return name1();            // иначе вызываем функцию без аргументов
end

Теперь необходимо определить функцию-обработчик:

Code:
// Возвращает первый аргумент, если объект мужского пола, иначе – второй аргумент. Аргументы разделены ‘|’
procedure sex( variable args )
begin
variable m,f;
m := tokenize( args, 0, '|' ); // мужской
f := tokenize( args, m, '|' ); // женский
if get_critter_stat( self_obj, 34 ) == 1 then
return f;
else
return m;
end

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

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

Code:
{100}{}{Это %name%, у котор%sex:ого|ой% %iq:123|низкий|456|средний|78910|высокий|% интеллект.}

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

Code:
procedure iq(variable args )
begin
variable str, iqq;
iqq := get_critter_stat( self_obj, 4 ) + "";
str := tokenize( args, iqq, '|');
return str;
end

Вот так вот с помощью нескольких строчек кода можно реализовать достаточно мощное и гибкое средство плейсхолдеров. На самом деле такая реализация имеет один ОЧЕНЬ большой недостаток. Каждый скрипт, использующий плейсхолдеры должен содержать в себе определения ВСЕХ функций-обработчиков, т.к. заранее неизвестно, какие из них будут применятся в файле сообщений. При достаточном количестве этих обработчиков размер скрипта может вырасти до космических масштабов, а скрипт такой далеко не один. Поэтому удобнее иметь под рукой библиотеку таких функций, которые буду экспортироваться во все скрипты, при этом код будет присутствовать только в одном скрипте. Но это совсем другая история, о которой я расскажу позже.
« Last Edit: 22 November 2010, 00:22:05 by KLIMaka »
Jordan
Пользователь
Posts: 416

476228895
Re: Placeholders
« Reply #1 on: 22 November 2010, 01:28:08 »

Здорова.

К стати эта тема не нова, Raven над этим тоже экспериментировал.

http://teamx.ru/cgi-bin/ikonboard/topic.cgi?forum=14&topic=44&start=0

А возможно ли в ближайшее время рассмотреть вот этот вопрос?

Quote
Пока все прекрасно работает, и может успешно применятся. Но заканчивать на этом как-то не интересно. Вышеописанная возможность SSL вызывать функции с помощью строкового представления их имен дает огромные возможности, граничащие с возможностью писать скрипты в MSG-файлах. Но пока не станем настолько радикально использовать данный подход, а лишь рассмотрим некоторое расширение.

Воспрянет Россия, из праха отцов
Расправятся крылья, миллионов сердец
Поднимут все головы и грудью вздохнут
И громка скажут, что пришли
Мы пришли, со столетней войны
Jordan
Пользователь
Posts: 416

476228895
Re: Placeholders
« Reply #2 on: 22 November 2010, 16:32:48 »

KLIMaka

С помощью tokeniz, можно узнать сколько символов в строке? Если да, то как?

Воспрянет Россия, из праха отцов
Расправятся крылья, миллионов сердец
Поднимут все головы и грудью вздохнут
И громка скажут, что пришли
Мы пришли, со столетней войны
KLIMaka
Пользователь
Posts: 72


Re: Placeholders
« Reply #3 on: 22 November 2010, 23:40:22 »

Нельзя, увы. Но есть в  sfall  функция string_split, с помощью которой можно это узнать. Например так:

Code:
len := len_array(string_split("foobar",""));
rws5
Пользователь
Posts: 53


Re: Placeholders
« Reply #4 on: 16 January 2011, 14:02:31 »

Я не поленился и заглянул в KA_SSL. У меня возникло два вопроса:
  • Чем компилировать вышенаписанное, compile.exe в папке ka_ssl?
  • Какая связь между Fallout2 и Star Trek: Klingon Academy?

---

Не переводится ли SSL как Startrek Scripting Language?
« Last Edit: 16 January 2011, 15:06:08 by rws5 »
Master
Пользователь
Posts: 211

Чистосердечный зевака


Re: Placeholders
« Reply #5 on: 16 January 2011, 14:08:33 »

Quote
Какая связь между Fallout2 и Star Trek: Klingon Academy?
Осмелюсь преположить, что на основе компилятора скриптов KA был сделан компилятор скриптов Фола. Исходный код-с.

Bugs...? Dammit Gus! I`m a dessert chef, not a programmer!
KLIMaka
Пользователь
Posts: 72


Re: Placeholders
« Reply #6 on: 16 January 2011, 15:51:21 »

Quote
Чем компилировать вышенаписанное, compile.exe в папке ka_ssl?
Нет, компилить компилятором, идущим в поставке с Sfall. Насколько я знаю, только в нем исправлен баг с tokenize.

Quote
Не переводится ли SSL как Startrek Scripting Language?
Именно так и переводится, не поленись заглянуть в шапки фоловских компиляторов.
rws5
Пользователь
Posts: 53


Re: Placeholders
« Reply #7 on: 16 January 2011, 16:25:44 »

Quote from: KLIMaka on 16 January 2011, 15:51:21
не поленись
Ну ты меня выставил просто крайне ленивым человеком  Подмигивающий

Что еще вкусного и полезного можно извлечь из КА, помимо tokenize?
KLIMaka
Пользователь
Posts: 72


Re: Placeholders
« Reply #8 on: 16 January 2011, 16:36:05 »

Собсно, все что можно уже извлекли. Весь остальной функционал чисто для КА специфичен и из фоловского SSL выкинут за ненадобностью. Вот может вскоре напишу несколько строчек о SSL-параллелизме, всякие там fork, spawn, exec, wait... А больше ничего интересного и нету вроде...
Pages: [1] |   Go Up