コード例 #1
0
def main():
    args = parse_args()

    game = Game.load(args.game)

    # Sample quests.
    rng = np.random.RandomState(args.seed)
    chains = []
    rules_per_depth = {}

    for i in range(args.nb_quests):
        chain = sample_quest(game.world.state,
                             rng,
                             max_depth=args.quest_length,
                             allow_partial_match=False,
                             exceptions=[],
                             rules_per_depth=rules_per_depth,
                             backward=False)
        chains.append(chain)

    print_chains(chains, verbose=args.verbose)
    actions_tree = build_tree_from_chains(chains)

    # Convert tree to networkx graph/tree
    filename = "sample_tree.svg"
    G, labels = actions_tree.to_networkx()
    if len(G) > 0:
        tree = nx.bfs_tree(G, actions_tree.no)
        save_graph_to_svg(tree, labels, filename, backward=False)
    else:
        try:
            os.remove(filename)
        except:
            pass
コード例 #2
0
ファイル: test_game.py プロジェクト: vishalbelsare/TextWorld
    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.max_length = 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)
コード例 #3
0
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 = textworld.start(game_file)
            env.reset()
            game_state, _, done = env.step("look")
            assert not done
            assert not game_state.won

            game_state, _, done = env.step(event.commands[0])
            assert done
            assert game_state.won
コード例 #4
0
def make_game(options: GameOptions) -> Game:
    """
    Make a game (map + objects + quest).

    Arguments:
        options:
            For customizing the game generation (see
            :py:class:`textworld.GameOptions <textworld.generator.game.GameOptions>`
            for the list of available options).

    Returns:
        Generated game.
    """
    rngs = options.rngs

    # Generate only the map for now (i.e. without any objects)
    world = make_world(options.nb_rooms, nb_objects=0, rngs=rngs)

    # Sample a quest.
    chaining_options = options.chaining.copy()
    # Go, examine, look and inventory shouldn't be used for chaining.
    exclude = ["go.*", "examine.*", "look.*", "inventory.*"]
    chaining_options.rules_per_depth = [
        options.kb.rules.get_matching(".*", exclude=exclude)
    ]
    chaining_options.backward = True
    chaining_options.create_variables = True
    chaining_options.rng = rngs['quest']
    chaining_options.restricted_types = {"r", "d"}
    chain = sample_quest(world.state, chaining_options)

    subquests = []
    for i in range(1, len(chain.nodes)):
        if chain.nodes[i].breadth != chain.nodes[i - 1].breadth:
            event = Event(chain.actions[:i])
            subquests.append(Quest(win_events=[event]))

    event = Event(chain.actions)
    subquests.append(Quest(win_events=[event]))

    # Set the initial state required for the quest.
    world.state = chain.initial_state

    # Add distractors objects (i.e. not related to the quest)
    world.populate(options.nb_objects, rng=rngs['objects'])

    grammar = make_grammar(options.grammar, rng=rngs['grammar'])
    game = make_game_with(world, subquests, grammar)
    game.change_grammar(grammar)
    game.metadata["uuid"] = options.uuid

    return game
コード例 #5
0
def make_quest(world, quest_length, rng=None, rules_per_depth=(), backward=False):
    state = world
    if hasattr(world, "state"):
        state = world.state

    rng = g_rng.next() if rng is None else rng

    # Sample a quest according to quest_length.
    options = ChainingOptions()
    options.backward = backward
    options.max_depth = quest_length
    options.rng = rng
    options.rules_per_depth = rules_per_depth
    chain = sample_quest(state, options)
    return Quest(chain.actions)
コード例 #6
0
def make_game(world_size: int,
              nb_objects: int,
              quest_length: int,
              grammar_flags: Mapping = {},
              rngs: Optional[Dict[str, RandomState]] = None) -> Game:
    """
    Make a game (map + objects + quest).

    Arguments:
        world_size: Number of rooms in the world.
        nb_objects: Number of objects in the world.
        quest_length: Minimum nb. of actions the quest requires to be completed.
        grammar_flags: Options for the grammar.

    Returns:
        Generated game.
    """
    if rngs is None:
        rngs = {}
        rng = g_rng.next()
        rngs['rng_map'] = RandomState(rng.randint(65635))
        rngs['rng_objects'] = RandomState(rng.randint(65635))
        rngs['rng_quest'] = RandomState(rng.randint(65635))
        rngs['rng_grammar'] = RandomState(rng.randint(65635))

    # Generate only the map for now (i.e. without any objects)
    world = make_world(world_size, nb_objects=0, rngs=rngs)

    # Sample a quest according to quest_length.
    chain = sample_quest(world.state,
                         rngs['rng_quest'],
                         max_depth=quest_length,
                         nb_retry=20,
                         allow_partial_match=True,
                         backward=True,
                         exceptions=["r"])
    quest = Quest([c.action for c in chain])

    # Set the initial state required for the quest.
    world.state = chain[0].state

    # Add distractors objects (i.e. not related to the quest)
    world.populate(nb_objects, rng=rngs['rng_objects'])

    grammar = make_grammar(grammar_flags, rng=rngs['rng_grammar'])
    game = make_game_with(world, [quest], grammar)
    return game
コード例 #7
0
ファイル: __init__.py プロジェクト: sharmer156/TextWorld
def make_game(world_size: int,
              nb_objects: int,
              quest_length: int,
              grammar_flags: Mapping = {},
              rngs: Optional[Dict[str, RandomState]] = None) -> Game:
    """
    Make a game (map + objects + quest).

    Arguments:
        world_size: Number of rooms in the world.
        nb_objects: Number of objects in the world.
        quest_length: Minimum nb. of actions the quest requires to be completed.
        grammar_flags: Options for the grammar.

    Returns:
        Generated game.
    """
    if rngs is None:
        rngs = {}
        rng = g_rng.next()
        rngs['rng_map'] = RandomState(rng.randint(65635))
        rngs['rng_objects'] = RandomState(rng.randint(65635))
        rngs['rng_quest'] = RandomState(rng.randint(65635))
        rngs['rng_grammar'] = RandomState(rng.randint(65635))

    # Generate only the map for now (i.e. without any objects)
    world = make_world(world_size, nb_objects=0, rngs=rngs)

    # Sample a quest according to quest_length.
    options = ChainingOptions()
    options.backward = True
    options.max_depth = quest_length
    options.create_variables = True
    options.rng = rngs['rng_quest']
    options.restricted_types = {"r", "d"}
    chain = sample_quest(world.state, options)
    quest = Quest(chain.actions)

    # Set the initial state required for the quest.
    world.state = chain.initial_state

    # Add distractors objects (i.e. not related to the quest)
    world.populate(nb_objects, rng=rngs['rng_objects'])

    grammar = make_grammar(grammar_flags, rng=rngs['rng_grammar'])
    game = make_game_with(world, [quest], grammar)
    return game
コード例 #8
0
def make_quest(world,
               quest_length,
               rng=None,
               rules_per_depth={},
               backward=False):
    state = world
    if hasattr(world, "state"):
        state = world.state

    rng = g_rng.next() if rng is None else rng

    # Sample a quest according to quest_length.
    chain = sample_quest(state,
                         rng,
                         max_depth=quest_length,
                         nb_retry=20,
                         rules_per_depth=rules_per_depth,
                         backward=backward)
    quest = [c.action for c in chain]
    return Quest(quest)
コード例 #9
0
def make_quest(world: Union[World, State],
               options: Optional[GameOptions] = None):
    state = getattr(world, "state", world)

    if options is None:
        options = GameOptions()

        # By default, exclude quests finishing with: go, examine, look and inventory.
        exclude = ["go.*", "examine.*", "look.*", "inventory.*"]
        options.chaining.rules_per_depth = [
            options.kb.rules.get_matching(".*", exclude=exclude)
        ]
        options.chaining.rng = options.rngs['quest']

    chains = []
    for _ in range(options.nb_parallel_quests):
        chain = sample_quest(state, options.chaining)
        if chain is None:
            msg = "No quest can be generated with the provided options."
            raise NoSuchQuestExistError(msg)

        chains.append(chain)
        state = chain.initial_state  # State might have changed, i.e. options.create_variable is True.

    if options.chaining.backward and hasattr(world, "state"):
        world.state = state

    quests = []
    actions = []
    for chain in reversed(chains):
        for i in range(1, len(chain.nodes)):
            actions.append(chain.actions[i - 1])
            if chain.nodes[i].breadth != chain.nodes[i - 1].breadth:
                event = Event(actions)
                quests.append(Quest(win_events=[event]))

        actions.append(chain.actions[-1])
        event = Event(actions)
        quests.append(Quest(win_events=[event]))

    return quests
コード例 #10
0
def main():
    args = parse_args()

    # Load game for which to sample quests for.
    game = Game.load(args.game.replace(".ulx", ".json"))

    options = ChainingOptions()
    options.backward = False
    options.max_depth = args.quest_length
    options.max_breadth = args.quest_breadth
    options.rules_per_depth = {}
    options.create_variables = False
    options.rng = np.random.RandomState(args.seed)

    # Sample quests.
    chains = []
    for i in range(args.nb_quests):
        chain = sample_quest(game.world.state, options)
        chains.append(chain)

    inform7 = Inform7Game(game)
    print_chains(chains, inform7)

    # Convert chains to networkx graph/tree
    filename_world = pjoin(args.output, "sample_world.png")
    filename_tree = pjoin(args.output, "sample_tree.svg")
    filename_graph = pjoin(args.output, "sample_graph.svg")
    G, labels = build_tree_from_chains(chains, inform7)
    if len(G) > 0:
        image = visualize(game)
        image.save(filename_world)
        tree = nx.bfs_tree(G, "root")
        save_graph_to_svg(tree, labels, filename_tree)
        save_graph_to_svg(G, labels, filename_graph)
    else:
        try:
            os.remove(filename_world)
            os.remove(filename_tree)
            os.remove(filename_graph)
        except:
            pass
コード例 #11
0
ファイル: test_game.py プロジェクト: zp312/TextWorld
    def test_win_action(self):
        g_rng.set_seed(2018)
        map_ = make_small_map(n_rooms=5, possible_door_states=["open"])
        world = World.from_map(map_)

        for max_depth in range(1, 3):
            for rule in data.get_rules().values():
                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
                if len(actions) != max_depth:
                    print(chain)
                assert len(actions) == max_depth, rule.name
                quest = Quest(actions)
                tmp_world = World.from_facts(chain.initial_state.facts)

                state = tmp_world.state
                for action in actions:
                    assert not state.is_applicable(quest.win_action)
                    state.apply(action)

                assert state.is_applicable(quest.win_action)

                # Build the quest by only providing the winning conditions.
                quest = Quest(actions=None,
                              winning_conditions=actions[-1].postconditions)
                tmp_world = World.from_facts(chain.initial_state.facts)

                state = tmp_world.state
                for action in actions:
                    assert not state.is_applicable(quest.win_action)
                    state.apply(action)

                assert state.is_applicable(quest.win_action)
コード例 #12
0
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_)

    for rule in data.get_rules().values():
        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
        quest = Quest(chain.actions)

        # 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, game_name, games_folder=tmpdir)

            env = textworld.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(quest.commands[0])
            assert done
            assert game_state.has_won
コード例 #13
0
def make_game(world_size: int, nb_objects: int, quest_length: int, quest_breadth: int,
              grammar_flags: Mapping = {},
              rngs: Optional[Dict[str, RandomState]] = None
              ) -> Game:
    """
    Make a game (map + objects + quest).

    Arguments:
        world_size: Number of rooms in the world.
        nb_objects: Number of objects in the world.
        quest_length: Minimum nb. of actions the quest requires to be completed.
        quest_breadth: How many branches the quest can have.
        grammar_flags: Options for the grammar.

    Returns:
        Generated game.
    """
    if rngs is None:
        rngs = {}
        rng = g_rng.next()
        rngs['rng_map'] = RandomState(rng.randint(65635))
        rngs['rng_objects'] = RandomState(rng.randint(65635))
        rngs['rng_quest'] = RandomState(rng.randint(65635))
        rngs['rng_grammar'] = RandomState(rng.randint(65635))

    # Generate only the map for now (i.e. without any objects)
    world = make_world(world_size, nb_objects=0, rngs=rngs)

    # Sample a quest according to quest_length.
    class Options(ChainingOptions):

        def get_rules(self, depth):
            if depth == 0:
		        # Last action should not be "go <dir>".
                return data.get_rules().get_matching("^(?!go.*).*")
            else:
                return super().get_rules(depth)

    options = Options()
    options.backward = True
    options.min_depth = 1
    options.max_depth = quest_length
    options.min_breadth = 1
    options.max_breadth = quest_breadth
    options.create_variables = True
    options.rng = rngs['rng_quest']
    options.restricted_types = {"r", "d"}
    chain = sample_quest(world.state, options)

    subquests = []
    for i in range(1, len(chain.nodes)):
        if chain.nodes[i].breadth != chain.nodes[i - 1].breadth:
            quest = Quest(chain.actions[:i])
            subquests.append(quest)

    quest = Quest(chain.actions)
    subquests.append(quest)

    # Set the initial state required for the quest.
    world.state = chain.initial_state

    # Add distractors objects (i.e. not related to the quest)
    world.populate(nb_objects, rng=rngs['rng_objects'])

    grammar = make_grammar(grammar_flags, rng=rngs['rng_grammar'])
    game = make_game_with(world, subquests, grammar)
    game.change_grammar(grammar)

    return game