0

I have been trying to produce an exploration game, so naturally I started with a world generator. I am stuck, however, on populating my list of biomes. The "biome_map" list is essentially an array that is equal in width and height to whatever size the user requested. Here is the code I have written:

EWbiome_map = [] #produces an empty row that is E_W_Size km wide for chunk1 in range (1, (E_W_Size + 1)): EWbiome_map = EWbiome_map + ["empty"] biome_map = [] for chunk2 in range (1, (N_S_Size + 1)): biome_map = biome_map + [EWbiome_map] print ("Map Initialized") print ("Assigning Biomes...") # produces an empty array print (biome_map) Seed1 = Seed random.seed (Seed) x = 0 for element in biome_map: y = 0 for chunk3 in element: (biome_map[x])[y] = random.choice (biome_list) y = y + 1 x = x + 1 print ("Biomes Assigned") print (biome_map) 

The error shows up in the result, where each list is a copy of the last.

Modules Successfully Imported Biomes Initialized Map Initialized Assigning Biomes... [['empty', 'empty', 'empty'], ['empty', 'empty', 'empty'],['empty', 'empty', 'empty']] Biomes Assigned [['tundra', 'tundra', 'plateaus'], ['tundra', 'tundra', 'plateaus'], ['tundra', 'tundra', 'plateaus']] 
2
  • For the love of Guido, don't put spaces between your function name and the call parentheses: print('hi') instead of print ('hi') Commented Jul 28, 2016 at 18:12
  • @Sнаđошƒаӽ no, but it is an issue of style Commented Jul 28, 2016 at 18:17

3 Answers 3

1

You are using a reference to the same list EWbiome_map when creating biome_map. Instead do something like:

biome_map = [['empty']*E_W_Size]*N_S_Size 

Your entire code could however be pretty much shortened to:

biome_map = [[random.choice(biome_list) for _ in range(E_W_Size)] for _ in range(N_S_Size)] 
Sign up to request clarification or add additional context in comments.

2 Comments

Why would you use range(1,E_W_Size +1) instead of range(E_W_Size) if you don't use the value, as both will spawn E_W_Size elements ?
you are right, I just copied from the question. I edited my answer accordingly.
0

Your problem is the line

biome_map = biome_map + [EWbiome_map] 

You are making biome_map to be a list where each element is the list EWbiome_map. Note that each element is not a copy of the list, it is the list itself. To correct this you want a copy of the EWbiome_map list. One way to do this is

biome_map = biome_map + [list(EWbiome_map)] 

Another way is

biome_map = biome_map + [EWbiome_map[:]] 

There are also other ways, but these should be clear enough.


To clarify what is happening in your code, remember that everything in Python is an object, and an object is handled internally as a pointer to where the data in the object is stored. When you add EWbiome_map to your biome_map list, that list actually stores a pointer to EWbiome_map and not the data itself. So when you change one occurrence of that data it is changed for all references everywhere.

Doing copies by list(EWbiome_map) or EWbiome_map[:] makes a new list with its own data and pointer. Now you can change one of those without affecting the others.

TL;DR Variables are handled differently in Python than in many other languages, since everything is an object. Pointers are used more extensively than you think, but the implementation is (usually) hidden from you.

Comments

0

As other answers have mentioned, you are referencing the same EWbiome_map each time, which causes you to alter it in all rows of biome_map.

However, your code also does a lot of unnecessary things, like initializing an empty map and iterating with 'chunk3' and 'element' instead of just using x and y directly.

Faster would be to use numpy and replace all of that code with:

import numpy as np biome_map = np.random.choice(biome_list,size=(N_S_Size,E_W_Size)) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.