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
def is_forest(g): """ A forest is an acyclic, undirected graph. :param g: undirected graph :return: True if graph is a forest, otherwise False """ if not isinstance(g, Graph): return False djset = DisjointSet() for v in g.vertices: djset.make_set(v) eset = set() for v1, v2 in g.edges: if (v2, v1) not in eset: eset.add((v1, v2)) for v1, v2 in eset: if djset.find_set(v1) != djset.find_set(v2): djset.union(v1, v2) else: return False return True
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)
def cluster(Vlist, dim): ''' Function to cluster a list of nodes so that the single link distance between each pair of cluster is at least 3 and the number of clusters is maximized Input: Vlist: bit string representation of all nodes dim : dimension of each node (length of bit string) Output: Largest number of clusters such that the spacing between any pair of clusters is at least 3 ''' distinct_V = {} i = 0 for V in Vlist: intV = int(V, 2) if intV not in distinct_V: distinct_V[intV] = i i += 1 dset = DisjointSet(len(distinct_V)) ## create a list of bit strings with length <= dim and at most 2 bits are "1" permutation_lst = [] for i in range(dim): permutation_lst.append("1" + "0" * i) for i in range(dim - 1): for j in range(i + 1, dim): permutation_lst.append("1" + "0" * (j - i - 1) + "1" + "0" * (23 - j)) permutation_lst = [int(x, 2) for x in permutation_lst] for V in distinct_V.keys(): V_permu2 = [V ^ x for x in permutation_lst] for v_permu in V_permu2: if v_permu in distinct_V: dset.union(distinct_V[V], distinct_V[v_permu]) return len(dset)
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])
def testUnionFind(self): ds = DisjointSet(range(100)) for i in range(100): ds.union(i, i % 5) for i in range(100): for j in range(i, 100): self.assertEqual( ds.find_set(i) == ds.find_set(j), i % 5 == j % 5)
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
def connected_components(self): "Returns a list of sets of connected components" ds = DisjointSet() for v in self.vertices(): ds.make_set(v) for u,v in self.edges(): if ds.find_set(u) != ds.find_set(v): ds.union(u,v) return ds.collection
def connected_components_dj(g): djset = DisjointSet() for v in g.vertices: djset.make_set(v) for v1, v2 in g.edges: if djset.find_set(v1) != djset.find_set(v2): djset.union(v1, v2) return djset.get_set()
def mst_kruskal(g): djset = DisjointSet() mst = Graph() for u in g.vertices: djset.make_set(u) for u, v in sorted(g.edges, key=lambda e: g.weight(e[0], e[1])): if djset.find_set(u) != djset.find_set(v): djset.union(u, v) mst.add_edge(u, v, g.weight(u, v)) return mst
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
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
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')
def makeKruskal(self): disjoint = DisjointSet() a = [] soma = 0 for node in self.nodes: disjoint.makeSet(node) sorted_edges = sorted(self.edges) for edge in sorted_edges: if disjoint.findSet(edge.node_from) != disjoint.findSet( edge.node_to): soma += edge.weight a.append((edge.node_from, edge.node_to, edge.weight)) disjoint.union(edge.node_from, edge.node_to) print('Caminho:') for edge in a: print(edge[0], ' -- ', edge[1], 'Peso:', edge[2]) print('Peso do caminho gerado pelo Kruskal:', soma)
def kruskal(graph): djs = DisjointSet(numel=len(graph.nodes)) all_nodes = set(range(len(graph.nodes))) weight = 0 edges = list(graph.get_edges()) edges.sort(key=lambda tup: tup[2]) fs = set() for e in edges: source = e[0] dest = e[1] wt = e[2] if not djs.same_set(source, dest): fs.add(source) fs.add(dest) weight += wt djs.union(source, dest) return weight
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)
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]
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'))
def Prim(graph): # A revoir totalement avec tas binaire minimun ou fibonacci """Algorithme de Prim + Union-Find Retourne la liste des arretes du graphe de coût minimum """ forest = DisjointSet() chemin = [] tempEdges = [] usedNodes = [] for n in graph['Nodes']: forest.add(n) nbrNodes = len(graph['Nodes']) origin = graph['Nodes'][0] usedNodes.append(origin) while(len(chemin) != nbrNodes-1): tempNodes = [] tempEdges = [] for node in forest: if forest[node] in usedNodes: # On cherche tous les sommets dont le père fait parti des sommet déjà parcouru tempNodes.append(node) for node in tempNodes: # A AMELIORER !! SOURCE DE PERTE DE TEMPS !!!! for edge in graph['Edges']: if node in edge and edge not in chemin: tempEdges.append(edge) tempEdges = sorted(tempEdges, key=itemgetter(2)) chemin.append(tempEdges[0]) # On prend l'arrete avec le plus petit poids if graph['Type'].upper() == "UNDIRECTED GRAPH": if chemin[-1][0] in usedNodes: forest.union(chemin[-1][0], chemin[-1][1]) usedNodes.append(chemin[-1][0]) else: forest.union(chemin[-1][1], chemin[-1][0]) usedNodes.append(chemin[-1][1]) else: forest.union(chemin[-1][1], chemin[-1][0]) usedNodes.append(chemin[-1][1]) return chemin
def __cmp__(self,other): return self.e - other.e def __str__(self): return str(self.v1) + ',' + str(self.v2) + ',' + str(self.e) file = open('./clustering1.txt','r') N = int(file.readline()) K = 4 data = file.readlines() edges = [edge(int(line.split(' ')[0]),int(line.split(' ')[1]),int(line.split(' ')[2])) for line in data] heap = [] for e in edges: heapq.heappush(heap,e) clusterNum = N disjointSet = DisjointSet(N) while clusterNum > K: aedge = heapq.heappop(heap) if not disjointSet.within(aedge.v1,aedge.v2): disjointSet.union(aedge.v1,aedge.v2) clusterNum -= 1 vmin = 32767 for e in edges: if not disjointSet.within(e.v1,e.v2) and vmin > e.e: vmin = e.e print vmin
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)
result = [] result.append(modify(l,-1,-1)) for i in range(0,dimension): result.append(modify(l,-1,i)) for i in range(0,dimension): for j in range(i + 1,dimension): result.append(modify(l,i,j)) return result def modify(l,i,j): k = list(l) if i != -1: if k[i] == '1':k[i] = '0' else:k[i] = '1' if j != -1: if k[j] == '1':k[j] = '0' else:k[j] = '1' return ''.join(k) for i in range(0,N): for candidates in candidate(nodes[i]): for id in dic[candidates]: disjointSet.union(i,id) print disjointSet.countSet() - 1
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)
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)
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)
def __str__(self): return str(self.v1) + ',' + str(self.v2) + ',' + str(self.e) file = open('./clustering1.txt', 'r') N = int(file.readline()) K = 4 data = file.readlines() edges = [ edge(int(line.split(' ')[0]), int(line.split(' ')[1]), int(line.split(' ')[2])) for line in data ] heap = [] for e in edges: heapq.heappush(heap, e) clusterNum = N disjointSet = DisjointSet(N) while clusterNum > K: aedge = heapq.heappop(heap) if not disjointSet.within(aedge.v1, aedge.v2): disjointSet.union(aedge.v1, aedge.v2) clusterNum -= 1 vmin = 32767 for e in edges: if not disjointSet.within(e.v1, e.v2) and vmin > e.e: vmin = e.e print vmin
def candidate(l): result = [] result.append(modify(l, -1, -1)) for i in range(0, dimension): result.append(modify(l, -1, i)) for i in range(0, dimension): for j in range(i + 1, dimension): result.append(modify(l, i, j)) return result def modify(l, i, j): k = list(l) if i != -1: if k[i] == '1': k[i] = '0' else: k[i] = '1' if j != -1: if k[j] == '1': k[j] = '0' else: k[j] = '1' return ''.join(k) for i in range(0, N): for candidates in candidate(nodes[i]): for id in dic[candidates]: disjointSet.union(i, id) print disjointSet.countSet() - 1
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)
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)
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)