Exemplo n.º 1
0
 def test_delete(self):
     self.do_sort()
     self.assertEqual(len(self.candidates), 5)
     self.assertEqual(self.candidates.nb_to_be_deleted, 0)
     self.candidates.delete(Vect(1, 1))
     self.assertEqual(len(self.candidates), 4)
     self.assertEqual(self.candidates.nb_to_be_deleted, 1)
     self.assertEqual([tile.pos for tile in self.candidates.iterate()], [Vect(0, 0), Vect(2, 2), Vect(3, 3), Vect(4, 4)])
Exemplo n.º 2
0
 def test_from_edge(self):
     bottom_lefts = defaultdict(int)
     for orientation in [Orientation.CLOCKWISE, Orientation.COUNTERCLOCKWISE]:
         for domain in [Domain.INTERIOR, Domain.EXTERIOR]:
             border = boundary.from_edge(Vect(3, 5), Vect(1, 0), orientation, domain)
             self.assertEqual(len(border), 4)
             self.assertEqual(border.orientation(), orientation)
             bottom_lefts[border.bottom_left()] += 1
     self.assertEqual(bottom_lefts, {Vect(3, 5): 2, Vect(3, 4): 2})
Exemplo n.º 3
0
    def test_merge(self):
        border = Boundary()

        border.merge(boundary.get_tile(Vect(0, 0), 'FFFF'))
        self.assertEqual(len(border), 4)
        self.assertEqual(border.labels, list('FFFF'))

        border.merge(boundary.get_tile(Vect(1, 0), 'FFFF'))
        self.assertEqual(len(border), 6)
        self.assertEqual(border.labels, list('FFFFFF'))
Exemplo n.º 4
0
    def test_segment_labels(self):
        placed_tile = PlacedTile(self.test_tile, Vect(2, 1), r = 0, segment = (42, 1, 2))
        self.assertEqual(list(Boundary.label_getter(placed_tile.iter_segment())), list('PT'))
        self.assertEqual(list(Boundary.label_getter(placed_tile.iter_complement_segment())), list('PF'))

        placed_tile = PlacedTile(self.test_tile, Vect(2, 1), r = 1, segment = (42, 1, 2))
        self.assertEqual(list(Boundary.label_getter(placed_tile.iter_segment())), list('FP'))
        self.assertEqual(list(Boundary.label_getter(placed_tile.iter_complement_segment())), list('TP'))

        placed_tile = PlacedTile(self.test_tile, Vect(2, 1), r = 0, segment = (42, 1, 0))
        self.assertEqual(list(Boundary.label_getter(placed_tile.iter_segment())), [])
        self.assertEqual(list(Boundary.label_getter(placed_tile.iter_complement_segment())), list('PTPF'))
Exemplo n.º 5
0
 def test_find_matching_rotations(self):
     tiles_args = [
         (Vect(0, 0), 'FFFF'),
         (Vect(0, 1), 'FFFF'),
         (Vect(1, 1), 'TFFF')]
     border = make_border_from_tiles(tiles_args)
     border.rotate_to_start_with(Vect(0, 0))
     self.assertEqual(len(border), 8)
     self.assertEqual(border.labels, list('FFTFFFFF'))
     tile = boundary.get_tile(Vect(1, 0), 'TFFF')
     self.assertEqual(border.common_segments(tile), [(1, 2, 2)])
     self.assertEqual(list(border.find_matching_rotations(tile, (1, 2, 2))), [2])
Exemplo n.º 6
0
 def test_self(self):
     self.assertEqual(len(self.border), 6)
     self.assertEqual(self.border.orientation(), Orientation.COUNTERCLOCKWISE)
     self.assertEqual(self.border.get_point(2), Vect(2, 0))
     self.assertEqual(self.border.get_point(8), self.border.get_point(2))
     self.assertEqual(self.border.get_point(-4), self.border.get_point(2))
     self.assertEqual(self.border.get_label(2), 'T')
     self.assertEqual(self.border.get_label(8), self.border.get_label(2))
     self.assertEqual(self.border.get_label(-4), self.border.get_label(2))
     self.assertEqual(self.border.get_edge(0), Vect(1, 0))
     self.assertEqual(self.border.get_edge(-1), Vect(0, -1))
     self.assertEqual(self.border.bottom_left(), Vect(0, 0))
Exemplo n.º 7
0
 def test_get_tile(self):
     bottom_left = Vect(5, 7)
     tile = boundary.get_tile(bottom_left, 'FFTF')
     self.assertEqual(len(tile), 4)
     self.assertEqual(tile.orientation(), Orientation.COUNTERCLOCKWISE)
     self.assertEqual(tile.get_point(0), bottom_left)
     self.assertEqual(tile.bottom_left(), bottom_left)
     self.assertEqual(tile.get_edge(0), Vect(1, 0))
     self.assertEqual(tile.get_edge(1), Vect(0, 1))
     self.assertEqual(tile.get_edge(2), Vect(-1, 0))
     self.assertEqual(tile.get_edge(3), Vect(0, -1))
     self.assertEqual(tile.get_label(0), 'F')
     self.assertEqual(tile.get_label(2), 'T')
Exemplo n.º 8
0
    def test_rotate_to_start_with(self):
        border = self.border.copy()

        border.rotate_to_start_with(Vect(2, 0))
        self.assertEqual(len(border), len(self.border))
        self.assertEqual(border.points[0], Vect(2, 0))
        self.assertEqual(border.labels, list('TPFPFF'))

        border.rotate_to_start_with(Vect(2, 1))
        self.assertEqual(len(border), len(self.border))
        self.assertEqual(border.points[0], Vect(2, 1))
        self.assertEqual(border.labels, list('PFPFFT'))

        with self.assertRaises(ValueError):
            border.rotate_to_start_with(Vect(99, 99))
Exemplo n.º 9
0
 def test_common_segments_2(self):
     tiles_bottom_left = [Vect(0, 0), Vect(1, 0), Vect(1, 1), Vect(0, 1)]
     for single_idx in range(4):
         single_tile = boundary.get_tile(tiles_bottom_left[single_idx])
         three_other_tiles = [(bl,) for bl in tiles_bottom_left[single_idx+1:] + tiles_bottom_left[:single_idx]]
         border = make_border_from_tiles(three_other_tiles)
         self.assertEqual(len(border), 8)
         border.rotate_to_start_with(Vect(1, 1))
         for ii in range(len(border)):
             segments = border.common_segments(single_tile)
             self.assertEqual(len(segments), 1)
             (i, j, L) = segments[0]
             self.assertEqual(L, 2)
             self.assertEqual(j, (single_idx + 1) % 4)
             self.assertEqual(i, 7 - ii)
             border.rotate_to_start_with(border.points[1])
Exemplo n.º 10
0
 def append(self, tile):
     offset = None
     for tag in tile.tags:
         result = self.vect_re.match(tag)
         if result:
             offset = Vect(int(result.group(1)), int(result.group(2)))
     if offset:
         self.elts.append(CompositeTile.Elt(tile, offset))
     else:
         warn('Could not find the offset pattern in the tags for tile {}. Tags = {}.'.format(tile, tile.tags))
Exemplo n.º 11
0
 def test_corner_case_2(self):
     tiles_args = [
         (Vect(2, 0), 'FFFF'),
         (Vect(2, 1), 'FFFF'),
         (Vect(2, 2), 'FFFF'),
         (Vect(1, 2), 'FFFF'),
         (Vect(0, 2), 'FFFF'),
         (Vect(0, 1), 'FFFF'),
         (Vect(0, 0), 'FFFF')]
     border = make_border_from_tiles(tiles_args)
     self.assertEqual(len(border), 16)
     tile = boundary.get_tile(Vect(1, 0), 'FFFF')
     segments = border.common_segments(tile)
     self.assertEqual(len(segments), 2)
Exemplo n.º 12
0
 def setUp(self):
     self.border = Boundary()
     self.border.append(Vect(0, 0), 'F')
     self.border.append(Vect(1, 0), 'F')
     self.border.append(Vect(2, 0), 'T')
     self.border.append(Vect(2, 1), 'P')
     self.border.append(Vect(1, 1), 'F')
     self.border.append(Vect(0, 1), 'P')
Exemplo n.º 13
0
 def setUp(self):
     self.candidates = CandidateTiles()
     self.candidates.update(PositionedTile(Vect(5, 5), segments = [(0, 0, 1), (1, 1, 1)]))
     self.candidates.update(PositionedTile(Vect(4, 4), segments = [(0, 0, 1)]))
     self.candidates.update(PositionedTile(Vect(3, 3), segments = [(0, 0, 1)]))
     self.candidates.update(PositionedTile(Vect(2, 2), segments = [(0, 0, 2)]))
     self.candidates.update(PositionedTile(Vect(1, 1), segments = [(0, 0, 2)]))
     self.candidates.update(PositionedTile(Vect(0, 0), segments = [(0, 0, 3)]))
Exemplo n.º 14
0
 def test_common_segments_1(self):
     tile1 = boundary.get_tile(Vect(2, 1), 'FFFF')
     self.assertEqual(self.border.common_segments(tile1), [(3, 0, 0)])
     tile2 = boundary.get_tile(Vect(1, 1), 'FFFF')
     self.assertEqual(self.border.common_segments(tile2), [(3, 0, 1)])
     self.assertEqual(tile1.common_segments(tile2), [(3, 1, 1)])
     self.assertEqual(tile2.common_segments(tile1), [(1, 3, 1)])
     tile3 = Boundary()
     tile3.append(Vect(2, 2), 'F')
     tile3.append(Vect(1, 2), 'F')
     tile3.append(Vect(1, 1), 'F')
     tile3.append(Vect(2, 1), 'F')
     self.assertEqual(tile1.common_segments(tile3), [(3, 3, 1)])
     self.assertEqual(tile3.common_segments(tile1), [(3, 3, 1)])
Exemplo n.º 15
0
 def test_sort(self):
     self.assertEqual(len(self.candidates), 5)
     self.do_sort()
     self.assertEqual([tile.pos for tile in self.candidates.iterate()], [Vect(0, 0), Vect(1, 1), Vect(2, 2), Vect(3, 3), Vect(4, 4)])
Exemplo n.º 16
0
 def test_operations(self):
     self.assertTrue(Vect(1, 0) == Vect(1, 0))
     self.assertFalse(Vect(1, 0) == Vect(1, 1))
     self.assertEqual(Vect(1, 0) + Vect(0, 1), Vect(1, 1))
     self.assertEqual(Vect(1, 2) - Vect(1, 2), Vect(0, 0))
     self.assertEqual(Vect(1, 2).mult(2), Vect(2, 4))
     self.assertEqual(Vect(1, 0).cross_z(Vect(0, 1)), 1)
     self.assertEqual(Vect(0, 1).cross_z(Vect(1, 0)), -1)
     self.assertEqual(Vect(-3, 5).l1_distance(), 8)
Exemplo n.º 17
0
def main():
    parser = argparse.ArgumentParser(description='Display a randomized Carcassonne map')
    parser.add_argument('files', metavar='FILE', nargs='*', help='Tile description file (JSON format)')
    parser.add_argument('-d', '--debug', dest='debug_mode', action='store_true', help='Display non-game tiles, etc.')
    parser.add_argument('-n', metavar='N', type=int, dest='max_tiles', default = 0, help='Number of tiles to display (Default: The whole tileset)')
    parser.add_argument('-z', '--zoom-factor', metavar='Z', type=float, dest='zoom_factor', default = 1.0, help='Initial zoom factor (Default: 1.0)')
    parser.add_argument('--draw-all', dest='draw_all', action='store_true', help='Draw all tiles')
    parser.add_argument('-f', '--full-screen', dest='full_screen', action='store_true', help='Full screen')
    parser.add_argument('-s', '--screenshot', dest='take_screenshot', action='store_true', help='Take a screenshot of the final display')
    parser.add_argument('--dump', dest='dump_to_img', action='store_true', help='Dump the final grid to an image')
    parser.add_argument('--river-policy', type=str, dest='river_policy', choices=[policy.name for policy in RiverPlacement], action='append', default=[], help='Placement policies for the river tileset. Can be used multiple times')
    parser.add_argument('--river-period', metavar='P', type=int, dest='river_period', default=1, help='Period of repetition of the river tileset. Set to zero for a single use of the river tileset')
    parser.add_argument('--seed', metavar='INT', type=int, dest='seed', default = 0, help='A seed for the random generator (Default: Use a system generated seed)')
    args = parser.parse_args()

    # Set random seed
    rng_seed = args.seed
    if rng_seed == 0:
        rng_seed = secrets.randbits(64)
    print('Random seed: {}'.format(rng_seed))
    random.seed(rng_seed)

    # Load tileset (JSON files)
    tileset = list(itertools.chain.from_iterable(parse_tileset_description_file(json_file) for json_file in args.files))
    if len(tileset) == 0:
        error('No tiles loaded')

    # River tiles placement policy and period
    river_placement_policies = parse_river_placement_policies([RiverPlacement[policy] for policy in args.river_policy])
    river_tileset_period = args.river_period if args.river_period >= 0 else 0
    if args.debug_mode and any('river' in tile.tags for tile in tileset):
        print('river_placement_policies: {}'.format([policy.name for policy in river_placement_policies]))
        print('river_tileset_period: {}'.format(river_tileset_period))

    try:
        # Load tile images, and draw missing ones
        graphics.init()
        tile_size = load_or_draw_tile_images(tileset, args.draw_all)
        carcassonne_city_tileset, tileset = TileSubset.carcassonne_city().partition_iter(tileset)
        city_start_flag = len(carcassonne_city_tileset) > 0
        river_tileset, regular_tileset = TileSubset.river().partition(tileset)
        del tileset

        # Non-game tiles
        riverside_tile = Tile.from_uniform_color((217, 236, 255), tile_size, 'riverside')
        forbidden_tile = Tile.from_uniform_color((100,  20,  20), tile_size, 'forbidden')
        segment_length_tiles = {
            0: forbidden_tile,
            1: Tile.from_uniform_color((10,  60, 10), tile_size, 'one_side'),
            2: Tile.from_uniform_color((40, 120, 40), tile_size, 'two_sides'),
            3: Tile.from_uniform_color((70, 180, 70), tile_size, 'three_sides')
        }

        # Open display
        (w, h) = (0, 0) if args.full_screen else (1280, 720)
        display = graphics.GridDisplay(w, h, tile_size)
        print('Press ESCAPE in the graphics window to quit', flush = True)

        # Place random tiles. The map must grow!
        candidate_tiles = CandidateTiles(
            on_update = lambda pos_tile: display.set_tile(segment_length_tiles[pos_tile.get_segment_length()].img, pos_tile.pos.x, pos_tile.pos.y) if args.debug_mode else None,
            on_delete = None)
        z = args.zoom_factor
        border = place_carcassonne_city(carcassonne_city_tileset, candidate_tiles, display, z, Vect(-2, -1)) if city_start_flag else Boundary()
        total_nb_tiles_placed = 0
        total_nb_tiles_not_placed = 0
        first_tileset_flag = not city_start_flag
        all_done_flag = False
        for tileset in iterate_tilesets(river_tileset, regular_tileset, river_tileset_period, infinite = (args.max_tiles > 0)):
            for tiles_to_place in shuffle_tileset(tileset, first_tileset_flag, river_placement_policies):
                local_nb_tiles_placed = 0
                while len(tiles_to_place) > 0:
                    tiles_not_placed = []
                    for tile in tiles_to_place:
                        if args.max_tiles > 0 and total_nb_tiles_placed >= args.max_tiles:
                            all_done_flag = True
                            break
                        if len(border) == 0:
                            # The first tile of the map is placed at the center
                            placed_tile = PlacedTile(tile, Vect(0, 0), r = 0)
                        else:
                            forced_segment = 'R' if 'river' in tile.tags and 'source' not in tile.tags else None
                            max_candidates = 1
                            candidate_placements = find_candidate_placements(tile, border, candidate_tiles, max_candidates, forced_segment)
                            placed_tile = select_tile_placement(candidate_placements) if len(candidate_placements) > 0 else None
                        if placed_tile:
                            update_border_and_candidate_tiles(placed_tile, border, candidate_tiles)
                            placed_tile.draw(display)
                            total_nb_tiles_placed += 1
                            local_nb_tiles_placed += 1
                            # z = 0.995 * z
                            # display.update(z, 100)
                        else:
                            tiles_not_placed.append(tile)
                    if all_done_flag:
                        break
                    if len(tiles_not_placed) == len(tiles_to_place):
                        # making no progress, stop there
                        total_nb_tiles_not_placed += len(tiles_not_placed)
                        for tile in tiles_not_placed:
                            warn('Could not place tile: {}'.format(tile))

                        break
                    assert len(tiles_not_placed) < len(tiles_to_place)
                    tiles_to_place = tiles_not_placed

                # Done with the current tiles subset
                if DEBUG_PRINTOUT or args.debug_mode:
                    print('total_nb_tiles_placed: {} (+{})'.format(total_nb_tiles_placed, local_nb_tiles_placed))
                if all_done_flag:
                    break

            # Done with the current tileset
            if all_done_flag:
                break
            first_tileset_flag = False
            display.update(z)

        # Completely done!
        display.update(z)
        print('Done!')
        print('total_nb_tiles_not_placed: {}'.format(total_nb_tiles_not_placed))
        print('total_nb_tiles_placed: {}'.format(total_nb_tiles_placed))
        sys.stdout.flush()

        # Wait until the user quits
        while True:
            display.check_event_queue(200)

    except graphics.MustQuit:
        pass

    finally:
        if args.debug_mode and 'display' in locals():
            print(display.get_debug_info())
        if (args.take_screenshot or args.debug_mode) and 'display' in locals():
            display.take_screenshot(SCREENSHOT_PATH)
            print('Screenshot saved in {}'.format(SCREENSHOT_PATH))
        if args.dump_to_img and 'display' in locals():
            display.dump_to_img(DUMP_PATH, args.zoom_factor)
            print('Dump grid to {}'.format(DUMP_PATH))
        graphics.quit()

    return 0
Exemplo n.º 18
0
 def test_update(self):
     self.do_sort()
     self.assertEqual(next(self.candidates.iterate()).pos, Vect(0, 0))
     self.candidates.update(PositionedTile(Vect(0, 0), segments = [(0, 0, 1)]))
     self.do_sort()
     self.assertEqual(next(self.candidates.iterate()).pos, Vect(1, 1))