def should_construct_matrix_from_multiline_string(self): data = textwrap.dedent("""\ .X.X. XXXXX """) m = Matrix.fromstring(data) self.assertEqual(m.width, 5) self.assertEqual(m.height, 2) self.assertEqual(m.data, [ '.', 'X', '.', 'X', '.', 'X', 'X', 'X', 'X', 'X', ]) with self.assertRaises(ValueError): Matrix.fromstring("short\nlong") data = textwrap.dedent("""\ .a.b. cabcd """) m = Matrix.fromstring(data, transformer=lambda c: -1 if c == '.' else ord(c) - ord('a')) self.assertEqual(m.width, 5) self.assertEqual(m.height, 2) self.assertEqual(m.data, [ -1, 0, -1, 1, -1, 2, 0, 1, 2, 3, ])
def should_iterate_over_indexes(self): m = Matrix((2, 2)) m.data = list('abcd') indexes = ' '.join(''.join(map(str, index)) for index in m) self.assertEqual(indexes, '00 10 01 11') indexes = ' '.join(''.join(map(str, index)) for index in m.keys()) self.assertEqual(indexes, '00 10 01 11') values = ' '.join(m.values()) self.assertEqual(values, 'a b c d')
def should_construct_matrix_from_iterable(self): with self.assertRaises(ValueError): Matrix.from_iterable( (range(3), range(4)) ) m = Matrix.from_iterable( (range(4), range(4, 8)) ) self.assertEqual(m.width, 4) self.assertEqual(m.height, 2) self.assertEqual(m.data, [ 0, 1, 2, 3, 4, 5, 6, 7, ])
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 should_fill_rectangle(self): m = Matrix((10, 5), '.') m.fill(Point(3, 1), Point(8, 3), 'X') expected = textwrap.dedent("""\ .......... ...XXXXXX. ...XXXXXX. ...XXXXXX. .......... """) actual = m.tostring() self.assertEqual(actual, expected)
def should_find_value_in_matrix(self): a = Matrix.fromstring(textwrap.dedent("""\ ab ca """)) self.assertEqual(list(a.find('a')), [Point(0, 0), Point(1, 1)]) self.assertEqual(list(a.find('X')), []) self.assertEqual(list(a.find_if(lambda c:c>'a')), [Point(1, 0), Point(0, 1)]) self.assertEqual(list(a.find_if(lambda c:c<'a')), [])
def should_transform_matrix(self): original = Matrix.fromstring('01\n23') processed = original.transform(int) self.assertEqual(processed.width, 2) self.assertEqual(processed.height, 2) self.assertEqual(processed.data, [ 0, 1, 2, 3, ])
def __init__(self, level_id=None, rooms=None, tunnels=None, items=None, monsters=None, objects=None, ): # pragma: no cover self.level_id = level_id self.rooms = rooms or Matrix( (3, 3) ) self.tunnels = tunnels or [] self.items = items or [] self.monsters = monsters or [] self.objects = objects or []
def should_get_neighbours(self): m = Matrix.fromstring('01\n23') neighbours = list(clckwrkbdgr.math.get_neighbours(m, (0, 0))) self.assertEqual(neighbours, [Point(1, 0), Point(0, 1)]) neighbours = list(clckwrkbdgr.math.get_neighbours(m, (0, 0), with_diagonal=True)) self.assertEqual(neighbours, [Point(1, 0), Point(0, 1), Point(1, 1)]) neighbours = list(clckwrkbdgr.math.get_neighbours(m, (0, 0), check=lambda c: int(c) > 1)) self.assertEqual(neighbours, [Point(0, 1)]) neighbours = list(clckwrkbdgr.math.get_neighbours(m, (0, 0), with_diagonal=True, check=lambda c: int(c) > 1)) self.assertEqual(neighbours, [Point(0, 1), Point(1, 1)])
def should_compare_matrices(self): a = Matrix((2, 3), default='*') with self.assertRaises(TypeError): a == 'something that is not matrix' b = Matrix((5, 6), default='*') self.assertNotEqual(a, b) a = Matrix.fromstring(textwrap.dedent("""\ .X. XXX """)) b = Matrix.fromstring(textwrap.dedent("""\ #.# .#. """)) c = Matrix.fromstring(textwrap.dedent("""\ .X. XXX """)) self.assertNotEqual(a, b) self.assertEqual(a, c)
def should_recognize_invalid_coords(self): m = Matrix((2, 2), default='*') self.assertTrue(m.valid((0, 0))) self.assertTrue(m.valid((0, 1))) self.assertTrue(m.valid((1, 0))) self.assertTrue(m.valid((1, 1))) self.assertFalse(m.valid((2, 2))) self.assertFalse(m.valid((-1, 0)))
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_parse_layout_correctly(self): gridmap = self._map() result = Matrix.fromstring(MockGenerator.MAIN_LEVEL) result.clear(' ') for room in gridmap.rooms.values(): for x in range(room.left, room.right + 1): result.set_cell((x, room.top), '#') result.set_cell((x, room.bottom), '#') for y in range(room.top, room.bottom + 1): result.set_cell((room.left, y), '#') result.set_cell((room.right, y), '#') for tunnel in gridmap.tunnels: cells = list(tunnel.iter_points()) for cell in cells: result.set_cell(cell, '.') result.set_cell(cells[0], '+') result.set_cell(cells[-1], '+') for pos, obj in gridmap.objects: result.set_cell(pos, obj.sprite) self.assertEqual(result.tostring(), MockGenerator.MAIN_LEVEL)
def should_convert_matrix_to_string(self): m = Matrix((5, 2)) m.data = [ '.', 'X', '.', 'X', '.', 'X', 'X', 'X', 'X', 'X', ] expected = textwrap.dedent("""\ .X.X. XXXXX """) self.assertEqual(m.tostring(), expected) m = Matrix((5, 2)) m.data = [ -1, 0, -1, 1, -1, 2, 0, 1, 2, 3, ] expected = textwrap.dedent("""\ .a.b. cabcd """) self.assertEqual(m.tostring(transformer=lambda c: '.' if c < 0 else chr(c + ord('a'))), expected)
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
def should_resize_matrix(self): m = Matrix((2, 3), default='*') self.assertEqual(m.size, (2, 3)) m.resize((3, 2), default='_') self.assertEqual(m.size, (3, 2))
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 should_create_matrix(self): m = Matrix((2, 3), default='*') self.assertEqual(m.size, (2, 3)) self.assertEqual(m.width, 2) self.assertEqual(m.height, 3)