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