Roguelike labirent üretimi için en uzun yol algoritması


10

Bu gibi odalardan oluşan basit bir ızgara tabanlı harita var (A = giriş, B = çıkış):

   0 1 2 3
  #########
0 # B # #####
  #########
1 # ### #
  #########
2 # # #
  # # #
3 # # #
  #########
4 # ### #
  #########
5 ### A #
  ### #
6 ### #
  #########

Ve odalar arasında bir kapı yolu oluşturmak için uygun bir algoritma yapmaya çalışıyorum, böylece oyuncu çıkışı bulmadan önce haritanın çoğunu keşfetmeli.

Başka bir deyişle, A'dan B'ye mümkün olan en uzun yolu bulmaya çalışıyorum .

(Bu sorunun asiklik grafikler için çözülebileceğinin farkındayım; ancak bu durumda döngüler olabilir.)

DÜZENLEME: Odaların taşkın dolgu kullanılarak bağlandığı ve çıkışın girişten en uzak oda olarak seçildiği başka bir örnek:

   0 1 2 3
  #########
0 # B # #
  # # - #####
1 # | # #
  ### # #
2 ### # #
  ### - # - ###
3 # | ###
  # - #######
4 #A | #
  # # #
5 # # #
  # # #
6 # # #
  #########

Çıkış yolunun mümkün olan en uzun yol olmadığını unutmayın.


Oynatıcıyı mümkün olan en uzun yolu almaya zorlarsanız, aslında karmaşık gibi davranan düz bir yol inşa edersiniz. Bu kötü.
o0 '.

Kötü değil (örneğin, raylı atıcı türünün temeli), ancak bunu yaptığınızın farkında olmanız ve oyununuzun geri kalanını onunla iyi çalışacak şekilde tasarlamanız gerekir.

Seviyeler çoğunlukla doğrusal olduğunda oyunun hızını kontrol etmek de daha kolaydır. Örneğin, özellikle zor bir canavar odasından sonra bir kurtarma odası eklemeyi mümkün kılar. Ana yol olmasaydı, zorlukların ve ödüllerin dağılımı rastgele olurdu.
Kullanıcı bulunamadı

Yanıtlar:


11

Bence bunu yanlış şekilde yapıyorsun. Döngüleri olan bir grafikteki maksimum yol teknik olarak tanımlanmamıştır çünkü döngü başlangıç ​​ve bitiş arasında bulunuyorsa sonsuzdur. Muhtemelen maksimal yol tanımını genişletebileceğiniz / kısıtlayabileceğiniz akıllı yollar vardır, ancak buradaki en iyi yaklaşımın bu olduğunu düşünmüyorum.

Gerçek bir uzun yolu modellemeye çalışmıyorsunuz (örneğin bir haritadaki alanı mümkün olduğunca keşfetmeye çalışan bir robot). Sadece oyuncunun birçok odayı keşfetmesini sağlamaya çalışıyorsunuz.

Bu nedenle, oyuncunun çıkışı şu ana kadar keşfedilen haritanın yüzdesi ile orantılı bulma şansını yakalayın . Diyelim ki bir seviyede X odası var ve oyuncu karakteri Y'yi keşfetti. Karakter bir odaya girdiğinde, çıkışı f (Y, X) olasılığıyla oraya yerleştirin. F'nin önemsiz bir örneği (Y * Y) / (X * X) olabilir - örneğin 10 oda için, son odada% 100 şans, son odada yanında% 81 şans var - ve sadece bir İlk odada% 1 şans.

Oyunu doğru hissettirmek istediğinizde denklemi düzenleyebilirsiniz ve hatta oyuncuya oluşturma olasılığını arttırmak için bazı yetenekler verebilirsiniz. Önemli olan, karakter aslında odaya girene kadar çıkış üretmeyin. Bu yöntem ayrıca zindan üretme algoritması hakkında oyuncu bilgisine karşı da bağışık değildir; oyuncunun şövalyenin NetHack'teki zıplaması veya ışınlanma gibi garip hareket modelleri olsa bile, çıkışı bulmak için daha fazla oda keşfetmek zorunda kalacaklar.

Eğer varsa gereken statik çıkış oluşturmak, sanal bir karakter ile aynı fikri kullanabilirsiniz. Her yinelemede bir hücre hareket ederek karakterin konumundan başlayarak bir sel dolgusu düşünün. Doldurulacak son oda, çıkışın ait olduğu odadır (aslında, doldurulacak son hücre, oynatıcıdan en uzak olan hücredir). Bununla birlikte, bu durumda oyuncu çıkış hakkında daha fazla bilgiye sahiptir - eğer soldalarsa, büyük olasılıkla sağdadır - ve ışınlanabiliyorlarsa, oraya normal bir rastgele yürüyüşten daha hızlı ulaşabilirler.

Sonunda, çıkışın oyuncu karakterinden haritanın diğer tarafında ortaya çıktığı roguelike'yi bitirdim ve sonra rastgele dolaştım. Zindandaki bazı eşyalar, daha hızlı aç olmak pahasına harita üzerinde görünür kıldı. Herhangi bir analiz yapmadım, ama kesinlikle haritayı bulmak için daha fazla keşfetmek zorunda kaldım ve seviyelere benzersiz bir his verdi.


Dinamik nesil, oyuncu farketmediği sürece oldukça iyi bir fikir gibi görünüyor. Aksi takdirde oldukça aldatılmış hissedeceklerini düşünüyorum. Taşkın dolgu fikrini seviyorum.
Kullanıcı

2
Tüm teklifiniz bir anlamda oyuncuyu aldatmak. Matematiği dünya modeli gerektirmeyecek şekilde geliştirmek için beni suçlama. ;) Ama daha lezzetli hale getirmek için tasarım hilelerini kullanabilirsiniz - örneğin, çıkış bir önsel yerleştirilir, ancak bunu tanımlamak için kullandığım yöntemde oluşturulur veya yalnızca X'i keşfettikten sonra ortaya çıkan bir canavara yerleştirilir. odalar / X canavarları öldürmek veya kapıyı açmak, her odada bir tane olmak üzere X anahtarlarını

Bir taşkın dolgu yaklaşımı denedim. Her odayı bağlamak iyi bir iş çıkarır ve kısa dallar üretir, ancak çıkış ziyaret edilen son düğüm (veya benim uygulamamda en uzak olanı olsa bile) çıkışa mümkün olan en uzun yolu üretmez. (örnek soruma eklendi)
Kullanıcı 21

Yine de anahtar / anahtar tabanlı labirentler için kullanıyorum. Bu tür şeyleri ağaçlarla uygulamak daha kolay görünüyor, çünkü o zaman iki dalınız varsa, hangi dalın çıkışa yol açtığını tespit edebilir, engelleyebilir ve anahtarı diğer dallara koyabilirsiniz.
Kullanıcı

Ancak bunun "A'dan B'ye" yol bulma sorunu olduğunu düşünmemde yanlış olduğumu itiraf ediyorum. Çıkışın algoritma sonucu bir hedef olmaktan ziyade bulunmasının daha anlamlı olduğunu anlıyorum.
Kullanıcı

6

Olası bir alternatif, Prim / Kruskal kullanarak (döngüleri ortadan kaldırmak için) bir (maksimum?) Yayılan ağaç oluşturmak ve yayılan ağaca geleneksel en uzun yol algoritmasını uygulamak olabilir.

Ancak, yayılan ağaç algoritmasının çıkmaz dallar oluşturma eğiliminde olacağından endişeleniyorum ve oyuncuyu sürekli olarak geri adım atmaya zorluyor.

EDIT: Kruskal tabanlı bir algoritma kullanarak ve çıkış en uzun dalın sonuna yerleştirilmesi sonucu:

   0 1 2 3
  #########
0 #A | #
  # ##### - #
1 # # #
  ### #
2 ### #
  ### #
3 ### #
  ### - #####
4 # | #
  # - ##### - #
5 # ### #
  # - #######
6 # # B #
  # # - #
7 # | #
  #########

1
Ben de Primm önerecektim :-), +1, backtrack da bir çok oyunun önemli bir parçası olduğunu düşünüyorum ... diablo 2'yi kontrol edin
Mr.Gando

2

İşte uğraşacağınız bir şey:

Connect each room with a door to another room.
N = 0.75*TotalNumberOfRooms
Until (pathSize > N) {
  Use A* pathing to get a path from A to B. (G being size of room, or # of monsters)
  if (pathSize < N) remove a connection/door
  if (noPath) choose a different door/connection
  if (room.doors < 1) choose a different door/connection
}

Yol boyunca rastgele kapıları kaldırırdım, aksi takdirde çıkışta 1 kapı ve başlangıçta tonlarca kapı ile sonuçlanırsınız.

Bence bu O(n^2)büyük haritalar için harika değil.


Prensip olarak çok zarif bir çözüm. Bir dahaki sefere kıvrık tekniklere gitmeden önce böyle bir şey düşünmeye çalışmalıyım.
Kullanıcı

Belki zarif ama bir işlemci domuzu olacak. O (n ^ 2) büyük haritalarda iyi ölçeklenmez.
Stephen Furlani


1

Zaten harika cevaplara sahip olduğuna inanıyorum, ama işte soruna 0.02 dolarlık teorik çözümüm.

İstediğiniz en uzun yol değil, en uzun yol. Odanın en kısa yolunu düşündüğünüzde, en uzaktaki odayı istiyorsunuz. Bu muhtemelen kafa karıştırıcı gelebilir, ancak hesaplanması çok kolaydır.

  1. Başlangıç ​​odanızdan başlayın. Komşularının her birini işaretleyin 1. Başlangıç ​​odasından 1 kilometre uzaklıktadır.
  2. 1 ile işaretlenmiş her oda için, UNMARKED komşularının her birini ziyaret edin ve 2'yi işaretleyin.
  3. Tüm odaları kaplayana kadar devam edin. Maksimum sayıya sahip oda başlangıçtan en uzaktadır.

Gerçek bir en uzun yolu hesaplamak (10 oda için çok uzun sürmeyecek) çalışmaz, çünkü oyuncuyu en uzun yolu seçemezsiniz. Yani giriş ve çıkışları birbirinden en uzak iki odaya koymak en iyi seçenektir. Bunu bulmak için, rastgele bir odadan en uzak odayı hesaplayın. Sonra o odadan en uzaktaki odayı bulun. Buna bir Grafiğin çapını bulma denir, lütfen Google'ı seçin.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.