ТОМ2 - платформа для парсерных игр

Объявление

Открыт сайт tom2-game.ru.


Последнюю версию платформы можно скачать здесь.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.



Диалоги с NPC на меню.

Сообщений 1 страница 4 из 4

1

Т.к. программы пока не научились думать и нормально общаться с человеком, создатели текстовых игр всячески избегают вставлять в свои игры несобственных персонажей, с которыми ГГ может говорить. Те же, кто всё-таки осмелился использовать NPC в своих играх, чаще всего применяют 2 способа общения между ГГ и NPC:
Парсерный - персонаж может реагировать на определённые фразы или шаблоны. Чаще всего "привет", "пока", "расскажи о <предмет/персонаж/место>" и прочие "малоподвижные" фразы, в которые довольно трудно "попасть", если не знаешь, что говорить. В этом случае, иногда игростроитель перед началом игры сам описывает, как нужно общаться с NPC: "Чтобы поговорить с другими персонажами, наберите 'говорить с [персонаж]' и используйте фразы 'расскажи о ...' и прочее......". При этом весь геймплей портится, а пользователь ощущает дискомфорт из-за сильно суженных рамок общения и вся атмосфера рушится.
Менюшный - при разговоре с персонажем появляется меню, из которого можно выбрать какой-нибудь пункт, персонаж отвечает, появляется другие пункты меню, снова выбираем и т.д. пока разговор не окончится, либо не будет выбран пункт "окончить разговор" или подобный. Тоже не на много лучше первого способа, но при этом не надо помнить "алгоритм общения с NPC", а надо просто выбирать пункты особо не напрягаясь. К сожалению данный способ чаще всего реализуется скверно - парочка пунктов меню, которые по сути приводят к одному и тому-же результату (иллюзия выбора), или ещё "лучше": зацикленное меню с несколькими пунктами, которые каждый раз повторяются и при выборе "отвечают" одно и то-же (или убираются, если уже читал).

Т.к. выбор небольшой, я больше склоняюсь ко второму варианту, но думаю, что можно делать менюшные диалоги гораздо более насыщеннее и с хорошо разветвлённой паутиной фраз, сильно влияющих на сюжетную линию.

Итак, к чему же я развёл всю эту лирику? А вот к чему: т.к. мне необходимо использовать много несобственных персонажей в игре(ах), причём "умных" персонажей, диалоги с которыми будут составлять важную роль в квесте, то надо разобраться с тем, как же "нормально" делаются меню в ТОМе? Именно диалоговые меню, а не какие-то выборы действий или навигацию по миру. Как наиболее оптимально создавать развёрнутые, разветвлённые менюшные диалоги в ТОМе?

Возможно даже удастся в состоянии аффекта написать какой-нибудь конструктор разветвлённого меню, нужно лишь понять принцип составления. :rolleyes:

2

Вот старый примерчик, но вроде бы еще работает...

Код:
//=============================================================================
// настройка меню собеседника
//=============================================================================
%Вы играете за Петю и можете поговорить с Васей и Вовой.
%_
%Нумеровать строки меню?
class собеседник
{ if(input("да/нет?>")=="да")
    this.menu_num = да //ставим автонумерацию для меню
}
//=============================================================================
// синонимы для строк меню
//=============================================================================
"1"="один"="первое"
"2"="два"="второе"
"3"="три"="третье"
"4"="четыре"="четвертое"
"5"="пять"="пятое"

//=============================================================================
// локация и 3 персонажа
//=============================================================================
location Комната
{ this.description="в комнате {item}
Для начала разговора введите 'говорить с Васей' или 'говорить с Вовой'.{menu()}"
  OnEnter() //покажем локацию
  { %<location>
    %{title}</location>
    %{description}
  }

  unique Вася
  { cls = собеседник
    title="Вас%; МрЕчОдСи; Ип; Зп=ь; Зп=я; Ип=я; Рп=и; Дп=е; Вп=ю; Тп=ей; Пп=е;"
  }
  unique Вова
  { cls = собеседник
    title="Вов%; МрЕчОдСи; Ип; Зп=; Зп=а; Ип=а; Рп=ы; Дп=е; Вп=у; Тп=ой; Пп=е;"
  }
  unique Петя
  { cls = собеседник
    title="Пет%; МрЕчОдСи; Ип; Зп=ь; Зп=я; Ип=я; Рп=и; Дп=е; Вп=ю; Тп=ей; Пп=е;"
    pers=this
  }
}

//=============================================================================
// парсерная составляющая диалога
//=============================================================================
action Поговорить
{ pat="поговорить=говорить=поговори=говори с @с_кем:собеседник*Тп"
  pat="спросить=спроси @с_кем:собеседник*Вп"
  с_кем(с_кем)
  { if(с_кем==actor)
      return "будет несколько странно, если {actor} начнет говорить с {actor*Тп}^^^"
  }
}

Петя.Поговорить(с_кем)
{ %для выбора меню введите номер строки, начальные буквы строки, или начало любого слова в меню.
  this > "Слушай, {с_кем*Зп}, давно тебя хотел спросить^^^<pause>"
  %{с_кем.menu()}
  this.is_not_recognized = "{menu_object} тебя не понял." //это вместо "Это предложение не понятно."
  с_кем.menu_name="Продолжаем разговор c {menu_object*Тп}:
___"

}

//=============================================================================
// менюшная составляющая диалога
//=============================================================================
class собеседник
{ //настройки меню
  this.menu_name="Разговор с {this*Тп}:
___"
  this.menu_separator = " //между строками меню перенос строки с отступом 
___" 

//при разговоре с любым собеседником должна быть опция выхода из меню:
  menu_item("{досвиданья()}",1000) //всегда в конце меню
  { pers > "Пока {menu_object}, было приятно поболтать.<pause>"
    this > "Пока {pers}.<pause>"
    this.is_not_recognized = null
    this.menu_name = null
    loc.OnEnter() //покажем локацию
  }
  досвиданья()
  { switch(rnd(5))
    case(1) return "досвиданья"
    case(2) return "пока"
    case(3) return "прощай"
    case(4) return "счастливо"
    case(5) return "еще увидимся"
  }
}

unique Вася
{ //формируем меню для разговора с Васей
  menu_item("про рыбалку")
  { pers > "Вася, а как ты относишься к рыбалке?<pause>"
    this > "Да не рыбак я совсем^^^<pause>"
    pers > "Жаль, очень жаль.<pause>"
    %{menu()} //в конце вызываем меню для продолжения диалога
  }
}

unique Вова
{ //формируем меню для разговора с Вовой
  menu_item("про рыбалку")
  { this.говорили_про_рыбалку = да
    pers > "Вова, а как ты относишься к рыбалке?<pause>"
    this > "Вчера я поймал вот такую (разводит руки в стороны) рыбу!<pause>"
    pers > "Да ну! Ты просто супер-рыбак!<pause>"
    %{menu()} //в конце вызываем меню для продолжения диалога
  }
}


//отдельная тема сокровищ
mental ПроСокровища //помещаем тему в разговор с Васей
{ menu_item("а где ты хранишь свои сокровища?")
  { Вася - ПроСокровища //2й раз про сокровища спросить не судьба
    Вася + ПроКлюч //добавляем тему ключа
    pers > "А где ты хранишь свои сокровища?<pause>"
    menu_object > "В тумбочке стола^^^<pause>"
    pers > "Спасибо, ты мне очень помог!<pause>"
    %{menu_object.menu()}
  }
  Вася + this
}

//отдельная тема ключа
mental ПроКлюч
{ menu_item("эээ^^^ тумбочка закрыта, где ключ?")
  { Вася - ПроКлюч  //2й раз про ключ не спрашиваем
    Вова + ПроКлюч2 //становится известно что ключ у Вовы
    pers > "Эээ^^^ тумбочка закрыта, где ключ??<pause>"
    menu_object > "Ключ у Вовы.<pause>"
    pers > "Спасибо, ты мне снова помог!<pause>"
    %{menu_object.menu()}
  }
}
mental ПроКлюч2
{ menu_item("Вова! Вася сказал что у тебя есть ключ от тумбочки!")
  { Вова - ПроКлюч2 //2й раз про ключ не спрашиваем
    pers > "Вова! Вася сказал что у тебя есть ключ от тумбочки!<pause>"
    if(Вова.говорили_про_рыбалку)
    { menu_object > "На, держи! (отдает ключ)<pause>"
      pers > "Спасибо, ты меня выручил!<pause>"
    }
    else
    { menu_object > "Ключ, ключ^^^ А зачем он тебе?<pause>"
      pers > "Ну так^^^ нужен для одного дела^^^<pause>"
    }
    %{menu_object.menu()}
  }
}

3

Есть небольшая проблема в примере. Не могу понять, почему.

Комната
в комнате Вася, Вова и Петя

Для начала разговора введите 'говорить с Васей' или 'говорить с Вовой'.

Петя> осм
это предложение непонятно!

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

Разговор с Васей:

___1. а где ты хранишь свои сокровища?

___2. про рыбалку

___3. прощай.

Петя> Прощай
Петя: Пока Вася, было приятно поболтать.
Вася: Пока Петя.

Комната
в комнате Вася, Вова и Петя

Для начала разговора введите 'говорить с Васей' или 'говорить с Вовой'.

Петя> осм
Комната тебя не понял.

Глюк выделил красным цветом. Почему после разговора комната "оживает"? :disappointed:

4

В примере ошибка.  :surprise:

В этой строке подменяется стандартное сообщение об ошибке:
this.is_not_recognized = "{menu_object} тебя не понял." //это вместо "Это предложение не понятно."

В этой строке нестандартное сообщение должно сниматься, но не снимается...
this.is_not_recognized = null

Дело в том, что в первом случае this==Петя, а во втором случае this==Вася...
т.е. нестандартное сообщение остаётся сидеть в объекте "Петя".
Можно исправить, заменив this на pers. Так будет корректнее, главное чтобы pers в процессе диалога не поменялся  :D

--------
Почему оживает комната:
Нестандартное сообщение "{menu_object} тебя не понял." ссылается на menu_object.
menu_object - это системная переменная, которая хранит объект, для которого последний раз вызывался метод menu().
После выхода из диалога это будет текущая локация (см. вызов menu() в обработчике события OnEnter()).