def __init__(self, image, position=(0, 0), rotation=0, scale=1, opacity=255, color=(255, 255, 255), anchor=None, **kwargs): if isinstance(image, string_types): image = pyglet.resource.image(image) self.transform_anchor_x = 0 self.transform_anchor_y = 0 self._image_anchor_x = 0 self._image_anchor_y = 0 # These need to be forward-defined here because pyglet sprites don't have them. self._scale_x = 1 self._scale_y = 1 pyglet.sprite.Sprite.__init__(self, image, **kwargs) BatchableNode.__init__(self) if anchor is None: if isinstance(self.image, pyglet.image.Animation): anchor = (image.frames[0].image.width // 2, image.frames[0].image.height // 2) else: anchor = image.width // 2, image.height // 2 self.image_anchor = anchor # group. # This is for batching self.group = None # children group. # This is for batching self.children_group = None #: position of the sprite in (x, y) coordinates self.position = position #: rotation in degrees of the sprite. Default: 0 degrees self.rotation = rotation #: scale of the sprite where 1.0 is the default value self.scale = scale #: additional horizontal-only scale of the sprite where 1.0 is the default value self.scale_x = 1 #: additional vertical-only scale of the sprite where 1.0 is the default value self.scale_y = 1 #: opacity of the sprite where 0 is transparent and 255 is solid self.opacity = opacity #: color of the sprite in R, G, B format where 0, 0, 0 is black and #: 255, 255, 255 is white self.color = color
def __init__(self, mapFileName, cm=None, numPlayers = None, AIPlayers = None, seed = None): super(Map, self).__init__() self.cm = cm self.batchableNode = BatchableNode() self.batchableNode.position = 0,0 self.add(self.batchableNode,z=VERTEX_Z) # Initiliaze variables - these will be set in parse_map_file. self.vertexPositions = {} self.edgePositions = defaultdict( list) # key: vid of one end, v: vid of other end self.AS = {} # we can get list of vertices from here self.cores = {} # k: just the cores self.vertices = {} # k: all vertices and cores self.edges = [] # list of all edges self.startingUnits = defaultdict(lambda: defaultdict(list)) self.startingResearch = defaultdict(list) self.availResearch = [] self.w = - 1 # Width of map in terms of num of cells. set in parse_map_file self.h = - 1 # Height of map in terms of num of cells. set in parse_map_file self.players = [] # list of pids self.AIPlayers = [] self.pid = 0 if mapFileName == "random": # Generate a random map. Creates a map and writes it to the /maps/ directory. Returns the file name. # Set the seed. random.seed(seed) # Map Dimensions numRows = int(random.randint(6 * numPlayers, 14 * numPlayers)) # if 2 players, min of 12x12, max of 28x28 numCols = int(random.randint(6 * numPlayers, 14 * numPlayers)) # Number of ASes numASes = int(math.ceil((numCols * numRows) / 140.0)) # If 2 players, min of 2 ASes, max of 6. # Verts per AS minVertsPerAS = 2 maxVertsPerAS = 4 playerStartUnits = {0:[],1:[]} playerResearch = {0:[],1:[]} maxCoresPerAS = 2 mapFileName = self.generate_random_map(numPlayers, numCols, numRows, playerStartUnits, playerResearch, minVertsPerAS, maxVertsPerAS, numASes, maxCoresPerAS, AIPlayers, seed) # Parses the map file and sets all relevant information. self.parse_map_file(mapFileName) self.minimap = None # Starts as None. Eventually stores the instance of MiniMap built off this Map (happens in controller)
def __init__(self, image, position=(0, 0), rotation=0, scale=1, opacity=255, color=(255, 255, 255), anchor=None, **kwargs): if isinstance(image, string_types): image = pyglet.resource.image(image) self.transform_anchor_x = 0 self.transform_anchor_y = 0 self._image_anchor_x = 0 self._image_anchor_y = 0 # These need to be forward-defined here because pyglet<1.3 sprites don't have them. self._scale_x = 1 self._scale_y = 1 pyglet.sprite.Sprite.__init__(self, image, **kwargs) BatchableNode.__init__(self) if anchor is None: if isinstance(self.image, pyglet.image.Animation): anchor = (image.frames[0].image.width // 2, image.frames[0].image.height // 2) else: anchor = image.width // 2, image.height // 2 self.image_anchor = anchor # group. # This is for batching self.group = None # children group. # This is for batching self.children_group = None #: position of the sprite in (x, y) coordinates self.position = position #: rotation in degrees of the sprite. Default: 0 degrees self.rotation = rotation #: scale of the sprite where 1.0 is the default value self.scale = scale #: additional horizontal-only scale of the sprite where 1.0 is the default value self.scale_x = 1 #: additional vertical-only scale of the sprite where 1.0 is the default value self.scale_y = 1 #: opacity of the sprite where 0 is transparent and 255 is solid self.opacity = opacity #: color of the sprite in R, G, B format where 0, 0, 0 is black and #: 255, 255, 255 is white self.color = color
def __init__(self, top_left, pokemon, height=15): """ :param top_left: :type top_left: tuple[int, int] :param pokemon: :type pokemon: pokemon.Pokemon :param height: :type height: int """ BatchableNode.__init__(self) self.x, self.y = top_left self.pokemon = pokemon self.max_width = 150 self.height = height self.pokemon.push_handlers(self)
def _set_scale_y(self, s): BatchableNode._set_scale_y(self, s) self._update_position()
def _set_scale(self, s): BatchableNode._set_scale(self, s) pyglet.sprite.Sprite._set_scale(self, s)
def _set_rotation(self, a): BatchableNode._set_rotation(self, a) pyglet.sprite.Sprite._set_rotation(self, a)
def __init__(self, image, position=(0, 0), rotation=0, scale=1, opacity=255, color=(255, 255, 255), anchor=None): '''Initialize the sprite :Parameters: `image` : string or image name of the image resource or a pyglet image. `position` : tuple position of the anchor. Defaults to (0,0) `rotation` : float the rotation (degrees). Defaults to 0. `scale` : float the zoom factor. Defaults to 1. `scale_x` : float additional horizontal-only zoom factor. Defaults to 1. `scale_y` : float additional vertical-only zoom factor. Defaults to 1. `opacity` : int the opacity (0=transparent, 255=opaque). Defaults to 255. `color` : tuple the color to colorize the child (RGB 3-tuple). Defaults to (255,255,255). `anchor` : (float, float) (x,y)-point from where the image will be positions, rotated and scaled in pixels. For example (image.width/2, image.height/2) is the center (default). ''' if isinstance(image, string_types): image = pyglet.resource.image(image) self.transform_anchor_x = 0 self.transform_anchor_y = 0 self._image_anchor_x = 0 self._image_anchor_y = 0 # These need to be forward-defined here because pyglet sprites don't have them. self._scale_x = 1 self._scale_y = 1 pyglet.sprite.Sprite.__init__(self, image) BatchableNode.__init__(self) if anchor is None: if isinstance(self.image, pyglet.image.Animation): anchor = (image.frames[0].image.width // 2, image.frames[0].image.height // 2) else: anchor = image.width // 2, image.height // 2 self.image_anchor = anchor # group. # This is for batching self.group = None # children group. # This is for batching self.children_group = None #: position of the sprite in (x,y) coordinates self.position = position #: rotation degrees of the sprite. Default: 0 degrees self.rotation = rotation #: scale of the sprite where 1.0 the default value self.scale = scale #: additional horizontal-only scale of the sprite where 1.0 the default value self.scale_x = 1 #: additional vertical-only scale of the sprite where 1.0 the default value self.scale_y = 1 #: opacity of the sprite where 0 is transparent and 255 is solid self.opacity = opacity #: color of the sprite in R,G,B format where 0,0,0 is black and 255,255,255 is white self.color = color
def _set_y(self, y): BatchableNode._set_y(self, y) pyglet.sprite.Sprite._set_y(self, y)
def getFakeObject(self, position, width = 2, height = 2): obj = BatchableNode() obj.cshape = cm.AARectShape(position, width // 2,height // 2) return obj
def _set_position(self, p): BatchableNode._set_position(self, p) pyglet.sprite.Sprite.set_position(self, *p)
def _set_x(self, x): BatchableNode._set_x(self, x) pyglet.sprite.Sprite._set_x(self, x)
def __init__(self, image, position=(0, 0), rotation=0, scale=1, opacity = 255, color=(255, 255, 255), anchor = None): """Initialize the sprite :Parameters: `image` : string or image name of the image resource or a pyglet image. `position` : tuple position of the anchor. Defaults to (0,0) `rotation` : float the rotation (degrees). Defaults to 0. `scale` : float the zoom factor. Defaults to 1. `scale_x` : float additional horizontal-only zoom factor. Defaults to 1. `scale_y` : float additional vertical-only zoom factor. Defaults to 1. `opacity` : int the opacity (0=transparent, 255=opaque). Defaults to 255. `color` : tuple the color to colorize the child (RGB 3-tuple). Defaults to (255,255,255). `anchor` : (float, float) (x,y)-point from where the image will be positions, rotated and scaled in pixels. For example (image.width/2, image.height/2) is the center (default). """ if isinstance(image, string_types): image = pyglet.resource.image(image) self.transform_anchor_x = 0 self.transform_anchor_y = 0 self._image_anchor_x = 0 self._image_anchor_y = 0 # These need to be forward-defined here because pyglet sprites don't have them. self._scale_x = 1 self._scale_y = 1 pyglet.sprite.Sprite.__init__(self, image) BatchableNode.__init__(self) if anchor is None: if isinstance(self.image, pyglet.image.Animation): anchor = (image.frames[0].image.width // 2, image.frames[0].image.height // 2) else: anchor = image.width // 2, image.height // 2 self.image_anchor = anchor # group. # This is for batching self.group = None # children group. # This is for batching self.children_group = None #: position of the sprite in (x,y) coordinates self.position = position #: rotation degrees of the sprite. Default: 0 degrees self.rotation = rotation #: scale of the sprite where 1.0 the default value self.scale = scale #: additional horizontal-only scale of the sprite where 1.0 the default value self.scale_x = 1 #: additional vertical-only scale of the sprite where 1.0 the default value self.scale_y = 1 #: opacity of the sprite where 0 is transparent and 255 is solid self.opacity = opacity #: color of the sprite in R,G,B format where 0,0,0 is black and 255,255,255 is white self.color = color
class Map(scrolling.ScrollableLayer): def __init__(self, mapFileName, cm=None, numPlayers = None, AIPlayers = None, seed = None): super(Map, self).__init__() self.cm = cm self.batchableNode = BatchableNode() self.batchableNode.position = 0,0 self.add(self.batchableNode,z=VERTEX_Z) # Initiliaze variables - these will be set in parse_map_file. self.vertexPositions = {} self.edgePositions = defaultdict( list) # key: vid of one end, v: vid of other end self.AS = {} # we can get list of vertices from here self.cores = {} # k: just the cores self.vertices = {} # k: all vertices and cores self.edges = [] # list of all edges self.startingUnits = defaultdict(lambda: defaultdict(list)) self.startingResearch = defaultdict(list) self.availResearch = [] self.w = - 1 # Width of map in terms of num of cells. set in parse_map_file self.h = - 1 # Height of map in terms of num of cells. set in parse_map_file self.players = [] # list of pids self.AIPlayers = [] self.pid = 0 if mapFileName == "random": # Generate a random map. Creates a map and writes it to the /maps/ directory. Returns the file name. # Set the seed. random.seed(seed) # Map Dimensions numRows = int(random.randint(6 * numPlayers, 14 * numPlayers)) # if 2 players, min of 12x12, max of 28x28 numCols = int(random.randint(6 * numPlayers, 14 * numPlayers)) # Number of ASes numASes = int(math.ceil((numCols * numRows) / 140.0)) # If 2 players, min of 2 ASes, max of 6. # Verts per AS minVertsPerAS = 2 maxVertsPerAS = 4 playerStartUnits = {0:[],1:[]} playerResearch = {0:[],1:[]} maxCoresPerAS = 2 mapFileName = self.generate_random_map(numPlayers, numCols, numRows, playerStartUnits, playerResearch, minVertsPerAS, maxVertsPerAS, numASes, maxCoresPerAS, AIPlayers, seed) # Parses the map file and sets all relevant information. self.parse_map_file(mapFileName) self.minimap = None # Starts as None. Eventually stores the instance of MiniMap built off this Map (happens in controller) def batch_add(self,cocosNode,z=1): self.batchableNode.add(cocosNode,z=z) def batch_remove(self,cocosNode): self.batchableNode.remove(cocosNode) def parse_map_file(self, mapFileName): with open(mapFileName, 'r') as f: row = 0 # updated when size found in map file isCellInfo = False for line in f: line = line.split() if len(line) == 0 or line[0] == "#": continue elif line[0] == "MAP": isCellInfo = True self.w = int(line[1]) - 1 self.h = int(line[2]) - 1 elif line[0] == "ENDMAP": isCellInfo = False # Rot to the end of cell info elif line[0] == "EDGES:" or line[0] == "CORE_EDGES:": edgeList = [] for edge in line[1:]: formattedEdge = re.findall("[0-9]+|[a-z]+", edge) edgeList.append(formattedEdge) for edge in edgeList: self.edgePositions[edge[0] ].append(edge[1]) # edge[0] is key self.edgePositions[edge[1] ].append(edge[0]) # edge[1] is key elif line[0] == "AS": vertsInAS = [] for i in range(2, len(line)): # Loop through info in AS line to grab relevant vertices, if only one, do a "n-n" r = re.split('\-', line[i]) if r[0].isdigit(): vertsInAS += [str(v) for v in range(int(r[0]), int(r[1]) + 1)] else: #add core vertsInAS += [r[0]] self.AS[int(line[1])] = AS(int(line[1]), vertsInAS) # key is AS's ID elif "PLAYER" == line[0]: # Loop through starting units and add them to the # self.playerStartingUnits pid = int(line[1]) self.players.append(pid) for unit in line[2:]: unit = unit.split(",") unitType = unit[0] # For clarity. unitVert = unit[1] self.startingUnits[pid][unitVert].append(unitType) elif line[0] == "AI": self.AIPlayers = line[1:] self.AIPlayers = [int(i) for i in self.AIPlayers] for p in self.AIPlayers: self.players.remove(p) elif line[0] == "STARTRESEARCH": pid = int(line[1]) for research in line[2:]: self.startingResearch[pid].append(research) elif line[0] == "AVAILRESEARCH": for research in line[1:]: self.availResearch.append(research) elif isCellInfo == True: col = 0 for cell in line: if cell.isalpha() or cell.isdigit(): r = self.h - row self.vertexPositions[cell] = (col, r) col += 1 row += 1 f.close() def draw_map(self): for asID in self.AS.keys(): curAS = self.AS[asID] # create vertices for vid in curAS.vids: position = self.vertexPositions[str(vid)] if vid.isalpha(): v = Core(position[0], position[1], vid, asID, pid=self.pid) self.cores[vid] = v self.vertices[vid] = v curAS.cores[vid] = v else: v = Vertex(position[0], position[1], vid, asID, pid=self.pid) v.asCircle = ASCircle(v.position, curAS.color) v.color = curAS.color curAS.circles[vid] = v.asCircle v.draw_empty_slot_sprites(self) curAS.vertices[vid] = v self.vertices[vid] = v #selfbatch_add(v.asCircle, z=AS_CIRCLE_Z) self.batch_add(v, z=VERTEX_Z) for v1, v2s in self.edgePositions.items(): for v2 in v2s: position1 = self.vertexPositions[v1] position2 = self.vertexPositions[v2] vert1 = self.vertices[v1] vert2 = self.vertices[v2] if v1.isalpha() or (v2.isdigit() and (int(v1) > int(v2))): # create edges if vert1.asID != vert2.asID: # create asEdge vert1.borderVertices[vert2.asID].append(vert2) vert2.borderVertices[vert1.asID].append(vert1) edge = ASEdge( position1, position2, vert1, vert2, AS_EDGE_COLOR) else: # create normal edge edge = Edge( position1, position2, vert1, vert2, EDGE_COLOR) vert1.edges.append(edge) vert2.edges.append(edge) if not v1.isalpha(): vert1.adjacentVertices.append(vert2) vert2.adjacentVertices.append(vert1) self.edges.append(edge) # draw edges for v in self.edges: self.add(v, z=EDGE_Z) pass def generate_random_map(self, numPlayers, numCols, numRows, playerStartUnits, playerResearch, minVertsPerAS, maxVertsPerAS, numASes, maxCoresPerAS, AIPlayers, seed): # ---Add vertices and cores to each AS--- ASvertices, AScores = self.add_verts_and_cores(numRows, numCols, minVertsPerAS, maxVertsPerAS, numASes, maxCoresPerAS) # ---Generate the map lines (cells)--- mapLines, numCols, numRows, ASvertices, AScores = self.create_map_lines(numCols, numRows, ASvertices, AScores, maxVertsPerAS) # ---Generate edges in ASes and between ASes--- edges, coreEdges = self.make_edges(numCols, numRows, ASvertices, AScores) # ---Write the map info to a file--- playerStartUnits = [["Server","CPU"],["Server","CPU"]] fullMapName = self.write_map_info_to_file(mapLines, ASvertices, AScores, edges, coreEdges, numPlayers, playerStartUnits, playerResearch, AIPlayers) return fullMapName def add_verts_and_cores(self, numRows, numCols, minVertsPerAS, maxVertsPerAS, numASes, maxCoresPerAS): # Adds vertices and cores to each AS based on random info above. # RETURNS: tuple: (ASvertices (list), AScores (list)) endVert = random.randint(minVertsPerAS, maxVertsPerAS) ASvertices = [range(0,endVert + 1)] # Fill first AS with vertices so we start at 0. This is used for attaching vertex ID to each AS. for i in range(1, numASes): # Add one here since we are using range to generate the list. ASvertices.append(range(endVert + 1, 1 + random.randint(endVert + 2, endVert + 2 + random.randint(minVertsPerAS, maxVertsPerAS)))) endVert = ASvertices[i][-1] endCore = 'b' # First AS will have 'a' and 'b' valList = range(ord('a'), ord(endCore) + 1) for j in range(len(valList)): valList[j] = chr(valList[j]) # Generate CORES AScores = [valList] nextDigit = '' for i in range(1, numASes): # Fill AScores with cores. # Generate int list that corresponds to ASCII vals of chars lowerVal = ord(endCore[-1]) + 1 upperVal = ord(endCore[-1]) + 1 + random.randint(1,maxCoresPerAS) if upperVal > 122 and nextDigit == '': # TODO: fix this! We have too many cores. Add an a to the '26' digit slot to start going into two digit core count. nextDigit = 'a' upperVal = (upperVal % 122) + 97 elif upperVal > 122 and nextDigit != '': # We have too many cores. Increment our '26' digit slot. nextDigit = chr(ord(nextDigit) + 1) upperVal = (upperVal % 122) + 97 valList = range(lowerVal, upperVal) # Convert int list to char list for j in range(len(valList)): valList[j] = nextDigit + chr(valList[j]) AScores.append(valList) endCore = AScores[i][-1] return ASvertices, AScores def create_map_lines(self, numCols, numRows, ASvertices, AScores, maxVertices): # Generate map grid of proper dimensions # RETURNS: mapLines (list of lists of chars) mapLines = [["-" for i in range(int(numCols))] for j in range(int(numRows))] # Figure out where to place the ASes -> Use a bounding box to isolate AS locations numASes = len(ASvertices) # SET BOUNDING BOX SIZE -> If we want to change how 'spread out' ASes are, this is where to do it!!! dimensionFacilitator = maxVertices + 2 boundingBoxWidth = random.randint(3,dimensionFacilitator) dimensionFacilitator -= boundingBoxWidth boundingBoxHeight = random.randint(3,min(max(3,dimensionFacilitator),maxVertices)) # Define initial bounding box topLeft = (0,0) botRight = (topLeft[0] + boundingBoxWidth, topLeft[1] + boundingBoxHeight) # Define boundingBoxes boundingBoxes = [(topLeft,botRight)] # stores a tuple of topLeft, bottomRight points that define a boundingBox. # Populate the list <boundingBoxes> with the coordinates of all possible boundingBoxes for ASes boxesPlaced = 0 while boxesPlaced < (numASes + numASes): # While guarantees we have placed sufficient boundingBoxes. if botRight[0] + boundingBoxWidth > numCols: # We're at the right edge of mapLines and can't fit another box, so wrap around. topLeft = (1,botRight[1] + 3) # +3 so we don't overlap. and to spread the ASes out a bit else: # Set topLeft to be the next boundingBox over topLeft = (botRight[0] + 3, topLeft[1]) # +3 so we don't overlap. and to spread the ASes out a bit if (botRight[1] + boundingBoxHeight) > numRows: # We're at the bottom and haven't added enough bounding boxes yet. Expand the map a bit. numCols += 1 numRows += 1 for i in range(len(mapLines)): row = mapLines[i] row.append("-") mapLines[i] = row mapLines.append(["-" for row in range(int(numCols))]) else: # Set bottomRight point to be the topLeft point, + boundBoxWidth and + boundBoxHeight botRight = (topLeft[0] + boundingBoxWidth, topLeft[1] + boundingBoxHeight) boundingBoxes.append((topLeft,botRight)) boxesPlaced += 1 # Loop through each AS and add its vertices and cores to a bounding box. for i in range(numASes): # For clarity nextASverts = ASvertices[i] nextAScores = AScores[i] # Pick a bounding box. Remove the boundingBox from <boundingBoxes>. try: topLeft, botRight = random.choice(boundingBoxes) boundingBoxes.remove((topLeft, botRight)) except: # We've used every bounding box! Can't place any more ASes break # Add vertices to the AS bounding box. vertIndex = 0 while vertIndex < len(nextASverts): vert = nextASverts[vertIndex] vertRow = random.randint(topLeft[0], max(min(len(mapLines) - 1, botRight[0]),topLeft[0] + 1)) # Pick a ROW vertCol = random.randint(topLeft[1], max(min(len(mapLines[-1]) - 1, botRight[1]),topLeft[1] + 1)) # Pick a COLUMN try: while mapLines[vertRow][vertCol] != "-": # Slot we picked was already taken. Look for an empty slot. vertRow = random.randint(topLeft[0], min(len(mapLines) - 1, botRight[0])) # Pick a ROW vertCol = random.randint(topLeft[1], min(len(mapLines[-1]) - 1, botRight[1])) # Pick a COLUMN # Found an empty slot in the bounding box. Place the vertex. mapLines[vertRow][vertCol] = vert vertIndex += 1 except: ASvertices[i].remove(vert) # Decrement vertices we haven't added yet. for j in range(len(ASvertices[i])): if ASvertices[i][j] > vert: ASvertices[i][j] -= 1 # Don't increment our index, we just want to redo the next vert since we removed.. try: # Add cores to the AS bounding box. for core in nextAScores: coreRow = random.randint(topLeft[0], max(min(len(mapLines) - 1, botRight[0]),topLeft[0] + 1)) # Pick a ROW coreCol = random.randint(topLeft[1], max(min(len(mapLines[-1]) - 1, botRight[1]),topLeft[1] + 1)) # Pick a COLUMN while mapLines[coreRow][coreCol] != "-": # Slot we picked was already taken. Look for an empty slot. coreRow = random.randint(topLeft[0], min(len(mapLines) - 1, botRight[0])) # Pick a ROW coreCol = random.randint(topLeft[1], min(len(mapLines[-1]) - 1, botRight[1])) # Pick a COLUMN # Found an empty slot in the bounding box. Place the vertex. mapLines[coreRow][coreCol] = core except: AScores[i].remove(core) return mapLines, numCols, numRows, ASvertices, AScores def make_edges(self, numCols, numRows, ASvertices, AScores): # Randomizes edges between the vertices. Ensures they are connected. # RETURNS: <tuple> (edgeList, coreEdgeList) edgeList = [] coreEdgeList = [] # Generate edge for each individual AS for AS in ASvertices: # Loop through each AS to get the list of vertices in that AS. vertList = sorted(list(AS)) # Copies the vertices in AS to vertList (need to do this since we will end up destroying vertList) # Generate a random prufer seq based on the vertices. pruferSeq = self.generate_prufer_seq(sorted(list(AS))) edgeList += self.generate_mst(pruferSeq, vertList) # Connect the ASes asBorderRouters = [] for AS in ASvertices: if len(AS) > 0: asBorderRouters.append(random.choice(AS)) ASpruferSeq = self.generate_prufer_seq(list(asBorderRouters)) # Once again, have to list() asBorderRouters so it doesn't destroy it. edgeList += self.generate_mst(ASpruferSeq, asBorderRouters) # Generate core edges. # TODO: IMPROVE for i in range(len(AScores)): for j in range(len(AScores[i])): if len(ASvertices[i]) > 0: core = AScores[i][j] randomVertInSameAS = random.choice(ASvertices[i]) coreEdgeList.append([randomVertInSameAS, core]) return edgeList, coreEdgeList def generate_prufer_seq(self, vertList): # Given a list of vertices, generates a random prufer code. # Take lowest and put it in to exhausted. if len(vertList) == 0: return [] exhausted = [vertList.pop(0)] pruferSeq = [] while len(vertList) > 0: try: randVert = random.choice(exhausted) pruferSeq.append(randVert) new = vertList.pop(0) # remove from vertList and add it to exhausted exhausted.append(new) except: # Handles corner cases. break return pruferSeq def generate_mst(self, pruferSeq, vertList): # Build an MST from prufer code. if len(pruferSeq) == 0: return [] vertList.remove(pruferSeq[0]) edgeList = [] while True: if len(pruferSeq) == 1: edgeList.append([vertList[0], pruferSeq[0]]) break elif len(vertList) == 2: # Done. edgeList.append([vertList[0], pruferSeq[0]]) edgeList.append([vertList[1], pruferSeq[1]]) break else: nextVert = None for vert in vertList: if vert != pruferSeq[0]: nextVert = vert vertList.remove(vert) break otherVert = pruferSeq.pop(0) edgeList.append([nextVert, otherVert]) return edgeList def write_map_info_to_file(self, mapLines, ASvertices, AScores, edges, coreEdges, numPlayers, playerStartUnits, playerResearch, AIPlayers): # Writes a map file based on the randomized information. mapName = "random" + str(random.randint(1, 1000)) + ".map" numRows = len(mapLines) numCols = len(mapLines[0]) # DEBUG print "mapName: ", mapName fullMapName = os.path.join("maps", "random", mapName) newMapFile = file(fullMapName, "w") # Add edges edgeString = " " for edge in edges: temp = str(edge).replace(" ", "") # Remove the space to work with the parser. edgeString += temp + " " # Add coreEdges coreEdgeString = " " for coreEdge in coreEdges: temp = str(coreEdge).replace(" ", "").replace("\'","") # Remove the space to work with the parser. coreEdgeString += temp + " " newMapFile.write("EDGES:" + edgeString + "\n") newMapFile.write("CORE_EDGES:" + coreEdgeString + "\n") for index in range(len(ASvertices)): AS = ASvertices[index] # Format cores to write AScoreList = "" for core in AScores[index]: AScoreList += core + " " # Write the cores and vertices to the AS line if len(AS) > 0: newMapFile.write("AS " + str(index) + " " + str(AS[0]) + "-" + str(AS[-1]) + " " + AScoreList + "\n") newMapFile.write("\n") # Write dimensions to the map newMapFile.write("MAP " + str(numCols) + " " + str(numRows) + "\n") # Write the mapLines for line in mapLines: newMapFile.write(self.list_to_string(line) + "\n") newMapFile.write("ENDMAP\n") newMapFile.write("\n") # Add player units for i in range(0,numPlayers): nextUnitString = "" for j in range(len(playerStartUnits[i])): if len(ASvertices[i]) > 0: # Assign a vertex and/or core to each unit/cpu. if playerStartUnits[i][j] != "CPU": nextUnitString += playerStartUnits[i][j] + "," + str(random.choice(ASvertices[i])) + " " elif len(AScores) > 0: nextUnitString += playerStartUnits[i][j] + "," + str(random.choice(AScores[i])) + " " if len(ASvertices[i]) > 0: newMapFile.write("PLAYER " + str(i) + " " + str(nextUnitString) + "\n") if AIPlayers != None: newMapFile.write("\n") for AI in AIPlayers: AIstring = str(AI) newMapFile.write("AI " + AIstring + "\n") newMapFile.write("\n") newMapFile.close() return fullMapName def list_to_string(self, l): # Takes a list and converts its contents to a string. (basically a custom list-> string casting function) s = "" for item in l: s += str(item) + " " return s def get_path(self, source, dest, pid, troop, action=None): ''' Djikstra's Algorithm from Wikipedia: http://en.wikipedia.org/wiki/Dijkstra's_algorithm ''' vertices = [] for vertex in self.vertices.values(): if not vertex.is_blocking_troop(troop, action)[0]: h = HeapItem(vertex, sys.maxint) vertex.heapItem = h vertices.append(h) if vertex == source: h.depth = 0 heapq.heapify(vertices) while vertices: u = heapq.heappop(vertices) if u.vertex == dest and u.depth != sys.maxint: # Bingo path = [] while u: path.append(u.vertex.vid) u = u.parent path.reverse() return path for vertex in u.vertex.adjacentVertices: if not vertex.is_blocking_troop(troop, action)[0]: v = vertex.heapItem alt = u.depth + 1 if alt < v.depth: v.depth = alt v.parent = u vertices.append(v) # TODO: make this more efficient, can't use siftdown because of garbage collector heapq.heapify(vertices) return None # DEPRECATED FOR MULTIPLAYER, use get_path instead def get_moveable_path(self, sourceVertex, destVertex, pid, troop=None): # Returns the shortest path of vertices to get from sourceVertex to destVertex that the player can move to (cannot use vertices where opponent has a FireWall, or invisible vertices) # NOTE: only works for PLAYER move. We need to write account for enemy moving into invisible vertices (changes movability logic) # |-> should change this so it works for both. just don't allow exploration beyond an AS if the AS hasn't been discovered yet. vertices = sourceVertex.adjacentVertices if (type(troop) != EncryptedTroop) and (type(destVertex.building) == Firewall or type(destVertex.building) == Database) and destVertex.building.pid != pid: return False head = HeapItem(sourceVertex, 0) heapVertices = [] for vertex in vertices: # CONSOLIDATE THIS INTO A vertex.isBlocked property if vertex.visibilityState > 0 and (type(troop) == EncryptedTroop or type(vertex.building) != Firewall or vertex.building.pid == pid): heapVertex = HeapItem(vertex, 1, head) heapq.heappush(heapVertices, heapVertex) else: pass numVerticesInMap = len(self.vertices) # So we don't have to calculate this each time through the loop. deadVerts = [] while head.vertex != destVertex: if len(deadVerts) > numVerticesInMap: # NOTE: This condition is really bad... We should probably fix # it. return False head = heapq.heappop(heapVertices) newMoves = head.vertex.adjacentVertices for vertex in newMoves: if vertex.visibilityState > 0 and (type(troop) == EncryptedTroop or type(vertex.building) != Firewall or vertex.building.pid == pid): # Only add a vertex to the path if it's visible, or if it # does not have an Enemy Firewall in the way. heapVertex = HeapItem(vertex, head.depth + 1, head) # Don't add the vertex if we've already found it, or if it # contains an Enemy firewall | BUT we might want to check # to see if we've gotten to that vertex with less depth. if heapVertex.vertex.vid not in [heapVert.vertex.vid for heapVert in heapVertices] and heapVertex.vertex not in deadVerts: # or (heapVertex.vertex in [heapVert.vertex for # heapVert in heapVertices] and heapVertex.head.depth < # heapVertices[heapVertices.indexOf(heapVertex)].head.depth) heapq.heappush(heapVertices, heapVertex) else: deadVerts.append(vertex) path = [] while head.getParent(): path.insert(0, head.vertex) head = head.getParent() path.insert(0, head.vertex) return path def get_vertex(self, vid): if vid.isalpha(): return self.cores[vid] return self.vertices[vid]