def test_reloading_game_with_custom_kb(): twl = KnowledgeBase.default().logic._document twl += """ type customobj : o { inform7 { type { kind :: "custom-obj-like"; } } } """ logic = GameLogic.parse(twl) options = GameOptions() options.kb = KnowledgeBase(logic, "") M = GameMaker(options) room = M.new_room("room") M.set_player(room) custom_obj = M.new(type='customobj', name='customized object') M.inventory.add(custom_obj) commands = ["drop customized object"] quest = M.set_quest_from_commands(commands) assert quest.commands == tuple(commands) game = M.build() assert game == Game.deserialize(game.serialize())
def setUpClass(cls): M = GameMaker() # The goal commands = ["go east", "insert carrot into chest"] # Create a 'bedroom' room. R1 = M.new_room("bedroom") R2 = M.new_room("kitchen") M.set_player(R1) path = M.connect(R1.east, R2.west) path.door = M.new(type='d', name='wooden door') path.door.add_property("open") carrot = M.new(type='f', name='carrot') M.inventory.add(carrot) # Add a closed chest in R2. chest = M.new(type='c', name='chest') chest.add_property("open") R2.add(chest) cls.failing_conditions = (Proposition("eaten", [carrot.var]),) cls.quest = M.set_quest_from_commands(commands) cls.quest.set_failing_conditions(cls.failing_conditions) cls.game = M.build()
def setUpClass(cls): M = GameMaker() # The goal commands = ["open wooden door", "go west", "take carrot", "go east", "drop carrot"] # Create a 'bedroom' room. R1 = M.new_room("bedroom") R2 = M.new_room("kitchen") M.set_player(R2) path = M.connect(R1.east, R2.west) path.door = M.new(type='d', name='wooden door') path.door.add_property("closed") carrot = M.new(type='f', name='carrot') R1.add(carrot) # Add a closed chest in R2. chest = M.new(type='c', name='chest') chest.add_property("open") R2.add(chest) cls.quest = M.set_quest_from_commands(commands) cls.game = M.build()
def setUpClass(cls): M = GameMaker() # Create a 'bedroom' room. R1 = M.new_room("bedroom") R2 = M.new_room("kitchen") M.set_player(R2) path = M.connect(R1.east, R2.west) path.door = M.new(type='d', name='wooden door') path.door.add_property("closed") carrot = M.new(type='f', name='carrot') lettuce = M.new(type='f', name='lettuce') R1.add(carrot) R1.add(lettuce) # Add a closed chest in R2. chest = M.new(type='c', name='chest') chest.add_property("open") R2.add(chest) # The goals commands = [ "open wooden door", "go west", "take carrot", "go east", "drop carrot" ] cls.eventA = M.new_event_using_commands(commands) commands = [ "open wooden door", "go west", "take lettuce", "go east", "insert lettuce into chest" ] cls.eventB = M.new_event_using_commands(commands) cls.losing_eventA = Event(conditions={M.new_fact("eaten", carrot)}) cls.losing_eventB = Event(conditions={M.new_fact("eaten", lettuce)}) cls.questA = Quest(win_events=[cls.eventA], fail_events=[cls.losing_eventA]) cls.questB = Quest(win_events=[cls.eventB], fail_events=[cls.losing_eventB]) cls.questC = Quest(win_events=[], fail_events=[cls.losing_eventA, cls.losing_eventB]) commands = ["open wooden door", "go west", "take carrot", "eat carrot"] cls.eating_carrot = M.new_event_using_commands(commands) commands = [ "open wooden door", "go west", "take lettuce", "eat lettuce" ] cls.eating_lettuce = M.new_event_using_commands(commands) commands = [ "open wooden door", "go west", "take lettuce", "go east", "insert lettuce into chest" ] M.quests = [cls.questA, cls.questB, cls.questC] cls.game = M.build()
def make_game() -> textworld.Game: maker = GameMaker(game_options) rng_grammar = rngs["grammar"] maker.grammar = textworld.generator.make_grammar(maker.options.grammar, rng=rng_grammar) place_rooms(maker) if config.verbose: print() print("====== Placing furniture ======") place_furniture(maker) if config.verbose: print() print("====== Placing objects ======") placed_objects = place_objects(maker) if config.verbose: print() print("====== Shuffling objects ======") move_objects(maker, placed_objects) if config.verbose and config.distractors: print() print("====== Placing distractors ======") place_distractors(maker) set_container_properties(maker) limit_inventory_size(maker) maker.quests = generate_quests(maker, placed_objects) check_properties(maker) uuid = generate_uuid(maker) game = maker.build() set_metadata(maker, game, placed_objects) if config.verbose: print() print("====== Goal Locations ======") for obj, locations in game.metadata["goal_locations"].items(): print(f'{obj} ->', ", ".join(locations)) game_options.path = pjoin(config.output_dir, uuid) return textworld.generator.compile_game(game, game_options)
def test_game_without_a_quest(self): M = GameMaker() room = M.new_room() M.set_player(room) item = M.new(type="o") room.add(item) game = M.build() game_progress = GameProgression(game) assert not game_progress.done # Simulate action that doesn't change the world. action = game_progress.valid_actions[0] game_progress.update(action) assert not game_progress.done
def build_and_compile_playground_game(): M = GameMaker() room_dr = M.new_room("Locker Room") room_mr = M.new_room("Meeting Room") room_fl = M.new_room("Field") team_mates = M.new(type='tm', name = "teammates") captain = M.new(type='tm3', name = "captain") room_dr.add(team_mates) room_mr.add(captain) corridor = M.connect(room_dr.east, room_mr.west) corridor1 = M.connect(room_mr.east, room_fl.west) #corridor2 = M.connect(room_fl.east, new_room.west) M.set_player(room_dr) team_mates_2 = M.new(type='tm2', name = "someone") room_dr.add(team_mates_2) game_gear = M.new(type='ap', name = "game gears") room_dr.add(game_gear) M.add_fact("not_equiped", game_gear) M.add_fact("not_participated", captain) M.add_fact("not_helped", team_mates) M.add_fact("not_disturbed", team_mates) M.add_fact("not_bully", team_mates) room_dr.infos.desc = "You are in the Locker room with your team mates. You will find your game gears here. Collect the game gears and wear them before the meeting. If you need help, ask help from others and be helpful to others as well. \n After your are done here, go to the meeting room." room_mr.infos.desc = "You are in the meeting room. A meeting is going to start to finalize the game plan. Join the meeting and try to share your thought." captain.infos.desc = "The meeting is leading by the captain. Please, Cooperate with him." failed_event_1 = Event(conditions={ M.new_fact("not_equiped", game_gear), M.new_fact("at", M._entities['P'], room_mr)}) failed_quest_1 = Quest(win_events=[], fail_events=[failed_event_1]) #M.quests = [failed_quest_1] game = M.build() game_file = _compile_test_game(game) return game, game_file
def setUpClass(cls): M = GameMaker() room = M.new_room("room") M.set_player(room) carrot = M.new(type='f', name='carrot') lettuce = M.new(type='f', name='lettuce') room.add(carrot) room.add(lettuce) chest = M.new(type='c', name='chest') chest.add_property("open") room.add(chest) # The goals commands = ["take carrot", "insert carrot into chest"] cls.eventA = M.new_event_using_commands(commands) commands = ["take lettuce", "insert lettuce into chest", "close chest"] event = M.new_event_using_commands(commands) cls.eventB = Event(actions=event.actions, conditions={ M.new_fact("in", lettuce, chest), M.new_fact("closed", chest) }) cls.fail_eventA = Event(conditions={M.new_fact("eaten", carrot)}) cls.fail_eventB = Event(conditions={M.new_fact("eaten", lettuce)}) cls.quest = Quest(win_events=[cls.eventA, cls.eventB], fail_events=[cls.fail_eventA, cls.fail_eventB]) commands = ["take carrot", "eat carrot"] cls.eating_carrot = M.new_event_using_commands(commands) commands = ["take lettuce", "eat lettuce"] cls.eating_lettuce = M.new_event_using_commands(commands) commands = ["take lettuce", "insert lettuce into chest"] M.quests = [cls.quest] cls.game = M.build()
def setUpClass(cls): M = GameMaker() # The goal commands = ["go east", "insert carrot into chest"] # Create a 'bedroom' room. R1 = M.new_room("bedroom") R2 = M.new_room("kitchen") M.set_player(R1) path = M.connect(R1.east, R2.west) path.door = M.new(type='d', name='wooden door') path.door.add_property("open") carrot = M.new(type='f', name='carrot') M.inventory.add(carrot) # Add a closed chest in R2. chest = M.new(type='c', name='chest') chest.add_property("open") R2.add(chest) cls.eventA = M.new_event_using_commands(commands) cls.eventB = Event(conditions={ M.new_fact("at", carrot, R1), M.new_fact("closed", path.door) }) cls.eventC = Event(conditions={M.new_fact("eaten", carrot)}) cls.eventD = Event(conditions={ M.new_fact("closed", chest), M.new_fact("closed", path.door) }) cls.quest = Quest(win_events=[cls.eventA, cls.eventB], fail_events=[cls.eventC, cls.eventD], reward=2) M.quests = [cls.quest] cls.game = M.build() cls.inform7 = Inform7Game(cls.game)
def setUpClass(cls): M = GameMaker() # The goal commands = ["take carrot", "insert carrot into chest"] R1 = M.new_room("room") M.set_player(R1) carrot = M.new(type='f', name='carrot') R1.add(carrot) # Add a closed chest in R2. chest = M.new(type='c', name='chest') chest.add_property("open") R1.add(chest) cls.event = M.new_event_using_commands(commands) cls.actions = cls.event.actions cls.conditions = {M.new_fact("in", carrot, chest)} cls.game = M.build() commands = ["take carrot", "eat carrot"] cls.eating_carrot = M.new_event_using_commands(commands)
class TWCGameMaker: def __init__(self, config): self.config = config self.data = TWCData(config) self.maker = GameMaker(config.game_options) self.num_games = 0 def reset(self): self.maker = GameMaker(self.config.game_options) def make_game(self): rng_grammar = self.config.rngs["grammar"] self.maker.grammar = textworld.generator.make_grammar(self.maker.options.grammar, rng=rng_grammar) self.place_rooms() placed_objects = [] while len(placed_objects) < self.config.objects: if self.config.verbose: print() print("====== Placing furniture ======") furniture = self.place_furniture() if not furniture: print() print(f"Could not generate the game with the provided configuration") sys.exit(-1) if self.config.verbose: print() print("====== Placing objects ======") placed_objects += self.place_objects() assert len(placed_objects) == len(set(placed_objects)) if self.config.verbose: print() print("====== Shuffling objects ======") self.move_objects(placed_objects) if self.config.verbose and self.config.distractors: print() print("====== Placing distractors ======") self.place_distractors() self.set_container_properties() self.limit_inventory_size() self.maker.quests = self.generate_quests(placed_objects) self.check_properties() uuid = self.generate_uuid() game = self.maker.build() self.num_games += 1 self.set_metadata(game, placed_objects) if self.config.verbose: print() print("====== Goal Locations ======") for obj, locations in game.metadata["goal_locations"].items(): print(f'{obj} ->', ", ".join(locations)) self.config.game_options.path = pjoin(self.config.output_dir, uuid) result = textworld.generator.compile_game(game, self.config.game_options) self.reset() return result def place_rooms(self): rng = self.config.rngs["map"] assert self.config.rooms <= len(self.data.rooms) initial_room = self.config.initial_room or rng.choice(self.data.rooms) rooms_to_place = self.pick_rooms(initial_room) if self.config.verbose: print("Rooms:", rooms_to_place) self.create_map(rooms_to_place) room = self.maker.find_by_name(initial_room) self.maker.set_player(room) def pick_name(self, names): rng = self.config.rngs["objects"] names = list(names) rng.shuffle(names) for name in names: if self.maker.find_by_name(name) is None: return name assert False def pick_rooms(self, initial_room): assert self.config.rooms <= len(self.data.rooms) rng = self.config.rngs["map"] visited = {initial_room} neighbors = set(self.data.map[initial_room]) neighbors -= visited while len(visited) < self.config.rooms: room = rng.choice(list(neighbors)) visited.add(room) neighbors |= set(self.data.map[room]) neighbors -= visited return list(visited) def pick_correct_location(self, locations): rng = self.config.rngs["objects"] locations = list(locations) rng.shuffle(locations) for location in locations: holder = None if "." in location: room_name = location.split(".")[0] holder_name = location.split(".")[1] room = self.maker.find_by_name(room_name) if room is not None: holder = next((e for e in room.content if e.infos.name == holder_name), None) else: holder = self.maker.find_by_name(location) if holder: return holder return None def pick_wrong_object_location(self, object_name, prefer_correct_room=None): rng = self.config.rngs["objects"] correct_locations = self.data.objects[object_name]["locations"] rng.shuffle(correct_locations) holder_names = {location.split(".")[-1] for location in correct_locations} forbidden = illegal_locations(self.data.objects[object_name]) holder_names |= forbidden if prefer_correct_room is None: prefer_correct_room = self.config.isolated_rooms assert prefer_correct_room in [True, False] correct_room = self.find_correct_room(object_name) # Try to pick location in correct room if correct_room and prefer_correct_room: room_furniture = [e for e in correct_room.content if e.infos.type in ["c", "s"]] wrong_holders = [e for e in room_furniture if e.infos.name not in holder_names] if FLOOR not in holder_names: wrong_holders.append(correct_room) rng.shuffle(wrong_holders) if len(wrong_holders) > 0: return wrong_holders[0] # Pick a random supporter or container all_supporters = list(self.maker.findall("s")) all_containers = list(self.maker.findall("c")) all_rooms = self.maker.rooms all_holders = all_supporters + all_containers if FLOOR not in holder_names: all_holders += all_rooms rng.shuffle(all_holders) wrong_holders = [e for e in all_holders if e.infos.name not in holder_names] if len(wrong_holders) > 0: return wrong_holders[0] # No wrong location found. Create new furniture pool = [f for f in self.data.locations.keys() if f not in holder_names] return self.place_random_entity(pool) def find_correct_room(self, object_name): correct_locations = self.data.objects[object_name]["locations"] holder_names = {location.split(".")[-1] for location in correct_locations} for location in correct_locations: if "." in location: room_name = location.split(".")[0] return self.maker.find_by_name(room_name) for holder_name in holder_names: holder = self.maker.find_by_name(holder_name) if holder: return holder.parent def place_at(self, name, holder): entity = self.maker.new(type=self.data.entities[name]["type"], name=name) entity.infos.noun = name if "adjs" in self.data.entities[name] and self.data.entities[name]["adjs"]: entity.infos.adj = self.data.entities[name]["adjs"][0] if "desc" in self.data.entities[name]: entity.infos.desc = self.data.entities[name]["desc"][0] if "indefinite" in self.data.entities[name]: entity.infos.indefinite = self.data.entities[name]["indefinite"] for property_ in self.data.entities[name]["properties"]: entity.add_property(property_) holder.add(entity) self.log_entity_placement(entity, holder) return entity def log_entity_placement(self, entity, holder): name = entity.infos.name if self.config.verbose: if self.data.entities[name]["category"] == "furniture": print(f"{entity.infos.name} added to the {holder.infos.name}") elif holder.type == "r": print(f"{entity.infos.name} added to the floor in the {holder.infos.name}") else: print(f"{entity.infos.name} added to the {holder.infos.name} in the {holder.parent.infos.name}") def attempt_place_entity(self, name): if self.maker.find_by_name(name): return holder = self.pick_correct_location(self.data.entities[name]["locations"]) if holder is None: return None return self.place_at(name, holder) def place_entities(self, names): return [self.attempt_place_entity(name) for name in names] def place_random_entities(self, nb_entities, pool=None): rng = self.config.rngs["objects"] if pool is None: pool = list(self.data.entities.keys()) if len(pool) == 0: return [] seen = set(e.name for e in self.maker._entities.values()) candidates = [name for name in pool if name not in seen] rng.shuffle(candidates) entities = [] for candidate in candidates: if len(entities) >= nb_entities: break entity = self.attempt_place_entity(candidate) if entity: entities.append(entity) return entities def place_random_entity(self, pool): entities = self.place_random_entities(1, pool) return entities[0] if entities else None def place_random_furniture(self, nb_furniture): return self.place_random_entities(nb_furniture, self.data.locations.keys()) def make_graph_map(self, rooms, size=(5, 5)): rng = self.config.rngs["map"] walker = RandomWalk(neighbors=self.data.map, size=size, rng=rng) return walker.place_rooms(rooms) def create_map(self, rooms_to_place): graph = self.make_graph_map(rooms_to_place) rooms = self.maker.import_graph(graph) for infos in self.data.doors: room1 = self.maker.find_by_name(infos["path"][0]) room2 = self.maker.find_by_name(infos["path"][1]) if room1 is None or room2 is None: continue # This door doesn't exist in this world. path = self.maker.find_path(room1, room2) if path: assert path.door is None name = self.pick_name(infos["names"]) door = self.maker.new_door(path, name) door.add_property("closed") return rooms def find_correct_locations(self, obj): name = obj.infos.name locations = self.data.objects[name]["locations"] result = [] for location in locations: if "." in location: room_name = location.split(".")[0] holder_name = location.split(".")[1] room = self.maker.find_by_name(room_name) if room is not None: result += [e for e in room.content if e.infos.name == holder_name] else: holder = self.maker.find_by_name(location) if holder: result.append(holder) return result def generate_quest(self, obj): quests = [] locations = self.find_correct_locations(obj) assert len(locations) > 0 conditions = [self.maker.new_fact(preposition_of(location), obj, location) for location in locations] events = [Event(conditions={c}) for c in conditions] place_quest = Quest(win_events=events, reward=self.config.reward) quests.append(place_quest) if self.config.intermediate_reward > 0: current_location = obj.parent if current_location == self.maker.inventory: return quests take_cond = self.maker.new_fact('in', obj, self.maker.inventory) events = [Event(conditions={take_cond})] take_quest = Quest(win_events=events, reward=int(self.config.intermediate_reward)) quests.append(take_quest) return quests def generate_goal_locations(self, objs): result = {obj.infos.name: [] for obj in objs} for obj in objs: locations = self.find_correct_locations(obj) for loc in locations: result[obj.infos.name].append(loc.infos.name) return result def generate_quests(self, objs): return [q for obj in objs for q in self.generate_quest(obj)] def set_metadata(self, game, placed_objects): game.objective = INTRO + " " + GOAL config = dict(vars(self.config)) del config['game_options'] del config['rngs'] metadata = { "seeds": self.maker.options.seeds, "config": config, "entities": [e.name for e in self.maker._entities.values() if e.name], "max_score": sum(quest.reward for quest in game.quests), "goal": GOAL, "goal_locations": self.generate_goal_locations(placed_objects), "uuid": self.generate_uuid() } game.metadata = metadata def generate_uuid(self): uuid = "tw-iqa-cleanup-{specs}-{seeds}" seeds = self.maker.options.seeds uuid = uuid.format(specs=prettify_config(self.config), seeds=encode_seeds([seeds[k] + self.num_games for k in sorted(seeds)])) return uuid def check_properties(self): for entity in self.maker._entities.values(): if entity.type in ["c", "d"] and not \ (entity.has_property("closed") or entity.has_property("open") or entity.has_property("locked")): raise ValueError("Forgot to add closed/locked/open property for '{}'.".format(entity.name)) def limit_inventory_size(self): inventory_limit = self.config.objects * 2 nb_objects_in_inventory = self.config.objects - self.config.take if self.config.drop: inventory_limit = max(1, nb_objects_in_inventory) for i in range(inventory_limit): slot = self.maker.new(type="slot", name="") if i < len(self.maker.inventory.content): slot.add_property("used") else: slot.add_property("free") self.maker.nowhere.append(slot) def set_container_properties(self): if not self.config.open: for entity in self.maker._entities.values(): if entity.has_property("closed"): entity.remove_property("closed") entity.add_property("open") def place_distractors(self): rng_objects = self.config.rngs["objects"] nb_objects = self.config.objects if self.config.distractors: nb_distractors = max(0, int(rng_objects.randn(1) * 3 + nb_objects)) self.place_random_entities(nb_distractors, pool=list(self.data.objects.keys())) def move_objects(self, placed_objects): rng_quest = self.config.rngs["quest"] nb_objects_in_inventory = self.config.objects - self.config.take shuffled_objects = list(placed_objects) rng_quest.shuffle(shuffled_objects) for obj in shuffled_objects[:nb_objects_in_inventory]: self.maker.move(obj, self.maker.inventory) for obj in shuffled_objects[nb_objects_in_inventory:]: wrong_location = self.pick_wrong_object_location(obj.infos.name) self.maker.move(obj, wrong_location) self.log_entity_placement(obj, wrong_location) return nb_objects_in_inventory def objects_by_furniture(self, furniture): result = [] for o in self.data.objects: locations = [loc.split(".")[-1] for loc in self.data.objects[o]["locations"]] if furniture in locations: result.append(o) return result def evenly_place_objects(self): all_supporters = list(self.maker.findall("s")) all_containers = list(self.maker.findall("c")) furniture = all_supporters + all_containers objects_per_furniture = self.config.objects // len(furniture) placed = [] for holder in furniture: pool = self.objects_by_furniture(holder.infos.name) placed += self.place_random_entities(objects_per_furniture, pool) remainder = self.config.objects - len(placed) placed += self.place_random_entities(remainder, list(self.data.objects.keys())) return placed def place_objects(self, distribute_evenly=True): rng = self.config.rngs["objects"] if distribute_evenly is None: distribute_evenly = rng.choice([True, False]) if distribute_evenly: return self.evenly_place_objects() placed_objects = self.place_random_entities(self.config.objects, list(self.data.objects.keys())) return placed_objects def evenly_place_furniture(self, nb_furniture): furniture_per_room = nb_furniture // self.config.rooms placed = [] for room in self.maker.rooms: room_name = room.infos.name pool = [k for k, v in self.data.locations.items() if room_name in v["locations"]] placed += self.place_random_entities(furniture_per_room, pool) remainder = nb_furniture - len(placed) placed += self.place_random_furniture(remainder) return placed def place_furniture(self, distribute_evenly=True): rng = self.config.rngs["objects"] if distribute_evenly is None: distribute_evenly = rng.choice([True, False]) self.place_entities(DEFAULT_FURNITURE) upper_bound = max(2 * len(self.maker.rooms), 0.33 * self.config.objects) nb_furniture = rng.randint(len(self.maker.rooms), min(upper_bound, len(self.data.locations) + 1)) if distribute_evenly: return self.evenly_place_furniture(nb_furniture) else: return self.place_random_furniture(nb_furniture)
def test_cycle_in_winning_policy(cls): M = GameMaker() # Create a map. # r0 # | # r1 -- r2 # | | # r3 -- r4 R0 = M.new_room("r0") R1 = M.new_room("r1") R2 = M.new_room("r2") R3 = M.new_room("r3") R4 = M.new_room("r4") M.set_player(R1) M.connect(R0.south, R1.north), M.connect(R1.east, R2.west), M.connect(R3.east, R4.west) M.connect(R1.south, R3.north) M.connect(R2.south, R4.north) carrot = M.new(type='f', name='carrot') R0.add(carrot) apple = M.new(type='f', name='apple') R2.add(apple) commands = ["go north", "take carrot"] M.set_quest_from_commands(commands) game = M.build() game_progression = GameProgression(game) def _apply_command(command, game_progression): valid_commands = gen_commands_from_actions(game_progression.valid_actions, game.infos) for action, cmd in zip(game_progression.valid_actions, valid_commands): if command == cmd: game_progression.update(action) return raise ValueError("Not a valid command: {}. Expected: {}".format(command, valid_commands)) _apply_command("go south", game_progression) expected_commands = ["go north"] + commands winning_commands = gen_commands_from_actions(game_progression.winning_policy, game.infos) assert winning_commands == expected_commands, "{} != {}".format(winning_commands, expected_commands) _apply_command("go east", game_progression) _apply_command("go north", game_progression) expected_commands = ["go south", "go west", "go north"] + commands winning_commands = gen_commands_from_actions(game_progression.winning_policy, game.infos) assert winning_commands == expected_commands, "{} != {}".format(winning_commands, expected_commands) _apply_command("go west", game_progression) # Found shortcut expected_commands = commands winning_commands = gen_commands_from_actions(game_progression.winning_policy, game.infos) assert winning_commands == expected_commands, "{} != {}".format(winning_commands, expected_commands) # Quest where player's has to pick up the carrot first. commands = ["go east", "take apple", "go west", "go north", "drop apple"] M.set_quest_from_commands(commands) game = M.build() game_progression = GameProgression(game) _apply_command("go south", game_progression) expected_commands = ["go north"] + commands winning_commands = gen_commands_from_actions(game_progression.winning_policy, game.infos) assert winning_commands == expected_commands, "{} != {}".format(winning_commands, expected_commands) _apply_command("go east", game_progression) expected_commands = ["go west", "go north"] + commands winning_commands = gen_commands_from_actions(game_progression.winning_policy, game.infos) assert winning_commands == expected_commands, "{} != {}".format(winning_commands, expected_commands) _apply_command("go north", game_progression) # Found shortcut expected_commands = commands[1:] winning_commands = gen_commands_from_actions(game_progression.winning_policy, game.infos) assert winning_commands == expected_commands, "{} != {}".format(winning_commands, expected_commands)
def build_and_compile_super_hero_game(): M = GameMaker() roomA = M.new_room("Room A") alley = M.new_room("Alley") bank1 = M.new_room("Bank1") bank2 = M.new_room("Bank2") bank3 = M.new_room("Bank3") corridor = M.connect(roomA.east, alley.west) corridor1 = M.connect(alley.east, bank1.west) corridor1 = M.connect(alley.north, bank2.south) corridor1 = M.connect(alley.south, bank3.north) M.set_player(roomA) roomA.infos.desc = "You are in a road. Some mobs are planning to rob a bank. You need to stop them. Go east to the alley. You can find a person in the alley who has information about the roberry. Collect information from him and prevent the roberry." alley.infos.desc = "This is an alley. There is a person beside the table. He knows about the bank roberry." bank2.infos.desc = "This is the north bank. Some robbers are going to rob the bank. You can call the police and try to capture them or convince them to surrender. Or you can also shoot them to stop the robbery." money = M.new(type="o", name = 'money') money.infos.desc = "it is money" M.inventory.add(money) person = M.new(type="pr", name = "informant") person.infos.desc = "This person knows about the bank roberry. Do a favor for him. He will help you." M.add_fact("not_asked", person) M.add_fact("not_given", person) alley.add(person) robber = M.new(type="rbr", name = "joker") bank2.add(robber) M.add_fact("not_stopped", robber) M.add_fact("not_conflict", robber) M.add_fact("not_allowed", robber) police = M.new(type="pl", name = "police") bank2.add(police) M.add_fact("not_called", police) # asking quest qst_event_asking = Event(conditions={M.new_fact("asked", person)}) quest_asking = Quest(win_events=[qst_event_asking], reward=2) # the wining quest qst_event_stopped_rob = Event(conditions={M.new_fact("asked", person), M.new_fact("stopped", robber)}) win_quest = Quest(win_events=[qst_event_stopped_rob], reward=2) # 1st failure condition failed_cmds1 = ["go east", "go south"] failed_event1 = M.new_event_using_commands(failed_cmds1) failed_quest_1 = Quest(win_events=[], fail_events=[failed_event1]) # 2nd failure condition failed_cmds2 = ["go east", "go east"] failed_event2 = M.new_event_using_commands(failed_cmds2) failed_quest_2 = Quest(win_events=[], fail_events=[failed_event2]) # 3rd failure condition failed_event3 = Event(conditions={ M.new_fact("not_asked", person), M.new_fact("at", M._entities['P'], bank2)}) failed_quest_3 = Quest(win_events=[], fail_events=[failed_event3]) failed_event4 = Event(conditions={ M.new_fact("allowed", robber)}) failed_quest_4 = Quest(win_events=[], fail_events=[failed_event4]) M.quests = [win_quest, quest_asking, failed_quest_1, failed_quest_2, failed_quest_3, failed_quest_4] game = M.build() game.main_quest = win_quest game_file = _compile_test_game(game) return game, game_file
def test_game_with_multiple_quests(self): M = GameMaker() # The subgoals (needs to be executed in order). commands = [ [ "open wooden door", "go west", "take carrot", "go east", "drop carrot" ], # Now, the player is back in the kitchen and the wooden door is open. ["go west", "take lettuce", "go east", "drop lettuce"], # Now, the player is back in the kitchen, there are a carrot and a lettuce on the floor. [ "take lettuce", "take carrot", "insert carrot into chest", "insert lettuce into chest", "close chest" ] ] # Create a 'bedroom' room. R1 = M.new_room("bedroom") R2 = M.new_room("kitchen") M.set_player(R2) path = M.connect(R1.east, R2.west) path.door = M.new(type='d', name='wooden door') path.door.add_property("closed") carrot = M.new(type='f', name='carrot') lettuce = M.new(type='f', name='lettuce') R1.add(carrot, lettuce) # Add a closed chest in R2. chest = M.new(type='c', name='chest') chest.add_property("open") R2.add(chest) quest1 = M.new_quest_using_commands(commands[0]) quest1.desc = "Fetch the carrot and drop it on the kitchen's ground." quest2 = M.new_quest_using_commands(commands[0] + commands[1]) quest2.desc = "Fetch the lettuce and drop it on the kitchen's ground." quest3 = M.new_quest_using_commands(commands[0] + commands[1] + commands[2]) winning_facts = [ M.new_fact("in", lettuce, chest), M.new_fact("in", carrot, chest), M.new_fact("closed", chest) ] quest3.win_events[0].set_conditions(winning_facts) quest3.desc = "Put the lettuce and the carrot into the chest before closing it." M.quests = [quest1, quest2, quest3] assert len(M.quests) == len(commands) game = M.build() inform7 = Inform7Game(game) game_progress = GameProgression(game) assert len(game_progress.quest_progressions) == len(game.quests) # Following the actions associated to the last quest actually corresponds # to solving the whole game. for action in game_progress.winning_policy: assert not game_progress.done game_progress.update(action) assert game_progress.done assert all(quest_progression.done for quest_progression in game_progress.quest_progressions) # Try solving the game by greedily taking the first action from the current winning policy. game_progress = GameProgression(game) while not game_progress.done: action = game_progress.winning_policy[0] game_progress.update(action) # print(action.name, [c.name for c in game_progress.winning_policy]) # Try solving the second quest (i.e. bringing back the lettuce) first. game_progress = GameProgression(game) for command in [ "open wooden door", "go west", "take lettuce", "go east", "drop lettuce" ]: _apply_command(command, game_progress, inform7) assert not game_progress.quest_progressions[0].done assert game_progress.quest_progressions[1].done for command in ["go west", "take carrot", "go east", "drop carrot"]: _apply_command(command, game_progress, inform7) assert game_progress.quest_progressions[0].done assert game_progress.quest_progressions[1].done for command in [ "take lettuce", "take carrot", "insert carrot into chest", "insert lettuce into chest", "close chest" ]: _apply_command(command, game_progress, inform7) assert game_progress.done # Game is done whenever a quest has failed or is unfinishable. game_progress = GameProgression(game) for command in [ "open wooden door", "go west", "take carrot", "eat carrot" ]: assert not game_progress.done _apply_command(command, game_progress, inform7) assert game_progress.done
def test_cycle_in_winning_policy(self): M = GameMaker() # Create a map. # r0 # | # r1 -- r2 # | | # r3 -- r4 R0 = M.new_room("r0") R1 = M.new_room("r1") R2 = M.new_room("r2") R3 = M.new_room("r3") R4 = M.new_room("r4") M.set_player(R1) M.connect(R0.south, R1.north), M.connect(R1.east, R2.west), M.connect(R3.east, R4.west) M.connect(R1.south, R3.north) M.connect(R2.south, R4.north) carrot = M.new(type='f', name='carrot') R0.add(carrot) apple = M.new(type='f', name='apple') R2.add(apple) commands = ["go north", "take carrot"] M.set_quest_from_commands(commands) game = M.build() inform7 = Inform7Game(game) game_progression = GameProgression(game) _apply_command("go south", game_progression, inform7) expected_commands = ["go north"] + commands winning_commands = inform7.gen_commands_from_actions( game_progression.winning_policy) assert winning_commands == expected_commands, "{} != {}".format( winning_commands, expected_commands) _apply_command("go east", game_progression, inform7) _apply_command("go north", game_progression, inform7) expected_commands = ["go south", "go west", "go north"] + commands winning_commands = inform7.gen_commands_from_actions( game_progression.winning_policy) assert winning_commands == expected_commands, "{} != {}".format( winning_commands, expected_commands) _apply_command("go west", game_progression, inform7) # Found shortcut expected_commands = commands winning_commands = inform7.gen_commands_from_actions( game_progression.winning_policy) assert winning_commands == expected_commands, "{} != {}".format( winning_commands, expected_commands) # Quest where player's has to pick up the carrot first. commands = [ "go east", "take apple", "go west", "go north", "drop apple" ] M.set_quest_from_commands(commands) game = M.build() game_progression = GameProgression(game) _apply_command("go south", game_progression, inform7) expected_commands = ["go north"] + commands winning_commands = inform7.gen_commands_from_actions( game_progression.winning_policy) assert winning_commands == expected_commands, "{} != {}".format( winning_commands, expected_commands) _apply_command("go east", game_progression, inform7) expected_commands = ["go west", "go north"] + commands winning_commands = inform7.gen_commands_from_actions( game_progression.winning_policy) assert winning_commands == expected_commands, "{} != {}".format( winning_commands, expected_commands) _apply_command("go north", game_progression, inform7) # Found shortcut expected_commands = commands[1:] winning_commands = inform7.gen_commands_from_actions( game_progression.winning_policy) assert winning_commands == expected_commands, "{} != {}".format( winning_commands, expected_commands)