Ejemplo n.º 1
0
 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]
Ejemplo n.º 2
0
	def test_one(self):

		r = Rectangle(1, ['a'])
		r.get_next()

		final = r.get_final_string()

		self.assertEquals(
			final,
			"1x1\na"
		)
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
	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'],
		)
Ejemplo n.º 5
0
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
        )
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
 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
Ejemplo n.º 8
0
 def __init__(self):
     # Current position.
     self.pos = Vector3()
     
     # Current bounding box to test.
     self.bbox = Rectangle()
     
     self.reset(self.pos, 0, 0)
Ejemplo n.º 9
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
Ejemplo n.º 10
0
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')
Ejemplo n.º 11
0
	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"
		)
Ejemplo n.º 12
0
	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()
Ejemplo n.º 13
0
	def test_empty(self):

		r = Rectangle(1, [])

		with self.assertRaises(StopIteration):
			r.get_next()
Ejemplo n.º 14
0
	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'],
		)
Ejemplo n.º 15
0
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)) 
Ejemplo n.º 16
0
	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()
Ejemplo n.º 17
0
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)