Генерация подземелий с прямоугольными комнатами
Добавлено: 29 июл 2017, 12:56
Всем доброго времени суток! Для написания этого поста у меня несколько причин: хочется привести в порядок свои идеи и разложить всё по полочкам, а лучший вариант для этого - написать. Есть небольшая надежда, что кому - то из новичков пригодятся мои идеи, ну и, конечно, хочется услышать критику, ведь у самого глаз замыливается и некоторые, казалось бы, очевидные вещи, проходят мимо. Ну, начнем. Букв будет много, так что сначала краткое описание с примерами результата, а потом разбор по-порядку.
Общее
Скрипт написан на Python 3 с использованием BearLibTerminal (отдельное спасибо его создателям, пользуюсь с удовольствием, все быстро и интуитивно, минусов не замечено!). Больше ничего для его запуска не требуется. Писал под Windows, но на Linux тоже должен пойти, про MacOS ничего сказать не могу.
Что делает скрипт? На данный момент результат работы - двумерный массив заданной размерности, содержащий в себе иконки тайтлов. Для наглядности выводит их на экран. В данный момент скрипт полностью рабочий и имеет наиболее универсальный формат, не зависящий от логики игры. Дальнейшая разработка пойдет по специфике уже конкретного движка и выкладывать не вижу смысла. Так же большинство, думаю, заметят сходство (далеко не полное, к сожалению) выдаваемых карт с картами ADOM. Что я могу тут сказать? На него и равнялся))
Что планируется сделать конкретно под свой движок?
1. Добавить вероятность того, что коридор будет скрытый - оба его конца будут скрытыми дверями
2. Добавить вероятность того, что двери будут отсутствовать
3. Закрытые двери
4. Двери с ловушками
Как видно из списка, все это делается уже на основе полученного массива и затрагивает логику конкретной игры.
Недостатки скрипта:
1. Иногда (довольно редко) генерирует карту, где комнаты соединены строго последовательно
2. Иногда (так же редко) генерирует довольно большие участки пустого пространства
Планируемые способы решения:
1. Проверка по комнатам количества дверей в них, при отсутствии 3 комнат с количеством дверей больше или равном 3 добавить коридоры
2. Добавление схронов - скрытых комнат (коридор, ведущий к схрону будет иметь 2 скрытые двери) с лутом, стражниками и т.д.
Примеры работы скрипта:
Код скрипта:
Описание алгоритма
Предварительные действия:
Задается размер карты в тайтлах, у меня 80 на 20.Тайтлы хранятся в двумерном масиве. Первоначально значение тайтла - свободный или граница карты. Карта разбивается на минимальные ячейки. Ячейка это минимальный участок карты, который может содержать комнату. У меня задано 2 ряда по 8 ячеек, соответственно, их размер будет 10 на 10. При определении размера ячеек используется целочисленное деление. Комнаты могут быть различных типов и занимать различное количество минимальных ячеек.
1. Создается массив минимальных ячеек и все ячейки маркируются как свободные или границы карты.
2. Создание комнат
3. Комнаты созданы. Перед тем, как переходить к созданию коридоров между ними, маркируем углы комнат, как непроходимые (иначе возможны такие варианты, как проход коридора по стене комнаты)
4. Создаем коридоры, соединяющие комнаты:
Тут надо отметить две важные вещи:
1. При простом рандомном проведении коридоров часто получалось так, что коридор шел через стену комнаты или параллельно с другим коридором, что приводило к склейке комнат или появлению коридора шириной в 2 клетки. Так как мне это не очень понравилось, то я сделал каждый второй тайтл стен непроходимым (проверял сумму координат тайтлов и, если она четная, то маркировал стену, как непроходимую, иначе, как проходимую).
2. Если комнаты из сети и комнат выбирать рандомно, то ОЧЕНЬ часто получается так, что через 1 комнату проходит 4+ коридоров и, соответственно, 8+ дверей, что есть совсем не гуд. Так что рандомно я выбираю только первые 2 комнаты, а дальше рандомную из оставшихся и ближайшую к ней из сети.
Ну вот, кажется, и всё. Получилось несколько сумбурно, но как мог. Сам код содержит довольно много комментариев и довольно неплохо (надеюсь) читаем и без данного текста. Если будет интерес или вопросы по невнятно описанным моментам - готов к диалогу. Отдельно был бы благодарен людям, которые более-менее профессионально пишут на Python, ну или просто в теме за замечания по коду. Сам я начал изучать этот язык примерно год назад, но времени свободного очень мало, да и посоветоваться не с кем...
Всем спасибо за внимание.
Общее
Скрипт написан на Python 3 с использованием BearLibTerminal (отдельное спасибо его создателям, пользуюсь с удовольствием, все быстро и интуитивно, минусов не замечено!). Больше ничего для его запуска не требуется. Писал под Windows, но на Linux тоже должен пойти, про MacOS ничего сказать не могу.
Что делает скрипт? На данный момент результат работы - двумерный массив заданной размерности, содержащий в себе иконки тайтлов. Для наглядности выводит их на экран. В данный момент скрипт полностью рабочий и имеет наиболее универсальный формат, не зависящий от логики игры. Дальнейшая разработка пойдет по специфике уже конкретного движка и выкладывать не вижу смысла. Так же большинство, думаю, заметят сходство (далеко не полное, к сожалению) выдаваемых карт с картами ADOM. Что я могу тут сказать? На него и равнялся))
Что планируется сделать конкретно под свой движок?
1. Добавить вероятность того, что коридор будет скрытый - оба его конца будут скрытыми дверями
2. Добавить вероятность того, что двери будут отсутствовать
3. Закрытые двери
4. Двери с ловушками
Как видно из списка, все это делается уже на основе полученного массива и затрагивает логику конкретной игры.
Недостатки скрипта:
1. Иногда (довольно редко) генерирует карту, где комнаты соединены строго последовательно
2. Иногда (так же редко) генерирует довольно большие участки пустого пространства
Планируемые способы решения:
1. Проверка по комнатам количества дверей в них, при отсутствии 3 комнат с количеством дверей больше или равном 3 добавить коридоры
2. Добавление схронов - скрытых комнат (коридор, ведущий к схрону будет иметь 2 скрытые двери) с лутом, стражниками и т.д.
Примеры работы скрипта:
Скрытый текст: ПОКАЗАТЬ
Скрытый текст: ПОКАЗАТЬ
Предварительные действия:
Задается размер карты в тайтлах, у меня 80 на 20.Тайтлы хранятся в двумерном масиве. Первоначально значение тайтла - свободный или граница карты. Карта разбивается на минимальные ячейки. Ячейка это минимальный участок карты, который может содержать комнату. У меня задано 2 ряда по 8 ячеек, соответственно, их размер будет 10 на 10. При определении размера ячеек используется целочисленное деление. Комнаты могут быть различных типов и занимать различное количество минимальных ячеек.
1. Создается массив минимальных ячеек и все ячейки маркируются как свободные или границы карты.
2. Создание комнат
Скрытый текст: ПОКАЗАТЬ
4. Создаем коридоры, соединяющие комнаты:
Скрытый текст: ПОКАЗАТЬ
1. При простом рандомном проведении коридоров часто получалось так, что коридор шел через стену комнаты или параллельно с другим коридором, что приводило к склейке комнат или появлению коридора шириной в 2 клетки. Так как мне это не очень понравилось, то я сделал каждый второй тайтл стен непроходимым (проверял сумму координат тайтлов и, если она четная, то маркировал стену, как непроходимую, иначе, как проходимую).
2. Если комнаты из сети и комнат выбирать рандомно, то ОЧЕНЬ часто получается так, что через 1 комнату проходит 4+ коридоров и, соответственно, 8+ дверей, что есть совсем не гуд. Так что рандомно я выбираю только первые 2 комнаты, а дальше рандомную из оставшихся и ближайшую к ней из сети.
Ну вот, кажется, и всё. Получилось несколько сумбурно, но как мог. Сам код содержит довольно много комментариев и довольно неплохо (надеюсь) читаем и без данного текста. Если будет интерес или вопросы по невнятно описанным моментам - готов к диалогу. Отдельно был бы благодарен людям, которые более-менее профессионально пишут на Python, ну или просто в теме за замечания по коду. Сам я начал изучать этот язык примерно год назад, но времени свободного очень мало, да и посоветоваться не с кем...
Всем спасибо за внимание.