コード例 #1
0
ファイル: mapper.py プロジェクト: ychnlgy/map_generator_2d
    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()
コード例 #2
0
ファイル: mapper.py プロジェクト: ychnlgy/map_generator_2d
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()