Merge
authorDavid Sharpe <decoydavid@gmail.com>
Thu, 3 Mar 2016 21:08:58 +0000 (23:08 +0200)
committerDavid Sharpe <decoydavid@gmail.com>
Thu, 3 Mar 2016 21:08:58 +0000 (23:08 +0200)
1  2 
koperkapel/generators/maps.py

index 51aae6500f4ed313707fbb5353d185eae3f2ea77,94269294e914d6f7b6b9430119d279e54b758b36..4f917c68169ea454c9feb34d63ee4a2284ff70e7
  
  import random
  import math
+ import json
+ import os
  
  i = random.randint(0,100)
  
  
++<<<<<<< HEAD
 +class Room:
 +    def __init__(self, region):
 +        """
 +        """
 +        self.regions = [region]
 +        self.max_connections = 1
 +        self.passages = []
 +        self.tunnels = []
 +
 +    def is_linked(self):
 +        """
 +        Check if the room is linked to another room
 +        :return: Whether the room has any links or not
 +        """
 +        return len(self.passages) + len(self.tunnels) > 0
 +
 +    def add_passage(self, room_region, new_region):
 +        """ Add a passage link between rooms
 +        :param room_region: coordinate of region from which we are linking
 +        :param new_region: coordinate of region to which we are linking
 +        :return:
 +        """
 +        pass
 +
 +    def add_region(self, region):
 +        """
 +        Add a new region into an existing room
 +        :param region: region coordinates to be added to room
 +        :return:
 +        """
 +        self.regions.append(region)
 +
 +    def connect_rooms(self, other_rooms):
 +        """ Find the nearest rooms to this room
 +        :param other_rooms: list of Rooms objects that we are searching
 +        :return:
 +        """
 +        distance = []
 +        other_tile = []
 +        this_tile = []
 +        target_rooms = []
 +        for local_region in self.regions:
 +            for room in other_rooms:
 +                if self == room:
 +                    continue
 +                for new_region in room.regions:
 +                    distance.append(
 +                        math.sqrt((local_region[0] - new_region[0]) ** 2 +
 +                                  (local_region[1] - new_region[1]) ** 2))
 +                    other_tile.append(new_region)
 +                    this_tile.append(local_region)
 +                    target_rooms.append(room)
 +
 +        sorted_indices = [i[0] for i in sorted(enumerate(distance),
 +                                               key=lambda x:x[0])]
 +        for index in sorted_indices:
 +            if len(self.passages) + len(self.tunnels) >= self.max_connections:
 +                break
 +            if not target_rooms[index].is_linked():
 +                self.link_passage(this_tile[index], other_tile[index])
 +                target_rooms[index].link_passage(
 +                    other_tile[index], this_tile[index])
 +
 +    def link_passage(self, local_tile, foriegn_tile):
 +        """ Link a passage between two rooms
 +        :param local_tile: tile in this room to which we wish to link
 +        :param foriegn_tile: tile in another room to which we wish to link
 +        :return:
 +        """
 +        self.passages.append([local_tile, foriegn_tile])
++=======
+ ATTRIBUTE_MAP = {
+     '#': {'base': 'cwall', 
+           'behaviour': [],
+          },
+     ' ': {'base': 'floor',
+           'behaviour': ['walk', 'fly'],
+          },
+ }
++>>>>>>> 0b2149fff63b346192148b7eb334e00ad3b9283d
  
  
  class LevelGenerator:
      width = 0
      height = 0
 -    rooms = 0
 +    no_rooms = 0
 +    rooms = []
      map = None
      min_room_size = 0
      max_room_size = 0
      dist_from_edge = 0
      dist_from_other_rooms = 0
 -    regions = None
 -    region = 0
 -    region_size_in_tiles = 0
 +    region_map = None
 +    regions = 0
 +    region_size = 0
  
 -    def __init__(self, width, height, rooms, min_room_size, max_room_size, dist_from_edge,
 -                 dist_from_other_rooms, region_size_in_tiles):
 +    def __init__(self, width, height, no_rooms, min_room_size, max_room_size,
 +                 dist_from_edge, dist_from_other_rooms, region_size):
          """ Initialize the level parameters
          """
          self.width = width
          self.height = height
 -        self.rooms = rooms
 +        self.no_rooms = no_rooms
          self.min_room_size = min_room_size
          self.max_room_size = max_room_size
          self.dist_from_edge = dist_from_edge
          self.dist_from_other_rooms = dist_from_other_rooms
 -        self.region_size_in_tiles = region_size_in_tiles
 +        self.region_size = region_size
  
      def generate(self):
          """ Generate a random level map
          """
 -        self.generate_regions()
 -        row = ['#' for x in range(self.width * self.region_size_in_tiles)]
 -        self.map = [row[:] for x in range(self.height * self.region_size_in_tiles)]
 -        regions_selected = random.sample(range(self.region), min(self.region, self.rooms))
 +        self.generate_rooms()
 +        regions_selected = random.sample(range(self.regions),
 +                                         min(self.regions, self.no_rooms))
 +        row = ['#' for x in range(self.width * self.region_size)]
 +        self.map = [row[:] for x in range(self.height * self.region_size)]
          print('Regions: %s' % str(regions_selected))
          for region in regions_selected:
 -            self.generate_room(region)
 +            self.rooms[region].connect_rooms(
 +                [self.rooms[i] for i in regions_selected])
 +            self.generate_tiles(region)
  
 -    def generate_regions(self):
 +    def generate_rooms(self):
          """ Generate a random level region map
          """
 -        row = ['#' for x in range(self.width)]
 -        self.regions = [row[:] for x in range(self.height)]
 +        row = [0 for x in range(self.width)]
 +        self.region_map = [row[:] for x in range(self.height)]
          for h in range(self.height):
              for w in range(self.width):
                  random_number = random.randint(0, 2)
 +                increment_region = False
                  if w == h == 0:
 -                    self.regions[h][w] = self.region
 -                    self.region += 1
 +                    self.region_map[h][w] = self.regions
 +                    increment_region = True
                  elif h == 0:
                      if random_number > 1:
 -                        try:
 -                            self.regions[h][w] = self.regions[h][w - 1]
 -                        except:
 -                            print(h, w)
 -                            raise
 +                        self.region_map[h][w] = self.region_map[h][w - 1]
                      else:
 -                        self.regions[h][w] = self.region
 -                        self.region += 1
 +                        self.region_map[h][w] = self.regions
 +                        increment_region = True
                  elif w == 0:
                      if random_number > 1:
 -                        self.regions[h][w] = self.regions[h - 1][w]
 +                        self.region_map[h][w] = self.region_map[h - 1][w]
                      else:
 -                        self.regions[h][w] = self.region
 -                        self.region += 1
 +                        self.region_map[h][w] = self.regions
 +                        increment_region = True
                  else:
                      if random_number > 1:
 -                        self.regions[h][w] = self.regions[h - 1][w]
 +                        self.region_map[h][w] = self.region_map[h - 1][w]
 +
                      elif random_number > 0:
 -                        self.regions[h][w] = self.regions[h][w - 1]
 +                        self.region_map[h][w] = self.region_map[h][w - 1]
                      else:
 -                        self.regions[h][w] = self.region
 -                        self.region += 1
 +                        self.region_map[h][w] = self.regions
 +                        increment_region = True
 +                if increment_region:
 +                    self.regions += 1
 +                    r = Room([h, w])
 +                    self.rooms.append(r)
 +                else:
 +                    self.rooms[-1].add_region([h,w])
  
 -    def generate_room(self, region_selected):
 +    def generate_tiles(self, region_selected):
          """
 +        :param region_selected:
 +        :return:
          """
          for h in range(self.height):
              for w in range(self.width):
 -                if self.regions[h][w] == region_selected:
 +                if self.region_map[h][w] == region_selected:
                      if w == 0:
                          w_dist = self.dist_from_other_rooms
 -                    elif self.regions[h][w-1] == region_selected:
 +                    elif self.region_map[h][w-1] == region_selected:
                          w_dist = 0
                      else:
                          w_dist = self.dist_from_other_rooms
  
                      if w + 1 == self.width:
 -                        e_dist = self.region_size_in_tiles - self.dist_from_other_rooms
 -                    elif self.regions[h][w+1] == region_selected:
 -                        e_dist = self.region_size_in_tiles
 +                        e_dist = self.region_size - self.dist_from_other_rooms
 +                    elif self.region_map[h][w+1] == region_selected:
 +                        e_dist = self.region_size
                      else:
 -                        e_dist = self.region_size_in_tiles - self.dist_from_other_rooms
 +                        e_dist = self.region_size - self.dist_from_other_rooms
  
                      if h == 0:
                          n_dist = self.dist_from_other_rooms
 -                    elif self.regions[h-1][w] == region_selected:
 +                    elif self.region_map[h-1][w] == region_selected:
                          n_dist = 0
                      else:
                          n_dist = self.dist_from_other_rooms
  
                      if h + 1 == self.height:
 -                        s_dist = self.region_size_in_tiles - self.dist_from_other_rooms
 -                    elif self.regions[h+1][w] == region_selected:
 -                        s_dist = self.region_size_in_tiles
 +                        s_dist = self.region_size - self.dist_from_other_rooms
 +                    elif self.region_map[h+1][w] == region_selected:
 +                        s_dist = self.region_size
                      else:
 -                        s_dist = self.region_size_in_tiles - self.dist_from_other_rooms
 +                        s_dist = self.region_size - self.dist_from_other_rooms
  
                      for wt in range(w_dist, e_dist):
                          for ht in range(n_dist, s_dist):
 -                            self.map[h * self.region_size_in_tiles + ht][w * self.region_size_in_tiles + wt] = ' '
 +                            self.map[h * self.region_size + ht]\
 +                                [w * self.region_size + wt] = ' '
 +
 +    def generate_passage_tiles(self):
 +        """ Generate the tiles that form the passages between the rooms
 +        :return:
 +        """
 +
 +
  
      def display(self):
          file = open('map.txt', 'w')
              file.write(''.join(l))
              file.write('\n')
          file.close()
++<<<<<<< HEAD
 +        for l in self.region_map:
++=======
+         self._to_json()
+         for l in self.regions:
++>>>>>>> 0b2149fff63b346192148b7eb334e00ad3b9283d
              print(l)
  
+     def _to_json(self):
+         level = {}
+         level['tiles'] = []
+         for l in self.map:
+             row = []
+             for t in l:
+                 row.append(ATTRIBUTE_MAP[t])
+             level['tiles'].append(row)
+         name = os.path.join(os.path.dirname(__file__), '..', 'levels', 'map.json')
+         # FIXME: Do a lot better here 
+         # Crude hack so the level is written into the levels folder
+         f = open(name, 'w')
+         json.dump(level, f)
+         f.close()
  
  if __name__ == '__main__':
      while True:
 -        level = LevelGenerator(width=8, height=5, rooms=12, min_room_size=5, max_room_size=20,
 -                               dist_from_edge=2, dist_from_other_rooms=1, region_size_in_tiles=6)
 +        level = LevelGenerator(width=4, height=3, no_rooms=4,
 +                               min_room_size=5, max_room_size=20,
 +                               dist_from_edge=1, dist_from_other_rooms=1,
 +                               region_size=5)
          level.generate()
          level.display()
          input("Press Enter to continue...")