Пример #1
0
 def generate_name_fail(self):
     grammar = Grammar()
     try:
         grammar.generate_name('object', 'vault', False, exclude=ContainsEveryObjectContainer())
         self.assertTrue(False, "We should have errored about an impossible object name")
     except ValueError:
         pass
Пример #2
0
def describe_event(event: Event, game: Game, grammar: Grammar) -> str:
    """
    Assign a descripton to a quest.
    """
    # We have to "count" all the adj/noun/types in the world
    # This is important for using "unique" but abstracted references to objects
    counts = OrderedDict()
    counts["adj"] = CountOrderedDict()
    counts["noun"] = CountOrderedDict()
    counts["type"] = CountOrderedDict()

    # Assign name and description to objects.
    for obj in game.world.objects:
        if obj.type in ["I", "P"]:
            continue

        obj_infos = game.infos[obj.id]
        counts['adj'][obj_infos.adj] += 1
        counts['noun'][obj_infos.noun] += 1
        counts['type'][obj.type] += 1

    if len(event.actions) == 0:
        # We don't need to say anything if the quest is empty
        event_desc = ""
    else:
        # Generate a description for either the last, or all commands
        if grammar.options.only_last_action:
            actions_desc, _ = generate_instruction(event.actions[-1], grammar, game.infos, game.world, counts)
            only_one_action = True
        else:
            actions_desc_list = []
            # Decide if we blend instructions together or not
            if grammar.options.blend_instructions:
                instructions = get_action_chains(event.actions, grammar, game.infos)
            else:
                instructions = event.actions

            only_one_action = len(instructions) < 2
            for c in instructions:
                desc, separator = generate_instruction(c, grammar, game.infos, game.world, counts)
                actions_desc_list.append(desc)
                if c != instructions[-1] and len(separator) > 0:
                    actions_desc_list.append(separator)
            actions_desc = " ".join(actions_desc_list)

        if only_one_action:
            quest_tag = grammar.get_random_expansion("#quest_one_action#")
            quest_tag = quest_tag.replace("(action)", actions_desc.strip())

        else:
            quest_tag = grammar.get_random_expansion("#quest#")
            quest_tag = quest_tag.replace("(list_of_actions)", actions_desc.strip())

        event_desc = grammar.expand(quest_tag)
        event_desc = re.sub(r"(^|(?<=[?!.]))\s*([a-z])",
                            lambda pat: pat.group(1) + ' ' + pat.group(2).upper(),
                            event_desc)

    return event_desc
Пример #3
0
    def generate_name_force_numbered(self):
        suffix = '_1'

        grammar = Grammar(flags={'allowed_variables_numbering': True})
        name, adj, noun = grammar.generate_name('object', 'vault', False, exclude=ContainsEveryObjectContainer())
        self.assertTrue(name.endswith(suffix), 'Checking name ends with suffix')
        self.assertTrue(adj.endswith(suffix), 'Checking adj ends with suffix')
        self.assertTrue(noun.endswith(suffix), 'Checking noun ends with suffix')
Пример #4
0
def generate_text_from_grammar(game, grammar: Grammar):
    include_adj = grammar.flags.get("include_adj", False)
    only_last_action = grammar.flags.get("only_last_action", False)
    blend_instructions = grammar.flags.get("blend_instructions", False)
    blend_descriptions = grammar.flags.get("blend_descriptions", False)
    ambiguous_instructions = grammar.flags.get("ambiguous_instructions", False)

    # Assign a specific room type and name to our rooms
    for room in game.world.rooms:
        # First, generate a unique roomtype and name from the grammar
        if game.infos[room.id].room_type is None and grammar.has_tag(
                "#room_type#"):
            game.infos[room.id].room_type = grammar.expand("#room_type#")

        assign_name_to_object(room, grammar, game.infos, include_adj)

        # Next, assure objects contained in a room must have the same room type
        for obj in game.world.get_all_objects_in(room):
            if game.infos[obj.id].room_type is None:
                game.infos[obj.id].room_type = game.infos[room.id].room_type

    # Objects in inventory can be of any room type.
    for obj in game.world.get_objects_in_inventory():
        if game.infos[obj.id].room_type is None and grammar.has_tag(
                "#room_type#"):
            game.infos[obj.id].room_type = grammar.expand("#room_type#")

    # We have to "count" all the adj/noun/types in the world
    # This is important for using "unique" but abstracted references to objects
    counts = OrderedDict()
    counts["adj"] = CountOrderedDict()
    counts["noun"] = CountOrderedDict()
    counts["type"] = CountOrderedDict()

    # Assign name and description to objects.
    for obj in game.world.objects:
        if obj.type in ["I", "P"]:
            continue

        obj_infos = game.infos[obj.id]
        assign_name_to_object(obj, grammar, game.infos, include_adj)
        assign_description_to_object(obj, grammar, game.infos)

        counts['adj'][obj_infos.adj] += 1
        counts['noun'][obj_infos.noun] += 1
        counts['type'][obj.type] += 1

    # Generate the room descriptions.
    for room in game.world.rooms:
        assign_description_to_room(room, game, grammar, blend_descriptions)

    # Generate the instructions.
    for quest in game.quests:
        assign_description_to_quest(quest, game, grammar, counts,
                                    only_last_action, blend_instructions,
                                    ambiguous_instructions)

    return game
Пример #5
0
 def split_name_adj_noun_fail(self):
     """
     What happens if we have too many separators?
     """
     grammar = Grammar()
     try:
         grammar.split_name_adj_noun('A|B|C', True)
         self.assertTrue(False, "We should have errored about too many separators")
     except ValueError:
         pass
Пример #6
0
 def test_grammar_get_random_expansion_fail(self):
     """
     Tests failure when getting a non-existent flag
     (unsuccess used in names as _fail is a special flag in nosetests)
     """
     grammar = Grammar()
     bad_tag_name = 'fahawagads'
     try:
         grammar.get_random_expansion(tag=bad_tag_name)
         self.assertTrue(False, "We should have errored with a value error about a non-existent tag")
     except ValueError as e:
         self.assertTrue(bad_tag_name in str(e), "Tag name does not occur in error message")
Пример #7
0
def generate_text_from_grammar(game, grammar: Grammar):
    # Assign a specific room type and name to our rooms
    for room in game.world.rooms:
        # First, generate a unique roomtype and name from the grammar
        if game.infos[room.id].room_type is None and grammar.has_tag(
                "#room_type#"):
            game.infos[room.id].room_type = grammar.expand("#room_type#")

        assign_name_to_object(room, grammar, game.infos)

        # Next, assure objects contained in a room must have the same room type
        for obj in game.world.get_all_objects_in(room):
            if game.infos[obj.id].room_type is None:
                game.infos[obj.id].room_type = game.infos[room.id].room_type

    # Objects in inventory can be of any room type.
    for obj in game.world.get_objects_in_inventory():
        if game.infos[obj.id].room_type is None and grammar.has_tag(
                "#room_type#"):
            game.infos[obj.id].room_type = grammar.expand("#room_type#")

    # Assign name and description to objects.
    for obj in game.world.objects:
        if obj.type in ["I", "P"]:
            continue

        assign_name_to_object(obj, grammar, game.infos)
        assign_description_to_object(obj, grammar, game.infos)

    # Generate the room descriptions.
    for room in game.world.rooms:
        if game.infos[
                room.
                id].desc is None:  # Skip rooms which already have a description.
            game.infos[room.id].desc = assign_description_to_room(
                room, game, grammar)

    # Generate the instructions.
    for quest in game.quests:
        if quest.desc is None:  # Skip quests which already have a description.
            quest.desc = assign_description_to_quest(quest, game, grammar)

    if grammar.options.only_last_action and len(game.quests) > 1:
        main_quest = Quest(
            actions=[quest.actions[-1] for quest in game.quests])
        only_last_action_bkp = grammar.options.only_last_action
        grammar.options.only_last_action = False
        game.objective = assign_description_to_quest(main_quest, game, grammar)
        grammar.options.only_last_action = only_last_action_bkp

    return game
Пример #8
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.
        """

        version = data.get("version", cls._SERIAL_VERSION)
        if version != cls._SERIAL_VERSION:
            raise ValueError(
                "Cannot deserialize a TextWorld version {} game, expected version {}"
                .format(version, cls._SERIAL_VERSION))

        world = World.deserialize(data["world"])
        game = cls(world)
        game.grammar = Grammar(data["grammar"])
        game.quests = tuple([Quest.deserialize(d) for d in data["quests"]])
        game._infos = {k: EntityInfo.deserialize(v) for k, v in data["infos"]}
        game.kb = KnowledgeBase.deserialize(data["KB"])
        game.metadata = data.get("metadata", {})
        game._objective = data.get("objective", None)
        game.extras = data.get("extras", {})
        if "main_quest" in data:
            game.main_quest = Quest.deserialize(data["main_quest"])

        return game
Пример #9
0
def extract_vocab(grammar_options: GrammarOptions,
                  kb: Optional[KnowledgeBase] = None) -> List[str]:
    kb = kb or KnowledgeBase.default()

    # Extract words from logic.
    text = kb.logic.serialize()

    # Extract words from text grammar.
    rng_grammar = np.random.RandomState(
        1234)  # Fix generator. #XXX really needed?
    grammar = Grammar(grammar_options, rng=rng_grammar)
    grammar_words = grammar.get_vocabulary()

    text += " ".join(set(grammar_words)).lower()

    # Strip out all non-alphanumeric characters.
    text = re.sub(r"[^a-z0-9\-_ ']", " ", text)
    words = text.split()
    vocab = sorted(set(words))

    return vocab
Пример #10
0
def extract_vocab(games: Iterable[Game]) -> List[str]:
    i7_pattern = re.compile(r'\[[^]]*\]')  # Found in object descriptions.

    text = ""
    seen = set()
    for game in games:
        if game.kb not in seen:
            seen.add(game.kb)
            # Extract words from logic (only stuff related to Inform7).
            text += game.kb.inform7_addons_code + "\n"
            text += " ".join(game.kb.inform7_commands.values()) + "\n"
            text += " ".join(game.kb.inform7_events.values()) + "\n"
            text += " ".join(game.kb.inform7_variables.values()) + "\n"
            text += " ".join(game.kb.inform7_variables.values()) + "\n"
            text += " ".join(
                t for t in game.kb.inform7_variables_description.values()
                if t) + "\n"

        if game.grammar.options.uuid not in seen:
            seen.add(game.grammar.options.uuid)
            # Extract words from text grammar.
            grammar = Grammar(game.grammar.options)
            grammar_words = grammar.get_vocabulary()
            text += " ".join(set(grammar_words)).lower() + "\n"

        # Parse game specific entity names and descriptions.
        text += game.objective + "\n"
        for infos in game.infos.values():
            if infos.name:
                text += infos.name + " "

            if infos.desc:
                text += i7_pattern.sub(" ", infos.desc) + "\n"

    # Next strip out all non-alphabetic characters
    text = re.sub(r"[^a-z0-9\-_ ']", " ", text.lower())
    words = text.split()
    vocab = sorted(set(word.strip("-'_") for word in words))
    return vocab
Пример #11
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"])
        game = cls(world)
        game.grammar = Grammar(data["grammar"])
        game.quests = tuple([Quest.deserialize(d) for d in data["quests"]])
        game._infos = {k: EntityInfo.deserialize(v) for k, v in data["infos"]}
        game.kb = KnowledgeBase.deserialize(data["KB"])
        game.metadata = data.get("metadata", {})
        game._objective = data.get("objective", None)
        return game
Пример #12
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
Пример #13
0
def make_grammar(options: Mapping = {},
                 rng: Optional[RandomState] = None) -> Grammar:
    rng = g_rng.next() if rng is None else rng
    grammar = Grammar(options, rng)
    grammar.check()
    return grammar
Пример #14
0
 def test_grammar_eq2(self):
     grammar = Grammar(options={'theme': 'house'})
     grammar2 = Grammar(options={'theme': 'basic'})
     self.assertNotEqual(
         grammar, grammar2,
         "Testing two different grammar files are not equal")
Пример #15
0
 def test_grammar_eq(self):
     grammar = Grammar()
     grammar2 = Grammar()
     self.assertEqual(grammar, grammar2, "Testing two grammar files are equivalent")
Пример #16
0
 def test_get_all_nouns_for_type(self):
     grammar = Grammar()
     result = grammar.get_all_nouns_for_type('d')
     self.assertNotEqual(len(result), 0, 'No nouns for door type found')
Пример #17
0
 def test_get_all_adj_for_type(self):
     grammar = Grammar()
     result = grammar.get_all_adjective_for_type('d')
     self.assertNotEqual(len(result), 0, 'No adjectives for door type found')
Пример #18
0
 def test_get_all_expansions_for_tag(self):
     grammar = Grammar()
     result = grammar.get_all_expansions_for_tag('#clean_(r)#')
     self.assertNotEqual(len(result), 0, 'No expansions for library tag found')
Пример #19
0
 def test_get_all_expansions_for_tag_not_existing(self):
     grammar = Grammar()
     result = grammar.get_all_expansions_for_tag('fahawagads')
     self.assertEqual(len(result), 0, 'Result is not empty')
Пример #20
0
 def test_grammar_eq2(self):
     grammar = Grammar()
     grammar2 = Grammar(flags={'unused': 'flag'})
     self.assertNotEqual(grammar, grammar2, "Testing two different grammar files are not equal")