def generate_instruction()

in textworld/generator/text_generation.py [0:0]


def generate_instruction(action, grammar, game, counts):
    """
    Generate text instruction for a specific action.
    """
    # Get the more precise command tag.
    cmd_tag = "#{}#".format(action.name)
    if not grammar.has_tag(cmd_tag):
        cmd_tag = "#{}#".format(action.name.split("-")[0])

        if not grammar.has_tag(cmd_tag):
            cmd_tag = "#{}#".format(action.name.split("-")[0].split("/")[0])

    separator_tag = "#action_separator_{}#".format(action.name)
    if not grammar.has_tag(separator_tag):
        separator_tag = "#action_separator_{}#".format(action.name.split("-")[0])

        if not grammar.has_tag(separator_tag):
            separator_tag = "#action_separator_{}#".format(action.name.split("-")[0].split("/")[0])

    if not grammar.has_tag(separator_tag):
        separator_tag = "#action_separator#"

    if not grammar.has_tag(separator_tag):
        separator = ""
    else:
        separator = grammar.expand(separator_tag)

    desc = grammar.expand(cmd_tag)

    # We generate a custom mapping.
    mapping = OrderedDict()
    if isinstance(action, MergeAction):
        action_mapping = action.mapping
    else:
        action_mapping = game.kb.rules[action.name].match(action)

    for ph, var in action_mapping.items():
        if var.type == "r":

            # We can use a simple description for the room
            r = game.world.find_room_by_id(var.name)  # Match on 'name'
            if r is None:
                mapping[ph.name] = ''
            else:
                mapping[ph.name] = game.infos[r.id].name
        elif var.type in ["P", "I"]:
            continue
        else:
            # We want a more complex description for the objects
            obj = game.world.find_object_by_id(var.name)
            obj_infos = game.infos[obj.id]

            if grammar.options.ambiguous_instructions:
                assert False, "not tested"
                choices = []

                for t in ["adj", "noun", "type"]:
                    if counts[t][getattr(obj_infos, t)] <= 1:
                        if t == "noun":
                            choices.append(getattr(obj_infos, t))
                        elif t == "type":
                            choices.append(game.kb.types.get_description(getattr(obj_infos, t)))
                        else:
                            # For adj, we pick an abstraction on the type
                            atype = game.kb.types.get_description(grammar.rng.choice(game.kb.types.get_ancestors(obj.type)))
                            choices.append("{} {}".format(getattr(obj_infos, t), atype))

                # If we have no possibilities, use the name (ie. prioritize abstractions)
                if len(choices) == 0:
                    choices.append(obj_infos.name)

                mapping[ph.name] = grammar.rng.choice(choices)
            else:
                mapping[ph.name] = obj_infos.name

    # Replace the keyword with one of the possibilities
    for keyword in re.findall(r'[(]\S*[)]', desc + separator):
        for key in keyword[1:-1].split("|"):
            if key in mapping:
                desc = desc.replace(keyword, mapping[key])
                separator = separator.replace(keyword, mapping[key])

    return desc, separator