def test_limit_wrapper(): # Make a game for testing purposes. max_episode_steps = 7 num_nodes = 3 num_items = 10 options = textworld.GameOptions() options.seeds = 1234 options.nb_rooms = num_nodes options.nb_objects = num_items options.quest_length = 3 options.grammar.theme = "house" options.grammar.include_adj = True game = textworld.generator.make_game(options) game_name = "test_limit_wrapper" with make_temp_directory(prefix=game_name) as tmpdir: options.path = tmpdir game_file = compile_game(game, options) env = textworld.start(game_file) env = Limit(env, max_episode_steps) state = env.reset() done = False assert state["moves"] == 0 for no_step in range(1, max_episode_steps + 1): assert not done state, score, done = env.step("wait") assert state["moves"] == no_step assert done
def test_html_viewer(): # Integration test for visualization service num_nodes = 3 num_items = 10 options = textworld.GameOptions() options.seeds = 1234 options.nb_rooms = num_nodes options.nb_objects = num_items options.quest_length = 3 options.grammar.theme = "house" options.grammar.include_adj = True game = textworld.generator.make_game(options) game_name = "test_html_viewer_wrapper" with make_temp_directory(prefix=game_name) as tmpdir: game_file = compile_game(game, path=tmpdir) env = textworld.start(game_file) env = HtmlViewer(env, open_automatically=False, port=8080) env.reset() # Cause rendering to occur. # options.binary_location = "/bin/chromium" driver = get_webdriver() driver.get("http://127.0.0.1:8080") nodes = driver.find_elements_by_class_name("node") assert len(nodes) == num_nodes items = driver.find_elements_by_class_name("item") objects = [obj for obj in game.world.objects if obj.type != "I"] assert len(items) == len(objects) env.close() driver.close()
def setUpClass(cls): g_rng.set_seed(201809) cls.tmpdir = tempfile.mkdtemp() cls.options = textworld.GameOptions() cls.options.path = cls.tmpdir cls.options.file_ext = ".ulx" cls.game, cls.game_file = testing.build_and_compile_game(cls.options)
def test_batch_env(): batch_size = 4 max_episode_steps = 13 with make_temp_directory() as tmpdir: options = textworld.GameOptions() options.path = tmpdir options.seeds = 1234 options.file_ext = ".ulx" game_file1, game1 = textworld.make(options) options.seeds = 4321 options.file_ext = ".z8" game_file2, game2 = textworld.make(options) env_options = EnvInfos(inventory=True, description=True, admissible_commands=True) env_id = textworld.gym.register_games([game_file1, game_file1, game_file2, game_file2], request_infos=env_options, batch_size=batch_size, max_episode_steps=max_episode_steps, name="test-auto-reset", asynchronous=True, auto_reset=True) env = gym.make(env_id) env.reset() # env.close() del env print("OKAY")
def test_registering_zmachine_game(self): with make_temp_directory() as tmpdir: options = textworld.GameOptions() options.path = tmpdir options.seeds = 1234 options.file_ext = ".z8" gamefile, game = textworld.make(options) os.remove(gamefile.replace( ".z8", ".json")) # Simulate an non-TextWorld Z-Machine game. env_options = EnvInfos(extras=["walkthrough"]) env_id = textworld.gym.register_game(gamefile, env_options, name="test-zmachine") env = gym.make(env_id) obs, infos = env.reset() assert len(infos) == len(env_options) for cmd in game.metadata["walkthrough"]: obs, score, done, infos = env.step(cmd) assert done assert score == 1 env.close()
def test_playing_generated_games(): NB_GAMES = 10 rng = np.random.RandomState(1234) for i in range(NB_GAMES): # Sample game specs. world_size = rng.randint(1, 10) nb_objects = rng.randint(0, 20) quest_length = rng.randint(2, 5) quest_breadth = rng.randint(3, 7) game_seed = rng.randint(0, 65365) with make_temp_directory(prefix="test_play_generated_games") as tmpdir: options = textworld.GameOptions() options.nb_rooms = world_size options.nb_objects = nb_objects options.quest_length = quest_length options.quest_breadth = quest_breadth options.seeds = game_seed game_file, game = textworld.make(options, path=tmpdir) # Solve the game using WalkthroughAgent. agent = textworld.agents.WalkthroughAgent() textworld.play(game_file, agent=agent, silent=True) # Play the game using RandomAgent and make sure we can always finish the # game by following the winning policy. env = textworld.start(game_file) agent = textworld.agents.RandomCommandAgent() agent.reset(env) env.compute_intermediate_reward() env.seed(4321) game_state = env.reset() max_steps = 100 reward = 0 done = False for step in range(max_steps): command = agent.act(game_state, reward, done) game_state, reward, done = env.step(command) if done: msg = "Finished before playing `max_steps` steps because of command '{}'.".format(command) if game_state.has_won: msg += " (winning)" assert len(game_state._game_progression.winning_policy) == 0 if game_state.has_lost: msg += " (losing)" assert game_state._game_progression.winning_policy is None print(msg) break # Make sure the game can still be solved. winning_policy = game_state._game_progression.winning_policy assert len(winning_policy) > 0 assert game_state.state.is_sequence_applicable(winning_policy)
def test_batch(): batch_size = 5 with make_temp_directory() as tmpdir: options = textworld.GameOptions() options.path = tmpdir options.seeds = 1234 gamefile, game = textworld.make(options) env_options = EnvInfos(inventory=True, description=True, admissible_commands=True) env_id = textworld.gym.register_games([gamefile], env_options, name="test-batch") env_id = textworld.gym.make_batch(env_id, batch_size) env = gym.make(env_id) obs, infos = env.reset() assert len(obs) == batch_size assert len(set(obs)) == 1 # All the same game. assert len(infos) == len(env_options) for values in infos.values(): assert len(values) == batch_size for cmd in game.main_quest.commands: obs, scores, dones, infos = env.step([cmd] * batch_size) env.close() assert all(dones) assert all(score == 1 for score in scores)
def test_making_a_game_without_a_quest(play_the_game=False): rng_map = np.random.RandomState(1234) map_ = textworld.generator.make_small_map(1, rng_map) world = World.from_map(map_) world.set_player_room() # First room generated (i.e. the only one). rng_objects = np.random.RandomState(1234) nb_objects = 10 world.populate(nb_objects, rng=rng_objects) quests = [] # Define the grammar we'll use. rng_grammar = np.random.RandomState(1234) grammar_flags = { "theme": "house", "include_adj": False, "only_last_action": True, "blend_instructions": True, "blend_descriptions": True, "refer_by_name_only": True, "instruction_extension": [], } grammar = textworld.generator.make_grammar(grammar_flags, rng=rng_grammar) # Generate the world representation. game = textworld.generator.make_game_with(world, quests, grammar) with make_temp_directory(prefix="test_render_wrapper") as tmpdir: options = textworld.GameOptions() options.path = tmpdir game_file = compile_game(game, options) if play_the_game: textworld.play(game_file)
def test_batch_sync(): batch_size = 5 with make_temp_directory() as tmpdir: options = textworld.GameOptions() options.path = tmpdir options.seeds = 1234 options.file_ext = ".ulx" gamefile1, game = textworld.make(options) options.file_ext = ".z8" gamefile2, game = textworld.make(options) env_options = EnvInfos(inventory=True, description=True, admissible_commands=True, extras=["walkthrough"]) env_id = textworld.gym.register_games([gamefile1, gamefile2], request_infos=env_options, batch_size=batch_size, name="test-batch", asynchronous=False) env = gym.make(env_id) obs, infos = env.reset() assert len(obs) == batch_size assert len(set(obs)) == 1 # All the same game. assert len(infos) == len(env_options) for values in infos.values(): assert len(values) == batch_size for cmds in infos.get("extra.walkthrough"): obs, scores, dones, infos = env.step(cmds) env.close() assert all(dones) assert all(score == 1 for score in scores)
def test_filter_wrapper(): # Make a game for testing purposes. num_nodes = 3 num_items = 10 options = textworld.GameOptions() options.seeds = 1234 options.nb_rooms = num_nodes options.nb_objects = num_items options.quest_length = 3 options.grammar.theme = "house" options.grammar.include_adj = True game = textworld.generator.make_game(options) game_name = "test_filter_wrapper" with make_temp_directory(prefix=game_name) as tmpdir: options.path = tmpdir game_file = compile_game(game, options) env = textworld.start(game_file) env_options = EnvInfos() for attr in env_options.__slots__: if attr == "extras": continue # Skip since it's not a boolean attribute. setattr(env_options, attr, True) assert len(env_options) == len(env_options.__slots__) - 1 assert len(env_options) == len(env_options.basics) env = Filter(env, env_options) _, infos = env.reset() for attr in env_options.basics: assert attr in infos
def generate_never_ending_game(args): g_rng.set_seed(args.seed) msg = "--max-steps {} --nb-objects {} --nb-rooms {} --quest-length {} --quest-breadth {} --seed {}" print( msg.format(args.max_steps, args.nb_objects, args.nb_rooms, args.quest_length, args.quest_breadth, g_rng.seed)) print("Generating game...") options = GameOptions() options.seeds = g_rng.seed options.nb_rooms = args.nb_rooms options.nb_objects = args.nb_objects options.quest_length = args.quest_length options.quest_breadth = args.quest_breadth game = textworld.generator.make_game(options) if args.no_quest: game.quests = [] game_name = "neverending" path = pjoin(args.output, game_name + ".ulx") options = textworld.GameOptions() options.path = path options.force_recompile = True game_file = textworld.generator.compile_game(game, options) return game_file
def test_playing_a_game(): for ext in [".ulx", ".z8"]: with make_temp_directory(prefix="test_tw-play") as tmpdir: options = textworld.GameOptions() options.file_ext = ext options.path = tmpdir options.nb_rooms = 5 options.nb_objects = 10 options.quest_length = 5 options.quest_breadth = 2 options.seeds = 1234 game_file, _ = textworld.make(options) command = [ "tw-play", "--max-steps", "100", "--mode", "random", game_file ] assert check_call(command) == 0 command = [ "tw-play", "--max-steps", "100", "--mode", "random-cmd", game_file ] assert check_call(command) == 0 command = [ "tw-play", "--max-steps", "100", "--mode", "walkthrough", game_file ] assert check_call(command) == 0
def setUp(self): self.tmpdir = tempfile.mkdtemp(prefix="test_textworld") options = textworld.GameOptions() options.nb_rooms = 5 options.nb_objects = 10 options.quest_length = 10 options.seeds = 1234 self.game_file, self.game = textworld.make(options, path=self.tmpdir)
def test_making_treasure_hunter_games(): for level in range(1, 30 + 1): options = textworld.GameOptions() options.seeds = 1234 settings = {"level": level} game = treasure_hunter.make(settings, options) assert len(game.quests[0].commands) == game.metadata["quest_length"], "Level {}".format(level) assert len(game.world.rooms) == game.metadata["world_size"], "Level {}".format(level)
def setUpClass(cls): cls.tmpdir = pjoin(tempfile.mkdtemp(prefix="test_textworld"), "") options = textworld.GameOptions() options.path = cls.tmpdir options.nb_rooms = 5 options.nb_objects = 10 options.quest_length = 10 options.seeds = 1234 cls.game_file, cls.game = textworld.make(options) options.file_ext = ".z8" cls.game_file_z8, _ = textworld.make(options)
def _make_game(): options = textworld.GameOptions() options.seeds = 1234 options.nb_rooms = 3 options.nb_objects = 10 options.quest_length = 3 options.grammar.theme = "house" options.grammar.include_adj = True game = textworld.generator.make_game(options) return game
def test_playing_generated_games(): NB_GAMES = 10 rng = np.random.RandomState(1234) for i in range(NB_GAMES): # Sample game specs. world_size = rng.randint(1, 10) nb_objects = rng.randint(0, 20) quest_depth = rng.randint(2, 5) quest_breadth = rng.randint(3, 7) game_seed = rng.randint(0, 65365) with make_temp_directory(prefix="test_play_generated_games") as tmpdir: options = textworld.GameOptions() options.path = tmpdir options.nb_rooms = world_size options.nb_objects = nb_objects options.chaining.max_depth = quest_depth options.chaining.max_breadth = quest_breadth options.seeds = game_seed game_file, game = textworld.make(options) # Solve the game using WalkthroughAgent. agent = textworld.agents.WalkthroughAgent() textworld.play(game_file, agent=agent, silent=True) # Play the game using RandomAgent and make sure we can always finish the # game by following the winning policy. env = textworld.start(game_file) env.infos.policy_commands = True env.infos.game = True agent = textworld.agents.RandomCommandAgent() agent.reset(env) env.seed(4321) game_state = env.reset() max_steps = 100 reward = 0 done = False for step in range(max_steps): command = agent.act(game_state, reward, done) game_state, reward, done = env.step(command) if done: assert game_state._winning_policy is None game_state, reward, done = env.reset(), 0, False # Make sure the game can still be solved. winning_policy = game_state._winning_policy assert len(winning_policy) > 0 assert game_state._game_progression.state.is_sequence_applicable( winning_policy)
def setUpClass(cls): cls.tmpdir = pjoin(tempfile.mkdtemp(prefix="test_textworld_gym"), "") options = textworld.GameOptions() options.path = cls.tmpdir options.seeds = 1234 cls.gamefile1, cls.game1 = textworld.make(options) options.seeds = 4321 cls.gamefile2, cls.game2 = textworld.make(options) options.file_ext = ".z8" options.seeds = 1234 cls.gamefile1_z8, _ = textworld.make(options)
def setUpClass(cls): g_rng.set_seed(201809) cls.tmpdir = tempfile.mkdtemp() cls.options = textworld.GameOptions() cls.options.path = pjoin(cls.tmpdir, "tw-game.z8") cls.game, cls.game_file = testing.build_and_compile_game(cls.options) cls.infos = EnvInfos( max_score=True, score=True, won=True, lost=True, )
def setUpClass(cls): cls.tmpdir = pjoin(tempfile.mkdtemp(prefix="test_tw_extract"), "") options = textworld.GameOptions() options.path = cls.tmpdir options.nb_rooms = 5 options.nb_objects = 10 options.quest_length = 5 options.quest_breadth = 2 options.seeds = 1234 cls.game_file1, cls.game1 = textworld.make(options) options.seeds = 12345 options.file_ext = ".z8" cls.game_file2, cls.game2 = textworld.make(options)
def test_making_cooking_games(): options = textworld.GameOptions() options.seeds = 1234 nb_ingredients = 2 settings = { "recipe": nb_ingredients, "take": 1, "open": True, "open": True, "cook": True, "cut": False, "drop": False, "go": 6, "recipe_seed": 123, "split": "valid" } game = cooking.make(settings, options) assert len(game.metadata["ingredients"]) == nb_ingredients # Change only the recipe. options = textworld.GameOptions() options.seeds = 1234 settings["recipe_seed"] = 321 game2 = cooking.make(settings, options) # Recipe's ingredients should be different. assert game.metadata["ingredients"] != game2.metadata["ingredients"] assert game.metadata["entities"] == game2.metadata["entities"] # The rest of the world should stay the same. POSITIONNING_FACTS = ("in", "on", "at", "west_of", "east_of", "south_of", "north_of") differing_facts = set(game.world.facts) - set(game2.world.facts) assert [ pred for pred in differing_facts if pred.name in POSITIONNING_FACTS ] == []
def setUpClass(cls): g_rng.set_seed(201809) cls.tmpdir = tempfile.mkdtemp() cls.options = textworld.GameOptions() cls.options.path = pjoin(cls.tmpdir, "tw-game.ulx") cls.game, cls.gamefile_ulx = testing.build_and_compile_game( cls.options) cls.options.path = pjoin(cls.tmpdir, "tw-game.z8") cls.gamefile_z8 = textworld.generator.compile_game( cls.game, cls.options) cls.infos = EnvInfos( max_score=True, objective=True, )
def setUpClass(cls): g_rng.set_seed(201809) cls.tmpdir = tempfile.mkdtemp() cls.options = textworld.GameOptions() cls.options.path = pjoin(cls.tmpdir, "tw-game.ulx") cls.game, cls.gamefile_ulx = testing.build_and_compile_game( cls.options) cls.options.path = pjoin(cls.tmpdir, "tw-game.z8") cls.gamefile_z8 = textworld.generator.compile_game( cls.game, cls.options) cls.infos = EnvInfos(facts=True, policy_commands=True, admissible_commands=True, intermediate_reward=True)
def setUpClass(cls): g_rng.set_seed(201809) cls.tmpdir = tempfile.mkdtemp() cls.options = textworld.GameOptions() cls.gamefile = pjoin(cls.tmpdir, "tw-game.json") cls.game = testing.build_game(cls.options) cls.game.save(cls.gamefile) cls.infos = EnvInfos( facts=True, policy_commands=True, admissible_commands=True, intermediate_reward=True )
def setUpClass(cls): g_rng.set_seed(201809) cls.tmpdir = tempfile.mkdtemp() cls.options = textworld.GameOptions() cls.options.path = pjoin(cls.tmpdir, "tw-game.ulx") cls.game, cls.gamefile_ulx = testing.build_and_compile_game(cls.options) cls.options.path = pjoin(cls.tmpdir, "tw-game.z8") cls.gamefile_z8 = textworld.generator.compile_game(cls.game, cls.options) cls.infos = EnvInfos( inventory=True, description=True, score=True, moves=True, won=True, lost=True, )
def test_making_game_is_reproducible_with_seed(): with make_temp_directory(prefix="test_render_wrapper") as tmpdir: options = textworld.GameOptions() options.nb_rooms = 2 options.nb_objects = 20 options.quest_length = 3 options.quest_breadth = 3 options.seeds = 123 game_file1, game1 = textworld.make(options, path=tmpdir) options2 = options.copy() game_file2, game2 = textworld.make(options2, path=tmpdir) assert game_file1 == game_file2 assert game1 == game2 # Make sure they are not the same Python objects. assert id(game1) != id(game2)
def test_no_quest_game(self): game_name = "tw-no_quest_game" with make_temp_directory(prefix=game_name) as tmpdir: for ext, env_class in [(".ulx", GitGlulxEnv), (".z8", JerichoEnv)]: options = textworld.GameOptions() options.path = pjoin(tmpdir, game_name + ext) game, gamefile = testing.build_and_compile_no_quest_game(options) env = TWInform7(env_class()) env.load(gamefile) game_state = env.reset() assert not game_state.game_ended game_state, _, done = env.step("look") assert not done assert not game_state.game_ended
def test_making_coin_collector(): expected = { 1: {"quest_length": 1, "nb_rooms": 1}, 100: {"quest_length": 100, "nb_rooms": 100}, 101: {"quest_length": 1, "nb_rooms": 2}, 200: {"quest_length": 100, "nb_rooms": 200}, 201: {"quest_length": 1, "nb_rooms": 3}, 300: {"quest_length": 100, "nb_rooms": 300}, } for level in [1, 100, 101, 200, 201, 300]: options = textworld.GameOptions() options.seeds = 1234 settings = {"level": level} game = coin_collector.make(settings, options) assert len(game.quests[0].commands) == expected[level]["quest_length"] assert len(game.world.rooms) == expected[level]["nb_rooms"]
def test_game_comparison(): options = textworld.GameOptions() options.nb_rooms = 5 options.nb_objects = 5 options.chaining.max_depth = 2 options.chaining.max_breadth = 2 options.seeds = {"map": 1, "objects": 2, "quest": 3, "grammar": 4} game1 = textworld.generator.make_game(options) game2 = textworld.generator.make_game(options) assert game1 == game2 # Test __eq__ assert game1 in {game2} # Test __hash__ options = options.copy() options.seeds = {"map": 4, "objects": 3, "quest": 2, "grammar": 1} game3 = textworld.generator.make_game(options) assert game1 != game3
def test_extract_entities(): with make_temp_directory(prefix="test_extract_entities") as tmpdir: options = textworld.GameOptions() options.path = tmpdir options.nb_rooms = 5 options.nb_objects = 10 options.quest_length = 5 options.quest_breadth = 2 options.seeds = 1234 game_file, _ = textworld.make(options) outfile = pjoin(tmpdir, "entities.txt") command = ["tw-extract", "entities", game_file, "--output", outfile] stdout = check_output(command).decode() assert os.path.isfile(outfile) nb_entities = len(open(outfile).readlines()) assert "Found {}".format(nb_entities) in stdout