Seite 1 von 1

Labyrinth generieren mit Python

Verfasst: Montag 7. September 2009, 20:04
von veers
Ich habe am Wochenende eine Funktion zum generieren von Irrgärten/Maps für mein Zombie Spiel entwickelt.

Den Sourcecode findet ihr in meinem Blog:
http://29a.ch/2009/9/7/generating-maps- ... ith-python

Beispiel:

Code: Alles auswählen

#############################################################
#     #           #              #        #           #     #
#     #           #              #        #           #     #
#  ####  ####  #  #  ##########  #  #  #  #  #######  #  ####
#     #  #     #     #           #  #  #     #     #  #     #
#     #  #     #     #           #  #  #     #     #  #     #
####  #  #  ##########  #############  #######  #  #  ####  #
#     #  #  #  #     #     #           #     #  #  #        #
#     #  #  #  #     #     #           #     #  #  #        #
#  #######  #  #  #  ####  #######  ####  ####  #  #######  #
#           #     #  #     #        #  #     #  #        #  #
#           #     #  #     #        #  #     #  #        #  #
#############  ####  #  ####  #######  #  #  #  #  #######  #
#                 #           #           #     #           #
#                 #           #           #     #           #
#############################################################
Über Feedback würde ich mich natürlich Freuen.

Gruss,
Jonas

Verfasst: Dienstag 8. September 2009, 04:02
von EyDu
Hallo!

Ich habe den Code jetzt nicht im Detail angeschaut, aber für so wenig Text scheinen ganz vernünftige Ergebnisse rauszukommen. Gibt es für die erzeugten Labyrinthe irgendwelche Garantien: Immer einen Weg von einer freien Zelle zu einer anderen freien, keine doppelten Wände, ...?

Vorschlag:

Code: Alles auswählen

if dx > 0:
    index = lambda offset : -1+field_width*offset
elif dx < 0:
    index = lambda offset : cellsize+field_width*offset
elif dy > 0:
    index = lambda offset : -field_width+offset
else:
    index = lambda offset : cellsize*field_width+offset

for offset in xrange(cellsize):
    field[fi+index(offset)] = 1
Die Schleife danach sieht mir auch etwas komisch aus.

Man könnte aus

Code: Alles auswählen

if nx < 0 or nx >= width or ny < 0 or ny >= height:
    continue
auch folgendes machen:

Code: Alles auswählen

if nx//width or ny//height:
    continue
Ob hier kürzer auch besser ist, ist natürlich fraglich.

Bei so einem kleinen Script nicht so schlimm, aber die Berechnung von x- und y-Koordinaten sind natürlich überall doppelt.

Hat es eigentlich einen tieferen Sinn, dass die Karte als eindimensionale Liste gespeichert wird?

Verfasst: Dienstag 8. September 2009, 06:30
von BlackJack
Das sieht insgesamt mehr nach BASIC oder nach einer Low-Level-Sprache aus, bei der man dem Compiler nicht vertraut, dass er effizienten Code für verschachtelte Arrays erzeugt. Da passt natürlich EyDu's ``if``-Variante ganz gut rein. Lesbar ist anders. ;-)

Ich hätte das zum Beispiel so ausgedrückt:

Code: Alles auswählen

if not (0 <= nx < width or 0 <= ny < height):
    continue

Verfasst: Dienstag 8. September 2009, 10:19
von EyDu
Aber wenn es doch um jede Millisekunde geht...! ^^

Verfasst: Dienstag 8. September 2009, 13:53
von Redprince
Gehts ja nicht: ;)

Code: Alles auswählen

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.

Verfasst: Samstag 12. September 2009, 22:14
von veers
EyDu hat geschrieben:Ich habe den Code jetzt nicht im Detail angeschaut, aber für so wenig Text scheinen ganz vernünftige Ergebnisse rauszukommen. Gibt es für die erzeugten Labyrinthe irgendwelche Garantien: Immer einen Weg von einer freien Zelle zu einer anderen freien, keine doppelten Wände, ...?
Das ganze Labyrinth ist ein Vollständig verbundener Graph. Es gibt zwischen zwei Zellen immer genau einen Weg.
EyDu hat geschrieben: Vorschlag:

Code: Alles auswählen

if dx > 0:
    index = lambda offset : -1+field_width*offset
elif dx < 0:
    index = lambda offset : cellsize+field_width*offset
elif dy > 0:
    index = lambda offset : -field_width+offset
else:
    index = lambda offset : cellsize*field_width+offset

for offset in xrange(cellsize):
    field[fi+index(offset)] = 1
Finde ich ehrlich gesagt nicht schöner.
Ich hab es nun so angepasst:

Code: Alles auswählen

        # tear down walls
        if dx > 0:
            a = -1
            b = field_width
        elif dx < 0:
            a = cellsize
            b = field_width
        elif dy > 0:
            a = -field_width
            b = 1
        else:
            a = cellsize*field_width
            b = 1
        for offset in xrange(cellsize):
            field[fi+a+b*offset] = 1
EyDu hat geschrieben:Hat es eigentlich einen tieferen Sinn, dass die Karte als eindimensionale Liste gespeichert wird?
Ist eine (schlechte?) Angewohnheit von mir.

BlackJack, Verschachtelte Listen in Python sind nicht sonderlich effizient. 8) Das If habe ich auch angepasst. Viel mehr Abstraktion halte ich bei einem so einfachen Script eigentlich nicht für sinnvoll. :)

Gruss,
Jonas