Ejemplo n.º 1
0
    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()
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
    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()
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
    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)}
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
    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