stupidpythonprojects/laby2/Laby.py

256 lines
8.4 KiB
Python

#!/usr/bin/python
from Kachel import *
from PIL import Image
from PIL import ImageDraw
import random
import sys
import math
CHAR_WALL = "X"
CHAR_START = "*"
CHAR_END = "#"
class Laby:
def __init__(self, size, arraySize, kachelSize, waySteps):
self.kachelArray = []
self.size = size
self.arraySize = arraySize
self.kachelSize = kachelSize
self.img = None
self.drawObject = None
self.createImage()
self.createArray()
self.visitedFields = 0
self.maxWaysteps = waySteps # ein aenderung dieses wertes duerfte
# den schwierigkeitsgrad beeinflussen
def createImage(self):
self.img = Image.new("RGB", (self.size[0], self.size[1]),
(255, 255, 255))
self.drawObject = ImageDraw.ImageDraw(self.img)
def createArray(self):
for x in range(self.arraySize[0]):
tmp = []
for y in range(self.arraySize[1]):
tmp.append(Kachel((x, y), self.kachelSize))
self.kachelArray.append(tmp)
def makeAllWalkable(self):
for y in self.kachelArray:
for x in y:
x.makeWalkable()
def draw(self):
for i in self.kachelArray:
for j in i:
j.draw(self.drawObject, self.kachelSize)
def saveToTxt(self, filename):
fobj = open(filename, "w")
for j in range(self.arraySize[0]*2 + 1):
fobj.write(CHAR_WALL)
fobj.write("\n")
for i in range(self.arraySize[1]):
fobj.write(CHAR_WALL)
for j in range(self.arraySize[0]):
if (i == 0 and j == 0):
fobj.write(CHAR_START)
elif(i == self.arraySize[1]-1 and j == self.arraySize[0]-1):
fobj.write(CHAR_END)
else:
fobj.write(" ")
if self.kachelArray[j][i].isOpen(EAST):
fobj.write(" ")
else:
fobj.write(CHAR_WALL)
fobj.write("\n" + CHAR_WALL)
for j in range(self.arraySize[0]):
if self.kachelArray[j][i].isOpen(SOUTH):
fobj.write(" ")
else:
fobj.write(CHAR_WALL)
fobj.write(CHAR_WALL)
fobj.write("\n")
fobj.close();
def showOnScreen(self):
self.img.show()
def save(self, filename):
self.img.save(filename)
def openWay(self, pos, direction):
self.kachelArray[pos[0]][pos[1]].open(direction)
if direction == NORTH:
if pos[1] > 0:
self.kachelArray[pos[0]][pos[1] - 1].open(SOUTH)
elif direction == EAST:
if pos[0] < self.arraySize[0] - 1:
self.kachelArray[pos[0] + 1][pos[1]].open(WEST)
elif direction == SOUTH:
if pos[1] < self.arraySize[1] - 1:
self.kachelArray[pos[0]][pos[1] + 1].open(NORTH)
elif direction == WEST:
if pos[0] > 0:
self.kachelArray[pos[0] - 1][pos[1]].open(EAST)
def scanNeighbours(self, scanPos):
scanResult = [0, 0, 0, 0] # 0 = nix, 1 = unbesucht, 2 = besucht
# NORTH:
if scanPos[1] > 0:
north = self.kachelArray[scanPos[0]][scanPos[1] - 1]
if north.isWalkable():
if north.isVisited():
scanResult[NORTH] = 2
else:
scanResult[NORTH] = 1
# SOUTH:
if scanPos[1] < self.arraySize[1] - 1:
south = self.kachelArray[scanPos[0]][scanPos[1] + 1]
if south.isWalkable():
if south.isVisited():
scanResult[SOUTH] = 2
else:
scanResult[SOUTH] = 1
# WEST:
if scanPos[0] > 0:
west = self.kachelArray[scanPos[0] - 1][scanPos[1]]
if west.isWalkable():
if west.isVisited():
scanResult[WEST] = 2
else:
scanResult[WEST] = 1
# EAST:
if scanPos[0] < self.arraySize[0] - 1:
east = self.kachelArray[scanPos[0] + 1][scanPos[1]]
if east.isWalkable():
if east.isVisited():
scanResult[EAST] = 2
else:
scanResult[EAST] = 1
return scanResult
def bakeWay(self, startPos):
self.pos = startPos
for c in range(self.maxWaysteps): # pro weg maximal waysteps schritte
self.kachelArray[self.pos[0]][self.pos[1]].touch()
self.visitedFields += 1
neighbours = self.scanNeighbours(self.pos)
if neighbours.count(1) == 0:
break
possibleDirections = []
for i in range(4):
if neighbours[i] == 1:
possibleDirections.append(i)
#zufaellige richtung waehlen:
nextDir = random.sample(possibleDirections, 1)[0]
self.openWay(self.pos, nextDir)
#zur naechsten Kachel gehen:
if nextDir == NORTH:
self.pos = (self.pos[0], self.pos[1] - 1)
elif nextDir == EAST:
self.pos = (self.pos[0] + 1, self.pos[1])
elif nextDir == SOUTH:
self.pos = (self.pos[0], self.pos[1] + 1)
elif nextDir == WEST:
self.pos = (self.pos[0] - 1, self.pos[1])
def bakeLaby(self, startPos, isFirstBake):
if isFirstBake:
print("Berechne Labyrinth...")
self.bakeWay(startPos)
unvisitedCounter = (self.arraySize[0]*self.arraySize[1]
- self.visitedFields)
while unvisitedCounter > 0:
#fortschritt in Prozent
print(str(float(self.visitedFields * 100.0)
/ float(self.arraySize[0] * self.arraySize[1])) + "%")
# zaehle unbesuchte, an besuchten Feldern angrenzende Felder
neighbours = []
unvisitedCounter = 0
for y in self.kachelArray:
for x in y:
if not x.isVisited():
if self.scanNeighbours(x.getPos()).count(2) > 0:
unvisitedCounter += 1
neighbours.append(x)
if unvisitedCounter > 0:
nextPos = random.sample(neighbours, 1)[0]
tmp = self.scanNeighbours(nextPos.getPos())
possibleConnectDirs = []
for i in range(4):
if tmp[i] == 2:
possibleConnectDirs.append(i)
connectDir = random.sample(possibleConnectDirs, 1)[0]
self.openWay(nextPos.getPos(), connectDir)
self.bakeWay(nextPos.getPos())
if __name__ == "__main__":
#programmaufruf: Laby.py [W] [H] [Feldgroesse] [filename]
try:
KACHELSIZE = int(sys.argv[3])
WIDTH = int(sys.argv[1])
HEIGHT = int(sys.argv[2])
FILENAME = sys.argv[4]
except:
print("\nFehlerhafte Parameter!")
print("Benoetigte Parameter:"
+ "[BREITE] [HOEHE] [FELDGROESSE] [DATEINAME] <WAYSTEPS>"
+ "\n\nBREITE: die Breite des Labyrinthes in Anzahl an Feldern"
+ "\n\nHOEHE: die Hoehe des Labyrinthes in Anzahl an Feldern"
+ "\n\nFELDGROESSE: Kantenlaenge eines Feldes in Pixeln"
+ "\n\nDATEINAME: Dateiname fuer das fertige Labyrinth (ohne dateiendung)"
+ "\n\nWAYSTEPS(optional): gibt die maximale Laenge eines "
+ "\nWegstuecks in Feldern an, die ohne Abzweigung vom Algorithmus"
+ "\ngeneriert werden kann. Pauschal kann man sagen: je kleiner "
+ "\nder Wert, desto kuerzer ist der kuerzeste Weg zwischen zwei "
+ "\nPunkten im Labyrinth. Standardwert ist 100 \n")
sys.exit(0)
# optionale Argumente:
try:
WAYSTEPS = int(sys.argv[5])
except:
WAYSTEPS = 100
laby = Laby(((WIDTH + 2) * KACHELSIZE, (HEIGHT + 2) * KACHELSIZE),
(WIDTH, HEIGHT), (KACHELSIZE, KACHELSIZE), WAYSTEPS)
laby.makeAllWalkable()
laby.bakeLaby((0, 0),True)
laby.saveToTxt(FILENAME + ".txt")
laby.openWay((0, 0), WEST)
laby.openWay((WIDTH - 1, HEIGHT - 1), EAST)
laby.draw()
laby.save(FILENAME + ".png")
laby.showOnScreen()