示例#1
0
    def gen_source_for_map(self, src_room: WorldRoom) -> str:
        source = ""
        src_room_id = src_room.id

        for src_exit, dest_room in src_room.exits.items():
            dest_room_id = dest_room.id

            if src_exit in src_room.doors:
                door = src_room.doors[src_exit]
                dest_exit = [
                    k for k, v in dest_room.doors.items() if v == door
                ][0]
                template = "{src_exit} of {src} and {dest_exit} of {dest} is a door called {door}.\n"
                source += template.format(src_exit=src_exit,
                                          src=src_room_id,
                                          dest_exit=dest_exit,
                                          dest=dest_room_id,
                                          door=door.name)
            else:
                sig = Signature("{}_of".format(src_exit), ["r", "r"])
                _, template = self.kb.inform7_predicates[sig]
                mapping = {'r': dest_room_id, "r'": src_room_id}
                source += template.format(**mapping) + ".\n"

        return source
示例#2
0
def query_for_important_facts(
    actions: List[Action],
    facts: Optional[List[Proposition]] = None,
    varinfos: Optional[Dict[str, EntityInfo]] = None
) -> Optional[List[Proposition]]:
    """ Queries the user, asking which facts are important.

    Args:
        actions: Actions used to determine or extract relevant facts.
        facts: All facts existing at the end of the game.
    
    Returns:
        The list of facts that are required to win;
        or `None` if `facts` was not provided;
        or `None` if the user cancels.
    """
    if facts is None:  # No facts to choose from.
        return None

    present_facts = set(facts)
    all_postconditions = set(
        flatten(a.postconditions for a in actions if a is not None))
    relevant_facts = sorted(all_postconditions & present_facts)

    def _get_name(var):
        if varinfos is not None and var.name in varinfos:
            if varinfos[var.name].name is not None:
                return varinfos[var.name].name

        return var.type

    # set up boxes
    checkboxes = []
    for fact in relevant_facts:
        signature = Signature(fact.name,
                              [_get_name(var) for var in fact.arguments])
        fact_str = str(signature)
        cb = urwid.CheckBox(fact_str)
        checkboxes.append(cb)

    # run
    quest_querier = UrwidQuestQuerier(checkboxes)
    loop = urwid.MainLoop(quest_querier, [('popbg', 'white', 'dark blue')],
                          pop_ups=True)
    loop.run()

    if quest_querier.action_cancelled:
        return None  # don't return, even if the user selected items
    else:
        checked_facts = list(
            compress(relevant_facts, [cb.state for cb in checkboxes]))
        return checked_facts
示例#3
0
def test_logic_parsing():
    P = Variable("P", "P")
    kitchen = Variable("kitchen", "r")
    egg = Variable("egg", "f")

    assert Variable.parse("P") == P
    assert Variable.parse("kitchen: r") == kitchen

    at_kitchen = Proposition("at", [P, kitchen])
    in_kitchen = Proposition("in", [egg, kitchen])
    raw_egg = Proposition("raw", [egg])
    cooked_egg = Proposition("cooked", [egg])

    assert Proposition.parse("at(P, kitchen: r)") == at_kitchen

    assert Signature.parse("at(P, r)") == at_kitchen.signature

    cook_egg = Action("cook", [at_kitchen, in_kitchen, raw_egg],
                      [at_kitchen, in_kitchen, cooked_egg])
    assert Action.parse(
        "cook :: $at(P, kitchen: r) & $in(egg: f, kitchen: r) & raw(egg: f) -> cooked(egg: f)"
    ) == cook_egg

    P = Placeholder("P", "P")
    r = Placeholder("r", "r")
    d = Placeholder("d", "d")
    rp = Placeholder("r'", "r")
    assert Placeholder.parse("P") == P
    assert Placeholder.parse("r") == r
    assert Placeholder.parse("d") == d
    assert Placeholder.parse("r'") == rp

    at_r = Predicate("at", [P, r])
    link = Predicate("link", [r, d, rp])
    unlocked = Predicate("unlocked", [d])
    at_rp = Predicate("at", [P, rp])
    assert Predicate.parse("link(r, d, r')") == link

    go = Rule("go", [at_r, link, unlocked], [link, unlocked, at_rp])
    assert Rule.parse(
        "go :: at(P, r) & $link(r, d, r') & $unlocked(d) -> at(P, r')") == go

    # Make sure the types match in the whole expression
    assert_raises(ValueError, Rule.parse,
                  "take :: $at(P, r) & $in(c, r) & in(o: k, c) -> in(o, I)")
示例#4
0
    def all_assignments(self, node: _Node,
                        rules: Iterable[Rule]) -> Iterable[_PartialAction]:
        """
        Compute all possible assignments for instantiating the given rules.
        """

        state = node.state

        at_p_r = None
        r = Placeholder("r", "r")
        if r not in self.fixed_mapping:
            # To make chaining more efficient, we fix the mapping of `r` to the current room,
            # i.e. at(P, r). This works since the player can only be at one place at a time.
            signature = Signature("at", ["P", "r"])
            facts = list(state.facts_with_signature(signature))
            if len(facts) > 0:
                assert len(
                    facts
                ) == 1, "There should only be one `at(P, r)` proposition."
                at_p_r = facts[0]

        def allow_partial(ph):
            count = len(state.variables_of_type(ph.type))
            return self.options.check_new_variable(state, ph.type, count)

        assignments = []
        for rule in rules:
            fixed_mapping = self.fixed_mapping.copy()

            if self.backward:
                rule = rule.inverse()

            fixed_mapping = self.get_fixed_mapping(rule, at_p_r)
            for mapping in state.all_assignments(rule, fixed_mapping,
                                                 self.create_variables,
                                                 allow_partial):
                assignments.append(_PartialAction(node, rule, mapping))

        # Keep everything in a deterministic order
        return sorted(assignments)
示例#5
0
def add_extra_door_facts(world,
                         world_facts,
                         local_facts=None,
                         where_fact=None):
    # adds to world_facts additional facts about door directions
    # and also about exits and door directions relative to the player if local_facts is not None
    if local_facts is not None:
        assert where_fact is not None
    door_facts = world.state.facts_with_signature(
        Signature('link', ('r', 'd', 'r')))
    if where_fact:
        the_player = where_fact.arguments[0]
        player_location = where_fact.arguments[1]
    else:
        the_player, player_location = None, None  # redundant, suppress warnings

    # for room in world.rooms:
    #     print(room)
    #     for e, p in room.exits.items():
    #         print('\t', e, p)

    for df in door_facts:
        assert len(df.arguments) == 3
        r0, door, r1 = df.arguments
        direction = find_link_direction(world, r1, r0)
        new_fact = Proposition("{}_of".format(direction), (door, r1))
        world_facts.append(new_fact)
        if local_facts is not None and r1 == player_location:
            local_facts.append(new_fact)
            local_facts.append(
                Proposition("{}_of".format(direction), (door, the_player)))
            # if world.state.is_fact(Proposition('free', (player_location, r1))):
            #     local_facts.append(Proposition("{}_of".format(direction), (
            #         the_player,
            #         Variable("exit_{}".format(direction), 'e'))))
            if world.state.is_fact(Proposition('closed', [door])):
                closed_fact = Proposition('closed', [door])
                if closed_fact not in local_facts:
                    local_facts.append(closed_fact)
示例#6
0
def test_mementos_memoization():
    # Variable-free proposition.
    fact = Proposition("name")
    assert Proposition("name") is fact
    assert Proposition(name="name") is fact
    assert Proposition("name", []) is fact
    assert Proposition("name", arguments=[]) is fact
    assert Proposition(name="name", arguments=[]) is fact
    assert Proposition("name2") is not fact

    # General proposition.
    variables = [Variable("var_1"), Variable("var_2")]
    fact2 = Proposition("name", variables)
    assert fact2 is not fact
    assert Proposition("name", variables) is fact2
    assert Proposition("name", arguments=variables) is fact2
    assert Proposition(name="name", arguments=variables) is fact2
    assert Proposition("name2", variables) is not fact2

    assert Proposition("name",
                       variables[:1]) is not fact2  # Missing a variable.
    assert Proposition("name",
                       variables[::-1]) is not fact2  # Variable are reversed.

    # Type-free signature.
    sig = Signature("name")
    assert Signature("name") is sig
    assert Signature("name", []) is sig
    assert Signature("name", types=[]) is sig
    assert Signature(name="name", types=[]) is sig

    # General signature.
    types = ["type_A", "type_B"]
    sig2 = Signature("name", types)
    assert sig2 is not sig
    assert Signature("name", types) is sig2
    assert Signature("name", types=types) is sig2
    assert Signature(name="name", types=types) is sig2

    assert Signature("name", types[:1]) is not sig2  # Missing a variable.
    assert Signature("name", types[::-1]) is not sig2  # Variable are reversed.
示例#7
0
def filter_observables(world_facts: List[Proposition],
                       verbose=False,
                       game=None):
    fixups = defaultdict(set)
    if not world_facts:
        return None
    world_facts = reconstitute_facts(world_facts)

    # print("WORLD FACTS:")
    for fact in world_facts:
        # print('\t', fact)
        for v in fact.arguments:
            #     print('\t\t{}:{}'.format(v.name, v.type))
            if not v.name:
                v_count = len(fixups[v.type])
                assert v not in fixups[v.type]
                if v.type == 'P' or v.type == 'I' or v.type == 'RECIPE' or v.type == 'MEAL':
                    v.name = v.type
                    if v_count == 0:
                        fixups[v.type].add(v)
                else:
                    v.name = '~{}_{}'.format(v.type, v_count)
                    fixups[v.type].add(v)

    world = World.from_facts(world_facts)
    world_state = world.state

    if 'P' in world_state._vars_by_type:
        players = world_state.variables_of_type('P')
        assert len(players) == 1
    #     for p in players:
    #         player = p
    # else:
    #     player = None

    where_sig = Signature('at', ('P', 'r'))
    where_am_i = world_state.facts_with_signature(where_sig)
    assert len(where_am_i) == 1
    where_fact = list(where_am_i)[0]
    the_player = where_fact.arguments[0]
    player_location = where_fact.arguments[1]
    # if verbose:
    #     print("WORLD FACTS:")
    #     for fact in world_facts:
    #         print('\t', fact)
    #         # print_fact(game, fact)

    # if verbose:
    #     print("VARIABLES:")
    #     for v in world_state.variables:
    #         print('\t\t{}:{}'.format(v.name, v.type))

    print(where_fact, world.player_room)
    facts_in_scope = world.get_facts_in_scope()
    observable_facts = []
    for fact in facts_in_scope:
        # print("***\t\t", fact)
        if is_observable_relation(fact.name):
            if fact != where_fact:
                observable_facts.append(fact)
            else:  # consider the player's current location to be directly observable
                observable_facts.append(fact)
        else:
            pass

    for e in world.player_room.exits:
        if world.state.is_fact(
                Proposition(
                    'free',
                    (world.player_room.exits[e], where_fact.arguments[1]))):
            observable_facts.append(
                Proposition(
                    "{}_of".format(e),
                    (
                        Variable("exit_{}".format(e), 'e'),
                        world.player_room  # the_player
                    )))
    # REFACTORING: the following is now handled within add_extra_door_facts()
    #     else:  # probably a closed door
    #         door_facts = world.state.facts_with_signature(Signature('link', ('r', 'd', 'r')))
    #         for df in door_facts:
    #             if df.arguments[0] == player_location:
    #                 the_door = df.arguments[1]
    #                 observable_facts.append(Proposition("{}_of".format(e), (
    #                                                                 the_player,
    #                                                                 the_door
    #                                                                 )))
    #                 if world.state.is_fact(Proposition('closed', [the_door])):
    #                     observable_facts.append(Proposition('closed', [the_door]))

    add_extra_door_facts(world,
                         world_facts,
                         local_facts=observable_facts,
                         where_fact=where_fact)

    if verbose:
        print("++WORLD FACTS++:")
        for fact in world_facts:
            prettyprint_fact(fact, game=game)
    return observable_facts, player_location