Небольшое примечание: вы говорите: «выглядит как карта реальной жизни со странами разных форм, но одинакового размера), но« реальные »страны сильно различаются по размеру даже в определенных регионах - даже« большие »страны Европы могут сильно различаться, например, Франция более чем в два раза больше Италии. С учетом вышесказанного, очевидно, есть игровые регионы, в которых можно попытаться сохранить размеры примерно одинаковыми - просто имейте в виду, что небольшая вариация здесь, вероятно, хорошая вещь!
Мой первоначальный подход к проблеме должен был бы «развивать» (а не «расти») ваши регионы:
- Начните с какого-то конкретного деления карты на куски примерно одинакового размера по прямым линиям (например, если вы хотите 6 стран, то вы можете разделить карту на три горизонтальных фрагмента, а затем разбить каждый из этих фрагментов «по диагонали»). на две части). Это очевидно легко сделать программно, тем более что это не обязательно должно быть очень точно (на самом деле, вероятно, не должно быть очень точно).
- Сделайте начальный проход по разделению, построив «граничную» структуру данных: набор гексов, сосед которых в данный момент принадлежит другой стране. Это также было бы хорошим временем для подсчета количества гексов в каждой стране.
Теперь сколько угодно, запустите следующий псевдокод:
Pick a random hex A from the boundary list;
Pick a random neighbor B of this hex from a different country;
if (A's country has more hexes than B's country has) {
change hex A to belong to B's country;
} else if (B's country has more hexes than A's country has) {
change hex B to belong to A's country;
} else {
flip a coin to decide which to change;
}
if ( the changed hex's old country has become disconnected ) {
undo and reject this move;
} else {
update the boundary list around the changed hex and its neighbors;
}
Это будет поддерживать приблизительный баланс между размерами любых двух соседних стран, а проверка «отсоединения» (которая может быть выполнена с помощью простого алгоритма заполнения паводком) гарантирует, что ни одна страна никогда не распадется на части. Обновление списка границ - это операция с постоянным временем - измененный гекс, очевидно, всегда будет по-прежнему на границе, и вы можете просто проверить его шесть соседей, чтобы увидеть, стал ли какой-либо из них граничной ячейкой (потому что его сосед теперь находится в другой стране) или перестали быть пограничной ячейкой (потому что ее сосед находится сейчас в той же стране), изменяя набор границ по мере необходимости.
Чтобы уточнить этот подход, вы можете даже сделать условие, что гекс для изменения немного рандомизирован - вместо того, чтобы всегда «балансировать» две страны, вы всегда можете сделать своп с определенной вероятностью и даже постепенно уменьшить эту вероятность в течение время (аналогично процессу охлаждения в алгоритме имитации отжига ), чтобы заставить их быть примерно одинакового размера.
Обратите внимание, что это не гарантирует того, что все области имеют одинаковый размер (что невозможно, если N в любом случае не разделит размер сетки), и даже не гарантирует, что все страны находятся в одном гексе друг от друга по площади; тем не менее, он должен гарантировать (запустить для достаточного количества итераций), что каждая страна не более чем на один гекс больше или меньше, чем каждый из ее непосредственных соседей.