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 = tw_textlabs.generator.make_game(options) if args.no_quest: game.quests = [] game_name = "neverending" path = pjoin(args.output, game_name + ".ulx") options = tw_textlabs.GameOptions() options.path = path options.force_recompile = True game_file = tw_textlabs.generator.compile_game(game, options) return game_file
def test_quest_winning_condition(): g_rng.set_seed(2018) map_ = make_small_map(n_rooms=5, possible_door_states=["open"]) world = World.from_map(map_) def _rule_to_skip(rule): # Examine, look and inventory shouldn't be used for chaining. if rule.name.startswith("look"): return True if rule.name.startswith("inventory"): return True if rule.name.startswith("examine"): return True return False for rule in KnowledgeBase.default().rules.values(): if _rule_to_skip(rule): continue options = ChainingOptions() options.backward = True options.max_depth = 1 options.create_variables = True options.rules_per_depth = [[rule]] options.restricted_types = {"r"} chain = sample_quest(world.state, options) assert len(chain.actions) > 0, rule.name event = Event(chain.actions) quest = Quest(win_events=[event]) # Set the initial state required for the quest. tmp_world = World.from_facts(chain.initial_state.facts) game = make_game_with(tmp_world, [quest], make_grammar({})) if tmp_world.player_room is None: # Randomly place the player in the world since # the action doesn't care about where the player is. tmp_world.set_player_room() game_name = "test_quest_winning_condition_" + rule.name.replace( "/", "_") with make_temp_directory(prefix=game_name) as tmpdir: game_file = _compile_game(game, path=tmpdir) env = tw_textlabs.start(game_file) env.reset() game_state, _, done = env.step("look") assert not done assert not game_state.has_won game_state, _, done = env.step(event.commands[0]) assert done assert game_state.has_won
def test_generating_quests(self): g_rng.set_seed(2018) map_ = make_small_map(n_rooms=5, possible_door_states=["open"]) world = World.from_map(map_) def _rule_to_skip(rule): # Examine, look and inventory shouldn't be used for chaining. if rule.name.startswith("look"): return True if rule.name.startswith("inventory"): return True if rule.name.startswith("examine"): return True return False for max_depth in range(1, 3): for rule in KnowledgeBase.default().rules.values(): if _rule_to_skip(rule): continue options = ChainingOptions() options.backward = True options.max_depth = max_depth options.create_variables = True options.rules_per_depth = [[rule]] options.restricted_types = {"r"} chain = sample_quest(world.state, options) # Build the quest by providing the actions. actions = chain.actions assert len(actions) == max_depth, rule.name quest = Quest(win_events=[Event(actions)]) tmp_world = World.from_facts(chain.initial_state.facts) state = tmp_world.state for action in actions: assert not quest.is_winning(state) state.apply(action) assert quest.is_winning(state) # Build the quest by only providing the winning conditions. quest = Quest( win_events=[Event(conditions=actions[-1].postconditions)]) tmp_world = World.from_facts(chain.initial_state.facts) state = tmp_world.state for action in actions: assert not quest.is_winning(state) state.apply(action) assert quest.is_winning(state)
def test_making_game_with_names_to_exclude(): g_rng.set_seed(42) with make_temp_directory(prefix="test_render_wrapper") as tmpdir: options = tw_textlabs.GameOptions() options.path = tmpdir options.nb_rooms = 2 options.nb_objects = 20 options.quest_length = 3 options.quest_breadth = 3 options.seeds = 123 game_file1, game1 = tw_textlabs.make(options) options2 = options.copy() game1_objects_names = [ info.name for info in game1.infos.values() if info.name is not None ] options2.grammar.names_to_exclude = game1_objects_names game_file2, game2 = tw_textlabs.make(options2) game2_objects_names = [ info.name for info in game2.infos.values() if info.name is not None ] assert len(set(game1_objects_names) & set(game2_objects_names)) == 0
def test_used_names_is_updated(verbose=False): # Make generation throughout the framework reproducible. g_rng.set_seed(1234) # Generate a map that's shape in a cross with room0 in the middle. P = Variable('P') r = Variable('r_0', 'r') k1 = Variable('k_1', 'k') k2 = Variable('k_2', 'k') c1 = Variable('c_1', 'c') c2 = Variable('c_2', 'c') facts = [ Proposition('at', [P, r]), Proposition('at', [k1, r]), Proposition('at', [k2, r]), Proposition('at', [c1, r]), Proposition('at', [c2, r]), Proposition('match', [k1, c1]), Proposition('match', [k2, c2]) ] world = World.from_facts(facts) world.set_player_room() # Set start room to the middle one. world.populate_room(10, world.player_room) # Add objects to the starting room. # Generate the world representation. grammar = tw_textlabs.generator.make_grammar({}, rng=np.random.RandomState(42)) for k, v in grammar.grammar.items(): grammar.grammar[k] = v[:2] # Force reusing variables. game = tw_textlabs.generator.make_game_with(world, [], grammar) for entity_infos in game.infos.values(): if entity_infos.name is None: continue assert entity_infos.name in grammar.used_names
def test_blend_instructions(verbose=False): # Make generation throughout the framework reproducible. g_rng.set_seed(1234) M = tw_textlabs.GameMaker() r1 = M.new_room() r2 = M.new_room() M.set_player(r1) path = M.connect(r1.north, r2.south) path.door = M.new(type="d", name="door") M.add_fact("locked", path.door) key = M.new(type="k", name="key") M.add_fact("match", key, path.door) r1.add(key) quest = M.set_quest_from_commands([ "take key", "unlock door with key", "open door", "go north", "close door", "lock door with key", "drop key" ]) game = M.build() grammar1 = tw_textlabs.generator.make_grammar( {"blend_instructions": False}, rng=np.random.RandomState(42)) grammar2 = tw_textlabs.generator.make_grammar( {"blend_instructions": True}, rng=np.random.RandomState(42)) quest.desc = None game.change_grammar(grammar1) quest1 = quest.copy() quest.desc = None game.change_grammar(grammar2) quest2 = quest.copy() assert len(quest1.desc) > len(quest2.desc)
def test_cannot_win_or_lose_a_quest_twice(): g_rng.set_seed(2018) M = tw_textlabs.GameMaker() # Create a 'bedroom' room. R1 = M.new_room("bedroom") R2 = M.new_room("kitchen") M.set_player(R1) path = M.connect(R1.east, R2.west) path.door = M.new(type='d', name='wooden door') path.door.add_property("open") carrot = M.new(type='f', name='carrot') lettuce = M.new(type='f', name='lettuce') M.inventory.add(carrot) M.inventory.add(lettuce) # Add a closed chest in R2. chest = M.new(type='c', name='chest') chest.add_property("open") R2.add(chest) # The goals event_carrot_in_closed_chest = Event(conditions={ M.new_fact("in", carrot, chest), M.new_fact("closed", chest) }) event_drop_carrot_R1 = Event(conditions={M.new_fact("at", carrot, R1)}) event_drop_carrot_R2 = Event(conditions={M.new_fact("at", carrot, R2)}) quest1 = Quest(win_events=[event_carrot_in_closed_chest], fail_events=[event_drop_carrot_R1, event_drop_carrot_R2]) event_lettuce_in_closed_chest = Event(conditions={ M.new_fact("in", lettuce, chest), M.new_fact("closed", chest) }) event_drop_lettuce_R1 = Event(conditions={M.new_fact("at", lettuce, R1)}) event_drop_lettuce_R2 = Event(conditions={M.new_fact("at", lettuce, R2)}) quest2 = Quest(win_events=[event_lettuce_in_closed_chest], fail_events=[event_drop_lettuce_R1, event_drop_lettuce_R2]) M.quests = [quest1, quest2] game = M.build() game_name = "test_cannot_win_or_lose_a_quest_twice" with make_temp_directory(prefix=game_name) as tmpdir: game_file = _compile_game(game, path=tmpdir) env = tw_textlabs.start(game_file) # Make sure we do not rely on the quest progression to # determine if the game was lost. assert not env._compute_intermediate_reward # Complete quest1 then fail it. env.reset() game_state, score, done = env.step("go east") assert score == 0 game_state, score, done = env.step("insert carrot into chest") assert score == 0 game_state, score, done = env.step("close chest") assert score == 1 assert not done game_state, score, done = env.step("open chest") # Re-completing quest1 doesn't award more points. game_state, score, done = env.step("close chest") assert score == 1 assert not done game_state, score, done = env.step("open chest") game_state, score, done = env.step("take carrot from chest") game_state, score, done = env.step("drop carrot") assert score == 1 assert not done # Then fail quest2. game_state, score, done = env.step("drop lettuce") assert done assert game_state.has_lost assert not game_state.has_won env.reset() game_state, score, done = env.step("go east") game_state, score, done = env.step("insert carrot into chest") game_state, score, done = env.step("insert lettuce into chest") game_state, score, done = env.step("close chest") assert score == 2 assert done assert not game_state.has_lost assert game_state.has_won
def test_quest_with_multiple_winning_and_losing_conditions(): g_rng.set_seed(2018) M = tw_textlabs.GameMaker() # Create a 'bedroom' room. R1 = M.new_room("bedroom") R2 = M.new_room("kitchen") M.set_player(R1) path = M.connect(R1.east, R2.west) path.door = M.new(type='d', name='wooden door') path.door.add_property("open") carrot = M.new(type='f', name='carrot') lettuce = M.new(type='f', name='lettuce') M.inventory.add(carrot) M.inventory.add(lettuce) # Add a closed chest in R2. chest = M.new(type='c', name='chest') chest.add_property("open") R2.add(chest) # The goal quest = Quest( win_events=[ Event(conditions={ M.new_fact("in", carrot, chest), M.new_fact("closed", chest) }), Event(conditions={M.new_fact("eaten", lettuce)}) ], fail_events=[ Event(conditions={ M.new_fact("in", lettuce, chest), M.new_fact("closed", chest) }), Event(conditions={M.new_fact("eaten", carrot)}) ]) M.quests = [quest] game = M.build() game_name = "test_quest_with_multiple_winning_and_losing_conditions" with make_temp_directory(prefix=game_name) as tmpdir: game_file = _compile_game(game, path=tmpdir) env = tw_textlabs.start(game_file) # Make sure we do not rely on the quest progression to # determine if the game was lost. assert not env._compute_intermediate_reward # Failing - 1 env.reset() game_state, _, done = env.step("eat carrot") assert done assert game_state.has_lost assert not game_state.has_won # Failing - 2 env.reset() game_state, _, done = env.step("go east") assert not done game_state, _, done = env.step("insert lettuce into chest") assert not done game_state, _, done = env.step("close chest") assert done assert game_state.has_lost assert not game_state.has_won # Failing - 1 env.reset() game_state, _, done = env.step("eat lettuce") assert done assert not game_state.has_lost assert game_state.has_won # Winning - 2 env.reset() game_state, _, done = env.step("go east") assert not done game_state, _, done = env.step("insert carrot into chest") assert not done game_state, _, done = env.step("close chest") assert done assert not game_state.has_lost assert game_state.has_won
def setUpClass(cls): g_rng.set_seed(201809) cls.game = build_test_game() cls.tmpdir = tempfile.mkdtemp() cls.game_file = _compile_game(cls.game, folder=cls.tmpdir)