def __init__(self, x=0, y=0): self.x = 0 self.y = 0 self.delta_x = 0 self.delta_y = 0 self.bb_right = Rectangle() self.bb_left = Rectangle() self.children = [0, 0]
def test_one(self): r = Rectangle(1, ['a']) r.get_next() final = r.get_final_string() self.assertEquals( final, "1x1\na" )
def create(self, nav_grid, map_data, config, max_area_size, max_area_size_merged): """ Creates navigation areas from a navigation grid. """ self.map_data = map_data self.config = config self.nav_grid = nav_grid self.max_area_size = max_area_size self.max_area_size_merged = max_area_size_merged self.max_size_elements = self.max_area_size / self.nav_grid.element_size # Determine the area where to test for elements. grid_area = Rectangle() grid_area.left = self.nav_grid.map_data.min.x / self.nav_grid.element_size grid_area.top = self.nav_grid.map_data.min.y / self.nav_grid.element_size grid_area.right = grid_area.left + self.nav_grid.size.x grid_area.bottom = grid_area.top + self.nav_grid.size.y # Generate square areas of decreasing size. min_side = self.max_size_elements while min_side > 0: print 'Size iteration {}...'.format(min_side) self.generate_iteration(grid_area, min_side) min_side -= 1 # Merge areas until none can be merged any more. print 'Merging...' while 1: old_len = len(self.areas) self.areas = filter(self.area_merge_filter, self.areas) new_len = len(self.areas) # If no areas were removed, stop merging. if new_len == old_len: break print 'Merged to {} navigation areas.'.format(new_len) print 'Adding areas to blockmap...' self.map_data.blockmap.generate_areas(self) print 'Pruning elements...' self.prune_elements() print 'Connecting areas...' count = self.connect_areas() print 'Generated {} connections.'.format(count) print 'Connecting teleporters...' self.connect_teleporters() return True
def test_columns_one_level(self): r = Rectangle(3, ['123']) self.assertEquals( r.get_next(), '123', ) self.assertEquals( list(r.get_cols()), [u'1', u'2', '3'], )
class PositionState(object): """ Keeps track of the collider's current test state. """ def __init__(self): # Current position. self.pos = Vector3() # Current bounding box to test. self.bbox = Rectangle() self.reset(self.pos, 0, 0) def reset(self, pos, radius, height): # Size to test. self.radius = radius self.height = height # Outermost z coordinates. self.floorz = -0x8000 self.ceilz = 0x8000 # Blocked by a linedef. self.blockline = False # Blocked by a thing. self.blockthing = False # Blocked by a steep slope. self.steep = False # The element's sector's ceiling or floor can move during gameplay. self.floor_moves = False self.ceiling_moves = False # This position's special sector index. self.special_sector = None # This position's floor plane. self.floor_plane = None self.pos.copy_from(pos) self.bbox.set( pos.x - radius, pos.y - radius, pos.x + radius, pos.y + radius )
def connect_teleporters(self): """ Creates area connections for teleporter line types. """ count = 0 rect = Rectangle() for teleporter in self.map_data.teleporters: target_area = None # Get the area that the teleporter target is in. if teleporter.kind == Teleporter.TELEPORTER_THING: floorz = self.map_data.get_floor_z(teleporter.dest.x, teleporter.dest.y) target_area = self.get_area_at(teleporter.dest, floorz) if teleporter.kind == Teleporter.TELEPORTER_LINE: dest = Vector2() dest.x, dest.y = self.map_data.get_line_center(teleporter.dest_line) floorz = self.map_data.get_floor_z(teleporter.dest.x, teleporter.dest.y) target_area = self.get_area_at(dest, floorz) # Ignore missing teleport targets. if target_area is None: print 'Teleporter linedef {} does not point to a place on the map with navigation areas.'.format(teleporter.source_line) continue # Create the teleport connection line from the linedef vertices. linedef = self.map_data.linedefs[teleporter.source_line] rect.set( linedef.vertex1.x, linedef.vertex1.y, linedef.vertex2.x, linedef.vertex2.y ) # Place a teleporter connection in all intersecting source areas. areas = self.get_areas_intersecting(rect) for area in areas: connection = Connection() connection.rect.copy_from(rect) connection.area_a = area connection.area_b = target_area connection.linedef = teleporter.source_line connection.flags = Connection.FLAG_AB | Connection.FLAG_TELEPORTER area.connections.append(connection) count += 1 print 'Connected {} teleporters.'.format(count)
def __init__(self, x1, y1, x2, y2, z): # Position and size. self.rect = Rectangle(x1, y1, x2, y2) # Average Z location of this area. If the area has a slope, this # should not be used. self.z = z # Can refer to a sector index to which this navigation area is linked. If the # sector's floor or ceiling moves, this area will need to be updated along with it. self.sector = None # Flags, taken from a NavElement object. self.flags = 0 # A plane describing the surface of this area. self.plane = None # Connection objects leading into other navigation areas. self.connections = [] # For internal use, to track elements belonging to this area. self.elements = [] self.inside_rect = Rectangle() self.index = -1 self.path = False self.visited = False
def __init__(self): # Current position. self.pos = Vector3() # Current bounding box to test. self.bbox = Rectangle() self.reset(self.pos, 0, 0)
def add_area(self, element, width, height): """ Adds a new navigation area. @param element: the top left element of the new area. @param width: the width of the new area, in map units. @param height: the height of the new area, in map units. @return: the new Area object. """ area_rect = Rectangle() area_rect.set_size(element.pos.x, element.pos.y, width, height) # Create a new nav area of the found width and height. x1, y1 = self.nav_grid.element_to_map(area_rect.p1) x2, y2 = self.nav_grid.element_to_map(area_rect.p2) p1 = Vector2(x1, y1) p2 = Vector2(x2, y2) # Offset to grid element center. p1.x -= (self.nav_grid.element_size / 2) p1.y -= (self.nav_grid.element_size / 2) p2.x -= (self.nav_grid.element_size / 2) p2.y -= (self.nav_grid.element_size / 2) area = Area(p1.x, p1.y, p2.x, p2.y, element.pos.z) # Assign this area to all the elements in it. xelement = element for _ in range(0, width): yelement = xelement for _ in range(0, height): yelement.area = area area.elements.append(yelement) yelement = yelement.elements[Element.DIR_DOWN] xelement = xelement.elements[Element.DIR_RIGHT] return area
def find_solution_for_size(size, dicts): """ Finds a solution for a given size :param size: a tuple of required size :param dicts: dictionary of lists of all available words, per word_length :returns: a solution (Rectangle object) or None """ rectangle_width = size[0] rectangle_height = size[1] words = dicts[rectangle_width] trie = get_trie(rectangle_width, dicts) r = Rectangle(rectangle_width, words) try: while True: r.get_next() #if the rectangle is valid so far, exit or go lower if all(trie.has_keys_with_prefix(col) for col in r.get_cols()): if rectangle_height == r.curr_height: logging.info('Found a solution: %s - %s', size, r) return r else: r.lower() except StopIteration: return None raise Exception('This should not happend')
def test_two(self): """ Just to make sure that if I actually find something, it will be printed out """ r = Rectangle(4, ['abcd', 'bafg']) r.get_next() r.lower() r.get_next() r.get_next() final = r.get_final_string() self.assertEquals( final, "4x2\na b c d\nb a f g" )
def test_one_level(self): r = Rectangle(1, ['1', '2', '3']) self.assertEquals( r.get_next(), '1', ) self.assertEquals( r.get_next(), '2', ) self.assertEquals( r.get_next(), '3', ) with self.assertRaises(StopIteration): r.get_next()
def test_empty(self): r = Rectangle(1, []) with self.assertRaises(StopIteration): r.get_next()
def test_columns_more_levels(self): r = Rectangle(3, ['123', '456', '789']) r.get_next() r.lower() r.get_next() r.lower() r.get_next() self.assertEquals( list(r.get_cols()), [u'111', u'222', u'333'], ) r.get_next() self.assertEquals( list(r.get_cols()), [u'114', u'225', u'336'], )
class Area(object): """ A navigation area. This describes a rectangle in which movement is freely possible. Connections to other navigation areas allow pathfinding throughout a map. """ __slots__ = ( 'rect', 'z', 'sector', 'flags', 'plane', 'connections', 'elements', 'inside_rect', 'index', 'path', 'visited' ) # Sides of a navigation area. SIDE_TOP = 0 SIDE_RIGHT = 1 SIDE_BOTTOM = 2 SIDE_LEFT = 3 SIDE_RANGE = [SIDE_TOP, SIDE_RIGHT, SIDE_BOTTOM, SIDE_LEFT] SIDE_RANGE_OPPOSITE = [SIDE_BOTTOM, SIDE_LEFT, SIDE_TOP, SIDE_RIGHT] def __init__(self, x1, y1, x2, y2, z): # Position and size. self.rect = Rectangle(x1, y1, x2, y2) # Average Z location of this area. If the area has a slope, this # should not be used. self.z = z # Can refer to a sector index to which this navigation area is linked. If the # sector's floor or ceiling moves, this area will need to be updated along with it. self.sector = None # Flags, taken from a NavElement object. self.flags = 0 # A plane describing the surface of this area. self.plane = None # Connection objects leading into other navigation areas. self.connections = [] # For internal use, to track elements belonging to this area. self.elements = [] self.inside_rect = Rectangle() self.index = -1 self.path = False self.visited = False def get_side(self, side): """ Returns the start and end coordinates of a side of this area. """ if side == Area.SIDE_TOP: return self.rect.left, self.rect.top, self.rect.right, self.rect.top elif side == Area.SIDE_RIGHT: return self.rect.right, self.rect.top, self.rect.right, self.rect.bottom elif side == Area.SIDE_BOTTOM: return self.rect.left, self.rect.bottom, self.rect.right, self.rect.bottom elif side == Area.SIDE_LEFT: return self.rect.left, self.rect.top, self.rect.left, self.rect.bottom return None def __repr__(self): return 'area {}, z {}, sector {}, width {}, height {}, plane {}, flags {}, connections {}'.format(self.rect, self.z, self.sector, self.rect.get_width(), self.rect.get_height(), self.plane, self.flags, len(self.connections))
def test_more_levels(self): r = Rectangle(1, ['1', '2', '3']) self.assertEquals( r.get_next(), '1', ) r.lower() self.assertEquals( r.get_next(), '1', ) r.lower() self.assertEquals( r.get_next(), '1', ) for item in ['2', '3', '2', '3', '2', '3']: self.assertEquals( r.get_next(), item, ) with self.assertRaises(StopIteration): r.get_next()
class Node(MapObject): """ A Doom node map object. """ __slots__ = ( 'x', 'y', 'delta_x', 'delta_y', 'bb_right', 'bb_left', 'children' ) STRUCT_DOOM = struct.Struct('<hhhhhhhhhhhhHH') STRUCT_HEXEN = struct.Struct('<hhhhhhhhhhhhHH') WAD_INDEX = 7 # Indicates that the node index is actually a subsector index. FLAG_SUBSECTOR = 0x8000 # Child node index. CHILD_RIGHT = 0 CHILD_LEFT = 1 def __init__(self, x=0, y=0): self.x = 0 self.y = 0 self.delta_x = 0 self.delta_y = 0 self.bb_right = Rectangle() self.bb_left = Rectangle() self.children = [0, 0] def unpack_from(self, data, is_hexen): self.x = data[0] self.y = data[1] self.delta_x = data[2] self.delta_y = data[3] self.bb_right.set(data[4], data[5], data[6], data[7]) self.bb_left.set(data[8], data[9], data[10], data[11]) self.children[0] = data[12] self.children[1] = data[13] def set_references(self, map_data): pass def __repr__(self): return 'Node: x {}, y {}, right {}, left {}'.format(self.x, self.y, self.bb_right, self.bb_left)