コード例 #1
0
ファイル: benchmarks.py プロジェクト: ra312/jericho
def bench_loading_speed():
    REPEAT = 1000

    start = time.time()
    rom = pjoin(DATA_PATH, "905.z5")
    for _ in range(REPEAT):
        env = jericho.FrotzEnv(rom)
        env.reset()
        env.close()

    duration1 = time.time() - start
    print("Calling FrotzEnv({}) {} times in {:6.2f} secs.".format(
        rom, REPEAT, duration1))
    del env

    start = time.time()
    env = jericho.FrotzEnv(rom)
    for _ in range(REPEAT - 1):
        env.load(rom)
        env.reset()
        env.close()

    duration2 = time.time() - start
    print("Calling env.load({}) {} times in {:6.2f} secs.".format(
        rom, REPEAT, duration2))
    print("Speedup: {}x.".format(duration1 / duration2))
コード例 #2
0
def test_saving_opcode_in_state():
    # At some point in yomomma.z8, the player is asked to hit [enter] to continue.
    # Restoring to that particular state without setting the opcode appropriately
    # would result in the emulated halting.
    COMMANDS = [
        'south', 'southeast', 'sit', 'wait', 'yes', 'west', 'north',  # Actions needed to reach the corner case.
        'get in stage',  # -> opcode == 246 (z_read_char)
        '',  # Pressing [enter] -> opcode == 246 (z_read_char)
        '[save]',
        '',  # Pressing [enter] -> opcode == 228 (z_read_line)
        '[restore]',  # If not resetted properly, opcode == 228 (z_read_line) instaead of 246 (z_read_char)
        'examine something',  # Causes an illegal opcode
        'look'  # Emulator has halted.
    ]

    rom = pjoin(DATA_PATH, "roms", "yomomma.z8")
    if not os.path.exists(rom):
        raise unittest.SkipTest("Missing data: {}".format(rom))

    env = jericho.FrotzEnv(rom)
    env.reset()

    state = None
    for cmd in COMMANDS:
        if cmd == "[save]":
            state = env.get_state()
        elif cmd == "[restore]":
            env.set_state(state)
        else:
            obs, rew, done, info = env.step(cmd)
            assert not env._emulator_halted()
コード例 #3
0
def test_loading_unsupported_game():
    with warnings.catch_warnings(record=True) as w:
        env = jericho.FrotzEnv(TEST_GAME)
        warnings.simplefilter("always")
        assert len(w) == 1
        assert issubclass(w[-1].category, UnsupportedGameWarning)
        assert TEST_GAME in str(w[-1].message)

    state = env.reset()
    assert env.get_score() == 0
    assert env.get_max_score() == 0  # Instead of 3.

    state, score, done, _ = env.step("go east")
    state, score, done, _ = env.step("insert carrot into chest")
    assert score == 0  # Instead of 2.
    state, score, done, _ = env.step("close chest")
    assert score == 0  # Instead of 3.

    assert "The End" in state
    assert not done  # Instead of True
    assert not env.victory()  # Instead of True

    state = env.reset()
    state, score, done, _ = env.step("eat carrot")
    assert "You lost" in state
    assert not done  # Instead of True
    assert not env.game_over()  # Instead of True
コード例 #4
0
def test_loading_a_textworld_game():
    env = jericho.FrotzEnv(TEST_GAME)
    state = env.reset()

    assert not env.victory()
    assert not env.game_over()
    assert env.get_score() == 0
    assert env.get_max_score() == 3

    state, score, done, _ = env.step("go east")
    assert not done
    assert score == 0

    state, score, done, _ = env.step("insert carrot into chest")
    assert not done
    assert score == 2

    state, score, done, _ = env.step("close chest")
    assert done
    assert env.victory()
    assert score == 3

    state = env.reset()
    state, score, done, _ = env.step("eat carrot")
    assert done
    assert env.game_over()  # Lost
    assert score == 0
コード例 #5
0
def test_loading_unsupported_game():
    # Note: dummy.z8 is the same as tw-game.z8.
    gamefile = "dummy.z8"
    with warnings.catch_warnings(record=True) as w:
        env = jericho.FrotzEnv(pjoin(DATA_PATH, gamefile))
        warnings.simplefilter("always")
        assert len(w) == 1
        assert issubclass(w[-1].category, UnsupportedGameWarning)
        assert gamefile in str(w[-1].message)

    state, info = env.reset()
    assert env.get_score() == 0
    assert env.get_max_score() == 0  # Instead of 3.

    state, score, done, _ = env.step("go east")
    state, score, done, _ = env.step("insert carrot into chest")
    assert score == 0  # Instead of 2.
    state, score, done, _ = env.step("close chest")
    assert score == 0  # Instead of 3.

    assert "The End" in state
    assert not done  # Instead of True
    assert not env.victory()  # Instead of True

    state, info = env.reset()
    state, score, done, _ = env.step("eat carrot")
    assert "You lost" in state
    assert not done  # Instead of True
    assert not env.game_over()  # Instead of True
コード例 #6
0
def test_loading_a_textworld_game():
    env = jericho.FrotzEnv(pjoin(DATA_PATH, "tw-game.z8"))
    state, info = env.reset()

    assert not env.victory()
    assert not env.game_over()
    assert env.get_score() == 0
    assert env.get_max_score() == 3

    state, reward, done, info = env.step("go east")
    assert not done
    assert reward == 0

    state, reward, done, info = env.step("insert carrot into chest")
    assert not done
    assert reward == 2

    state, reward, done, info = env.step("close chest")
    assert done
    assert env.victory()
    assert reward == 1
    assert info['score'] == 3

    state = env.reset()
    state, reward, done, info = env.step("eat carrot")
    assert done
    assert env.game_over()  # Lost
    assert info['score'] == 0
コード例 #7
0
ファイル: env.py プロジェクト: spencerfrazier/KG-A2C
 def create(self):
     ''' Create the Jericho environment and connect to redis. '''
     self.env = jericho.FrotzEnv(self.rom_path, self.seed)
     self.bindings = jericho.load_bindings(self.rom_path)
     self.act_gen = TemplateActionGenerator(self.bindings)
     self.max_word_len = self.bindings['max_word_length']
     self.vocab, self.vocab_rev = load_vocab(self.env)
     self.conn_valid = redis.Redis(host='localhost', port=6379, db=0)
     self.conn_openie = redis.Redis(host='localhost', port=6379, db=1)
コード例 #8
0
ファイル: test_valid_actions.py プロジェクト: ra312/jericho
def test_valid_action_identification():
    rom_path = pjoin(DATA_PATH, '905.z5')
    env = jericho.FrotzEnv(rom_path)
    obs, info = env.reset()
    valid = env.get_valid_actions()
    assert 'take wallet' in valid
    assert 'open wallet' in valid
    assert 'take keys' in valid
    assert 'get up' in valid
    assert 'take phone' in valid
コード例 #9
0
ファイル: jericho.py プロジェクト: mhmohona/TextWorld
    def reset(self):
        self.close()  # In case, it is running.

        # Start the game using Jericho.
        self._jericho = jericho.FrotzEnv(self.gamefile, self._seed)

        self.state = GameState()
        self.state.raw, _ = self._jericho.reset()
        self._gather_infos()
        return self.state
コード例 #10
0
    def __init__(self, rom_path, seed):
        self.jericho_env = jericho.FrotzEnv(rom_path, seed)
        self.action_space = NaturalLanguage(max_words=4)
        self.observation_space = NaturalLanguage()

        self.high = None
        self.low = None

        self.seed(seed)
        self.vocabulary = self.jericho_env.get_dictionary()
コード例 #11
0
ファイル: test_jericho.py プロジェクト: thunanguyen/jericho
def test_for_memory_leaks():
    # Make sure we don't have severe memory leaks.

    def _get_mem():
        import resource
        return resource.getrusage(resource.RUSAGE_SELF).ru_maxrss

    unit = 1024  # Denominator to get memory usage in MB.
    if sys.platform == 'darwin':
        # According to https://github.com/apple/darwin-xnu/blob/master/bsd/man/man2/getrusage.2#L95
        # OSX outputs ru_maxrss in bytes rather then kilobytes.
        unit = 1024 * 1024

    gamefile1 = pjoin(DATA_PATH, "905.z5")
    env1 = jericho.FrotzEnv(gamefile1)
    env1.reset()
    del env1

    mem_start = _get_mem()
    print('Memory usage: {:.1f}MB'.format(mem_start / unit))
    for _ in range(1000):
        # Make sure we don't have memory leak.
        env1 = jericho.FrotzEnv(gamefile1)
        env1.reset()
        del env1

    mem_mid = _get_mem()
    print('Memory usage: {:.1f}MB ({:+.1f}MB)'.format(
           mem_mid / unit, (mem_mid-mem_start) / unit ))

    for _ in range(1000):
        env1 = jericho.FrotzEnv(gamefile1)
        env1.reset()
        del env1

    mem_end = _get_mem()
    print('Memory usage: {:.1f}MB ({:+.1f}MB)'.format(
          mem_end / unit, (mem_end-mem_mid) / unit))

    # Less than 1MB memory leak per 1000 load/unload cycles.
    assert (mem_mid - mem_start) < 1024 * 1024
    assert (mem_end - mem_mid) < 1024 * 1024
コード例 #12
0
ファイル: test_jericho.py プロジェクト: thunanguyen/jericho
def test_multiple_instances():
    gamefile1 = pjoin(DATA_PATH, "905.z5")
    gamefile2 = pjoin(DATA_PATH, "tw-game.z8")

    # Make sure both frotz_lib have different handles.
    env1 = jericho.FrotzEnv(gamefile1)
    env2 = jericho.FrotzEnv(gamefile2)
    assert env1.frotz_lib._handle != env2.frotz_lib._handle

    # Test we can play two different games in parallel.
    state1, _ = env1.reset()
    state2, _ = env2.reset()
    assert "9:05 by Adam Cadre" in state1
    assert "TextWorld" in state2

    state1, _, _, _ = env1.step("examine me")
    env1.close()
    assert "You're covered with mud and dried sweat." in state1

    state2, _, _, _ = env2.step("examine me")
    env2.close()
    assert "As good-looking as ever." in state2
コード例 #13
0
ファイル: jericho.py プロジェクト: zp312/TextWorld
    def reset(self):
        self.close()  # In case, it is running.
        self.game_state = self.GAME_STATE_CLASS(self)

        # Start the game using Jericho.
        self._jericho = jericho.FrotzEnv(self.game_filename, self._seed)

        # Grab start info from game.
        start_output = self._jericho.reset()
        self.game_state.init(start_output)
        self.game_state._score = self._jericho.get_score()
        self.game_state._max_score = self._jericho.get_max_score()
        return self.game_state
コード例 #14
0
ファイル: text_utils.py プロジェクト: syh307611391/Research
def extract_vocab_from_gamefile(gamefile: str) -> Set[str]:
    vocab = set()
    jsonfile = os.path.splitext(gamefile)[0] + ".json"
    if os.path.isfile(jsonfile):
        game = Game.load(jsonfile)
        vocab |= extract_vocab(game)

    if re.search(r"\.z[1-8]$", gamefile):
        # For Z-Machine games, extract vocab using Jericho.
        import jericho
        env = jericho.FrotzEnv(gamefile)
        vocab |= set(entry.word for entry in env.get_dictionary())

    return vocab
コード例 #15
0
    def reset(self):
        # Since Jericho is not thread-safe, we load it locally so
        # its global memory is not shared accross multiple processes
        # when forking.
        import jericho

        self.close()  # In case, it is running.

        # Start the game using Jericho.
        self._jericho = jericho.FrotzEnv(self.gamefile, self._seed)

        self.state = GameState()
        self.state.raw, _ = self._jericho.reset()
        self._gather_infos()
        return self.state
コード例 #16
0
    def load(self, z_file: str) -> None:
        self.gamefile = os.path.abspath(z_file)
        _, ext = os.path.splitext(os.path.basename(self.gamefile))

        # Check if game is supported by Jericho.
        if not ext.startswith(".z"):
            raise ValueError("Only .z[1-8] files are supported!")

        if not os.path.isfile(self.gamefile):
            raise FileNotFoundError(self.gamefile)

        if self._jericho is None:
            # Start the game using Jericho.
            self._jericho = jericho.FrotzEnv(self.gamefile, self._seed)
        else:
            self._jericho.load(self.gamefile)
コード例 #17
0
ファイル: test_valid_actions.py プロジェクト: yazici/jericho
def test_valid_action_identification():
    rom_path = pjoin(DATA_PATH, '905.z5')
    env = jericho.FrotzEnv(rom_path)
    bindings = jericho.load_bindings(rom_path)
    act_gen = TemplateActionGenerator(bindings)
    obs, info = env.reset()
    # interactive_objs = [obj[0] for obj in env.identify_interactive_objects(use_object_tree=True)]
    interactive_objs = ['phone', 'keys', 'wallet']
    candidate_actions = act_gen.generate_actions(interactive_objs)

    valid = env.find_valid_actions(candidate_actions)
    assert 'take wallet' in valid
    assert 'open wallet' in valid
    assert 'take keys' in valid
    assert 'get up' in valid
    assert 'take phone' in valid
コード例 #18
0
def test_copy():
    rom = pjoin(DATA_PATH, "905.z5")
    env = jericho.FrotzEnv(rom)
    env.reset()

    walkthrough = env.get_walkthrough()
    expected = [env.step(act) for act in walkthrough]

    env.reset()
    for i, act in enumerate(walkthrough):
        obs, rew, done, info = env.step(act)

        if i + 1 < len(walkthrough):
            fork = env.copy()
            for j, cmd in enumerate(walkthrough[i+1:], start=i+1):
                obs, rew, done, info = fork.step(cmd)
                assert (obs, rew, done, info) == expected[j]
コード例 #19
0
ファイル: test_jericho.py プロジェクト: thunanguyen/jericho
def test_copy():
    rom = pjoin(DATA_PATH, "905.z5")
    bindings = jericho.load_bindings(rom)
    env = jericho.FrotzEnv(rom, seed=bindings['seed'])
    env.reset()

    walkthrough = bindings['walkthrough'].split('/')
    expected = [env.step(act) for act in walkthrough]

    env.reset()
    for i, act in enumerate(walkthrough):
        obs, rew, done, info = env.step(act)

        if i + 1 < len(walkthrough):
            fork = env.copy()
            for j, cmd in enumerate(walkthrough[i+1:], start=i+1):
                obs, rew, done, info = fork.step(cmd)
                assert (obs, rew, done, info) == expected[j]
コード例 #20
0
def test_cleaning_observation():
    gamefile = "tw-cooking-recipe3+cook+cut-2057SPdQu0mWiv0k.z8"
    env = jericho.FrotzEnv(pjoin(DATA_PATH, gamefile))
    state, info = env.reset()

    EXPECTED = textwrap.dedent(
    r"""


                        ________  ________  __    __  ________
                       |        \|        \|  \  |  \|        \
                        \$$$$$$$$| $$$$$$$$| $$  | $$ \$$$$$$$$
                          | $$   | $$__     \$$\/  $$   | $$
                          | $$   | $$  \     >$$  $$    | $$
                          | $$   | $$$$$    /  $$$$\    | $$
                          | $$   | $$_____ |  $$ \$$\   | $$
                          | $$   | $$     \| $$  | $$   | $$
                           \$$    \$$$$$$$$ \$$   \$$    \$$
                  __       __   ______   _______   __        _______
                 |  \  _  |  \ /      \ |       \ |  \      |       \
                 | $$ / \ | $$|  $$$$$$\| $$$$$$$\| $$      | $$$$$$$\
                 | $$/  $\| $$| $$  | $$| $$__| $$| $$      | $$  | $$
                 | $$  $$$\ $$| $$  | $$| $$    $$| $$      | $$  | $$
                 | $$ $$\$$\$$| $$  | $$| $$$$$$$\| $$      | $$  | $$
                 | $$$$  \$$$$| $$__/ $$| $$  | $$| $$_____ | $$__/ $$
                 | $$$    \$$$ \$$    $$| $$  | $$| $$     \| $$    $$
                  \$$      \$$  \$$$$$$  \$$   \$$ \$$$$$$$$ \$$$$$$$

    You are hungry! Let's cook a delicious meal. Check the cookbook in the kitchen for the recipe. Once done, enjoy your meal!

    -= Kitchen =-
    You arrive in a kitchen. An ordinary kind of place. The room seems oddly familiar, as though it were only superficially
    different from the other rooms in the building.

    You lean against the wall, inadvertently pressing a secret button. The wall opens up to reveal a fridge. The fridge is empty,
    what a horrible day! You make out a closed oven. You lean against the wall, inadvertently pressing a secret button. The wall
    opens up to reveal a table. You see a cookbook on the table. Now that's what I call TextWorld! What's that over there? It looks
    like it's a counter. You see a red apple and a knife on the counter. You make out a stove. But the thing hasn't got anything on
    it.


    """)
    assert [line.strip() for line in state.split("\n")] == [line.strip() for line in EXPECTED.split("\n")]
コード例 #21
0
    def __init__(self,
                 game_files: List[str],
                 request_infos: Optional[EnvInfos] = None,
                 action_space: Optional[gym.Space] = None,
                 observation_space: Optional[gym.Space] = None) -> None:
        """ Environment for playing text-based games.

        Each time `TextworldGamesEnv.reset()` is called, a new game from the
        pool starts. Each game of the pool is guaranteed to be played exactly
        once before a same game is played for a second time.

        Arguments:
            game_files:
                Paths of every game composing the pool (`*.ulx` + `*.json`, `*.z[1-8]`).
            request_infos:
                For customizing the information returned by this environment
                (see
                :py:class:`textworld.EnvInfos <textworld.envs.wrappers.filter.EnvInfos>`
                for the list of available information).

                .. warning:: This is only supported for `*.ulx` games generated with TextWorld.
            action_space:
                The action space of this TextWorld environment. By default, a
                :py:class:`textworld.gym.spaces.Word <textworld.gym.spaces.text_spaces.Word>`
                instance is used with a `max_length` of 8 and a vocabulary
                extracted from the TextWorld game.
            observation_space:
                The observation space of this TextWorld environment. By default, a
                :py:class:`textworld.gym.spaces.Word <textworld.gym.spaces.text_spaces.Word>`
                instance is used with a `max_length` of 200 and a vocabulary
                extracted from the TextWorld game.
        """
        self.gamefiles = game_files
        self.request_infos = request_infos or EnvInfos()
        self.ob = None
        self.last_command = None
        self.textworld_env = None
        self.current_gamefile = None
        self.seed(1234)

        if action_space is None or observation_space is None:
            # Extract vocabulary from games.
            json_files = [
                os.path.splitext(gamefile)[0] + ".json"
                for gamefile in self.gamefiles
            ]
            games_iter = (textworld.Game.load(gamefile)
                          for gamefile in json_files
                          if os.path.isfile(gamefile))
            vocab = set(textworld.text_utils.extract_vocab(games_iter))

            zmachine_games = [
                gamefile for gamefile in self.gamefiles
                if re.search(r"\.z[1-8]$", gamefile)
            ]
            for gamefile in zmachine_games:
                env = jericho.FrotzEnv(gamefile)
                vocab |= set(entry.word for entry in env.get_dictionary())

            vocab = sorted(vocab)

        self.action_space = action_space or text_spaces.Word(max_length=8,
                                                             vocab=vocab)
        self.observation_space = observation_space or text_spaces.Word(
            max_length=200, vocab=vocab)
コード例 #22
0
def parse_args():
    parser = argparse.ArgumentParser()

    parser.add_argument("filename",
                        help="Path to a Z-Machine game.")
    parser.add_argument("--walkthrough",
                        help="External walkthrough (one command per line). Default: use Jericho's one, if it exists.")
    parser.add_argument("--skip-to", type=int, default=0,
                        help="Auto-play walkthrough until the nth command before dropping into interactive mode.")

    return parser.parse_args()

args = parse_args()

bindings = jericho.load_bindings(args.filename)
env = jericho.FrotzEnv(args.filename, seed=bindings['seed'])

history = []
obs, info = env.reset()

history.append(env.get_state())

STEP_BY_STEP_WALKTRHOUGH = True

walkthrough = bindings.get('walkthrough', '').split('/')
if args.walkthrough:
    walkthrough = []
    for line in open(args.walkthrough):
        cmd = line.split("#")[0].strip()
        if cmd:
            walkthrough.append(cmd)
コード例 #23
0
ファイル: test_games.py プロジェクト: ra312/jericho
                        help="Launch ipdb on FAIL.")
    parser.add_argument(
        "-v",
        "--verbose",
        action="store_true",
        help="Print the last observation when not achieving max score.")
    return parser.parse_args()


args = parse_args()

filename_max_length = max(map(len, args.filenames))
for filename in sorted(args.filenames):
    print(filename.ljust(filename_max_length), end=" ")

    env = jericho.FrotzEnv(filename)
    if not env.is_fully_supported:
        print(colored("SKIP\tUnsupported game", 'yellow'))
        continue

    if "walkthrough" not in env.bindings:
        print(colored("SKIP\tMissing walkthrough", 'yellow'))
        continue

    env.reset()

    #walkthrough = bindings['walkthrough'].split('/')
    for cmd in env.get_walkthrough():
        obs, rew, done, info = env.step(cmd)

    if not done:
コード例 #24
0
ファイル: find_walkthrough.py プロジェクト: ra312/jericho
def parse_args():
    parser = argparse.ArgumentParser()

    parser.add_argument("filename",
                        help="Path to a Z-Machine game.")
    parser.add_argument("--walkthrough",
                        help="External walkthrough (one command per line). Default: use Jericho's one, if it exists.")
    parser.add_argument("--skip-to", type=int, default=0,
                        help="Auto-play walkthrough until the nth command before dropping into interactive mode.")

    return parser.parse_args()

args = parse_args()

history = []
env = jericho.FrotzEnv(args.filename)
obs, info = env.reset()

history.append(env.get_state())

STEP_BY_STEP_WALKTRHOUGH = True

walkthrough = env.get_walkthrough()
if args.walkthrough:
    walkthrough = []
    for line in open(args.walkthrough):
        cmd = line.split("#")[0].strip()
        if cmd:
            walkthrough.append(cmd)

obs_list = [obs]