def should_set_cell_value(self): m = Matrix((2, 2), default=' ') m.set_cell((0, 0), '*') self.assertEqual(m.cell((0, 0)), '*') with self.assertRaises(KeyError): m.set_cell((-1, -1), 'a') with self.assertRaises(KeyError): m.set_cell((1, 10), 'a')
def grid_of_rooms(self, room_class, map_size, grid_size, min_room_size, margin): """ Returns Matrix of grid_size with random sized and positioned Rooms within evenly spaced grid cells. Margin is a Size (width+height) from _both_ sides to leave space for tunnels (room walls included into room size). Min room size also includes walls. """ map_size, grid_size, min_room_size, margin = map(Size, (map_size, grid_size, min_room_size, margin)) grid = Matrix(grid_size) cell_size = Size(map_size.width // grid_size.width, map_size.height // grid_size.height) max_room_size = cell_size - margin * 2 if max_room_size.width < min_room_size.width: max_room_size.width = min_room_size.width if max_room_size.height < min_room_size.height: max_room_size.height = min_room_size.height for cell in grid: room_size = self.size(min_room_size, max_room_size) topleft = Point(cell.x * cell_size.width, cell.y * cell_size.height) topleft += self.point( cell_size.width - room_size.width - 1, cell_size.height - room_size.height - 1, ) grid.set_cell(cell, room_class(topleft, room_size)) return grid
def should_create_matrix_from_other_matrix(self): original = Matrix((2, 2)) original.set_cell((0, 0), 'a') original.set_cell((0, 1), 'b') original.set_cell((1, 0), 'c') original.set_cell((1, 1), 'd') copy = Matrix(original) self.assertEqual(copy.cell((0, 0)), 'a') self.assertEqual(copy.cell((0, 1)), 'b') self.assertEqual(copy.cell((1, 0)), 'c') self.assertEqual(copy.cell((1, 1)), 'd') copy.set_cell((0, 0), '*') self.assertEqual(original.cell((0, 0)), 'a') original.set_cell((0, 0), '#') self.assertEqual(copy.cell((0, 0)), '*')
def _parse_layout(layout): layout = Matrix.fromstring(layout) rects = [] for x in range(layout.width): for y in range(layout.height): if layout.cell((x, y)) != '#': continue if not layout.valid((x + 1, y)): continue if not layout.valid((x, y + 1)): continue if layout.cell((x + 1, y)) not in '#+' or layout.cell( (x, y + 1)) not in '#+': continue right = min([ _ for _ in range(x, layout.width) if layout.cell((_, y)) not in '#+' ] + [layout.width]) bottom = min([ _ for _ in range(y, layout.height) if layout.cell((x, _)) not in '#+' ] + [layout.height]) rects.append(((x, y), (right - x, bottom - y))) rects = sorted(rects, key=lambda rect: (rect[0][1], rect[0][0])) if len(rects) == 4: rooms = Matrix((2, 2)) rooms.set_cell((0, 0), Room(*(rects[0]))) rooms.set_cell((1, 0), Room(*(rects[1]))) rooms.set_cell((0, 1), Room(*(rects[2]))) rooms.set_cell((1, 1), Room(*(rects[3]))) else: rooms = Matrix((1, 1)) rooms.set_cell((0, 0), Room(*(rects[0]))) tunnels = [] for y in range(layout.height): for x in range(layout.width): if layout.cell((x, y)) != '+': continue if any(tunnel.contains((x, y)) for tunnel in tunnels): continue current = Point(x, y) path = [current] for _ in range(layout.width * layout.height): neighs = get_neighbours(layout, current, check=lambda p: p in '.+') neighs = [p for p in neighs if p not in path] if not neighs: break current, = neighs path.append(current) direction = '' bending = 0 for prev, current in zip(path, path[1:]): h, v = abs(prev.x - current.x), abs(prev.y - current.y) if not direction: direction = 'H' if h > v else 'V' elif not bending: if (direction == 'H') != (h > v): bending = max( abs(current.x - path[0].x), abs(current.y - path[0].y), ) tunnels.append( Tunnel(path[0], path[-1], direction, bending or 1)) objects = [] for y in range(layout.height): for x in range(layout.width): if layout.cell((x, y)) == '>': objects.append((Point(x, y), Elevator(None, None))) elif layout.cell((x, y)) == '<': objects.append((Point(x, y), Ladder('roof', 'roof'))) elif layout.cell((x, y)) == '=': objects.append((Point(x, y), Ladder('top', 'roof'))) return rooms, tunnels, objects