Ru/Response System

Система Реакций/Реагирования (Response System) используется для того, чтобы решить, какую реплику (и/или анимацию) следует использовать NPC (или игроку), когда они хотят что-то сказать, и стоит ли вообще что-то говорить.
Большинство пользователей системы Response System должны говорить в ответ на события, происходящие в игре. Речь может быть вызвана кодом или вводом данных с карты. Триггерная речь включает в себя реакцию концепт, которая соответствует реакциям в системе. Концепты - это категории речи, используемые в связи с определенным событием, например, с тем, что была замечена опасность (TLK_DANGER) или был увиден враг (TLK_STARTCOMBAT). Хотя концепт можно использовать отдельно для базового и простого диалога, речь также может быть вызвана различными Критериями которые описывают вещи, связанные с концепцией и/или текущим состоянием говорящего и окружающего его мира. Это позволяет создавать сложные диалоговые деревья, включающие разные реплики для разных ситуаций.
Например, в эпизодах серии Half-Life 2 использует концепт TLK_PLAYER_KILLED_NPC - когда игрок убивает враждебного NPC. Этот концепт является дополнительным критерием для условий, относящийся к NPC или способом, как был убит NPC. Если игрок убил NPC выстрелом в голову, система реагирования подберет ответ, включающий такой критерий, и в таком случае Аликс будет хвались игрока за точность или отметит убийство врага выстрелов голову.
По стандарту система реагирований использует скрипты, находящиеся по пути scripts/talker относительно GameInfo.txt. Получив концепцию и её критерии, он ищет в сценариях ответов правило, соответствующее концепции и критериям. Когда правило найдено, он использует его ответ или выбор ответов. Такой ответ может быть как , как заготовленной фразой, так и .
Несмотря на преимущества, большинство NPC не используют эту систему по умолчанию. Например, по умолчанию использует только звуковые скрипты и не использует систему ответов.
Краткий перечень, где используется система реагирования:
* В большинство NPC-компаньонов (, , и т.д.) используют систему правил реагирования для NPC.
* В все классы используют систему реагирования для голосовых команд и ответных колкостей.
* В все выжившие используют систему реагирования, чтобы отвечать на действия игроков и события в мире.
* В Атлас и P-body (роботы в совместном режиме) используют систему реагирования для дразнящих жестов.
* В все персонажи игроков используют систему ответов и следят за тем, какие ответы уже были использованы.
* А что касаемо - посмотрите отдельную статью .
==Задача==
Система Response System была создана для того, чтобы NPC, игроки и т.д. использовали единую и надежную систему управления речью. Она не только позволяет разработчикам и сценаристам создавать сложные диалоговые деревья, но и позволяет моддерам легко изменять или добавлять новую речь в игру без необходимости писать код или изменять BSP-файл, сохраняя при этом полный контроль над тем, как и когда будет использоваться речь.
Эту систему лучше всего использовать для речи, исходящей от системы ИИ, поскольку эти реплики будут произноситься много раз на протяжении всей игры. (например, граждане говорят что-то, когда перезаряжают оружие).
Вот пример сложного диалога с NPC, использующего систему ответов:
*Я только что убил врага.
:*Использовал дробовик?
::*"Съешь свинца!"
:*Был ли враг достаточно близко?
::*"Не так близко!"
::*"Спасибо что подошел!"
:*Был ли врагом ?
::*"Ты не получишь мою бошку!"
::*"Ненавижу хедкрабов!"
Вы также можете использовать комбинации различных критериев.
:*Использовал ли я дробовик против , который был достаточно близко ко мне?
::*"Отойди от моей пушки, хедкраб!"
Вы также можете управлять отдельными строками, чтобы они не повторялись в течение определенного времени или вообще не повторялись.
==Структура==
В Response System'е имеются четыре составные части: Концепты (Concepts), Критерии (Criteria), Правила (Rules), и Группы реакций (Response Groups). И вот каким образом они используются:
#NPC запрашивает реплику для концепции речи.
#*Например, наш NPC запрашивает строку речи для концепции TLK_SHOT. NPC произносит эту концепцию всякий раз, когда в него стреляет враг.
#NPC собирает кучу критериев, отражающих текущее состояние NPC и другие важные данные о состоянии мира. Многие концепции также имеют модификаторы - критерии, уникальные для конкретных концепций, которые обычно отражают само событие.
#*Когда NPC запрашивает концепт TLK_SHOT, игра собирает текущее здоровье NPC (например) как часть набора критериев по умолчанию. Затем он добавляет модификаторы концепции, которые могут включать тип врага, который в них стрелял, количество полученного урона и т.д.
#Концепт и Критерии передаются в систему ответа NPC, которая обычно представляет собой один глобальный экземпляр, общий для всех NPC.
#Теперь система реагирования просматривает большой список правил.
#*Каждое такое правило содержит в себе список критериев, которые который проверяется на соответствие критериям, собранным NPC. Обратите внимание, что на этом этапе концепция рассматривается как высокоприоритетный критерий.
#*Каждое правило получает оценку, основанную на том, сколько критериев верны. Если хотя бы один критерий отмечен как 'обязательный' и не выполнен, правило никогда не будет выбрано. Большинство критериев являются обязательными, но критерии, которые не являются обязательными, просто повышают оценку правила.
#**Для нашего TLK_SHOT может содержаться несколько TLK_SHOT правил, которые имеют различные реплики. Одно правило может содержать критерий, проверяющий насколько близок к NPC враг, который стрелял в него. Другое может проверять, выстелил ли в NPC враг особо класса сущности (как пример, Солдат Альянса). Ещё одно - уровень здоровья NPC (например, осталось ли у NPC хотя бы 25% уровня его здоровья после выстрела.)
#Система реагирования оценивает все правила в своем списке и выбирает то, которое набрало наибольшее количество баллов. Правило, набравшее наибольшее количество баллов, определяет группу реагирования.
#Группа ответов - это лишь список заготовленных заранее ответов, каждый из которых (ответов) может бы, например, репликой и/или анимацией (как в случае использования хореографической сцены). Один ответ выбирается на основе настроек группы ответов и отдельных ответов. Когда выбран правильный ответ, NPC воспроизводит его.
#*Давайте для нашего примера концепта TLK_SHOT сделаем правило, смотрящее за уровнем здоровья NPC (если у NPC меньше 25% его здоровья). У этого правила есть группа ответа, которая может содержать список реплик вроде «Ещё один такой выстрел, и мне конец!», «О, Боже, я в беде!» или «Мне нужна медицинская помощь!».
#*Другое правило для TLK_SHOT может проверить, является ли стреляющий в них враг Солдатом Альянса, и указать на группу ответа с репликами вроде «Этот солдат Альянса прижал меня к земле!» или «Помогите мне с этим солдатом!». Другое правило может проверять, не является ли враг Штурмовиком Альянса, и указывать на группу с репликами «Этот корабль надирает мне задницу!» и «Кто-нибудь, помогите мне уничтожить этот корабль, пока он меня не убил!».
#Если ни одно правило не соответствует заданным критериям (или выбранная группа ответов не повторяется и исчерпана), NPC вообще никак уникально не отреагирует.
===Концепты===
Концепты (Concepts) - это обозначение формата который представляет собой высокоуровневую причину попытки речи персонажа. В коде определен набор концептов, которые будут вызываться автоматически, но технически концепт - это просто специальный высокоуровневый критерий, который персонажи отслеживают. Они ни к чему не привязаны, и вы можете свободно создавать свои собственные в файле ответа. Вы можете вызывать концепции в коде или с помощью Input команды DispatchResponse или НПС.
Вот список некоторых предопределенных концепций NPC, используемых в Half-Life 2:
 TLK_HELLO		Когда я впервые увидел игрока.
 TLK_IDLE		Когда я долго бездействую.
 TLK_USE		 Когда игрок применил +USE ко мне.
 TLK_PLPUSH		Когда игрок толкнул меня.
 TLK_STARE		Когда игрок долгое время смотрит (буквально, пялиться) на меня.
 TLK_DANGER		Когда я понимаю, что рядом со мной опасная обстановка (например, граната).
 TLK_WOUND		Когда я получил урон.
 TLK_HIDEANDRELOAD	Когда я решу спрятаться и перезарядить пистолет.
 TLK_PLYR_PHYSATK	Когда в меня попадает предмет, брошенный игроком.
Не все NPC говорят на всех концептах, и не все NPC говорят на концептах при одинаковых обстоятельствах. Полный список см. в .
===Набор Критериев===
Критерии - это набор условий, которые содержат данные, связанные с текущим состоянием говорящего и обстоятельствами концепции, когда предпринимается попытка речи. Его можно интерпретировать как набор . Вот пример набора критериев, созданного , которая пытается говорить, потому что только что убила своего текущего врага:
 concept = TLK_ENEMY_DEAD Концепт, которое пытается озвучить NPC.
 map = d3_c17_07 Название текущей карты.
 classname = npc_alyx Класс сущности () говорящего NPC.
 name = alyx Имя () говорящего NPC.
 health = 75 Текущий уровень здоровья говорящего NPC.
 healthfrac = 0.9375 Здоровье говорящего NPC, как доля от максимального здоровья NPC (по умолчанию максимальное здоровье npc_alyx равно 80).
 skill.cfg = 1 Текущий уровень скила.
 timesinceseenplayer = 0.090000 Количество времени, прошедшее с тех пор, как говорящий NPC видел игрока.
 distancetoenemy = 312.639679 Расстояние от говорящего NPC до его текущего врага.
 activity = ACT_RUN Анимация, которую выполняет говорящий NPC.
 npcstate = [NPCState::Combat] Состояние ИИ говорящего NPC.
 enemy = npc_combine_s Класс сущности , выступающей врагом говорящего NPC.
 speed = 79.235 Момент скорости говорящего NPC.
 weapon = weapon_alyxgun Текущее оружие, которое держит в руках говорящий NPC.
 distancetoplayer = 211.240692 Расстояние от говорящего NPC до игрока.
 seeplayer = 1 Видит ли говорящий NPC игрока или нет.
 seenbyplayer = 0 Находится ли говорящий NPC в поле зрения игрока.
 readiness = agitated Уровень говорящего NPC.
 playerhealth = 100 Текущий уровень здоровья игрока.
 playerhealthfrac = 1.000 Текущее здоровье игрока, как доля от его максимального уровня.
 playerweapon = weapon_shotgun Текущее оружие, которое держит игрок.
 playeractivity = ACT_WALK Анимация, которую выполняет игрок.
 playerspeed = 0.000 Текущий момент скорости игрока.
По умолчанию у этой концепции нет модификаторов. Все критерии в приведенном выше списке являются общими и собираются для каждой концепции.
Критерии, подобные приведенным в списке, можно проверить по списку критериев правила и использовать для принятия решения о том, какую группу ответов использовать для нужной концепции. Например:
*Критерий enemy можно использовать для выбора правильной реакции на концепцию TLK_ENEMY_DEAD. Вместо того чтобы делать общие заявления, Аликс может сказать: "Я позаботилась о том солдате!" или "Я позаботилась о том хедкрабе!".
*Поле healthfrac можно использовать для выбора строки "Фух, это было близко!", если здоровье Аликс было <20%, когда она прикончила врага.
*Поле distancetoenemy Поле можно использовать для выбора разных реплик, когда она убивает врага на дальнем или ближнем расстоянии. Например, "Эти парни пугают, когда подходят так близко!" или "Нелегко попасть в них на таком расстоянии".
Несмотря на то, что перечисленные выше критерии являются общими и не зависят от конкретной концепции, они всегда будут меняться в зависимости от обстоятельств и не всегда могут быть доступны (например, у NPC, которые не находятся в бою, не будет критериев enemy или distancetoenemy). Кроме того, составители карт могут добавлять дополнительные критерии к определенным NPC или ко всем NPC в игре. Подробнее см. в разделе .
===Критерии правил===
Правила содержат список критериев, которые проверяются на соответствие набору критериев персонажа. Когда правило оценивается, каждый критерий проверяется по заданным данным, и правило получает очки за критерии, которые успешно совпали. Количество очков, которое критерий зарабатывает для правила, определяется его весом.
Критерии задаются в файлах сценариев (см. ниже). Используется следующий формат:
 criterion <criterion name> <key to check> <desired value> <optional: weight X> <optional: required>
Параметры следующие:
;criterion name
:Имя критерия. Не должно совпадать с уже существующими!
;key to check
: Значение в наборе критериев персонажа, которое проверяется этим критерием.
;desired value
: Желаемое значение ключа в наборе критериев. Оно может принимать различные формы:
:*Числовые значения: "0", "1", or "100".
:*Обратные числовые значения: "!=0" будет соответствовать любое значение, не равное нулю.
:*Строковое значение: "npc_alyx", "weapon_alyxgun", или "npc_combine_s".
:* и их значения: "[NPCState::Combat]".
:*Диапазоны: 
:**">0" : Соответствует, если значение больше "0".
:**"<=0.5" : Соответствует, если значение меньше или равно "0,5".
:**">10,<=50" : Соответствует, если значение превышает "10" и если значение не превышает или равно "50".
:**">0,<[NPCState::Alert] : Соответствует, если значение больше "0" и меньше значения перечисления для NPCState::Alert.
:
;weight X
: Необязательный параметр, где X - это количество очков, которое начисляется этому критерию, если он совпадает. Если параметр не указан, то по умолчанию критерий оценивается в 1 балл.
;required
: Необязательный параметр, указывающий, что этот критерий необходим для того, чтобы содержащие его правила вообще использовались. Если обязательный критерий не совпадает, правила, содержащие его, получают 0 баллов и сразу же пропускаются. Большинство критериев используют этот параметр.
И вот некоторые примеры из Half-Life 2:
*Определение критерия, названное PlayerNear, обозначает, что расстояние от игрока до говорящего NPC должно составлять хотя бы 500 юнитов.
:criterion "PlayerNear" "distancetoplayer" "<500" required
*Определение критерия, названное IsCitizen, обозначает, что класс говорящего NPC должен быть .
:criterion "IsCitizen" "classname" "npc_citizen" "required"
*Определение критерия, названное IsMap_d3_c17_12, обозначает, что текущая игра проходит на карте в названием d3_c17_12.bsp. Пригодится для того, чтобы заставить всех сущностей одной карты произносить реплики, отличные от других карт.
:criterion "IsMap_d3_c17_12" "map" "d3_c17_12" "required"
*Здесь определяется критерий IsBob, который проверяет, назван ли NPC как "bob" ("targetname" "bob"). Это уникальный гражданин в игре, и этот критерий позволяет легко заставить его произносить уникальные реплики.
:criterion "IsBob" "targetname" "bob" required
===Правила===
Правило содержит список критериев и по крайней мере одну группу ответов. Правило получает очки за каждый критерий, который успешно соответствует набору критериев говорящего. Правило, набравшее наибольшее количество очков, направляет в одну из своих групп ответов, которая используется для определения точной речи NPC. 
Правила задаются в файлах сценариев (см. ниже). Используется следующий формат:
rule <rule name>
{
 criteria <criterion name 1> [optional: <criterion name 2> <criterion name 3> etc.]
 response <response group name> [optional: <response group name 2> etc.]
 [optional: matchonce]
 [optional: applyContext ]
}
Параметры следующие:
*rule name : Имя правила.
*criteria : Список критериев, по которым правило должно оцениваться.
*response : Список групп ответов, которые должны быть выбраны, если это правило набрало наибольшее количество баллов.
*matchonce : Необязательный параметр, указание которого приводит к деактивации этого правила после того, как оно было выбрано один раз.
*applyContext : Необязательный параметр, который применяет .
Например, следующий текст определяет правило под названием CitizenTalkStare. ConceptTalkStare - это критерий, который проверяет, что концепция, которую хочет произнести говорящий NPC, является TLK_STARE. IsCitizen - критерий, проверяющий, что говорящий NPC является . NPCIdle - критерий, проверяющий, что состояние NPC равно «NPCState::Idle». Если это правило набирает наибольшее количество баллов, то будет использована группа ответа CitizenTalkStare.
rule CitizenTalkStare
{
 criteria ConceptTalkStare IsCitizen NPCIdle
 response CitizenTalkStare
}
Обратите внимание, что имя правила и имя группы ответа могут быть одинаковыми, поскольку имена правил должны быть уникальными только среди правил, а имена групп ответа - только среди групп.
===Группы реакций===
Группы реакций содержат в себе всевозможного рода реагирования вместе с некоторыми необязательными данными, определяющими, как эти ответы должны использоваться. Когда группа ответов выбирается правилом, ответ выбирается из списка и передается говорящему для использования.
Группы ответов определяются в файлах скриптов (см. ниже). Используется следующий формат:
response <response group name>
{
 [optional: permitrepeats]
 [optional: sequential]	 
 [optional: norepeat]		 
 <response type> <response> <optional: ...>
 <response type> <response> <optional: ...>
 <response type> <response> <optional: ...>
}
Параметры группы реагирований следующие:
*permitrepeats : Если указано, ответы в этой группе разрешено повторять. Если не указано, то по умолчанию используются все ответы в списке, прежде чем повторить какой-либо из них,
*sequential : Если указано, ответы будут использоваться в том порядке, в котором они перечислены в группе. Если не указано, то по умолчанию ответы будут выбираться из списка случайным образом.
*norepeat : Если указано, то после воспроизведения всех ответов в списке группа ответов будет отключена. Все правила, выбравшие эту группу ответов, не будут возвращать спикеру никакого ответа.
====Ответы====
Ответ (Response) - это фактический ответ, который выбирается системой и затем используется динамиком. В группе ответов может быть перечислено столько ответов, сколько необходимо, причем каждый ответ может быть одного из следующих типов:
*speak : Ответ в виде или сырого аудиофайла.
*sentence : Ответ в виде sentence строчки. Указывается имя фразы/предложения из .
*scene : Ответ формата файла .vcd. Чтобы больше узнать про реализацию хореографических сцен, ознакомьтесь с .
*response : Ответ представляет собой ссылку на другую группу ответов, которая должна быть выбрана вместо него.
*print : Этот ответ представляет собой текст, который должен быть напечатан на месте диктора при developer 1 (используется как временный заменитель полноценного ответа). 
*entityio : Ответ как , которое посылается определённой сущности на карте как активатор. Формат вида: entityio "<name> <input> <param>". Это отличается от последующих ответов, которые более подробно рассматриваются ниже.
*vscript : Ответ в виде кода, которая проходит через говорящего.
*vscript_file : Ответ как это путь к файлу VScript, который запускается из области видимости говорящего.
====Параметры задержки после ответа====
Each response supports a variety of optional parameters.
**nodelay : После завершения ответа говорящий может сразу вновь заговорить.
**defaultdelay : После завершения ответа говорящий не сможет говорить в течение произвольного времени - от "2,8" до "3,2" секунды.
**delay X : После завершения ответа говорящий не сможет говорить в течение заданного времени X в секундах. X также может быть диапазоном, например, "5.5,7.5"
*weapondelay X : После начала ответа говорящий не будет стрелять из своего оружия в течение X секунд. По умолчанию доступно только для NPC-союзников HL2.
*speakonce : Предотвращает использование ответа более одного раза.
*odds X : Если указано, то при выборе этого ответа есть вероятность, что говорящий вместо ответа ничего не скажет. Шанс - это (0-100)% вероятности отмены ответа, то есть коэффициент 25 дает 25 % вероятности того, что говорящий ничего не скажет.
*respeakdelay : Если указано, этот ответ не может быть использован, если концепция не была озвучена в течение как минимум X секунд. X также может быть диапазоном, например, "5.5,7.5".
*soundlevel : Если указано, этот уровень звука (soundlevel) должен использоваться для ответа вместо стандартного SNDLVL_TALKING.
*displayfirst : Если указано, то этот ответ должен использоваться первым (игнорируется параметр weight).
*displaylast : Если указано, этот ответ должен использоваться последним (игнорируется параметр weight).
*weight : Если указано, используется для определения веса при выборе ответов в списке. По умолчанию все ответы имеют вес "1". Обратите внимание, что ответы не будут повторяться до тех пор, пока не будут выбраны все остальные ответы, то есть после выбора всех ответов с большим весом система будет учитывать только ответы с меньшим весом. Этому можно противостоять с помощью permitrepeats.
*noscene : Запрещает системе ответа создавать автоматически генерируемую сцену для ответа говорить.
*stop_on_nonidle : Когда ответ произнесен, остановите сцену, когда NPC перейдет в неактивное состояние. В Source 2013 работает только в эпизодических модах HL2 на реакциях scene.
*predelay : Когда ответ выбран, он не будет произнесен до истечения X секунд. Работает только для ответов scene. X также может быть диапазоном, например, "5.5,7.5".
Например, следующая группа ответов используется для ответа на концепцию TLK_STARE. Граждане будут использовать ответы из списка в том порядке, в котором они перечислены (из-за параметра sequential). Каждый ответ, когда он выбран, останавливает разговор NPC на случайный промежуток времени между 10 и 20 секундами.
response "CitizenTalkStare"
{
 sequential
 scene "scenes/npc/$gender01/doingsomething.vcd" delay "10,20"
 scene "scenes/npc/$gender01/getgoingsoon.vcd" delay "10,20"
 scene "scenes/npc/$gender01/waitingsomebody.vcd" delay "10,20"
}
==Файлы скриптов==
Файл /scripts/talker/response_rules.txt - это базовый скрипт, содержащий все критерии, правила и группы ответов, используемые системой Response Rules System'ой. Файл также может включать в себя другие файлы с помощью ключевого слова #include, что позволяет четко разделить правила на NPC, карты и так далее.
Обратите внимание, что некоторые сущности, например , указывают свои файлы сценариев, содержащие подмножество критериев и правил, и группы ответов для использования сущностью. Ознакомьтесь с scripts/talker/terminal_pa.txt как пример, используемый в объявлении терминала на железнодорожном вокзале.
==Followup responses==
 introduced "followups", events which occur following the response. They are triggered as response parameters similar to odds, predelay, etc. 
*fire : Fires an input through the I/O system with the speaker as the activator and caller. Format is fire <target> <input> <delay>. Does not support parameters.
*then : Causes another response to be dispatched on an entity. Format is then <target> <concept> <response contexts> <delay>. Used for making characters dynamically respond to each other.
A few unique targetnames can be used:
*self : The entity speaking the response.
*subject : Uses the entity name found in the speaker's "Subject" context, if it exists. The game sets this for responses.
*from : Uses the entity name found in the speaker's "From" context, if it exists. The game sets this to the name of the previous followup respondent, allowing followups to bounce back and forth.
*any : Dispatched to any valid respondent within the range stored in rr_followup_maxdist (1800 by default).
*all : Dispatched to all valid respondents within the range stored in rr_followup_maxdist (1800 by default).
Пример из Left 4 Dead 2 в coach.txt:
Response _c1m4startelevator4bCoach
{
	scene "scenes/Coach/WorldC1M4B01.vcd" then mechanic _c1m4startelevator5a foo:0 -2.313 //Son, you got a DEAL.
	scene "scenes/Coach/WorldC1M4B02.vcd" then mechanic _c1m4startelevator5a foo:0 -5.790 //Ha HA! All the way to New Orleans! Baby, that sounds like a PLAN.
	scene "scenes/Coach/WorldC1M4B05.vcd" then mechanic _c1m4startelevator5b foo:0 -6.334 //Normally I wouldn't do this. But in these circumstances, I think Mr. Gibbs, Jr. ain't gonna mind.
	scene "scenes/Coach/WorldC1M4B10.vcd" then mechanic _c1m4startelevator5b foo:0 -2.685 //Forgive us Jimmy, but we need your car.
}
==Использование расширенных правил реагирования==
Система реагирований может быть использована во многих продвинутых и специализированных направлениях. Вот несколько советов и приемов для расширенного использования системы:
;Получение пользовательских ответов с помощью DispatchResponse
:В качестве концепции ответа NPC можно передать абсолютно все, что угодно, лишь бы это было найдено в файлах сценария. Вы не ограничены предопределенными концептами TLK_* ИИ.
:Например, вы можете захотеть, чтобы NPC из группы зрителей произносили поздравительные речи, когда игрок успешно решает часть головоломки.
:У союзников игрока в HL2 также есть вход SpeakResponseConcept с более продвинутой обработкой и условиями.
Смотрите скрипты ответа для Аликс в EP1/EP2 или скрипты ответа для выживших в L4D для других примеров использования продвинутой системы ответа.
==Debugging==
==Замечания==
* Для того, чтобы возможность использовать Response Rules, NPC должен быть основан на класса .
* Рекомендуется просмотреть файлы scripts/talker/npc_*.txt как примеры использования специфичных правил ответа NPC.
* scripts/talker/response_rules.txt - это манифест-файл системы правил ответов. Если вам необходимо добавить правила реагирования для вашего уникального NPC, убедитесь что вы включили вашего NPC в манифест (#include в конце файла scripts/talker/response_rules.txt).
==See also==
* 
* 
* 
* 
* 
==External links==
* Elan Ruskin's "Rule Databases for Contextual Dialog and Game Logic" presentation at GDC 2012, which describes the Response System and its evolution. (Slides: )
* Two Bots One Wrench: Environmentally Responsive Speech Video, Demo Video #1
* Two Bots One Wrench: Memory And Context, Demo Video #2
* Two Bots One Wrench: Conversation, Demo Video #3