В настоящее время я пишу свой собственный текстовый движок приключений из-за того, что Inform / Adrift / Quest имеет тенденцию иметь фатальный недостаток, который меня беспокоит - кошмарный, запутанный синтаксис Inform (и это исходит от UX-дизайнера, который любит вещи как можно более легким для начинающих), уродливого читателя Адрифта и отсутствия в Адрифте / Квестах реальной поддержки классов / объектов.
Возможно, это не лучший способ сделать это, но пока он работает нормально. Я посмотрел в Regex, но решил сделать это так.
Первое, что нужно сделать, это разделить строку ввода / команды игрока в список. К счастью, в этих играх первым элементом этого списка почти всегда является глагол.
Вам понадобятся классы данных глагол / объект / и т. Д., К которым можно получить доступ по ключу, содержащие все значения, которые могут соответствовать ему, например, «смотреть, исследовать, ex».
class Verb
{
string uniqueID;
List<string> values;
}
class Object
{
public uniqueID; // Because this is shared with Verbs, you could do a better unique ID system, but hey...
public List<string> articles;
public List<string> adjectives;
public List<string> noun;
}
Вам также понадобится набор подклассов «Действие», которые будут сопоставлены с входом игрока. Здесь вы «строите» структуру предложений, которая должна соответствовать входным данным игрока.
- Действие (базовый класс)
- вид
- посмотрите {на} [объект]
- посмотрите книгу
- Перейти
- Прыжок {вкл / на} [объект]
.
class Action
{
string uniqueID;
List<SentenceElement> sentence;
void Execute();
bool RestrictionsCheck();
}
class Look : Action
{
override void Execute();
override bool RestrictionsCheck();
}
class LookAtObject : Action
{
override void Execute();
override bool RestrictionsCheck();
}
class LookAtBook : Action
{
override void Execute();
override bool RestrictionsCheck();
}
Базовый класс Action имеет конструктор предложений, использующий SentenceElements. Это может быть Список, описывающий предложение по частям.
class SentenceElement
{
List<string> values;
bool isOptional;
}
class VerbID : SentenceElement {}
class ObjectID : SentenceElement {}
class ObjectAny : SentenceElement {}
class CharacterID : SentenceElement {}
class CharacterAny : SentenceElement {}
class TextOptional : SentenceElement {}
class TextRequired : SentenceElement {}
class Parameter : SentenceElement {}
Теперь вы можете искать в своих классах "Действие", сравнивать первый SentenceElement с первым входным глаголом игроков и вести список тех, которые соответствуют "потенциальным действиям". "string.Contains" будет работать.
Теперь вам нужно найти наиболее подходящее Действие, пройдя через команду ввода ваших игроков и пройдя через каждый SentenceElement, сравнивая их. Держите указатель того, где вы находитесь в каждом из них (playerInputIndex, потенциальный доступ к действию, индекс предложения в элементе).
Если вы найдете совпадение, увеличивайте playerInputIndex до тех пор, пока он не совпадет с SentenceElement, проверьте ваши настройки (isOptional и т. Д.), Затем перейдите к следующему фразеElementIndex и снова выполните сравнение. В конце концов вы достигнете конца ввода игрока или SentenceElements.
Сложность добавляется, когда у вас есть SentenceElements, которые являются «isOptional», поэтому его нужно будет проверить, или Действия, которые имеют SentenceElements типа ObjectAny, которые не должны соответствовать существующему, но отображают «Какой объект ты хотел поесть? " сообщение. Кроме того, в отличие от глаголов, у объектов есть дополнительные параметры соответствия, такие как префиксы / прилагательные / существительные, которые нужно учитывать.
Эта система также потребует нового класса для каждого действия, которое вы когда-либо захотите сделать. Каждое действие будет иметь собственные «Ограничения», которые оно также должно пройти, прежде чем оно будет выполнено, например «Жив ли указанный персонаж?» И т. Д.