def record_rawelevations(self): if self.seeds == set(): self.load_seeds() else: pass total_count = len(self.seeds)-1 p = Progress(total_count, 'Growing seeds...') dummyfile = FaFile('dummy.fa') if dummyfile.written == True: dummyfile._delete() elevation_MEMORY = {} memCOUNT = 0 # ex. {coord:elevation} for seed in self.seeds: p.update() for coord, rel_coord in self.get_tiles_within_radius(self.mountain_check_radius, seed): randfactor = random.randint(0, 2)/10.0 dh = 5.0/(abs(rel_coord[0])+abs(rel_coord[1])+1)**(1.0/self.mountain_fatness)+randfactor try: elevation_MEMORY[coord] += dh except KeyError: elevation_MEMORY[coord] = dh memCOUNT += 1 if memCOUNT > self.memLIMIT or p.progress == total_count: if self.raw_elevationfile.written == False: for key, value in self.coord2str(elevation_MEMORY): self.raw_elevationfile.entry(key, str(value)) elevation_MEMORY = {} memCOUNT = 0 else: str_eleMEMORY = self.construct_str_eleMEMORY(elevation_MEMORY) for key, value in self.raw_elevationfile.parse(): try: str_eleMEMORY[key] += float(value) except KeyError: dummyfile.entry(key, str(value)) self.raw_elevationfile._delete() dummyfile._rename(self.raw_elevationfile.filename) self.raw_elevationfile = dummyfile dummyfile = FaFile('dummy.fa') for key, value in str_eleMEMORY.items(): self.raw_elevationfile.entry(key, str(value)) elevation_MEMORY = {} memCOUNT = 0 else: continue p.close()
class Mapper: def __init__(self, parameter_filename='parameters.txt'): # Memory limit # self.memLIMIT = 10000 # Set parameters for world # self.parameter_filedir = 'input/' self.parameter_file = File(self.parameter_filedir+parameter_filename) for name, value in self.get_parameters(): setattr(self, name, value) output = 'output/' if not os.path.exists(output): os.mkdir(output) while self.mapname in os.listdir(output): ans = raw_input('This mapname cannot be created. Load? ') if ans == 'yes': break else: self.mapname = raw_input('New mapname: ') # File features # self.map_size = (120, 60) self.screen_size = (1200, 600) self.seeds = set() self.output_dir = os.path.join(output, self.mapname) self.ext = '.MAP' self.seedfile = File(self.output_dir+'seeds'+self.ext) self.elevationfile = File(self.output_dir+'elevations'+self.ext) self.raw_elevationfile = FaFile(self.output_dir+'raw_elevations.fa') self.temperaturefile = File(self.output_dir+'temperatures'+self.ext) self.waterfile = File(self.output_dir+'water'+self.ext) self.water_symbol = 'W' self.tilefile = File(self.output_dir+'tiles'+self.ext) self.infofile = File(self.output_dir+'INFO.txt') self.include_parameters = ('mapname', 'num_seeds', 'mountain_branch', 'mountain_spread', 'mountain_fatness', 'mountain_check_radius', 'equator_temp',\ 'mountain_temp', 'sealevel', 'water_check_radius', 'desert_temp', 'hottest', 'coldest') # Image setup # self.screen = Screen(self.screen_size[0], self.screen_size[1], 'World') self.screen.launch(topmost=False) self.tile_length = int(self.screen_size[0]/self.map_size[0]) self.tm = TileMaster((self.tile_length, self.tile_length)) self.tm.setup_images() # To be determined in self.setup()# self.num_tiles = None self.equator_y = None self.tRange = None self.sealevel = self.tm.det_sealevel() self.setup() self.STANDARD() def STANDARD(self): t0 = time.time() if self.infofile.written == False: self.record_info() if self.seedfile.written == False: self.plant_seeds() self.branch_seeds() self.record_seeds() if self.raw_elevationfile.written == False: self.record_rawelevations() if self.elevationfile.written == False: self.cleanup_elevations() if self.waterfile.written == False: self.record_watercount() if self.temperaturefile.written == False: self.record_temperatures() if self.tilefile.written == False: self.record_tiles() sys.stdout.write('\nTime: %f\n\n' % round(time.time()-t0, 7)) self.draw_tiles() def setup(self): if self.map_size[1]%2: self.equator_y = float((self.map_size[1]+1)/2) else: self.equator_y = float(self.map_size[1]/2) self.num_tiles = self.map_size[0]*self.map_size[1] self.tRange = self.hottest-self.coldest def get_parameters(self): for line in self.parameter_file._parse(): if self.parameter_file.begins_with(line, '#') or line.isspace(): continue else: key = '' value = '' equals = False for char in line: if char == '=': equals = True elif char.isspace(): continue elif equals == False: key += char else: value += char if '.' in value: yield (key, float(value)) else: try: yield (key, int(value)) except ValueError: yield (key, value) def record_info(self): for attr in self.include_parameters: value = getattr(self, attr) self.infofile.skipline_if_written() self.infofile._write('%s = %s' % (attr, str(value))) #-------------# # USEFUL FXNS # #-------------# def parse(self, FILE, give_coords=True): # Reads .map files # # Yields info and coord # if FILE.written == True: y = -1 if give_coords == True: for line in FILE._parse(): y += 1 x = -1 for char in line: x += 1 yield char, (x, y) else: for line in FILE._parse(): y += 1 x = -1 for char in line: x += 1 yield char else: raise ValueError('File: "%s" not found.' % FILE.filename) def yRadius(self, radius, x): return int(round(math.sqrt(radius**2-x**2), 0)) def get_tiles_within_radius(self, radius, coords): # Yields the coords of interest, but also their relative coords # # Ex. relative coords of the same tile as the one of inspection is (0,0) # for x in range(-radius, radius+1): yR = self.yRadius(radius, x) if yR == 0: yR = 1 for y in range(-yR, yR+1): new_coords = self.change_coords(coords, (x, y)) yield new_coords, (x, y) def change_coords(self, coords, change): x = coords[0]+change[0] if x < 0: x += self.map_size[0] elif x >= self.map_size[0]: x -= self.map_size[0] else: pass y = coords[1]+change[1] if y < 0: y += self.map_size[1] elif y >= self.map_size[1]: y -= self.map_size[1] else: pass return (x, y) def n2coords(self, n): test = n y = -1 while test >= 0: y += 1 test -= self.map_size[0] x = self.map_size[0]+test return (x, y) def coords2n(self, coords): return coords[1]*self.map_size[0]+coords[0] #-----------# # SEED FXNS # #-----------# def plant_seeds(self): self.seeds = set() for s in range(self.num_seeds): coord = (random.randint(0, self.map_size[0]-1), random.randint(0, self.map_size[1]-1)) self.seeds.add(coord) def branch_seeds(self): all_seeds = set() possible_dir = (-1, 1) self.min_spread = int(round(self.mountain_spread*0.2)) self.min_mountain_branch = int(round(self.mountain_branch*0.2)) for seed in self.seeds: all_seeds.add(seed) branch_num = random.randint(self.min_mountain_branch, self.mountain_branch) new_seed = seed dir_x = possible_dir[random.randint(0, 1)] dir_y = possible_dir[random.randint(0, 1)] for branch in range(branch_num): dx = random.randint(self.min_spread, self.mountain_spread)*dir_x dy = random.randint(self.min_spread, self.mountain_spread)*dir_y new_seed = self.change_coords(new_seed, (dx, dy)) all_seeds.add(new_seed) self.seeds = all_seeds def record_seeds(self): p = Progress(self.map_size[1], 'Getting seeds...') for y in range(self.map_size[1]): p.update() self.seedfile.skipline_if_written() for x in range(self.map_size[0]): test = (x, y) if test in self.seeds: self.seedfile._write('1') else: self.seedfile._write(' ') p.close() def load_seeds(self): p = Progress(self.num_tiles, 'Loading seeds...') for char, coord in self.parse(self.seedfile): p.update() if char == '1': self.seeds.add(coord) else: continue p.close() #----------------# # Elevation Calc # #----------------# def coord2str(self, elevation_MEMORY): for key, value in elevation_MEMORY.items(): corrected_key = '%d\t%d' % (key[0], key[1]) yield (corrected_key, value) def construct_str_eleMEMORY(self, elevation_MEMORY): new = {} for key, value in self.coord2str(elevation_MEMORY): new[key] = value return new def str2coord(self, strcoord): coord1 = '' coord2 = '' readtab = False for char in strcoord: if char.isspace(): readtab = True elif readtab == False: coord1 += char else: coord2 += char return (int(coord1), int(coord2)) def record_rawelevations(self): if self.seeds == set(): self.load_seeds() else: pass total_count = len(self.seeds)-1 p = Progress(total_count, 'Growing seeds...') dummyfile = FaFile('dummy.fa') if dummyfile.written == True: dummyfile._delete() elevation_MEMORY = {} memCOUNT = 0 # ex. {coord:elevation} for seed in self.seeds: p.update() for coord, rel_coord in self.get_tiles_within_radius(self.mountain_check_radius, seed): randfactor = random.randint(0, 2)/10.0 dh = 5.0/(abs(rel_coord[0])+abs(rel_coord[1])+1)**(1.0/self.mountain_fatness)+randfactor try: elevation_MEMORY[coord] += dh except KeyError: elevation_MEMORY[coord] = dh memCOUNT += 1 if memCOUNT > self.memLIMIT or p.progress == total_count: if self.raw_elevationfile.written == False: for key, value in self.coord2str(elevation_MEMORY): self.raw_elevationfile.entry(key, str(value)) elevation_MEMORY = {} memCOUNT = 0 else: str_eleMEMORY = self.construct_str_eleMEMORY(elevation_MEMORY) for key, value in self.raw_elevationfile.parse(): try: str_eleMEMORY[key] += float(value) except KeyError: dummyfile.entry(key, str(value)) self.raw_elevationfile._delete() dummyfile._rename(self.raw_elevationfile.filename) self.raw_elevationfile = dummyfile dummyfile = FaFile('dummy.fa') for key, value in str_eleMEMORY.items(): self.raw_elevationfile.entry(key, str(value)) elevation_MEMORY = {} memCOUNT = 0 else: continue p.close() def cleanup_elevations(self): total_entries = self.raw_elevationfile.get_total_entries() p = Progress(total_entries, 'Getting high...') dummymap = File('dummy') if dummymap.written == True: dummymap._delete() elevationMEMORY = {} memCOUNT = 0 for strcoord, floatelevation in self.raw_elevationfile.parse(): p.update() coord = self.str2coord(strcoord) # elevation = int(round(float(floatelevation), 0)) if elevation > 9: elevation = 9 elif elevation < 0: elevation = 0 else: pass elevationMEMORY[coord] = elevation memCOUNT += 1 if memCOUNT > self.memLIMIT or p.progress == total_entries: if self.elevationfile.written == False: for y in range(self.map_size[1]): self.elevationfile.skipline_if_written() for x in range(self.map_size[0]): try: elevation = elevationMEMORY[(x, y)] except KeyError: elevation = 0 self.elevationfile._write(str(elevation)) else: y = -1 for line in self.elevationfile._parse(): dummymap.skipline_if_written() y += 1 x = -1 for char in line: x += 1 if char != '0': dummymap._write(char) else: try: elevation = elevationMEMORY[(x, y)] except KeyError: elevation = 0 dummymap._write(str(elevation)) self.elevationfile._delete() dummymap._rename(self.elevationfile.filename) self.elevationfile = dummymap dummymap = File('dummy') elevationMEMORY = {} memCOUNT = 0 else: continue p.close() #-------------# # Water Count # #-------------# def get_watercount(self, coord): water_count = 0 check_coords = set() for test_coord, useless_information_not_needed in self.get_tiles_within_radius(self.water_check_radius, coord): check_coords.add(test_coord) max_check = len(check_coords) checked = 0 for char, inspect_coord in self.parse(self.elevationfile): if inspect_coord in check_coords: elevation = int(char) if elevation > self.sealevel: pass else: water_count += 1 if water_count == 9: break else: pass checked += 1 if checked == max_check: break else: continue else: continue return water_count def record_watercount(self): p = Progress(self.num_tiles, 'Getting H2O...') for char, coord in self.parse(self.elevationfile): p.update() if coord[0] == 0 and self.waterfile.written == True: self.waterfile._write('\n') else: pass elevation = int(char) if elevation <= self.sealevel: watercount = self.water_symbol else: watercount = self.get_watercount(coord) self.waterfile._write(str(watercount)) p.close() #------------------# # Temperature Calc # #------------------# def get_temperature_LATITUDE(self, latitude_y): dLat = float(abs(latitude_y-self.equator_y)) dT = self.equator_temp*(1-dLat/self.equator_y) return dT def get_temperature_ELEVATION(self, elevation): dT = self.mountain_temp*float(elevation)/9 return dT def get_temperature_WATER(self, watercount, y_lattitude): if watercount == self.water_symbol: dT = 0 else: dT = self.desert_temp*(1-float(watercount)/9)*(1-abs(y_lattitude-self.equator_y)/float(self.equator_y))**0.5 return dT def record_temperatures(self): p = Progress(self.num_tiles, 'Getting hot...') iter_elevationfile = iter(self.parse(self.elevationfile)) iter_waterfile = iter(self.parse(self.waterfile, give_coords=False)) for tile in range(self.num_tiles): p.update() ele_char, coord = next(iter_elevationfile) wat_char = next(iter_waterfile) if coord[0] == 0 and self.temperaturefile.written == True: self.temperaturefile._write('\n') else: pass temp_lat = self.get_temperature_LATITUDE(coord[1]) temp_ele = self.get_temperature_ELEVATION(int(ele_char)) temp_wat = self.get_temperature_WATER(wat_char, coord[1]) total = temp_lat+temp_ele+temp_wat+random.randint(0, 2)/10.0 if total > 9: total = 9 elif total < 0: total = 0 else: total = int(round(total)) self.temperaturefile._write(str(total)) p.close() #----------------# # Matching Tiles # #----------------# def record_tiles(self): p = Progress(self.num_tiles, 'Building tiles...') iter_elevationfile = iter(self.parse(self.elevationfile)) iter_temperaturefile = iter(self.parse(self.temperaturefile, give_coords=False)) for tile in range(self.num_tiles): p.update() ele_char, coord = next(iter_elevationfile) temp_char = next(iter_temperaturefile) corrected_temp = float(temp_char)/9*self.tRange+self.coldest tile_symbol = self.tm.choose_tile(int(ele_char), corrected_temp) if coord[0] == 0 and self.tilefile.written == True: self.tilefile._write('\n') else: pass if tile_symbol == None: raise Exception(str(ele_char)+'\t'+str(corrected_temp)) else: self.tilefile._write(str(tile_symbol)) p.close() #------------# # Draw tiles # #------------# def draw_tiles(self): p = Progress(self.map_size[1], 'Drawing tiles...') y = -1 for line in self.tilefile._parse(): p.update() y += 1 x = -1 for char in line.strip(): x += 1 tile = self.tm.tile_map[char] position = (x*self.tile_length, y*self.tile_length) CanvasTile(self, tile, position) p.close() raw_input()