Exemple #1
0
 def __init__(self) -> None:
     self._state = State(KnowledgeBase.default().logic)
     self._entities = OrderedDict()
     self._rooms = []
     self._objects = []
     self._update()
     self._player_room = None
def test_is_sequence_applicable():
    state = State(KnowledgeBase.default().logic, [
        Proposition.parse("at(P, r_1: r)"),
        Proposition.parse("empty(r_2: r)"),
        Proposition.parse("empty(r_3: r)"),
    ])

    assert state.is_sequence_applicable([
        Action.parse(
            "go :: at(P, r_1: r) & empty(r_2: r) -> at(P, r_2: r) & empty(r_1: r)"
        ),
        Action.parse(
            "go :: at(P, r_2: r) & empty(r_3: r) -> at(P, r_3: r) & empty(r_2: r)"
        ),
    ])

    assert not state.is_sequence_applicable([
        Action.parse(
            "go :: at(P, r_1: r) & empty(r_2: r) -> at(P, r_2: r) & empty(r_1: r)"
        ),
        Action.parse(
            "go :: at(P, r_1: r) & empty(r_3: r) -> at(P, r_3: r) & empty(r_1: r)"
        ),
    ])

    assert not state.is_sequence_applicable([
        Action.parse(
            "go :: at(P, r_2: r) & empty(r_3: r) -> at(P, r_3: r) & empty(r_2: r)"
        ),
        Action.parse(
            "go :: at(P, r_3: r) & empty(r_1: r) -> at(P, r_1: r) & empty(r_3: r)"
        ),
    ])
Exemple #3
0
 def __init__(self) -> None:
     self._state = State()
     self._entities = OrderedDict()
     self._rooms = []
     self._objects = []
     self._update()
     self._player_room = None
Exemple #4
0
def test_is_sequence_applicable():
    state = State([
        Proposition.parse("at(P, r_1: r)"),
        Proposition.parse("empty(r_2: r)"),
        Proposition.parse("empty(r_3: r)"),
    ])

    assert state.is_sequence_applicable([
        Action.parse(
            "go :: at(P, r_1: r) & empty(r_2: r) -> at(P, r_2: r) & empty(r_1: r)"
        ),
        Action.parse(
            "go :: at(P, r_2: r) & empty(r_3: r) -> at(P, r_3: r) & empty(r_2: r)"
        ),
    ])

    assert not state.is_sequence_applicable([
        Action.parse(
            "go :: at(P, r_1: r) & empty(r_2: r) -> at(P, r_2: r) & empty(r_1: r)"
        ),
        Action.parse(
            "go :: at(P, r_1: r) & empty(r_3: r) -> at(P, r_3: r) & empty(r_1: r)"
        ),
    ])

    assert not state.is_sequence_applicable([
        Action.parse(
            "go :: at(P, r_2: r) & empty(r_3: r) -> at(P, r_3: r) & empty(r_2: r)"
        ),
        Action.parse(
            "go :: at(P, r_3: r) & empty(r_1: r) -> at(P, r_1: r) & empty(r_3: r)"
        ),
    ])
def test_going_through_door():
    P = Variable("P", "P")
    room = Variable("room", "r")
    kitchen = Variable("kitchen", "r")
    state = State(KnowledgeBase.default().logic)
    state.add_facts([
        Proposition("at", [P, room]),
        Proposition("north_of", [kitchen, room]),
        Proposition("free", [kitchen, room]),
        Proposition("free", [room, kitchen]),
        Proposition("south_of", [room, kitchen])
    ])

    options = ChainingOptions()
    options.backward = True
    options.max_depth = 3
    options.max_length = 3
    options.subquests = True
    options.create_variables = True
    options.rules_per_depth = [
        [KnowledgeBase.default().rules["take/c"], KnowledgeBase.default().rules["take/s"]],
        KnowledgeBase.default().rules.get_matching("go.*"),
        [KnowledgeBase.default().rules["open/d"]],
    ]

    chains = list(get_chains(state, options))
    assert len(chains) == 18
Exemple #6
0
 def __init__(self, kb: Optional[KnowledgeBase] = None) -> None:
     self.kb = kb or KnowledgeBase.default()
     self._state = State(self.kb.logic)
     self._entities = OrderedDict()
     self._rooms = []
     self._objects = []
     self._update()
     self._player_room = None
def test_parallel_quests():
    logic = GameLogic.parse("""
        type foo {
            rules {
                do_a :: not_a(foo) & $not_c(foo) -> a(foo);
                do_b :: not_b(foo) & $not_c(foo) -> b(foo);
                do_c :: $a(foo) & $b(foo) & not_c(foo) -> c(foo);
            }

            constraints {
                a_or_not_a :: a(foo) & not_a(foo) -> fail();
                b_or_not_b :: b(foo) & not_b(foo) -> fail();
                c_or_not_c :: c(foo) & not_c(foo) -> fail();
            }
        }
    """)
    kb = KnowledgeBase(logic, "")

    state = State(kb.logic, [
        Proposition.parse("a(foo)"),
        Proposition.parse("b(foo)"),
        Proposition.parse("c(foo)"),
    ])

    options = ChainingOptions()
    options.backward = True
    options.kb = kb

    options.max_depth = 3
    options.max_breadth = 1
    options.max_length = 3
    chains = list(get_chains(state, options))
    assert len(chains) == 2

    options.max_breadth = 2
    chains = list(get_chains(state, options))
    assert len(chains) == 3

    options.min_breadth = 2
    chains = list(get_chains(state, options))
    assert len(chains) == 1
    assert len(chains[0].actions) == 3
    assert chains[0].nodes[0].depth == 2
    assert chains[0].nodes[0].breadth == 2
    assert chains[0].nodes[0].parent == chains[0].nodes[2]
    assert chains[0].nodes[1].depth == 2
    assert chains[0].nodes[1].breadth == 1
    assert chains[0].nodes[1].parent == chains[0].nodes[2]
    assert chains[0].nodes[2].depth == 1
    assert chains[0].nodes[2].breadth == 1
    assert chains[0].nodes[2].parent is None

    options.min_breadth = 1
    options.create_variables = True
    state = State(kb.logic)
    chains = list(get_chains(state, options))
    assert len(chains) == 5
Exemple #8
0
def test_room_connections():
    kb = KnowledgeBase.default()

    room0 = Variable("room0", "r")
    room1 = Variable("room1", "r")
    room2 = Variable("room2", "r")

    # Only one connection can exist between two rooms.
    # r1
    # |
    # r0 - r1
    state = State(kb.logic, [
        Proposition("north_of", [room1, room0]),
        Proposition("south_of", [room0, room1]),
        Proposition("east_of", [room1, room0]),
        Proposition("west_of", [room0, room1])
    ])

    assert not check_state(state)

    # Non Cartesian layout are allowed.
    # r1
    # |
    # r0 - r2 - r1
    state = State(kb.logic, [
        Proposition("north_of", [room1, room0]),
        Proposition("south_of", [room0, room1]),
        Proposition("east_of", [room2, room0]),
        Proposition("west_of", [room0, room2]),
        Proposition("east_of", [room1, room2]),
        Proposition("west_of", [room2, room1])
    ])

    assert check_state(state)

    # A room cannot have more than 4 'link' propositions.
    room3 = Variable("room3", "r")
    room4 = Variable("room4", "r")
    room5 = Variable("room5", "r")
    door1 = Variable("door1", "d")
    door2 = Variable("door2", "d")
    door3 = Variable("door3", "d")
    door4 = Variable("door4", "d")
    door5 = Variable("door5", "d")

    state = State(kb.logic, [
        Proposition("link", [room0, door1, room1]),
        Proposition("link", [room0, door2, room2]),
        Proposition("link", [room0, door3, room3]),
        Proposition("link", [room0, door4, room4]),
        Proposition("link", [room0, door5, room5])
    ])

    assert not check_state(state)
Exemple #9
0
    def test_count(self):
        rng = np.random.RandomState(1234)
        types_counts = {t: rng.randint(2, 10) for t in self.types.variables}

        state = State()
        for t in self.types.variables:
            v = Variable(get_new(t, types_counts), t)
            state.add_fact(Proposition("dummy", [v]))

        counts = self.types.count(state)
        for t in self.types.variables:
            assert counts[t] == types_counts[t], (counts[t], types_counts[t])
Exemple #10
0
    def check_state(self, state: State) -> bool:
        """Check that a state satisfies the constraints."""

        fail = Proposition("fail", [])

        constraints = state.all_applicable_actions(self.constraints)
        for constraint in constraints:
            copy = state.apply_on_copy(constraint)
            if copy and copy.is_fact(fail):
                return False

        return True
Exemple #11
0
def test_all_instantiations():
    state = State([
        Proposition.parse("at(P, kitchen: r)"),
        Proposition.parse("in(key: o, kitchen: r)"),
        Proposition.parse("in(egg: o, kitchen: r)"),
        Proposition.parse("in(book: o, study: r)"),
        Proposition.parse("in(book: o, study: r)"),
        Proposition.parse("in(map: o, I)"),
    ])

    take = Rule.parse("take :: $at(P, r) & in(o, r) -> in(o, I)")
    actions = set(state.all_instantiations(take))
    assert actions == {
        Action.parse("take :: $at(P, kitchen: r) & in(key: o, kitchen: r) -> in(key: o, I)"),
        Action.parse("take :: $at(P, kitchen: r) & in(egg: o, kitchen: r) -> in(egg: o, I)"),
    }

    drop = take.inverse(name="drop")
    actions = set(state.all_instantiations(drop))
    assert actions == {
        Action.parse("drop :: $at(P, kitchen: r) & in(map: o, I) -> in(map: o, kitchen: r)"),
    }

    state.apply(*actions)
    actions = set(state.all_instantiations(drop))
    assert len(actions) == 0

    # The state is no longer aware of the I variable, so there are no solutions
    actions = set(state.all_instantiations(take))
    assert len(actions) == 0
Exemple #12
0
def test_going_through_door():
    P = Variable("P", "P")
    room = Variable("room", "r")
    kitchen = Variable("kitchen", "r")
    state = State()
    state.add_facts([
        Proposition("at", [P, room]),
        Proposition("north_of", [kitchen, room]),
        Proposition("free", [kitchen, room]),
        Proposition("free", [room, kitchen]),
        Proposition("south_of", [room, kitchen])
    ])

    # Sample quests.
    chains = []
    rules_per_depth = {
        0: [data.get_rules()["take/c"],
            data.get_rules()["take/s"]],
        1: data.get_rules().get_matching("go.*"),
        2: [data.get_rules()["open/d"]]
    }
    tree_of_possible = chaining.get_chains(state,
                                           max_depth=3,
                                           allow_partial_match=True,
                                           exceptions=[],
                                           rules_per_depth=rules_per_depth,
                                           backward=True)
    chains = list(tree_of_possible.traverse_preorder(subquests=True))
    # chaining.print_chains(chains)
    # 1. take/c(P, room, c_0, o_0, I)
    # 2. take/c(P, room, c_0, o_0, I) -> go/north(P, r_0, room)
    # 3. take/c(P, room, c_0, o_0, I) -> go/north(P, r_0, room) -> open/d(P, r_0, d_0, room)
    # 4. take/c(P, room, c_0, o_0, I) -> go/south(P, kitchen, room)
    # 5. take/c(P, room, c_0, o_0, I) -> go/south(P, kitchen, room) -> open/d(P, kitchen, d_0, room)
    # 6. take/c(P, room, c_0, o_0, I) -> go/east(P, r_0, room)
    # 7. take/c(P, room, c_0, o_0, I) -> go/east(P, r_0, room) -> open/d(P, r_0, d_0, room)
    # 8. take/c(P, room, c_0, o_0, I) -> go/west(P, r_0, room)
    # 9. take/c(P, room, c_0, o_0, I) -> go/west(P, r_0, room) -> open/d(P, r_0, d_0, room)
    # 10. take/s(P, room, s_0, o_0, I)
    # 11. take/s(P, room, s_0, o_0, I) -> go/north(P, r_0, room)
    # 12. take/s(P, room, s_0, o_0, I) -> go/north(P, r_0, room) -> open/d(P, r_0, d_0, room)
    # 13. take/s(P, room, s_0, o_0, I) -> go/south(P, kitchen, room)
    # 14. take/s(P, room, s_0, o_0, I) -> go/south(P, kitchen, room) -> open/d(P, kitchen, d_0, room)
    # 15. take/s(P, room, s_0, o_0, I) -> go/east(P, r_0, room)
    # 16. take/s(P, room, s_0, o_0, I) -> go/east(P, r_0, room) -> open/d(P, r_0, d_0, room)
    # 17. take/s(P, room, s_0, o_0, I) -> go/west(P, r_0, room)
    # 18. take/s(P, room, s_0, o_0, I) -> go/west(P, r_0, room) -> open/d(P, r_0, d_0, room)
    assert len(chains) == 18
Exemple #13
0
def process_full_facts(info_game, facts):
    state = State(info_game.kb.logic, facts)
    state = convert_link_predicates(
        state)  # applies all applicable actions for fully observable graph
    inventory_facts = set(find_predicates_in_inventory(state))
    # recipe_facts = set(find_predicates_in_recipe(state))
    return set(state.facts) | inventory_facts  #| recipe_facts
Exemple #14
0
    def check_state(self, state: State) -> bool:
        """Check that a state satisfies the constraints."""

        fail = Proposition("fail", [])

        constraints = state.all_applicable_actions(self.constraints)
        for constraint in constraints:
            if state.is_applicable(constraint):
                # Optimistically delay copying the state
                copy = state.copy()
                copy.apply(constraint)

                if copy.is_fact(fail):
                    return False

        return True
def process_local_facts(info_game, info_facts):
    state = State(info_game.kb.logic, info_facts)
    scope_facts = set(find_predicates_in_scope(state))
    exit_facts = set(find_exits_in_scope(state))
    inventory_facts = set(find_predicates_in_inventory(state))
    recipe_facts = set(find_predicates_in_recipe(state))
    return scope_facts | exit_facts | inventory_facts | recipe_facts
def build_state(locked_door=False):
    # Set up a world with two rooms and a few objecs.
    P = Variable("P")
    I = Variable("I")
    bedroom = Variable("bedroom", "r")
    kitchen = Variable("kitchen", "r")
    rusty_key = Variable("rusty key", "k")
    small_key = Variable("small key", "k")
    wooden_door = Variable("wooden door", "d")
    chest = Variable("chest", "c")
    cabinet = Variable("cabinet", "c")
    robe = Variable("robe", "o")

    state = State(KnowledgeBase.default().logic, [
        Proposition("at", [P, bedroom]),
        Proposition("south_of", [kitchen, bedroom]),
        Proposition("north_of", [bedroom, kitchen]),
        Proposition("link", [bedroom, wooden_door, kitchen]),
        Proposition("link", [kitchen, wooden_door, bedroom]),

        Proposition("locked" if locked_door else "closed", [wooden_door]),

        Proposition("in", [rusty_key, I]),
        Proposition("match", [rusty_key, chest]),
        Proposition("locked", [chest]),
        Proposition("at", [chest, kitchen]),
        Proposition("in", [small_key, chest]),

        Proposition("match", [small_key, cabinet]),
        Proposition("locked", [cabinet]),
        Proposition("at", [cabinet, bedroom]),
        Proposition("in", [robe, cabinet]),
    ])

    return state
Exemple #17
0
def process_step_facts(prev_facts, info_game, info_facts, info_last_action,
                       cmd):
    kb = info_game.kb

    if prev_facts is None or cmd == "restart" or len(prev_facts) == 0:
        new_facts = set()
    else:
        if cmd == "inventory":  # Bypassing TextWorld's action detection.
            new_facts = set(
                find_predicates_in_inventory(State(kb.logic, info_facts)))
            return prev_facts | new_facts

        elif info_last_action is None:
            return prev_facts  # Invalid action, nothing has changed.

        # Check recipe from cookbook here
        elif info_last_action.name == "examine" and "cookbook" in [
                v.name for v in info_last_action.variables
        ]:
            new_facts = set(
                find_predicates_in_recipe(State(kb.logic, info_facts)))
            return prev_facts | new_facts

        state = State(kb.logic,
                      prev_facts | set(info_last_action.preconditions))
        success = state.apply(info_last_action)
        assert success
        new_facts = set(state.facts)

    new_facts |= set(find_predicates_in_scope(State(kb.logic, info_facts)))
    new_facts |= set(find_exits_in_scope(State(kb.logic, info_facts)))
    return new_facts
Exemple #18
0
def process_facts(prev_facts, info_game, info_facts, info_last_action, cmd):
    kb = info_game.kb
    if prev_facts is None or cmd == "restart":
        facts = set()
    else:
        if cmd == "inventory":  # Bypassing TextWorld's action detection.
            facts = set(find_predicates_in_inventory(State(kb.logic, info_facts)))
            return prev_facts | facts

        elif info_last_action is None :
            return prev_facts  # Invalid action, nothing has changed.

        elif info_last_action.name == "examine" and "cookbook" in [v.name for v in info_last_action.variables]:
            facts = set(find_predicates_in_recipe(State(kb.logic, info_facts)))
            return prev_facts | facts

        state = State(kb.logic, prev_facts | set(info_last_action.preconditions))
        success = state.apply(info_last_action)
        assert success
        facts = set(state.facts)

    # Always add facts in sight.
    facts |= set(find_predicates_in_scope(State(kb.logic, info_facts)))
    facts |= set(find_exits_in_scope(State(kb.logic, info_facts)))

    return facts
Exemple #19
0
    def state(self) -> State:
        """ Current state of the world. """
        facts = []
        for room in self.rooms:
            facts += room.facts

        for path in self.paths:
            facts += path.facts

        facts += self.inventory.facts
        facts += self._distractors_facts

        return State(facts)
Exemple #20
0
def test_get_reverse_action():
    kb = KnowledgeBase.default()
    for rule in kb.rules.values():
        empty_state = State(KnowledgeBase.default().logic)
        action = maybe_instantiate_variables(rule, kb.types.constants_mapping.copy(), empty_state)
        r_action = kb.get_reverse_action(action)

        if rule.name.startswith("eat"):
            assert r_action is None
        else:
            assert r_action is not None

            # Check if that when applying the reverse rule we can re-obtain
            # the previous state.
            state = State(KnowledgeBase.default().logic, action.preconditions)

            new_state = state.copy()
            assert new_state.apply(action)

            r_state = new_state.copy()
            r_state.apply(r_action)
            assert state == r_state
Exemple #21
0
    def check_action(self, state: State, action: Action) -> bool:
        """
        Check if an action should be allowed in this state.

        The default implementation disallows actions that would create new facts
        that don't mention any new variables.

        Args:
            state: The current state.
            action: The action being applied.

        Returns:
            Whether that action should be allowed.
        """

        for prop in action.preconditions:
            if not state.is_fact(prop):
                if all(state.has_variable(var) for var in prop.arguments):
                    # Don't allow creating new predicates without any new variables
                    return False

        return True
Exemple #22
0
def test_backward_chaining():
    P = Variable("P", "P")
    room = Variable("room", "r")
    kitchen = Variable("kitchen", "r")
    state = State([
        Proposition("at", [P, room]),
        Proposition("north_of", [kitchen, room]),
        Proposition("south_of", [room, kitchen]),
    ])

    rules_per_depth = {
        0: [data.get_rules()["take/c"],
            data.get_rules()["take/s"]],
        1: [data.get_rules()["open/c"]]
    }

    tree_of_possible = chaining.get_chains(state,
                                           max_depth=2,
                                           allow_partial_match=True,
                                           exceptions=['d'],
                                           rules_per_depth=rules_per_depth,
                                           backward=True)

    chains = list(tree_of_possible.traverse_preorder(subquests=True))
    assert len(chains) == 3
    for chain in chains:
        for depth, action in enumerate(chain):
            assert action.action.name in [
                rule.name for rule in rules_per_depth[depth]
            ]

    rules_per_depth = {
        0: [data.get_rules()["put"]],
        1: [data.get_rules()["go/north"]],
        2: [data.get_rules()["take/c"]]
    }

    tree_of_possible = chaining.get_chains(state,
                                           max_depth=3,
                                           allow_partial_match=True,
                                           exceptions=['d'],
                                           rules_per_depth=rules_per_depth,
                                           backward=True)

    chains = list(tree_of_possible.traverse_preorder(subquests=True))
    assert len(chains) == 3
    for chain in chains:
        for depth, action in enumerate(chain):
            assert action.action.name in [
                rule.name for rule in rules_per_depth[depth]
            ]
Exemple #23
0
def test_get_reverse_rules(verbose=False):
    for rule in data.get_rules().values():
        r_rule = data.get_reverse_rules(rule)

        if verbose:
            print(rule, r_rule)

        if rule.name.startswith("eat"):
            assert r_rule is None
        else:
            # Check if that when applying the reverse rule we can reobtain
            # the previous state.
            action = maybe_instantiate_variables(
                rule,
                data.get_types().constants_mapping.copy(), State([]))
            state = State(action.preconditions)

            new_state = state.copy()
            assert new_state.apply(action)

            assert r_rule is not None
            actions = list(
                new_state.all_applicable_actions(
                    [r_rule],
                    data.get_types().constants_mapping))
            if len(actions) != 1:
                print(actions)
                print(r_rule)
                print(new_state)
                print(
                    list(
                        new_state.all_instantiations(
                            r_rule,
                            data.get_types().constants_mapping)))
                assert len(actions) == 1
            r_state = new_state.copy()
            r_state.apply(actions[0])
            assert state == r_state
Exemple #24
0
 def __init__(self) -> None:
     """
     Creates an empty world, with a player and an empty inventory.
     """
     self._entities = {}
     self._quests = []
     self.rooms = []
     self.paths = []
     self._types_counts = data.get_types().count(State())
     self.player = self.new(type='P')
     self.inventory = self.new(type='I')
     self.grammar = textworld.generator.make_grammar()
     self._game = None
     self._distractors_facts = []
Exemple #25
0
def process_facts(prev_facts, info_game, info_facts, info_last_action, cmd):
    kb = textworld.Game.deserialize(info_game).kb
    if prev_facts is None:
        facts = set()
    else:
        if cmd == "inventory":  # Bypassing TextWorld's action detection.
            facts = set(
                find_predicates_in_inventory(State(kb.logic, info_facts)))
            return prev_facts | facts

        elif info_last_action is None:
            return prev_facts  # Invalid action, nothing has changed.

        state = State(kb.logic,
                      prev_facts | set(info_last_action.preconditions))
        success = state.apply(info_last_action)
        assert success
        facts = set(state.facts)

    # Always add facts in sight.
    facts |= set(find_predicates_in_scope(State(kb.logic, info_facts)))

    return facts
Exemple #26
0
 def __init__(self) -> None:
     """
     Creates an empty world, with a player and an empty inventory.
     """
     self._entities = {}
     self._named_entities = {}
     self.quests = []
     self.rooms = []
     self.paths = []
     self._types_counts = KnowledgeBase.default().types.count(State())
     self.player = self.new(type='P')
     self.inventory = self.new(type='I')
     self.nowhere = []
     self.grammar = textworld.generator.make_grammar()
     self._game = None
     self._distractors_facts = []
Exemple #27
0
 def __init__(self, options: Optional[GameOptions] = None) -> None:
     """
     Creates an empty world, with a player and an empty inventory.
     """
     self.options = options or GameOptions()
     self._entities = {}
     self._named_entities = {}
     self.quests = []
     self.rooms = []
     self.paths = []
     self._kb = self.options.kb
     self._types_counts = self._kb.types.count(State(self._kb.logic))
     self.player = self.new(type='P')
     self.inventory = self.new(type='I')
     self.nowhere = []
     self._game = None
     self._distractors_facts = []
Exemple #28
0
def test_backward_chaining():
    P = Variable("P", "P")
    room = Variable("room", "r")
    kitchen = Variable("kitchen", "r")
    state = State(KnowledgeBase.default().logic, [
        Proposition("at", [P, room]),
        Proposition("north_of", [kitchen, room]),
        Proposition("south_of", [room, kitchen]),
    ])

    options = ChainingOptions()
    options.backward = True
    options.max_depth = 2
    options.max_length = 2
    options.subquests = True
    options.create_variables = True
    options.rules_per_depth = [
        [
            KnowledgeBase.default().rules["take/c"],
            KnowledgeBase.default().rules["take/s"]
        ],
        [KnowledgeBase.default().rules["open/c"]],
    ]
    options.restricted_types = {"d"}

    chains = list(get_chains(state, options))
    assert len(chains) == 3

    options = ChainingOptions()
    options.backward = True
    options.max_depth = 3
    options.max_length = 3
    options.subquests = True
    options.create_variables = True
    options.rules_per_depth = [
        [KnowledgeBase.default().rules["put"]],
        [KnowledgeBase.default().rules["go/north"]],
        [KnowledgeBase.default().rules["take/c"]],
    ]
    options.restricted_types = {"d"}

    chains = list(get_chains(state, options))
    assert len(chains) == 3
Exemple #29
0
    def deserialize(cls, data: Mapping) -> "Game":
        """ Creates a `Game` from serialized data.

        Args:
            data: Serialized data with the needed information to build a
                  `Game` object.
        """
        world = World.deserialize(data["world"])
        grammar = None
        if "grammar" in data:
            grammar = Grammar(data["grammar"])
        quests = [Quest.deserialize(d) for d in data["quests"]]
        game = cls(world, grammar, quests)
        game._infos = {k: EntityInfo.deserialize(v) for k, v in data["infos"]}
        game.state = State.deserialize(data["state"])
        game._rules = {k: Rule.deserialize(v) for k, v in data["rules"]}
        game._types = VariableTypeTree.deserialize(data["types"])
        game.metadata = data.get("metadata", {})

        return game
Exemple #30
0
    def try_instantiate(self, state: State, partial: _PartialAction) -> Optional[Action]:
        """
        Try to instantiate a partial action, by creating new variables if
        necessary.
        """

        rule, mapping = partial.rule, partial.mapping

        if self.create_variables:
            type_counts = Counter({ph.type: len(state.variables_of_type(ph.type)) for ph in rule.placeholders})

        for ph in rule.placeholders:
            if mapping.get(ph) is None:
                var = self.create_variable(state, ph, type_counts)
                if var:
                    mapping[ph] = var
                else:
                    return None

        return rule.instantiate(mapping)