示例#1
0
def kruskals(inputFile):
    graph = open(inputFile)
    edges = [ ]
    nodes = {}
    count = 0
    '''
    The following reads in the input file
    and constructs an adjacency list of
    the graph.
    '''
    for line in graph:
        entry = line.split()
        edges.append((entry[2],entry[0],entry[1]))
        if entry[0] not in nodes.keys():
            nodes[entry[0]]= count
            count = count + 1
    total = 0
    solutions =[]
    disjoint = DisjointSet(len(nodes))
    edges.sort()
    for edge in edges:
        if disjoint.find(nodes[edge[1]]) != disjoint.find(nodes[edge[2]]):
            if disjoint.find(nodes[edge[1]]) < disjoint.find(nodes[edge[2]]):
                disjoint.union(nodes[edge[1]], nodes[edge[2]])
            else:
                disjoint.union(nodes[edge[2]], nodes[edge[1]])
            solutions.append(edge)
            total += int(edge[0])
    return total, solutions
示例#2
0
 def test_compress_path(self):
     s = DisjointSet(10)
     s.union(1, 2)
     s.union(3, 4)
     s.union(1, 3)
     self.assertEqual(s.getPath(1), [1, 2, 4])
     s.find(1)
     self.assertEqual(s.getPath(1), [1, 4])
示例#3
0
    def DisjointCycle(self, vertices):
        d = DisjointSet(vertices)
        for i, j in self.edges:
            a, b = d.find(i), d.find(j)
            if a == b:
                return True
            d.union(i, j)

        return False
示例#4
0
def _create_sets(game_map, width, height):

    ds = DisjointSet()

    for x in range(0, width):

        for y in range(0, height):

            if game_map[x][y] == FLOOR:
                ds.find((x, y))

                _join_adjacent_tiles(x, y, game_map, ds)

    return ds
示例#5
0
def Kruskal(graph):
  """Algorithme de Kruskal
  Retourne la liste des arretes du graphe de coût minimum
  """

  forest = DisjointSet()
  chemin = []

  for n in graph['Nodes']:
    forest.add(n)

  nbrNodes = len(graph['Nodes']) - 1

  for arc in sorted(graph['Edges'], key=itemgetter(2)): #O( --- )
    n1, n2, poids = arc

    t1 = forest.find(n1)
    t2 = forest.find(n2)

    if t2 != t1:
      chemin.append(arc)
      nbrNodes -= 1

      if nbrNodes == 0:
        return chemin

      forest.union(t1, t2)
示例#6
0
def minimum_spanning_tree(graph):
    """
    Find the minimum spanning tree in the given graph using 
    Kruskal's algorithm
    :param graph: the graph to find the MST in
    :return: the set of all edges in the MST
    """
    d = DisjointSet()  # initialize disjoint set data structure
    d.make_sets(graph.get_vertices())
    edges = graph.get_edges()  # All edges in graph
    solution = set()  # Set of edges in MST
    quick_sort(edges, 0, len(edges) - 1)  # Sort by edge weight in asc

    for e in edges:
        if d.find(e[0]) != d.find(e[1]):  # if the vertices wont make a cycle
            d.union(e[0], e[1])  # union them
            solution.add(e)  # add the edge to the solution
    return solution
示例#7
0
    def constructSpanningTree(self, vertexList, edgeList):

        disjointSet = DisjointSet(vertexList)
        spanningTree = []

        edgeList.sort()

        for edge in edgeList:
            u = edge.startVertex
            v = edge.targetVertex

            # check whether the edges don't form a cycle
            # if they don't then add the edge to the spanning tree
            # and union the two nodes
            if disjointSet.find(u.parentNode) != disjointSet.find(
                    v.parentNode):
                spanningTree.append(edge)
                disjointSet.union(u.parentNode, v.parentNode)

        # print the spanning tree by printing all the edges
        for edge in spanningTree:
            print(edge.startVertex.name, "-", edge.targetVertex.name)
示例#8
0
def cluster(Elist, nV, k):
    '''
    Function for single-linkage hierarchical clustering, which is based on 
    Kruskal's minimum spanning tree algorithm.
    Input:
        Elist: Edge list for a complete graph(contains end verticies and edge cost)
        nV   : total number of vertices
        k    : number of clusters
    Output:
        The shortest distance between two verticies that belong to different clusters.
    '''
    assert nV >= k, "Number of clusters can't be greater than number of nodes!"
    Elist.sort(key=lambda x: x[2])
    dset = DisjointSet(nV)
    i = 0
    while len(dset) > k:
        e = Elist[i]
        i += 1
        if dset.find(e[0]) != dset.find(e[1]):
            dset.union(e[0], e[1])
    while dset.find(Elist[i][0]) == dset.find(Elist[i][1]):
        i += 1
    return Elist[i][2]
示例#9
0
    def __init__(self, points, edges):

        self.h0 = {}
        for p in points:
            self.h0[p['index']] = [p['time'], math.inf]

        djs = DisjointSet()
        edges.sort(key=itemgetter('time'))

        for d in edges:
            i0, i1 = d['p0']['index'], d['p1']['index']
            f0, f1 = djs.find(i0), djs.find(i1)
            if f0 != f1:
                djs.union(f0, f1)
                self.h0[f0][1] = d['time']

        self.h0 = list(
            map((lambda h: {
                'index': h,
                'life': self.h0[h],
                'persistence': (self.h0[h][1] - self.h0[h][0])
            }), self.h0.keys()))
        self.h0 = list(filter((lambda h: h['persistence'] > 0), self.h0))
        self.h0.sort(key=itemgetter('persistence'))
示例#10
0
def kruskals(inputFile):

    graph = open(inputFile)
    
    pqueue = [] 
    
    mst = []
    
    totalCost = 0
    
    for line in graph:
        entry = line.split()
           
        # construct an edge for the adjacency list
        'We construct this edge and use the cost as the starting element for this tuple to use in the priority queue'
        edge = (int(entry[2]), entry[0], entry[1])
        'we push the edge onto the priority queue'
        heapq.heappush(pqueue, edge)

    '''
    We convert the length of the priority queue into an integer to use with a disjointset
    '''      
    size = len(pqueue)
    frontier = DisjointSet(size)
    
    '''
    Going through each edge in the priority queue, we set the newEdge equal to the current tuple in the priority queue
    and then perform the find function from disjointset on the two vertexes. Since the vertexes are in string form from 
    the tuple, the ord function is used to convert the vertexes into integers for use in the find function. 96 is subtracted from the 
    tuple vertexes to set the unicode code pointer equal to the integer value of the letter in the alphabet (a = 97 with the ord function, and subtracting 97 gives us a = 1).
    We then check if the two vertexes through integer values are not equal to each other. If they are not, we add the the nextEdge tuple to the 
    minimum spanning tree list, and perform a union of the two vertices using the find function from Disjoin set. We also calculate the cost in this 
    if statement.
    '''
    for newEdge in sorted(pqueue):
        newEdge = heapq.heappop(pqueue)
        v1 = frontier.find(ord(newEdge[1])-96)
        v2 = frontier.find(ord(newEdge[2])-96)
        if v1 != v2:
            totalCost = newEdge[0] + totalCost
            mst.append(newEdge)
            frontier.union(v1, v2)
    'Returns the total cost of the mst and the mst list'        
    return totalCost,mst
        
        
    return 0
示例#11
0
def MST(G):
    '''
    图G
    '''
    V = G.V
    E = G.Adjlist

    MSTV = set()
    MSTE = {}
    Ds = DisjointSet(V)
    for v in V:
        MSTE[v] = Linklist()
    for u in MSTE.keys():
        curList = E[u]
        curNode = curList.head
        while (curNode != 0):
            v = curNode.data
            #使用并查集判断是否生成环
            #------------------------------------
            parentu = Ds.find(u)
            parentv = Ds.find(v)
            if parentu != parentv:
                #不会生成环
                MSTV.add(u)
                MSTV.add(v)
                MSTE[u].pushback(Node(v, curNode.weight))
                MSTE[v].pushback(Node(u, curNode.weight))
                #合并两并查集
                Ds.union(parentu, parentv)
            else:
                #加入该边会生成环
                MaxWeightEdge = getMaxWeightEdge(MSTV, MSTE, u, v)
                if curNode.weight < MaxWeightEdge.w:
                    MSTE[MaxWeightEdge.u].remove(MaxWeightEdge.v)
                    MSTE[MaxWeightEdge.v].remove(MaxWeightEdge.u)
                    MSTE[u].pushback(Node(v, curNode.weight))
                    MSTE[v].pushback(Node(u, curNode.weight))
                    #合并
                    Ds.union(parentu, parentv)
            curNode = curNode.next

    return Graph(MSTV, None, MSTE, kind='nodirect')
示例#12
0
class CA_CaveFactory:
    def __init__(self, width, height, initial_open=0.60):
        self.__height = height
        self.__width = width
        self.__area = height * width
        self.__CAmap = []
        self.__rooms = []
        self.__leveldata = {}
        self.__ds = DisjointSet()
        self.__up_loc = 0
        self.center_pt = (int(self.__height/2), int(self.__width/2))
        self.__gen_initial_map(width, height, initial_open)

    # Performs the CA operation, then joins separate rooms.  Returns the map, consisting of a grid of ints.
    def gen_map(self):
        loops = random.randrange(2, 4)
        while loops > 0:
            for r in range(1, self.__height-1):
                for c in range(1, self.__width-1):
                    if not self.__CAmap[c][r].permanent:
                        wall_count = self.__adj_wall_count(r, c)
                        if not self.__CAmap[c][r].blocked:
                            if wall_count > 5:
                                self.__CAmap[c][r].blocked = True
                                self.__CAmap[c][r].block_sight = True
                        elif wall_count < 4:
                            self.__CAmap[c][r].blocked = False
                            self.__CAmap[c][r].block_sight = False

            loops -= 1

        self.__join_rooms()

        return self.__CAmap

    def get_rooms(self):
        return self.__rooms

    def create_room(self, room, layout):
        # go through the tiles in the defined rectangle and construct them according to the layout
        x = room.x1 + 1
        y = room.y1
        for char in layout:
            if char == ".":
                self.__CAmap[x][y].permanent = True
                self.__CAmap[x][y].blocked = False
                self.__CAmap[x][y].block_sight = False
            if char == ",":
                self.__CAmap[x][y].permanent = False
                self.__CAmap[x][y].blocked = False
                self.__CAmap[x][y].block_sight = False
            if char == "X":
                self.__CAmap[x][y].permanent = True
                self.__CAmap[x][y].blocked = True
                self.__CAmap[x][y].block_sight = True
            if char == "x":
                self.__CAmap[x][y].permanent = False
                self.__CAmap[x][y].blocked = True
                self.__CAmap[x][y].block_sight = True
            x += 1
            if char == "\n":
                x = room.x1 + 1
                y += 1

    def create_room_features(self, room, layout):
        # Start with an empty set to put level data in
        leveldata = {}

        # go through the tiles in the defined rectangle and construct them according to the layout
        x = room.x1 + 1
        y = room.y1
        for char in layout:
            element = None
            if char == "=": element = "monastery doorway"
            if char == "b": element = "brazier"
            if element: leveldata.update({(x,y):element})
            x += 1
            if char == "\n":
                x = room.x1 + 1
                y += 1

        return leveldata


    def __set_border(self):
        # make all border squares walls
        # This could be moved to a superclass
        for j in range(0,self.__width-1):
            self.__CAmap[j][0].permanent = True
            self.__CAmap[j][self.__height-1].permanent = True

        for j in range(0,self.__height-1):
            self.__CAmap[0][j].permanent = True
            self.__CAmap[self.__width-1][j].permanent = True


    def __gen_initial_map(self,width,height,initial_open):
        # Create an initial map with random tiles removed, plus rooms and fixtures.
        self.__CAmap = map_init(height,width)

        open_count = int(self.__area * initial_open)
        self.__set_border()

        for r in range(MAX_ROOMS):

            # Pick a random selection from our options.
            roomselection = random.choice(roommaking.templefurniture.keys())
            layoutselection = roommaking.templefurniture[roomselection]

            # Get the width and height
            w, h = roommaking.measurements(layoutselection)

            # Find a spot without going off the edge of the map
            x = random.randrange(0, self.__width - w - 1)
            y = random.randrange(0, self.__height - h - 1)

            # Build rooms as Chambers
            new_room = Chamber(x, y, w, h, 'temple')

            # Check against other rooms to ensure this new room overlaps none of the others
            failed = False
            for other_room in self.__rooms:
                if new_room.intersect(other_room):
                    failed = True
                    break

            if not failed:
                # i.e., no intersections, so paint a room
                self.create_room(new_room, layoutselection)

                # Give it some features
                new_room_features = self.create_room_features(new_room, layoutselection)
                self.__leveldata.update(new_room_features)

                print self.__leveldata
                self.__rooms.append(new_room)

                (new_x, new_y) = new_room.center()  # Previously used for player placement (center of first room)

        tree = bspmaking.Leaf(20,20,20,10)
        tree.branch()
        leaves = tree.gatherleaves()
        for leaf in leaves:
            print "Leaf:", leaf.w, leaf.y

        # Chew out a certain amount of 'noise' for the CA function to work over.
        while open_count > 0:
            rand_r = random.randrange(1,self.__height-1)
            rand_c = random.randrange(1,self.__width-1)

            if self.__CAmap[rand_c][rand_r].blocked and not self.__CAmap[rand_c][rand_r].permanent:
                self.__CAmap[rand_c][rand_r].blocked = False
                self.__CAmap[rand_c][rand_r].block_sight = False
                open_count -= 1

    def __adj_wall_count(self,sr,sc):
    # How many walls are surrounding a tile?
        count = 0

        for r in (-1,0,1):
            for c in (-1,0,1):
                if self.__CAmap[(sc + c)][sr + r].blocked and not(c == 0 and r == 0):
                    count += 1

        return count

    def __join_rooms(self):
        # divide the square into equivalence classes
        for r in range(1,self.__height-1):
            for c in range(1,self.__width-1):
                if not self.__CAmap[c][r].blocked:
                    self.__union_adj_sqr(c,r)

        all_caves = self.__ds.split_sets()

        for cave in all_caves.keys():
            self.__join_points(all_caves[cave][0])

    def __join_points(self,pt1):
        next_pt = pt1

        while 1:
            dir = self.__get_tunnel_dir(pt1,self.center_pt) ### This determines the next point to 'drill' to.  Unfortunately it will still drill through 'permanent' tiles.  How to fix?  We could, possibly, use a pathfinding algorithm to get to work our way to the center point.  That should work but might be overkill.  Let's see how often it happens first while I work on cave building.

            if (dir[0] == 0) or (dir[1] == 0):
                next_pt = (pt1[0] + dir[0],pt1[1] + dir[1])
            else:
                if random.randrange(0,1):
                    next_pt = (pt1[0] + dir[0],pt1[1])
                else:
                    next_pt = (pt1[0],pt1[1] + dir[1])

            if self.__CAmap[next_pt[0]][next_pt[1]].permanent: print "Uh oh, permanent tile at", next_pt[0], next_pt[1]

            if self.__stop_drawing(pt1,next_pt,self.center_pt):
                return

            root1 = self.__ds.find(next_pt)
            root2 = self.__ds.find(pt1)

            if root1 != root2:
                self.__ds.union(root1,root2)

            self.__CAmap[next_pt[0]][next_pt[1]].blocked = False
            self.__CAmap[next_pt[0]][next_pt[1]].block_sight = False
            self.__CAmap[next_pt[0]][next_pt[1]].debug = True          # DEBUG

            pt1 = next_pt

    def __stop_drawing(self,pt,npt,cpt):
        if self.__ds.find(npt) == self.__ds.find(cpt):
            return 1
        if self.__ds.find(pt) != self.__ds.find(npt) and not self.__CAmap[npt[0]][npt[1]].blocked:
            return 1
        else:
            return 0

    def __get_tunnel_dir(self,pt1,pt2):
        if pt1[0] < pt2[0]:
            h_dir = +1
        elif pt1[0] > pt2[0]:
            h_dir = -1
        else:
            h_dir = 0

        if pt1[1] < pt2[1]:
            v_dir = +1
        elif pt1[1] > pt2[1]:
            v_dir = -1
        else:
            v_dir = 0

        return (h_dir,v_dir)

    def __union_adj_sqr(self,sr,sc):
        loc = (sr,sc)

        for r in (-1,0):
            for c in (-1,0):
                nloc = (sr+r,sc+c)

                if not self.__CAmap[nloc[0]][nloc[1]].blocked and (r+c != -2):
                    root1 = self.__ds.find(loc)
                    root2 = self.__ds.find(nloc)

                    if root1 != root2:
                        self.__ds.union(root1,root2)
示例#13
0
class CA_CaveFactory:
    def __init__(self, length, width, initial_open=0.40):
        self.__length = length
        self.__width = width
        self.__area = length * width
        self.__map = []
        self.__ds = DisjointSet()
        self.__up_loc = 0
        self.center_pt = (int(self.__length / 2), int(self.__width / 2))
        self.__gen_initial_map(initial_open)

    def print_grid(self):
        x = 0
        row = ""

        for r in range(0, self.__length):
            for c in range(0, self.__width):
                if self.__map[r][c] in (WALL, PERM_WALL):
                    print '#',
                else:
                    print '.',

            print

    def gen_map(self):
        for r in range(1, self.__length - 1):
            for c in range(1, self.__width - 1):
                wall_count = self.__adj_wall_count(r, c)

                if self.__map[r][c] == FLOOR:
                    if wall_count > 5:
                        self.__map[r][c] = WALL
                elif wall_count < 4:
                    self.__map[r][c] = FLOOR

        self.__join_rooms()

        return self.__map

    # make all border squares walls
    # This could be moved to a superclass
    def __set_border(self):
        for j in range(0, self.__length):
            self.__map[j][0] = PERM_WALL
            self.__map[j][self.__width - 1] = PERM_WALL

        for j in range(0, self.__width):
            self.__map[0][j] = PERM_WALL
            self.__map[self.__length - 1][j] = PERM_WALL

    def __gen_initial_map(self, initial_open):
        for r in range(0, self.__length):
            row = []
            for c in range(0, self.__width):
                row.append(WALL)
            self.__map.append(row)

        open_count = int(self.__area * initial_open)
        self.__set_border()

        while open_count > 0:
            rand_r = randrange(1, self.__length - 1)
            rand_c = randrange(1, self.__width - 1)

            if self.__map[rand_r][rand_c] == WALL:
                self.__map[rand_r][rand_c] = FLOOR
                open_count -= 1

    def __adj_wall_count(self, sr, sc):
        count = 0

        for r in (-1, 0, 1):
            for c in (-1, 0, 1):
                if self.__map[(sr + r)][sc + c] != FLOOR and not(r == 0 and c == 0):
                    count += 1

        return count

    def __join_rooms(self):
        # divide the square into equivalence classes
        for r in range(1, self.__length - 1):
            for c in range(1, self.__width - 1):
                if self.__map[r][c] == FLOOR:
                    self.__union_adj_sqr(r, c)

        all_caves = self.__ds.split_sets()

        for cave in all_caves.keys():
            self.__join_points(all_caves[cave][0])

    def __join_points(self, pt1):
        next_pt = pt1

        while 1:
            dir = self.__get_tunnel_dir(pt1, self.center_pt)
            move = randrange(0, 3)

            if move == 0:
                next_pt = (pt1[0] + dir[0], pt1[1])
            elif move == 1:
                next_pt = (pt1[0], pt1[1] + dir[1])
            else:
                next_pt = (pt1[0] + dir[0], pt1[1] + dir[1])

            if self.__stop_drawing(pt1, next_pt, self.center_pt):
                return

            root1 = self.__ds.find(next_pt)
            root2 = self.__ds.find(pt1)

            if root1 != root2:
                self.__ds.union(root1, root2)

            self.__map[next_pt[0]][next_pt[1]] = FLOOR

            pt1 = next_pt

    def __stop_drawing(self, pt, npt, cpt):
        if self.__ds.find(npt) == self.__ds.find(cpt):
            return 1
        if self.__ds.find(pt) != self.__ds.find(npt) and self.__map[npt[0]][npt[1]] == FLOOR:
            return 1
        else:
            return 0

    def __get_tunnel_dir(self, pt1, pt2):
        if pt1[0] < pt2[0]:
            h_dir = +1
        elif pt1[0] > pt2[0]:
            h_dir = -1
        else:
            h_dir = 0

        if pt1[1] < pt2[1]:
            v_dir = +1
        elif pt1[1] > pt2[1]:
            v_dir = -1
        else:
            v_dir = 0

        return (h_dir, v_dir)

    def __union_adj_sqr(self, sr, sc):
        loc = (sr, sc)

        for r in (-1, 0):
            for c in (-1, 0):
                nloc = (sr + r, sc + c)

                if self.__map[nloc[0]][nloc[1]] == FLOOR:
                    root1 = self.__ds.find(loc)
                    root2 = self.__ds.find(nloc)

                    if root1 != root2:
                        self.__ds.union(root1, root2)
示例#14
0
class FullMap:
    # A map using CA to build caves but also pre-set rooms.
    def __init__(self, width, height, levelnum, initial_open=0.60):
        self.__height = height
        self.__width = width
        self.__area = height * width
        self.__map = []
        self.__levelnum = levelnum
        self.__rooms = []
        self.__ds = DisjointSet()
        self.__up_loc = 0
        self.center_pt = (int(self.__height / 2), int(self.__width / 2))
        self.objects = []
        self.eventdict = {}
        self.gen_map(initial_open)

    def gen_map(self, initial_open):
        # Create an initial map
        self.__map = map_init(self.__height, self.__width)

        # make all border squares walls
        for j in range(0, self.__width - 1):
            self.__map[j][0].permanent = True
            self.__map[j][self.__height - 1].permanent = True

        for j in range(0, self.__height - 1):
            self.__map[0][j].permanent = True
            self.__map[self.__width - 1][j].permanent = True

        # Chew out randomized spots on the map
        self.randomize(initial_open)

        # Make a list of level features to make
        levellist = levelmaking.choose_levelset(self.__levelnum)

        # Init a counter for events
        currentevent = 1

        # For each item, get the features to make a Chamber out of.  Make a chamber and dig a proper room out of it.
        for item in levellist:
            # Select an item from the possible ones, given the type.
            itemselection = levelmaking.select_elements(item)

            # Want to look until a placement is found.
            placed = False
            while not placed:

                # Given this item, what arguments do we need to actually make the room?
                args = levelmaking.set_element_values(item, itemselection,
                                                      self.__width,
                                                      self.__height)
                new_room = Chamber(*args)

                # Check against other rooms to ensure this new room overlaps none of the others
                # This needs to go somewhere else!
                intersected = False
                for other_room in self.__rooms:
                    if new_room.intersect(other_room):
                        intersected = True
                        print "Failed intersection test!"
                        break

                # In cases of intersection, note the failure, and try again (another loop).  Otherwise, perform the
                # dig-a-room operations and make a note to finish the loop.
                if intersected:
                    print "Failed making", new_room.style
                else:
                    # i.e., no intersections, so paint a room
                    levelmaking.dig_room(self.__map, new_room, itemselection)
                    roomobjects = levelmaking.collect_features(
                        self.__map, new_room, itemselection)
                    self.objects += roomobjects
                    print "Successfully dug", new_room.style
                    self.__rooms.append(new_room)
                    placed = True

                    (new_x, new_y) = new_room.center(
                    )  # Previously used for player placement (center of first room)

        # Perform CA operation - how many loops to perform?
        loops = random.randrange(4, 5)
        self.ca_operation(loops)

        # Check for other room-making operations

        # Join the areas of the level
        self.__join_rooms()

    def finalize_map(self):
        return self.__map

    def finalize_obects(self):
        return self.objects

    def get_rooms(self):
        return self.__rooms

    def is_map_blocked(self, x, y):
        if self.__map[x][y].is_blocked:
            return True
        else:
            return False

    def randomize(self, initial_open):
        open_count = int(self.__width * self.__height * initial_open)
        while open_count > 0:
            rand_r = random.randrange(1, self.__height - 1)
            rand_c = random.randrange(1, self.__width - 1)

            if self.__map[rand_c][rand_r].blocked and not self.__map[rand_c][
                    rand_r].permanent:
                self.__map[rand_c][rand_r].blocked = False
                self.__map[rand_c][rand_r].block_sight = False
                open_count -= 1

    def check_open(self):
        count = 0
        for x in range(1, self.__width):
            for y in range(1, self.__height):
                if self.__map[x][y].blocked:
                    count += 1
        print 'open tiles: ', count

    def ca_operation(self, loops):
        # For non-permanent tiles, grow or kill depending on their surroundings.
        while loops > 0:
            for r in range(1, self.__height - 1):
                for c in range(1, self.__width - 1):
                    if not self.__map[c][r].permanent:
                        wall_count = self.__adj_wall_count(r, c)
                        if not self.__map[c][r].blocked:
                            if wall_count > 5:
                                self.__map[c][r].blocked = True
                                self.__map[c][r].block_sight = True
                        elif wall_count < 4:
                            self.__map[c][r].blocked = False
                            self.__map[c][r].block_sight = False
            loops -= 1

    def __adj_wall_count(self, sr, sc):
        # How many walls are surrounding a tile?
        count = 0

        for r in (-1, 0, 1):
            for c in (-1, 0, 1):
                if self.__map[(sc + c)][sr +
                                        r].blocked and not (c == 0 and r == 0):
                    count += 1

        return count

    def __join_rooms(self):

        all_caves = self.__determine_areas()

        # Build a tunneling map for pathing - use the permanent state check to determine passability.
        tunnelingmap = libtcod.map_new(self.__width, self.__height)
        for x in range(1, self.__width - 1):
            for y in range(1, self.__height - 1):
                perm_wall = (self.__map[x][y].permanent
                             and self.__map[x][y].blocked)
                libtcod.map_set_properties(tunnelingmap, x, y, True,
                                           not perm_wall)

        # The tunneling path will let us move from the origin to the center.
        tunnelingpath = libtcod.dijkstra_new(tunnelingmap, 0.0)

        # The center needs to be non-permanent, otherwise we can't path to it.
        center_x, center_y = self.__find_good_center(self.center_pt)

        for cave in all_caves.keys():
            # This comment used to run the joining.  The function is still usable!
            #self.__join_points(all_caves[cave][0])
            origin_x = all_caves[cave][0][0]
            origin_y = all_caves[cave][0][1]

            libtcod.dijkstra_compute(tunnelingpath, origin_x, origin_y)
            if not libtcod.dijkstra_path_set(tunnelingpath, center_x,
                                             center_y):
                print "Could not path! Center point permanent:", self.__map[
                    center_x][center_y].permanent
            prev_pt = (origin_x, origin_y)
            while not libtcod.dijkstra_is_empty(tunnelingpath):
                x, y = libtcod.dijkstra_path_walk(tunnelingpath)
                next_pt = (x, y)
                if x is not None:

                    root1 = self.__ds.find(next_pt)
                    root2 = self.__ds.find(prev_pt)

                    if root1 != root2:
                        self.__ds.union(root1, root2)

                    self.__map[next_pt[0]][next_pt[1]].blocked = False
                    self.__map[next_pt[0]][next_pt[1]].block_sight = False
                    self.__map[next_pt[0]][next_pt[1]].debug = True  # DEBUG

                    if self.__stop_drawing(prev_pt, next_pt, self.center_pt):
                        print "Done cave", cave
                        break

                    prev_pt = next_pt

        all_caves = self.__determine_areas()
        if len(all_caves.keys()) > 1:
            self.__join_rooms()

    def __determine_areas(self):
        # divide the square into equivalence classes
        for r in range(1, self.__height - 1):
            for c in range(1, self.__width - 1):
                if not self.__map[c][r].blocked:
                    self.__union_adj_sqr(c, r)

        # Get a list of areas to work on, then remove small caves before returning
        areas = self.__ds.split_sets()
        zones = areas.keys()
        for zone in zones:
            if len(areas[zone]) < 9:
                for location in areas[zone]:
                    x = location[0]
                    y = location[1]
                    self.__map[x][y].permanent = False
                    self.__map[x][y].blocked = True
                    self.__map[x][y].block_sight = True
                areas.pop(zone)

        print "Number of areas is", len(areas)
        return areas

    def __find_good_center(self, pt):
        # This function randomly moves the center to find a good 'end' point for cave joining function.
        # That is, the center can't be permanent.
        x = pt[0]
        y = pt[1]
        while self.__map[x][y].permanent:
            x += random.randrange(-1, 1)
            y += random.randrange(-1, 1)
        pt = (x, y)
        return pt

    def __stop_drawing(self, pt, npt, cpt):
        if self.__ds.find(npt) == self.__ds.find(cpt):
            return 1
        if self.__ds.find(pt) != self.__ds.find(npt) and not self.__map[
                npt[0]][npt[1]].blocked:
            return 1
        else:
            return 0

    def __get_tunnel_dir(self, pt1, pt2):
        if pt1[0] < pt2[0]:
            h_dir = +1
        elif pt1[0] > pt2[0]:
            h_dir = -1
        else:
            h_dir = 0

        if pt1[1] < pt2[1]:
            v_dir = +1
        elif pt1[1] > pt2[1]:
            v_dir = -1
        else:
            v_dir = 0

        return h_dir, v_dir

    def __union_adj_sqr(self, sr, sc):
        loc = (sr, sc)

        for r in (-1, 0):
            for c in (-1, 0):
                nloc = (sr + r, sc + c)

                if not self.__map[nloc[0]][nloc[1]].blocked and (r + c != -2):
                    root1 = self.__ds.find(loc)
                    root2 = self.__ds.find(nloc)

                    if root1 != root2:
                        self.__ds.union(root1, root2)
示例#15
0
class CA_CaveFactory:
    def __init__(self, length, width, initial_open=0.40):
        self.__length = length
        self.__width = width
        self.__area = length * width
        self.__map = []
        self.__ds = DisjointSet()
        self.__up_loc = 0
        self.center_pt = (int(self.__length / 2), int(self.__width / 2))
        self.__gen_initial_map(initial_open)

    def intialize_frmt_ar(self, ar):

        for r in range(0, self.__length):
            ar.append([])

    def format_grid(self):
        x = 0
        row = ""
        local_ar = []
        self.intialize_frmt_ar(local_ar)

        for r in range(0, len(local_ar)):
            for c in range(0, self.__width):
                if self.__map[r][c] in (WALL, PERM_WALL):
                    local_ar[r].append(1)
                else:
                    local_ar[r].append(0)

        return local_ar

    def gen_map(self):
        for r in range(1, self.__length - 1):
            for c in range(1, self.__width - 1):
                wall_count = self.__adj_wall_count(r, c)

                if self.__map[r][c] == FLOOR:
                    if wall_count > 5:
                        self.__map[r][c] = WALL
                elif wall_count < 4:
                    self.__map[r][c] = FLOOR

        self.__join_rooms()

        return self.__map

    # make all border squares walls
    # This could be moved to a superclass
    def __set_border(self):
        for j in range(0, self.__length):
            self.__map[j][0] = PERM_WALL
            self.__map[j][self.__width - 1] = PERM_WALL

        for j in range(0, self.__width):
            self.__map[0][j] = PERM_WALL
            self.__map[self.__length - 1][j] = PERM_WALL

    def __gen_initial_map(self, initial_open):
        for r in range(0, self.__length):
            row = []
            for c in range(0, self.__width):
                row.append(WALL)
            self.__map.append(row)

        open_count = int(self.__area * initial_open)
        self.__set_border()

        while open_count > 0:
            rand_r = randrange(1, self.__length - 1)
            rand_c = randrange(1, self.__width - 1)

            if self.__map[rand_r][rand_c] == WALL:
                self.__map[rand_r][rand_c] = FLOOR
                open_count -= 1

    def __adj_wall_count(self, sr, sc):
        count = 0

        for r in (-1, 0, 1):
            for c in (-1, 0, 1):
                if self.__map[(sr + r)][sc + c] != FLOOR and not (r == 0
                                                                  and c == 0):
                    count += 1

        return count

    def __join_rooms(self):
        # divide the square into equivalence classes
        for r in range(1, self.__length - 1):
            for c in range(1, self.__width - 1):
                if self.__map[r][c] == FLOOR:
                    self.__union_adj_sqr(r, c)

        all_caves = self.__ds.split_sets()

        for cave in all_caves.keys():
            self.__join_points(all_caves[cave][0])

    def __join_points(self, pt1):
        next_pt = pt1

        while 1:
            dir = self.__get_tunnel_dir(pt1, self.center_pt)
            move = randrange(0, 3)

            if move == 0:
                next_pt = (pt1[0] + dir[0], pt1[1])
            elif move == 1:
                next_pt = (pt1[0], pt1[1] + dir[1])
            else:
                next_pt = (pt1[0] + dir[0], pt1[1] + dir[1])

            if self.__stop_drawing(pt1, next_pt, self.center_pt):
                return

            root1 = self.__ds.find(next_pt)
            root2 = self.__ds.find(pt1)

            if root1 != root2:
                self.__ds.union(root1, root2)

            self.__map[next_pt[0]][next_pt[1]] = FLOOR

            pt1 = next_pt

    def __stop_drawing(self, pt, npt, cpt):
        if self.__ds.find(npt) == self.__ds.find(cpt):
            return 1
        if self.__ds.find(pt) != self.__ds.find(npt) and self.__map[npt[0]][
                npt[1]] == FLOOR:
            return 1
        else:
            return 0

    def __get_tunnel_dir(self, pt1, pt2):
        if pt1[0] < pt2[0]:
            h_dir = +1
        elif pt1[0] > pt2[0]:
            h_dir = -1
        else:
            h_dir = 0

        if pt1[1] < pt2[1]:
            v_dir = +1
        elif pt1[1] > pt2[1]:
            v_dir = -1
        else:
            v_dir = 0

        return (h_dir, v_dir)

    def __union_adj_sqr(self, sr, sc):
        loc = (sr, sc)

        for r in (-1, 0):
            for c in (-1, 0):
                nloc = (sr + r, sc + c)

                if self.__map[nloc[0]][nloc[1]] == FLOOR:
                    root1 = self.__ds.find(loc)
                    root2 = self.__ds.find(nloc)

                    if root1 != root2:
                        self.__ds.union(root1, root2)
示例#16
0
 def test_union(self):
     s = DisjointSet(10)
     s.union(1, 2)
     s.union(3, 4)
     self.assertEqual(len(s), 8)
     self.assertEqual(s.find(1), 2)
示例#17
0
class CA_CaveFactory:
    def __init__(self, width, height, initial_open=0.60):
        self.__height = height
        self.__width = width
        self.__area = height * width
        self.__CAmap = []
        self.__rooms = []
        self.__leveldata = {}
        self.__ds = DisjointSet()
        self.__up_loc = 0
        self.center_pt = (int(self.__height / 2), int(self.__width / 2))
        self.__gen_initial_map(width, height, initial_open)

    # Performs the CA operation, then joins separate rooms.  Returns the map, consisting of a grid of ints.
    def gen_map(self):
        loops = random.randrange(2, 4)
        while loops > 0:
            for r in range(1, self.__height - 1):
                for c in range(1, self.__width - 1):
                    if not self.__CAmap[c][r].permanent:
                        wall_count = self.__adj_wall_count(r, c)
                        if not self.__CAmap[c][r].blocked:
                            if wall_count > 5:
                                self.__CAmap[c][r].blocked = True
                                self.__CAmap[c][r].block_sight = True
                        elif wall_count < 4:
                            self.__CAmap[c][r].blocked = False
                            self.__CAmap[c][r].block_sight = False

            loops -= 1

        self.__join_rooms()

        return self.__CAmap

    def get_rooms(self):
        return self.__rooms

    def create_room(self, room, layout):
        # go through the tiles in the defined rectangle and construct them according to the layout
        x = room.x1 + 1
        y = room.y1
        for char in layout:
            if char == ".":
                self.__CAmap[x][y].permanent = True
                self.__CAmap[x][y].blocked = False
                self.__CAmap[x][y].block_sight = False
            if char == ",":
                self.__CAmap[x][y].permanent = False
                self.__CAmap[x][y].blocked = False
                self.__CAmap[x][y].block_sight = False
            if char == "X":
                self.__CAmap[x][y].permanent = True
                self.__CAmap[x][y].blocked = True
                self.__CAmap[x][y].block_sight = True
            if char == "x":
                self.__CAmap[x][y].permanent = False
                self.__CAmap[x][y].blocked = True
                self.__CAmap[x][y].block_sight = True
            x += 1
            if char == "\n":
                x = room.x1 + 1
                y += 1

    def create_room_features(self, room, layout):
        # Start with an empty set to put level data in
        leveldata = {}

        # go through the tiles in the defined rectangle and construct them according to the layout
        x = room.x1 + 1
        y = room.y1
        for char in layout:
            element = None
            if char == "=": element = "monastery doorway"
            if char == "b": element = "brazier"
            if element: leveldata.update({(x, y): element})
            x += 1
            if char == "\n":
                x = room.x1 + 1
                y += 1

        return leveldata

    def __set_border(self):
        # make all border squares walls
        # This could be moved to a superclass
        for j in range(0, self.__width - 1):
            self.__CAmap[j][0].permanent = True
            self.__CAmap[j][self.__height - 1].permanent = True

        for j in range(0, self.__height - 1):
            self.__CAmap[0][j].permanent = True
            self.__CAmap[self.__width - 1][j].permanent = True

    def __gen_initial_map(self, width, height, initial_open):
        # Create an initial map with random tiles removed, plus rooms and fixtures.
        self.__CAmap = map_init(height, width)

        open_count = int(self.__area * initial_open)
        self.__set_border()

        for r in range(MAX_ROOMS):

            # Pick a random selection from our options.
            roomselection = random.choice(roommaking.templefurniture.keys())
            layoutselection = roommaking.templefurniture[roomselection]

            # Get the width and height
            w, h = roommaking.measurements(layoutselection)

            # Find a spot without going off the edge of the map
            x = random.randrange(0, self.__width - w - 1)
            y = random.randrange(0, self.__height - h - 1)

            # Build rooms as Chambers
            new_room = Chamber(x, y, w, h, 'temple')

            # Check against other rooms to ensure this new room overlaps none of the others
            failed = False
            for other_room in self.__rooms:
                if new_room.intersect(other_room):
                    failed = True
                    break

            if not failed:
                # i.e., no intersections, so paint a room
                self.create_room(new_room, layoutselection)

                # Give it some features
                new_room_features = self.create_room_features(
                    new_room, layoutselection)
                self.__leveldata.update(new_room_features)

                print self.__leveldata
                self.__rooms.append(new_room)

                (new_x, new_y) = new_room.center(
                )  # Previously used for player placement (center of first room)

        tree = bspmaking.Leaf(20, 20, 20, 10)
        tree.branch()
        leaves = tree.gatherleaves()
        for leaf in leaves:
            print "Leaf:", leaf.w, leaf.y

        # Chew out a certain amount of 'noise' for the CA function to work over.
        while open_count > 0:
            rand_r = random.randrange(1, self.__height - 1)
            rand_c = random.randrange(1, self.__width - 1)

            if self.__CAmap[rand_c][rand_r].blocked and not self.__CAmap[
                    rand_c][rand_r].permanent:
                self.__CAmap[rand_c][rand_r].blocked = False
                self.__CAmap[rand_c][rand_r].block_sight = False
                open_count -= 1

    def __adj_wall_count(self, sr, sc):
        # How many walls are surrounding a tile?
        count = 0

        for r in (-1, 0, 1):
            for c in (-1, 0, 1):
                if self.__CAmap[(sc + c)][sr + r].blocked and not (c == 0
                                                                   and r == 0):
                    count += 1

        return count

    def __join_rooms(self):
        # divide the square into equivalence classes
        for r in range(1, self.__height - 1):
            for c in range(1, self.__width - 1):
                if not self.__CAmap[c][r].blocked:
                    self.__union_adj_sqr(c, r)

        all_caves = self.__ds.split_sets()

        for cave in all_caves.keys():
            self.__join_points(all_caves[cave][0])

    def __join_points(self, pt1):
        next_pt = pt1

        while 1:
            dir = self.__get_tunnel_dir(
                pt1, self.center_pt
            )  ### This determines the next point to 'drill' to.  Unfortunately it will still drill through 'permanent' tiles.  How to fix?  We could, possibly, use a pathfinding algorithm to get to work our way to the center point.  That should work but might be overkill.  Let's see how often it happens first while I work on cave building.

            if (dir[0] == 0) or (dir[1] == 0):
                next_pt = (pt1[0] + dir[0], pt1[1] + dir[1])
            else:
                if random.randrange(0, 1):
                    next_pt = (pt1[0] + dir[0], pt1[1])
                else:
                    next_pt = (pt1[0], pt1[1] + dir[1])

            if self.__CAmap[next_pt[0]][next_pt[1]].permanent:
                print "Uh oh, permanent tile at", next_pt[0], next_pt[1]

            if self.__stop_drawing(pt1, next_pt, self.center_pt):
                return

            root1 = self.__ds.find(next_pt)
            root2 = self.__ds.find(pt1)

            if root1 != root2:
                self.__ds.union(root1, root2)

            self.__CAmap[next_pt[0]][next_pt[1]].blocked = False
            self.__CAmap[next_pt[0]][next_pt[1]].block_sight = False
            self.__CAmap[next_pt[0]][next_pt[1]].debug = True  # DEBUG

            pt1 = next_pt

    def __stop_drawing(self, pt, npt, cpt):
        if self.__ds.find(npt) == self.__ds.find(cpt):
            return 1
        if self.__ds.find(pt) != self.__ds.find(npt) and not self.__CAmap[
                npt[0]][npt[1]].blocked:
            return 1
        else:
            return 0

    def __get_tunnel_dir(self, pt1, pt2):
        if pt1[0] < pt2[0]:
            h_dir = +1
        elif pt1[0] > pt2[0]:
            h_dir = -1
        else:
            h_dir = 0

        if pt1[1] < pt2[1]:
            v_dir = +1
        elif pt1[1] > pt2[1]:
            v_dir = -1
        else:
            v_dir = 0

        return (h_dir, v_dir)

    def __union_adj_sqr(self, sr, sc):
        loc = (sr, sc)

        for r in (-1, 0):
            for c in (-1, 0):
                nloc = (sr + r, sc + c)

                if not self.__CAmap[nloc[0]][nloc[1]].blocked and (r + c !=
                                                                   -2):
                    root1 = self.__ds.find(loc)
                    root2 = self.__ds.find(nloc)

                    if root1 != root2:
                        self.__ds.union(root1, root2)
示例#18
0
 def test_create(self):
     s = DisjointSet(10)
     self.assertEqual(len(s), 10)
     self.assertEqual(s.find(1), 1)
示例#19
0
class FullMap:
    # A map using CA to build caves but also pre-set rooms.
    def __init__(self, width, height, levelnum, initial_open=0.60):
        self.__height = height
        self.__width = width
        self.__area = height * width
        self.__map = []
        self.__levelnum = levelnum
        self.__rooms = []
        self.__ds = DisjointSet()
        self.__up_loc = 0
        self.center_pt = (int(self.__height/2), int(self.__width/2))
        self.objects = []
        self.eventdict = {}
        self.gen_map(initial_open)

    def gen_map(self, initial_open):
        # Create an initial map
        self.__map = map_init(self.__height, self.__width)

        # make all border squares walls
        for j in range(0, self.__width-1):
            self.__map[j][0].permanent = True
            self.__map[j][self.__height-1].permanent = True

        for j in range(0, self.__height-1):
            self.__map[0][j].permanent = True
            self.__map[self.__width-1][j].permanent = True

        # Chew out randomized spots on the map
        self.randomize(initial_open)

        # Make a list of level features to make
        levellist = levelmaking.choose_levelset(self.__levelnum)

        # Init a counter for events
        currentevent = 1

        # For each item, get the features to make a Chamber out of.  Make a chamber and dig a proper room out of it.
        for item in levellist:
            # Select an item from the possible ones, given the type.
            itemselection = levelmaking.select_elements(item)

            # Want to look until a placement is found.
            placed = False
            while not placed:

                # Given this item, what arguments do we need to actually make the room?
                args = levelmaking.set_element_values(item, itemselection, self.__width, self.__height)
                new_room = Chamber(*args)

                # Check against other rooms to ensure this new room overlaps none of the others
                # This needs to go somewhere else!
                intersected = False
                for other_room in self.__rooms:
                    if new_room.intersect(other_room):
                        intersected = True
                        print "Failed intersection test!"
                        break

                # In cases of intersection, note the failure, and try again (another loop).  Otherwise, perform the
                # dig-a-room operations and make a note to finish the loop.
                if intersected:
                    print "Failed making", new_room.style
                else:
                    # i.e., no intersections, so paint a room
                    levelmaking.dig_room(self.__map, new_room, itemselection)
                    roomobjects = levelmaking.collect_features(self.__map, new_room, itemselection)
                    self.objects += roomobjects
                    print "Successfully dug", new_room.style
                    self.__rooms.append(new_room)
                    placed = True

                    (new_x, new_y) = new_room.center()  # Previously used for player placement (center of first room)

        # Perform CA operation - how many loops to perform?
        loops = random.randrange(4, 5)
        self.ca_operation(loops)

        # Check for other room-making operations


        # Join the areas of the level
        self.__join_rooms()

    def finalize_map(self):
        return self.__map

    def finalize_obects(self):
        return self.objects

    def get_rooms(self):
        return self.__rooms

    def is_map_blocked(self, x, y):
        if self.__map[x][y].is_blocked:
            return True
        else:
            return False

    def randomize(self, initial_open):
        open_count = int(self.__width * self.__height * initial_open)
        while open_count > 0:
            rand_r = random.randrange(1, self.__height-1)
            rand_c = random.randrange(1, self.__width-1)

            if self.__map[rand_c][rand_r].blocked and not self.__map[rand_c][rand_r].permanent:
                self.__map[rand_c][rand_r].blocked = False
                self.__map[rand_c][rand_r].block_sight = False
                open_count -= 1

    def check_open(self):
        count = 0
        for x in range(1, self.__width):
            for y in range(1, self.__height):
                if self.__map[x][y].blocked:
                    count += 1
        print 'open tiles: ', count


    def ca_operation(self, loops):
    # For non-permanent tiles, grow or kill depending on their surroundings.
        while loops > 0:
            for r in range(1, self.__height-1):
                for c in range(1, self.__width-1):
                    if not self.__map[c][r].permanent:
                        wall_count = self.__adj_wall_count(r, c)
                        if not self.__map[c][r].blocked:
                            if wall_count > 5:
                                self.__map[c][r].blocked = True
                                self.__map[c][r].block_sight = True
                        elif wall_count < 4:
                            self.__map[c][r].blocked = False
                            self.__map[c][r].block_sight = False
            loops -= 1

    def __adj_wall_count(self, sr, sc):
    # How many walls are surrounding a tile?
        count = 0

        for r in (-1, 0, 1):
            for c in (-1, 0, 1):
                if self.__map[(sc + c)][sr + r].blocked and not(c == 0 and r == 0):
                    count += 1

        return count

    def __join_rooms(self):

        all_caves = self.__determine_areas()


        # Build a tunneling map for pathing - use the permanent state check to determine passability.
        tunnelingmap = libtcod.map_new(self.__width, self.__height)
        for x in range(1, self.__width-1):
            for y in range(1, self.__height-1):
                perm_wall = (self.__map[x][y].permanent and self.__map[x][y].blocked)
                libtcod.map_set_properties(tunnelingmap, x, y, True, not perm_wall)

        # The tunneling path will let us move from the origin to the center.
        tunnelingpath = libtcod.dijkstra_new(tunnelingmap, 0.0)

        # The center needs to be non-permanent, otherwise we can't path to it.
        center_x, center_y = self.__find_good_center(self.center_pt)

        for cave in all_caves.keys():
            # This comment used to run the joining.  The function is still usable!
            #self.__join_points(all_caves[cave][0])
            origin_x = all_caves[cave][0][0]
            origin_y = all_caves[cave][0][1]

            libtcod.dijkstra_compute(tunnelingpath, origin_x, origin_y)
            if not libtcod.dijkstra_path_set(tunnelingpath, center_x, center_y):
                print "Could not path! Center point permanent:", self.__map[center_x][center_y].permanent
            prev_pt = (origin_x, origin_y)
            while not libtcod.dijkstra_is_empty(tunnelingpath):
                x, y = libtcod.dijkstra_path_walk(tunnelingpath)
                next_pt = (x, y)
                if x is not None:

                    root1 = self.__ds.find(next_pt)
                    root2 = self.__ds.find(prev_pt)

                    if root1 != root2:
                        self.__ds.union(root1, root2)

                    self.__map[next_pt[0]][next_pt[1]].blocked = False
                    self.__map[next_pt[0]][next_pt[1]].block_sight = False
                    self.__map[next_pt[0]][next_pt[1]].debug = True          # DEBUG

                    if self.__stop_drawing(prev_pt, next_pt, self.center_pt):
                        print "Done cave", cave
                        break

                    prev_pt = next_pt

        all_caves = self.__determine_areas()
        if len(all_caves.keys())>1:
            self.__join_rooms()


    def __determine_areas(self):
        # divide the square into equivalence classes
        for r in range(1, self.__height-1):
            for c in range(1, self.__width-1):
                if not self.__map[c][r].blocked:
                    self.__union_adj_sqr(c, r)

        # Get a list of areas to work on, then remove small caves before returning
        areas = self.__ds.split_sets()
        zones = areas.keys()
        for zone in zones:
            if len(areas[zone])<9:
                for location in areas[zone]:
                    x = location[0]
                    y = location[1]
                    self.__map[x][y].permanent = False
                    self.__map[x][y].blocked = True
                    self.__map[x][y].block_sight = True
                areas.pop(zone)

        print "Number of areas is", len(areas)
        return areas

    def __find_good_center(self, pt):
        # This function randomly moves the center to find a good 'end' point for cave joining function.
        # That is, the center can't be permanent.
        x = pt[0]
        y = pt[1]
        while self.__map[x][y].permanent:
            x += random.randrange(-1, 1)
            y += random.randrange(-1, 1)
        pt = (x, y)
        return pt

    def __stop_drawing(self, pt, npt, cpt):
        if self.__ds.find(npt) == self.__ds.find(cpt):
            return 1
        if self.__ds.find(pt) != self.__ds.find(npt) and not self.__map[npt[0]][npt[1]].blocked:
            return 1
        else:
            return 0

    def __get_tunnel_dir(self, pt1, pt2):
        if pt1[0] < pt2[0]:
            h_dir = +1
        elif pt1[0] > pt2[0]:
            h_dir = -1
        else:
            h_dir = 0

        if pt1[1] < pt2[1]:
            v_dir = +1
        elif pt1[1] > pt2[1]:
            v_dir = -1
        else:
            v_dir = 0

        return h_dir, v_dir

    def __union_adj_sqr(self, sr, sc):
        loc = (sr, sc)

        for r in (-1, 0):
            for c in (-1, 0):
                nloc = (sr+r, sc+c)

                if not self.__map[nloc[0]][nloc[1]].blocked and (r+c != -2):
                    root1 = self.__ds.find(loc)
                    root2 = self.__ds.find(nloc)

                    if root1 != root2:
                        self.__ds.union(root1, root2)