0

I've made a simple terrain generator, but it takes an excessive amount of time to generate anything bigger than 50x50. Is there anything I can do to optimise the code so that I can generate larger things? I know that things such as pygame or numpy might be better for doing this, but at my school they wont install those, so this is what I have to work with.

Here's the relevant code:

def InitMap(self):
    aliveCells = []

    for x in range(self.width):
        for y in range(self.height):
            if random.random() < self.aliveChance:
                aliveCells.append(self.FindInGrid(x,y))

    return aliveCells

def GenerateMap(self):
    aliveCells = self.InitMap()
    shallowCells=[]

    self.count = 1
    for i in range(self.steps):
        aliveCells = self.DoGenStep(aliveCells)

    for i in aliveCells:
        self.canvas.itemconfig(i,fill="green")

    for i in aliveCells:
        for j in self.FindNeighbours(i):
            if j not in aliveCells:  self.canvas.itemconfig(i,fill="#0000FF")

def DoGenStep(self,oldAliveCells):
    newAliveCells = []
    for allCells in self.pos:
        for cell in allCells:

            self.root.title(str(round((self.count/(self.height*self.width)*100)/self.steps))+"%")
            self.count += 1

            aliveNeighbours = 0
            for i in self.FindNeighbours(cell):
                if i in oldAliveCells: aliveNeighbours += 1

            if cell in oldAliveCells:
                if aliveNeighbours < self.deathLimit:
                    pass
                else:
                    newAliveCells.append(cell)
            else:
                if aliveNeighbours > self.birthLimit:
                    newAliveCells.append(cell)

    return newAliveCells

def FindNeighbours(self,cell):
    cellCoords = self.GetCoords(cell) 
    neighbours = []

    for xMod in [-1,0,1]:
        x = xMod+cellCoords[0]
        for yMod in [-1,0,1]:
            y = yMod+cellCoords[1]

            if x < 0 or x >= self.width: pass
            elif y < 0 or y >= self.height: pass
            elif xMod == 0 and yMod == 0: pass
            else: neighbours.append(self.FindInGrid(x,y))

    return neighbours
Mrchooch
  • 171
  • 1
  • 1
  • 9

1 Answers1

1

NB: You didn't add the method "FindInGrid", so I'm making some assumptions. Please correct me if I'm wrong.

One thing which would help immensely for larger maps, and also when at high densities, is not to store just the alive cells, but the entire grid. By storing the alive cells, you make the behavior of your program in the order O( (x*y)^2), since you have to iterate over all alive cells for each alive cell. If you would store the entire grid, this would not be necessary, and the calculation can be performed with a time complexity linear to the surface of your grid, rather than a quadratic one.

Additional point:

self.root.title(str(round((self.count/(self.height*self.width)*100)/self.steps))+"%")

That's a string operation, which makes it relatively expensive. Are you sure you need to do this after each and every update of a single cell?

Manfred Radlwimmer
  • 13,257
  • 13
  • 53
  • 62
IRBosman
  • 96
  • 5