class ConfigReader(): def __init__(self, config_file): self.super_cc_loc = None self.tile_world_loc = None self.super_cc_save_file = None self.tile_world_save_file = None self.puzzle_script_save_file = None self.engine = None self.level_count = None self.play_or_generate = None self.ask_for_rating = None self.name = None self.ratings_file = None self.draw_graph = None self.aesthetic = None self.generate_level_count = None self.keep_level_count = None with open(config_file) as f: config = json.load(f) self.from_config_data(config) self.aesthetic = AestheticSettings() self.aesthetic.from_config_data(config['aesthetic']) def from_config_data(self, config): for setting in self.__dict__: if setting not in config: raise LookupError("You are missing '{}' in your config file!".format(setting)) self.__dict__[setting] = config[setting]
def level_aesthetic(self, i): data = self.file_data.splitlines()[i].split( Ratings.CSV_SEPARATOR)[Ratings. SETTINGS_INDEX:Ratings.SETTINGS_INDEX + len(AestheticSettings.get_csv_data_paths())] aesthetic = AestheticSettings() aesthetic.from_csv_data(data) return aesthetic
def test_csv_roundtrip(self): aesthetic_settings = AestheticSettings() paths = AestheticSettings.get_csv_data_paths() for i, path in enumerate(paths): aesthetic, setting = path aesthetic_settings.__dict__[aesthetic].__dict__[setting] = i aesthetic_settings.mission_aesthetic.hazard_spread_probability = { Tiles.water: 1, Tiles.fire: 2 } aesthetic_settings.mission_graph_aesthetic.branch_probability = [ 0, 1, 2, 3 ] csv_data = aesthetic_settings.to_csv_data() expected_csv_data = [ "0", "1", "2", "3", "4", "5", "6", "[1, 2]", "8", "9", "10", "[0, 1, 2, 3]", "12", "13", "14", "15", "16", "17", "18", "19" ] self.assertEqual(expected_csv_data, csv_data) aesthetic_settings2 = AestheticSettings() aesthetic_settings2.from_csv_data(csv_data) expected_values = [ 0.0, 1.0, 2, 3, 4, 5.0, 6.0, { Tiles.water: 1.0, Tiles.fire: 2.0 }, 8, 9, 10.0, [0.0, 1.0, 2.0, 3.0], 12.0, 13.0, 14.0, 15, 16, 17, 18, 19.0 ] for path, expected_value in zip(paths, expected_values): aesthetic, setting = path value = aesthetic_settings2.__dict__[aesthetic].__dict__[setting] self.assertEqual(value, expected_value)
def test_get_csv_header(self): header = AestheticSettings.get_csv_header() expected_header = [ "level_space_aesthetic.noise_empty_percentage", "level_space_aesthetic.noise_percentage", "level_space_aesthetic.rectangle_count", "level_space_aesthetic.rectangle_max", "level_space_aesthetic.rectangle_min", "level_space_aesthetic.x_mirror_probability", "level_space_aesthetic.y_mirror_probability", "mission_aesthetic.hazard_spread_probability", "mission_aesthetic.max_seconds_per_move", "mission_aesthetic.min_seconds_per_move", "mission_aesthetic.single_lock_is_hazard_probability", "mission_graph_aesthetic.branch_probability", "mission_graph_aesthetic.collectable_in_room_probability", "mission_graph_aesthetic.insert_room_probability", "mission_graph_aesthetic.key_is_sokoban_probability", "mission_graph_aesthetic.max_depth", "mission_graph_aesthetic.max_locks_per_multi_lock", "mission_graph_aesthetic.max_multi_lock_count", "mission_graph_aesthetic.min_depth", "tweaker_aesthetic.should_fill_unused_space" ] self.assertEqual(header, expected_header)
def test_mission_generator_rooms(self): start = Start() key = Key() lock = Lock() room = Room() end = End() start.add_child_s([room, lock]) room.add_child_s(key) key.add_lock_s(lock) lock.add_child_s(end) level = Level() w = Tiles.wall e = Tiles.empty layer = np.array([[w, w, w, w, w, w, w, w], [w, e, e, w, e, e, e, w], [w, e, e, w, e, e, e, w], [w, w, w, w, w, w, w, w], [w, e, e, w, e, e, e, w], [w, e, e, w, e, e, e, w], [w, e, e, w, e, e, e, w], [w, w, w, w, w, w, w, w]], dtype=object) aesthetic_settings = AestheticSettings() was_successful = Generator.generate( level_type=Level, size=layer.shape, aesthetic_settings=aesthetic_settings, max_retry_count=10, pregenerated_level_layer=layer, pregenerated_mission_start_node=start) self.assertTrue(was_successful)
def __init__(self, config_file): self.super_cc_loc = None self.tile_world_loc = None self.super_cc_save_file = None self.tile_world_save_file = None self.puzzle_script_save_file = None self.engine = None self.level_count = None self.play_or_generate = None self.ask_for_rating = None self.name = None self.ratings_file = None self.draw_graph = None self.aesthetic = None self.generate_level_count = None self.keep_level_count = None with open(config_file) as f: config = json.load(f) self.from_config_data(config) self.aesthetic = AestheticSettings() self.aesthetic.from_config_data(config['aesthetic'])
def test_works_with_branched_graphs(self): # return # S # |----------- # | | | # L1 K2 L2 # | | # E K1 start = Start() key1 = Key("1") key2 = Key("2") lock1 = Lock("1") lock2 = Lock("2") end = End() start.add_child_s([lock1, key2, lock2]) lock1.add_child_s(end) lock2.add_child_s(key1) key1.add_child_s(lock1) key2.add_child_s(lock2) key1.add_lock_s(lock1) key2.add_lock_s(lock2) np.random.seed(4) level = Level() w = Tiles.wall e = Tiles.empty layer = np.array([[w, w, w, w, w, w, w, w], [w, e, e, e, e, e, e, w], [w, e, e, e, e, e, e, w], [w, w, w, w, w, w, w, w], [w, e, e, w, e, e, e, w], [w, e, e, w, e, e, e, w], [w, e, e, w, e, e, e, w], [w, w, w, w, w, w, w, w]], dtype=object) solution_node_order = Node.find_all_nodes(start, method="topological-sort") aesthetic_settings = AestheticSettings() was_successful = Generator.generate( level=level, size=layer.shape, aesthetic_settings=aesthetic_settings, max_retry_count=10, pregenerated_level_layer=layer, pregenerated_solution_node_order=solution_node_order) self.assertTrue(was_successful) Log.print(level)
def __init__(self, file): # Open the csv file self.file = file self.file_data = '' self.header = Ratings.CSV_SEPARATOR.join( ["id", "seed"] + AestheticSettings.get_csv_header() + ["brandon_rating", "ryan_rating"]) + "\n" open(file, 'a').close() # Create a file if it doesn't exist. with open(file, 'r') as csvfile: csv_reader = csv.reader(csvfile, delimiter=Ratings.CSV_SEPARATOR) for i, row in enumerate(csv_reader): if i == 0: continue self.file_data += Ratings.CSV_SEPARATOR.join(row) + "\n"
def test_mission_generator(self): # S # |----------- # | | | # L1 K2 L2 # | | # E K1 start = Start() key1 = Key("1") key2 = Key("2") lock1 = Lock("1") lock2 = Lock("2") end = End() start.add_child_s([lock1, key2, lock2]) lock1.add_child_s(end) lock2.add_child_s(key1) key1.add_lock_s(lock1) key2.add_lock_s(lock2) level = Level() w = Tiles.wall e = Tiles.empty layer = np.array([[w, w, w, w, w, w, w, w], [w, e, e, e, e, e, e, w], [w, e, e, e, e, e, e, w], [w, w, w, w, w, w, w, w], [w, e, e, w, e, e, e, w], [w, e, e, w, e, e, e, w], [w, e, e, w, e, e, e, w], [w, w, w, w, w, w, w, w]], dtype=object) aesthetic_settings = AestheticSettings() was_successful = Generator.generate( level_type=Level, size=layer.shape, aesthetic_settings=aesthetic_settings, max_retry_count=10, pregenerated_level_layer=layer, pregenerated_mission_start_node=start) self.assertTrue(was_successful)
def test_get_csv_data_paths(self): l = "level_space_aesthetic" m = "mission_aesthetic" g = "mission_graph_aesthetic" t = "tweaker_aesthetic" data_paths = AestheticSettings.get_csv_data_paths() expected_data_paths = [(l, "noise_empty_percentage"), (l, "noise_percentage"), (l, "rectangle_count"), (l, "rectangle_max"), (l, "rectangle_min"), (l, "x_mirror_probability"), (l, "y_mirror_probability"), (m, "hazard_spread_probability"), (m, "max_seconds_per_move"), (m, "min_seconds_per_move"), (m, "single_lock_is_hazard_probability"), (g, "branch_probability"), (g, "collectable_in_room_probability"), (g, "insert_room_probability"), (g, "key_is_sokoban_probability"), (g, "max_depth"), (g, "max_locks_per_multi_lock"), (g, "max_multi_lock_count"), (g, "min_depth"), (t, "should_fill_unused_space")] self.assertEqual(expected_data_paths, data_paths)
def test_works_with_difficult_graph(self): return start = Start() key_red = Key("red") lock_red = Lock("red") flippers = Key("flippers") water1 = Lock("water1") water2 = Lock("water2") key_green = Key("green") lock_green = Lock("green") fire_boots = Key("fireboots") fire1 = Lock("fire1") fire2 = Lock("fire2") end = End() start.add_child_s([fire2, key_red, lock_red]) key_red.add_lock_s(lock_red) lock_red.add_child_s([flippers, water1]) flippers.add_lock_s([water1, water2]) water1.add_child_s(water2) water2.add_child_s([fire_boots, fire1]) fire_boots.add_lock_s([fire1, fire2]) fire1.add_child_s(key_green) key_green.add_lock_s(lock_green) fire2.add_child_s(lock_green) lock_green.add_child_s(end) np.random.seed(12) level = Level() w = Tiles.wall e = Tiles.empty layer = np.array( [[w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w], [w, e, e, w, e, e, w, e, e, w, e, e, w, e, e, w, e, e, w], [w, e, e, w, e, e, w, e, e, w, e, e, w, e, e, w, e, e, w], [w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w], [w, e, e, w, e, e, w, e, e, w, e, e, w, e, e, w, e, e, w], [w, e, e, w, e, e, w, e, e, w, e, e, w, e, e, w, e, e, w], [w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w], [w, e, e, w, e, e, w, e, e, w, e, e, w, e, e, w, e, e, w], [w, e, e, w, e, e, w, e, e, w, e, e, w, e, e, w, e, e, w], [w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w, w]], dtype=object) solution_node_order = Node.find_all_nodes(start, method="topological-sort") start_time = time.time() aesthetic_settings = AestheticSettings() aesthetic_settings.mission_aesthetic.single_lock_is_hazard_probability = 0 aesthetic_settings.mission_aesthetic.hazard_spread_probability[ Tiles.water] = 0 aesthetic_settings.mission_aesthetic.hazard_spread_probability[ Tiles.fire] = 0 was_successful = Generator.generate( level=level, size=layer.shape, aesthetic_settings=aesthetic_settings, max_retry_count=10, pregenerated_level_layer=layer, pregenerated_solution_node_order=solution_node_order) end_time = time.time() self.assertTrue(was_successful) Log.print(level) Log.print("Generated in {} seconds".format(end_time - start_time))
def test_from_config_data(self): config = { "level_space_aesthetic": { "rectangle_count": 1, "rectangle_min": 2, "rectangle_max": 3, "noise_percentage": 0.4, "noise_empty_percentage": 0.6, "x_mirror_probability": 0.7, "y_mirror_probability": 0.8 }, "mission_graph_aesthetic": { "max_depth": 1, "min_depth": 2, "branch_probability": [0.3, 0.4], "max_multi_lock_count": 5, "max_locks_per_multi_lock": 6, "collectable_in_room_probability": 0.7, "insert_room_probability": 0.8, "key_is_sokoban_probability": 0.9 }, "tweaker_aesthetic": { "should_fill_unused_space": 0.5 }, "mission_aesthetic": { "hazard_spread_probability": { "water": 0.1, "fire": 0.2 }, "single_lock_is_hazard_probability": 0.3, "max_seconds_per_move": 4, "min_seconds_per_move": 5 } } aesthetic = AestheticSettings() aesthetic.from_config_data(config) self.assertEqual(aesthetic.level_space_aesthetic.rectangle_count, 1) self.assertEqual(aesthetic.level_space_aesthetic.rectangle_min, 2) self.assertEqual(aesthetic.level_space_aesthetic.rectangle_max, 3) self.assertEqual(aesthetic.level_space_aesthetic.noise_percentage, 0.4) self.assertEqual( aesthetic.level_space_aesthetic.noise_empty_percentage, 0.6) self.assertEqual(aesthetic.level_space_aesthetic.x_mirror_probability, 0.7) self.assertEqual(aesthetic.level_space_aesthetic.y_mirror_probability, 0.8) self.assertEqual(aesthetic.mission_graph_aesthetic.max_depth, 1) self.assertEqual(aesthetic.mission_graph_aesthetic.min_depth, 2) self.assertEqual(aesthetic.mission_graph_aesthetic.branch_probability, [0.3, 0.4]) self.assertEqual( aesthetic.mission_graph_aesthetic.max_multi_lock_count, 5) self.assertEqual( aesthetic.mission_graph_aesthetic.max_locks_per_multi_lock, 6) self.assertEqual( aesthetic.mission_graph_aesthetic.collectable_in_room_probability, 0.7) self.assertEqual( aesthetic.mission_graph_aesthetic.insert_room_probability, 0.8) self.assertEqual( aesthetic.mission_graph_aesthetic.key_is_sokoban_probability, 0.9) self.assertEqual(aesthetic.tweaker_aesthetic.should_fill_unused_space, 0.5) self.assertEqual( aesthetic.mission_aesthetic.hazard_spread_probability[Tiles.water], 0.1) self.assertEqual( aesthetic.mission_aesthetic.hazard_spread_probability[Tiles.fire], 0.2) self.assertEqual( aesthetic.mission_aesthetic.single_lock_is_hazard_probability, 0.3) self.assertEqual(aesthetic.mission_aesthetic.max_seconds_per_move, 4) self.assertEqual(aesthetic.mission_aesthetic.min_seconds_per_move, 5)
def add_level(self, id, seed): settings = ["0"] * len(AestheticSettings.get_csv_data_paths()) line = [str(id), str(int(seed))] + settings + ["0", "0"] self.file_data += Ratings.CSV_SEPARATOR.join(line) + "\n"