Source code for jaclearn.rl.envs.nintendo.mario
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# File : mario.py
# Author : Jiayuan Mao
# Email : maojiayuan@gmail.com
# Date : 02/17/2018
#
# This file is part of Jacinle.
# Distributed under terms of the MIT license.
import copy
from ._wrapper import GymNintendoWrapper
from ..gym import GymRLEnv
try:
import gym
import ppaquette_gym_super_mario
from ppaquette_gym_super_mario import wrappers
except ImportError:
from jacinle.logging import get_logger
logger = get_logger(__file__)
logger.warning('Cannot import gym and ppaquette_gym_super_mario.')
gym = None
ppaquette_gym_super_mario = None
[docs]
class GymMarioRLEnv(GymRLEnv):
"""
Using https://github.com/ppaquette/gym-super-mario/tree/gabegrand
dhh: use meta-env and change_level to hack restart,
old restart might restore to a non-start intermediate state
"""
[docs]
def __init__(self, name, dump_dir=None, force_dump=False, state_mode='DEFAULT'):
super().__init__(name, dump_dir, force_dump, state_mode)
self._cur_iter = -1
def _make_env(self, name):
name_split = name.split('-')
if name_split[0] != 'meta':
prefix, world, level = name_split[:3]
author, prefix = prefix.split('/')
suffix = '-'.join(name_split[3:])
self._env_name = '/'.join([author, '-'.join(['meta', prefix, suffix])])
self._env_level = (int(world) - 1) * 4 + int(level) - 1
else:
self._env_name = name
self._env_level = None
env = gym.make(self._env_name)
# modewrapper = wrappers.SetPlayingMode('algo')
return GymNintendoWrapper(env)
def _set_info(self, info):
self.info = copy.copy(info)
def _action(self, action):
o, r, is_over, info = self._gym.step(action)
is_over = info.get('iteration', -1) > self._cur_iter
if self._env_level is not None:
if 'distance' in self.info and 'distance' in info:
r = info['distance'] - self.info['distance']
else:
r = 0
self._set_info(info)
self._set_current_state(o)
return r, is_over
def _restart(self):
if self._cur_iter < 0:
self._gym.reset() # hard mario fceux reset
if self._env_level is not None:
self._gym.unwrapped.locked_levels = [False, ] * 32
else:
o, _, _, info = self._gym.step(7) # take one step right
self._gym.unwrapped.change_level(self._env_level)
# https://github.com/ppaquette/gym-super-mario/issues/4
# https://github.com/pathak22/noreward-rl/blob/master/src/env_wrapper.py#L142
o, _, _, info = self._gym.step(7) # take right once to start game
if info.get('ignore', False): # assuming this happens only in beginning
self._cur_iter = -1
self._gym.close()
self._restart()
self._cur_iter = info.get('iteration', -1)
self._set_info(info)
self._set_current_state(o)
def _finish(self):
pass
[docs]
def close(self):
self._gym.close()