Generowanie proceduralnych lochów: czy istnieje prosty algorytm, aby upewnić się, że wszystkie te pokoje są połączone za pomocą minimalnych korytarzy?

9

Czy można uzyskać strukturę przypominającą ul, łączącą wszystkie pokoje bez zbyt wielu korytarzy? (Zbyt wiele to 3-4 + korytarze wychodzące z jednego pokoju)

Poniżej znajduje się wynik tego, jak wyglądają moje pokoje, w zasadzie losowo rozmieszczone.

wyjście z pomieszczeń gridu, rozmieszczonych losowo

Mam nadzieję, że rozwiążę sprawę korytarza.

http://i.imgur.com/9GUi6Yy.png

Mikser
źródło
Nie sądzę, aby 3 lub 4 to „zbyt wiele korytarzy”. Zwłaszcza jeśli masz 9 pokoi w lochu. Poza tym nie jestem pewien, co rozumiesz przez „strukturę przypominającą ul”, czy mógłbyś rozwinąć swój wygląd?
fnord,
Może zawierać „ukończoną” mapę, aby pokazać, co chcesz mieć.
MichaelHouse
Ach tak, miałem na myśli maksymalnie 3 lub 4 korytarze wychodzące z każdego pokoju.
Blenderer,
Dodałem obraz tego, do czego dążę, aż do korytarzy.
Blenderer,
2
Jeśli nie masz 3 korytarzy z żadnego pokoju, będziesz w stanie wykonać proste liniowe połączenie pokoi, a więc po prostu wybierz jeden i połącz go z dwoma najbliższymi sąsiadami.
Nick

Odpowiedzi:

6

Cóż, najprostszy sposób, jaki mogę wymyślić, zaczyna się od upewnienia się, że wszystkie pokoje są połączone przynajmniej jednym korytarzem:

  1. Zacznij od ostatniego lub pierwszego pokoju.
  2. Chwyć losowy pokój w odległości 1 odległości, który nie jest jeszcze połączony z jakimś pokojem (wszystkie pokoje zaczynają się rozłączać, więc będziesz śledził to podczas podróży).
  3. Jeśli nie ma takiego pokoju, idź na odległość +1. Jeśli tunelowanie nad / pod innym pokojem jest w porządku, jest to łatwiejsze, zakładając, że nie chcesz łączyć korytarzy.
  4. Poruszaj się pseudolosowo, aż wszystkie pokoje zostaną połączone.

Teraz wiemy, że możesz dostać się do wszystkich pokoi, ale teraz, jeśli chcesz więcej niż ten ściśle liniowy labirynt, możesz po prostu przejść przez pokoje i losowo utworzyć nową ścieżkę łączenia pokoi, do limitu na pokój 2-3, lub dopóki określony procent pokoi nie osiągnie maksymalnej liczby połączeń - itp.

Ostatnim krokiem jest dodanie reguł, które zmieniłyby wyniki w zależności od różnych sytuacji. Na przykład można zauważyć, że każdy pokój z tylko 1 korytarzem jest z definicji ślepą uliczką; Możesz zrobić więcej ślepych zaułków lub możesz je wszystkie wyeliminować, upewniając się, że wszystko ma co najmniej 2 połączenia. Możesz sprawić, że ślepe zaułki mają tajne przejście. Możesz upewnić się, że pokój szefa jest ślepym zaułkiem. Możesz upewnić się, że Twój pokój początkowy jest ślepy, ale upewnij się, że drugi pokój ma minimum X połączeń. Ad infinitum.

Każde założenie i zasada może radykalnie zmienić wygląd twoich poziomów, ale to część zabawy! Powinno to przynajmniej zacząć od stworzenia pomieszczeń przypominających jaskinie / jaskinie.

BrianH
źródło
Jest to dość zbliżone do algorytmu minimalnego drzewa opinającego Kruskala - to modyfikuje warunek w 2 z „nie podłączony do jakiegoś pokoju” na „jeszcze nie podłączony do tego samego klastra ”, co naprawia błąd w zasadach opisanych powyżej, w których można mieć sytuacja, w której każdy pokój jest połączony z jakimś pokojem, ale loch jako całość nadal tworzy wiele odłączonych wysp. Kruskal ma gwarancję znalezienia wykresu połączenia z minimalną całkowitą długością korytarza.
DMGregory
3

Po prostu zbuduj pokoje już połączone. Zacznij od jednego pokoju, a następnie zbuduj 1-3 korytarze do innych pomieszczeń. Następnie powtarzaj, aż dodasz wystarczającą liczbę pokoi.

Nicol Bolas
źródło
2

Ponieważ te pokoje są wierzchołkami grafu osadzonymi na równinie 2d, teoretycznie można to zrobić, rozwiązując problem podróżnego sprzedawcy (co byłoby w porządku, gdyby było tylko kilka pokoi). Oczywiście prosta heurystyka byłaby w porządku i umożliwiałaby rozsądną skalowalność.

Obliczasz krawędzie (długości korytarza) między wszystkimi pokojami. Sortujesz je według długości. Dodajesz najkrótszy korytarz, chyba że tworzy on cykl lub nie zwiększa stopnia wierzchołka (pomieszczenia) powyżej pożądanej wartości maksymalnej (3-4) (Powtórz). Aby sprawdzić cykle, możesz zastosować UnionFind lub wykonać szybki BFS na małych danych.

AturSams
źródło
Ta odpowiedź jest lepsza niż odpowiedź zaakceptowana. Powinna działać chciwa strategia wybierania najkrótszych łączących się korytarzy. Aby uniknąć cykli, nie twórz połączeń z pokojami, które mają już połączony korytarz.
Jelle van Campen
@JellevanCampen Thanks. ;) Możesz mieć dwa izolowane podłączone komponenty. Prawdopodobnie więc chciałbyś użyć funkcji znajdowania lub sprawdzenia unii w BFS, jeśli dwa węzły są połączone.
AturSams,
Ach tak, masz rację, mój zły.
Jelle van Campen