Генерация имён по базе имён

Материал из Клуб любителей рогаликов
Перейти к: навигация, поиск

Введение

Очень часто в играх возникает необходимость назвать того или иного монстра собственным именем. Или какое-то место, деревню, например. Если это стационарные монстры/пункты, не меняющиеся от игры к игре, то никакой проблемы их именование не составляет. Ненамногим сложнее данное действие в случае небольшого количества случайно именуемых или нет объектов. Тогда для каждого из них составляется список подходящих имён/названий, из которого для очередной новой игры выбирается случайным образом одно. Но, предположим вам требуется называть, ну даже если и не всё подряд, но очень многое. Список названий в данном случае не очень годится; думаю несколько тяжеловато подбирать четырёхзначное число, к примеру, гномьих имён, проставляя при этом им вероятности выпадения.

Во-первых, следует сразу сказать, что различных схем и методов для генерации имён и названий можно разработать достаточно большое количество. Но следует заметить, что не все они оптимальны. Предположим, вы создали отличный генератор имён. Основанный на чередование гласных-согласных, длине слов, дифтонгах, буквенных конструкциях, приставках, окончаниях, словом всё-всё он учитывает. Который, естественно, выдаёт очень и очень толковые примеры в хорошей пропорции. И вы называете с помощью него множество NPC в вашей игре. Собственно порядок вроде бы. Но, не совсем. Ведь в вашей игре уж наверняка не одна единственная раса. И ведь наверно должно смущать, что имя тролля может быть ровно таким, как имя человека-крысы, а то и как название эльфийского меча. Что делать? Писать отдельный генератор на каждую расу? Можно и так. Но всё ж предложу способ.


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

Теперь попробую объяснить действие такого генератора по пунктам.


Создание базы имён

Это не совсем работа программы конечно, а ручной подбор списка, но несколько советов не повредят.

Первое. Лучше имена для базы подбирать, не выдумывая их из головы, но имея какой-то список. Например, если нужно получить названия монгольских населённых пунктов - то следует найти карту Монголии и взять названия оттуда, а если нужны имёна орков - то из книжки, где таких имён много, либо сайта в инете, посвященному культуре орков. А уже из них выбирать подходящие на ваш взляд. Поскольку иначе можно упустить целый класс подходящих имён. Второе. Сразу нужно откидывать имена, не вписывающиеся в структуру языка (мне тяжело более чётко определить какие именно, ну иноземные точно. Если на примере - то в список русских городов, типа Тверь, Торжок, Корчев, Ярославль уж точно не стоит пхать Дзержинск). Третье. Если какое-то из имён кажется здорово выдающимся, в полной мере отражающим все аспекты того рода названий, что вам нужны - его можно добавить в базу два, три и более раз, чтобы увеличить вероятность выпадения такой языковой конструкции.


Обработка базы имён

При обработке базы можно получить множество различных параметров, но я довольствуюсь лишь несколькими. 1 параметр - это средняя длина слов базы. Это просто. 2 параметр - это допустимое чередование гласных-согласных. То есть определяются все возможные в данной базе варианты слов, если гласные в них заменить на букву "а", а согласные на букву "б". Создаётся множество чисел, таких, что если их записать в двоичной форме, где 1 - это согласная, а 0 - это гласная, они как раз и будут этими представлениями слов. Ну, и плюс указатель с какой позиции число это считать. 3 параметр - это какая буква может следовать за какой, а также, какая буква может следовать за какими двумя. И какое количество раз. То есть создаётся массив М размером 34х34х34 (для русского языка) или 27х27х27 для английского, где 34-ым или 27-ым элементом является пробел, который означает начало и конец слова. И в который на место М[i,j,k] записывается сколько раз за сочетанием букв "i" и "j" следует буква "k".

На примере. Скажем из базы считываются слова "Гор" и "Отто". 1 параметр понятно. Для этих двух слов, он равен 3,5. 2 параметр. "Гор" преобразуется в "баб", а далее в 101 и в в множество добавляется число 5 с указателем 3 (длина слова). "Отто" преобразуется в "абба", а далее в 0110 и в множество добавляется число 6 с указателем 4 (длина слова). 3 параметр. "Гор" преобразуется в "__гор_", а затем элементы массива М[_,_,г] М[_,г,о] М[г,о,р] М[о,р,_] увеличиваются на один. "Отто" преобразуется в "__отто_", а затем элементы массива М[_,_,о] М[_,о,т] М[о,т,т] М[т,т,о] М[т,о,_] увеличиваются на один.

*** (4 параметр) Можно ещё определять и некоторые другие характеристики базы как-то - может ли отдельно взятая буква стоять на н-ом месте слова, окончания/начала слова считать трёхбуквенными (а не двух, как это подсчитывается для массива М) константами, вытащить из базы все возможные комбинации идущих подряд согласных. Да и ещё много чего.


Генерация имён по полученным из базы сведениям

Для начала распишу процесс генерации без всяких корректоров, то есть только по одному лишь 3-му параметру (то есть по матрице М), с помощью "двухбуквенной" генерации.

Задаём первую букву слова, как "_" и вторую букву слова как "_". Суммируем все элементы массива М[_,_,*], где звёздочка принимает все значения от "а" до "я" и "_". И выбираем случайное число от 1 до этой суммы. Таким образом опеределяем реальную первую букву получающегося слова. Например "г". Далее суммируем все элементы массива М[_,г,*], где звёздочка принимает все значения от "а" до "я" и "_". Определяем вторую букву. Так до тех пор, пока очередной буквой не окажется "_", которая определяет конец слова.

Процесс "однобуквенной" генерации отличется от "двухбуквенной" тем, что для определения первой буквы мы бы суммировали не.М[_,_,*], а М[*,_,*], а для определения следующей не [_,г,*], а [*,г,*], то есть каждая новая буква опеределялась бы исходя из одной лишь только буквы.

Пример "однобуквенной" генерации на базе из слов "Гор", "Отто", "Тор". Первой буквой может получтся "г", "о" или "т", кажая с вероятностью 1/3. Пусть "г". Далее после "г" может идти лишь "о" , поэтому "го". После "о" может быть "р" с вероятностью 1/2, "т" и "конец слова" с вероятностью 1/4. Например "т", тогда "гот". После "т" или "т" с 1/3 или "о" с 2/3 - "гото". И далее "конец слова", допустим. Полученное имя "Гото".

Корректировка полученного по ходу

  1. Зачем "однобуквенные" и "двухбуквенные" генерации?
    Употребление различных генераций определяется количеством слов в базе, а также тем, какой процент повторяющихся имён вам нужно получать. Скажем, запустив программу на базу в 10 слов и употребив лишь "двухбуквенные" сочетания можно быть уверенным, что полученные имена не будут радовать своим разнообразием, но при "однобуквенной" генерации на некоторую неодинаковость можно рассчитывать. Правда при использовании только лишь одних "однобуквенных" сочетаний во многих случаях теряется структура слов, что есть несомненно минусом. Я использую комбинации "двух" и "однобуквенных" сочетаний, чередующиеся по ходу накидывания слова с вероятностью, которая мне кажется наиболее подходящей для каждой конкретной базы.
  2. Корректировка длины слов.
    В показанном выше примере для слов "Гор", "Отто", "Тор", используя "однобуквенную" генерацию, вполне можно получить что-то типа "Готтттооттототттотттор", что конечно не очень хорошо. Поэтому стоит корректировать слова по их длине. Приблизительно так: если слово уже на 1 превышает среднюю длину слов, то при выпадении очередной буквы не "концом слова", её следует повторно переопределить. При превышении на 2 - дважды, на 3 - трижды. Если с первого раза выпадет "конец слова", то второй раз переопределять не стоит. И, наоборот, если слово заканчивается вдруг ранее, чем средняя длина на 1, то стоит переопределить "конец слова" один раз, если на 2 - то дважды... Можно использовать и более гибкую схему переброса основываясь на матожидании и дисперсии. Во многих случаях можно усилить эти перебросы, если перебрасывать только с "однобуквенной" генерацией.
  3. Корректировка по сочетанию гласных/согласных.
    Тут всё просто. Преобразуем полученное слово в комбинацию "а" и "б", то есть в двоичное число, и проверяем есть ли это число в множестве чисел (2 параметр). Слово "Гото", что было получено, как пример, переводится в число 1010, то есть в 10 с указателем 4. Такого в том множестве не было. Значит слово не подходит.
    Кстати, если использовать эту корректировку по гласным/согласным для базы "Гор", "Отто", "Тор" никаких других имён кроме этих трёх получить будет нельзя. Её использование тоже зависит от количества слов в базе.
  4. Другие варианты корректировок.
    Под *** (4 параметр) было предложено ещё несколько вариантов характеристик слов, которые можно определить для каждой базы. Естественно на них тоже можно проверять, если в этом есть потребность или желание улучшить. Стоит лишь помнить, что добавляя очередное ограничение вы тем самым уменьшаете варианты слов, которые можно получить. Поэтому, вводя ограничение, следует увеличить количество слов в базе или послабить другое ограничение.


Приведу примеры работы этой программы.

База состоящяя из названий 53 немецких городов. В режиме "двухбуквенной" генерации с высокой коррекцией по длине.

Борфург
Гёрцбург
Ронноверт
Потбург
Гёттинц
Дюнбадт
Ханкфорт
Дуйсбург
Дюрбранд
Кассельфель
Дорн
Мюншток


База состоящяя из чешских, словацких, польских и подобных имён, количеством 39 штук, работяя в режиме "однобуквенной" генерации, без корректировки по длине, с корректировкой по гласным/согласным.

Йожей
Штепавел
Люденек
Кшишек
Антимаш
Одриладр
Штофрав
Яромаш
Анжеф
Либор
Фратим
Влавел

Думаю, в конце следует упомянуть, что корректировка по сочетанию гласных/согласных не моя идея, а взял я её в генераторе Sami Pyorre. Ну не совсем в чистом виде взял, у него в генераторе вообще на этом всё базируется - накидывается не буква за буквой, как в этом, а комбинация гласных букв за комбинацией согласных и наоборот. Тоже вариант для использования.



Автор: Troll.
Источник: Статья для обсуждения: "Генерация имён по базе имён".