├── .gitignore ├── LICENSE ├── README.md ├── behavioural_cloning.py ├── getting_familiar_with_minerl_and_gym.py ├── playing_with_minerl.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 MineRL Labs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tasks for getting started with MineRL 2 | 3 | **Note**: These were designed for MineRL v0.4 and the code examples may not work on MineRL v1.0. 4 | 5 | This repository contains examples and small tasks on getting 6 | started with MineRL environment. 7 | 8 | To begin, install the [requirements for MineRL](https://minerl.readthedocs.io/en/latest/tutorials/index.html), 9 | and then install Python requirements with with `pip install -r requirements.txt`. We also have Colab notebooks 10 | in case installing these libraries is not possible. 11 | 12 | If you have any questions, you can reach us on [Discord](https://discord.com/invite/BT9uegr). 13 | If you spot typos/bugs in any of the tasks or this repo, do tell us via Github issues! 14 | 15 | ## Tasks 16 | 17 | Stars indicate the difficulty of the task. Click the task to see more details. 18 | 19 | **:star: Getting started with MineRL.** 20 | * Start by playing bit of Minecraft via MineRL with `playing_with_minerl.py` script. 21 | * Check out `getting_familiar_with_minerl_and_gym.py` and follow the instructions to get familiar with the agent-environment (Gym) API. 22 | * You can find the latter task on Colab [here](https://colab.research.google.com/drive/11CVCeb7f0P2nqcgWGLG1wDZcE3AxngxL?usp=sharing). 23 | 24 | **:star::star: Improve Intro baseline of the Diamond competition.** 25 | * Step-by-step instructions on how to improve a simple, fully-scripted agent for obtaining wood and stone in the MineRLObtainDiamond-v0 task. 26 | * Start out by [opening this document](https://docs.google.com/document/d/12d0jMnsoR5xjyye4Rlpo84yJOZRMbfSYOb17OWOJdFw/edit) and following the instructions. 27 | * If you are overwhelmingly stuck, you may look for reference answers [from this documentation](https://docs.google.com/document/d/1Q9xWoi06h7oL_XXjMLlvkRe626bTjwXupE-LFztRbNU/edit?usp=sharing). 28 | 29 | **:star::star: Implementing behavioural cloning from (almost) scratch.** 30 | * Start by opening up `behavioural_cloning.py` and following the instructions at the beginning of the file. 31 | * You can also find the task on Colab [here](https://colab.research.google.com/drive/1JQ9suwMe-TnyBoDjhdydI6Ic35-m6NLh?usp=sharing). 32 | * You can find a crude reference answers [in this Colab notebook](https://colab.research.google.com/drive/1rap2ROcbN2jNEutj5ciIA_kip4a1r7HU?usp=sharing). 33 | This task is built on the [BC + scripted baseline solution](https://github.com/KarolisRam/MineRL2021-Intro-baselines/blob/main/standalone/BC_plus_script.py). 34 | 35 | **:star::star::star: Learn how to use stable-baselines and imitation libraries with MineRL.** 36 | * This walk-through demonstrates how to combine well-established reinforcement learning ([stable-baselines3](https://github.com/DLR-RM/stable-baselines3)) and imitation learning ([imitation](https://github.com/HumanCompatibleAI/imitation)) libraries with MineRL to train more sophisticated agents. 37 | * Start by opening [this Colab link](https://colab.research.google.com/drive/13_jI8YLk9ATRQSd7_3rV5rOsll7jsSz0) (NOTE 6.1.2025: This colab link is known to be dead). 38 | 39 | **:star::star::star: Improve Research baseline of the Diamond competition.** 40 | * Similar to the second task here, but in a more difficult setting where you may not manually encode actions. 41 | * Get started by opening [this documentation](https://docs.google.com/document/d/1BxKAFZN1-qfc83GjVYMdsJamU01sngn2LlreuvdxWu0/edit?usp=sharing). 42 | * Once done, you can check reference answers [from here](https://docs.google.com/document/d/1p6V3fvLAy8psQPs-v3JXrzBjM8PD_CUi_XBH-1v4qUg/edit?usp=sharing). 43 | 44 | **:star::star::star: Useful utilities for the BASALT 2021 competition.** 45 | * A collection and a walkthrough of approaches and methods that are useful for the [BASALT competition](https://www.aicrowd.com/challenges/neurips-2021-minerl-basalt-competition) (learning without rewards). 46 | * Get started by opening [this Colab](https://colab.research.google.com/drive/1MtMaNd23mToUvzPnHx4LFmNDseaOTZ_X). 47 | -------------------------------------------------------------------------------- /behavioural_cloning.py: -------------------------------------------------------------------------------- 1 | from tqdm import tqdm 2 | import numpy as np 3 | import torch as th 4 | from torch import nn 5 | import gym 6 | import minerl 7 | 8 | 9 | """ 10 | Your task: Implement behavioural cloning for MineRLTreechop-v0. 11 | 12 | Behavioural cloning is perhaps the simplest way of using a dataset of demonstrations to train an agent: 13 | learn to predict what actions they would take, and take those actions. 14 | In other machine learning terms, this is almost like building a classifier to classify observations to 15 | different actions, and taking those actions. 16 | 17 | For simplicity, we build a limited set of actions ("agent actions"), map dataset actions to these actions 18 | and train on the agent actions. During evaluation, we transform these agent actions (integerse) back into 19 | MineRL actions (dictionaries). 20 | 21 | To do this task, fill in the "TODO"s and remove `raise NotImplementedError`s. 22 | 23 | Note: For this task you need to download the "MineRLTreechop-v0" dataset. See here: 24 | https://minerl.readthedocs.io/en/latest/tutorials/data_sampling.html#downloading-the-minerl-dataset-with-minerl-data-download 25 | """ 26 | 27 | 28 | class ConvNet(nn.Module): 29 | """ 30 | :param input_shape: A three-item tuple telling image dimensions in (C, H, W) 31 | :param output_dim: Dimensionality of the output vector 32 | """ 33 | 34 | def __init__(self, input_shape, output_dim): 35 | super().__init__() 36 | # TODO Create a torch neural network here to turn images (of shape `input_shape`) into 37 | # a vector of shape `output_dim`. This output_dim matches number of available actions. 38 | # See examples of doing CNN networks here https://pytorch.org/tutorials/beginner/nn_tutorial.html#switch-to-cnn 39 | raise NotImplementedError("TODO implement a simple convolutional neural network here") 40 | 41 | def forward(self, observations: th.Tensor) -> th.Tensor: 42 | # TODO with the layers you created in __init__, transform the `observations` (a tensor of shape (B, C, H, W)) to 43 | # a tensor of shape (B, D), where D is the `output_dim` 44 | raise NotImplementedError("TODO implement forward function of the neural network") 45 | 46 | 47 | def agent_action_to_environment(noop_action, agent_action): 48 | """ 49 | Turn an agent action (an integer) into an environment action. 50 | This should match `environment_action_batch_to_agent_actions`, 51 | e.g. if attack=1 action was mapped to agent_action=0, then agent_action=0 52 | should be mapped back to attack=1. 53 | 54 | noop_action is a MineRL action that does nothing. You may want to 55 | use this as a template for the action you return. 56 | """ 57 | raise NotImplementedError("TODO implement agent_action_to_environment (see docstring)") 58 | 59 | 60 | def environment_action_batch_to_agent_actions(dataset_actions): 61 | """ 62 | Turn a batch of actions from environment (from BufferedBatchIterator) to a numpy 63 | array of agent actions. 64 | 65 | Agent actions _have to_ start from 0 and go up from there! 66 | 67 | For MineRLTreechop, you want to have actions for the following at the very least: 68 | - Forward movement 69 | - Jumping 70 | - Turning camera left, right, up and down 71 | - Attack 72 | 73 | For example, you could have seven agent actions that mean following: 74 | 0 = forward 75 | 1 = jump 76 | 2 = turn camera left 77 | 3 = turn camera right 78 | 4 = turn camera up 79 | 5 = turn camera down 80 | 6 = attack 81 | 82 | This should match `agent_action_to_environment`, by converting dictionary 83 | actions into individual integeres. 84 | 85 | If dataset action (dict) does not have a mapping to agent action (int), 86 | then set it "-1" 87 | """ 88 | # There are dummy dimensions of shape one 89 | batch_size = len(dataset_actions["camera"]) 90 | actions = np.zeros((batch_size,), dtype=np.int) 91 | 92 | for i in range(batch_size): 93 | # TODO this will make all actions invalid. Replace with something 94 | # more clever 95 | actions[i] = -1 96 | raise NotImplementedError("TODO map dataset action at index i to an agent action, or if no mapping, -1") 97 | return actions 98 | 99 | 100 | def train(): 101 | # Path to where MineRL dataset resides (should contain "MineRLTreechop-v0" directory) 102 | DATA_DIR = "." 103 | # How many times we train over dataset and how large batches we use. 104 | # Larger batch size takes more memory but generally provides stabler learning. 105 | EPOCHS = 1 106 | BATCH_SIZE = 32 107 | 108 | # TODO create data iterators for going over MineRL data using BufferedBatchIterator 109 | # https://minerl.readthedocs.io/en/latest/tutorials/data_sampling.html#sampling-the-dataset-with-buffered-batch-iter 110 | # NOTE: You have to download the Treechop dataset first for this to work, see: 111 | # https://minerl.readthedocs.io/en/latest/tutorials/data_sampling.html#downloading-the-minerl-dataset-with-minerl-data-download 112 | raise NotImplementedError("TODO create dataset samplers") 113 | iterator = None 114 | 115 | number_of_actions = None 116 | # TODO we need to tell the network how many possible actions there are, 117 | # so assign the value in above variable 118 | raise NotImplementedError("TODO add number of actions to `number_of_actions`") 119 | network = ConvNet((3, 64, 64), number_of_actions).cuda() 120 | # TODO create optimizer and loss functions for training 121 | # see examples here https://pytorch.org/tutorials/beginner/basics/optimization_tutorial.html 122 | raise NotImplementedError("TODO Create an optimizer and a loss function.") 123 | optimizer = None 124 | loss_function = None 125 | 126 | iter_count = 0 127 | losses = [] 128 | for dataset_obs, dataset_actions, _, _, _ in tqdm(iterator.buffered_batch_iter(num_epochs=EPOCHS, batch_size=BATCH_SIZE)): 129 | # We only use camera observations here 130 | obs = dataset_obs["pov"].astype(np.float32) 131 | # Transpose observations to be channel-first (BCHW instead of BHWC) 132 | obs = obs.transpose(0, 3, 1, 2) 133 | # Normalize observations, otherwise the neural network will get spooked 134 | obs /= 255.0 135 | 136 | # Turn dataset actions into agent actions 137 | actions = environment_action_batch_to_agent_actions(dataset_actions) 138 | assert actions.shape == (obs.shape[0],), "Array from environment_action_batch_to_agent_actions should be of shape {}".format((obs.shape[0],)) 139 | 140 | # Remove samples that had no corresponding action 141 | mask = actions != -1 142 | obs = obs[mask] 143 | actions = actions[mask] 144 | 145 | # TODO perform optimization step: 146 | # - Predict actions using the neural network (input is `obs`) 147 | # - Compute loss with the predictions and true actions. Store loss into variable `loss` 148 | # - Use optimizer to do a single update step 149 | # See https://pytorch.org/tutorials/beginner/basics/optimization_tutorial.html 150 | # for a tutorial 151 | # NOTE: Variables `obs` and `actions` are numpy arrays. You need to convert them into torch tensors. 152 | 153 | # Keep track of how training is going by printing out the loss 154 | iter_count += 1 155 | losses.append(loss.item()) 156 | if (iter_count % 1000) == 0: 157 | mean_loss = sum(losses) / len(losses) 158 | tqdm.write("Iteration {}. Loss {:<10.3f}".format(iter_count, mean_loss)) 159 | losses.clear() 160 | 161 | # Store the network 162 | th.save(network, "behavioural_cloning.pth") 163 | 164 | 165 | def enjoy(): 166 | # Load up the trained network 167 | network = th.load("behavioural_cloning.pth").cuda() 168 | 169 | env = gym.make('MineRLTreechop-v0') 170 | 171 | # Play 10 games with the model 172 | for game_i in range(10): 173 | obs = env.reset() 174 | done = False 175 | reward_sum = 0 176 | while not done: 177 | # TODO Process the observation: 178 | # - Take only the camera observation 179 | # - Add/remove batch dimensions 180 | # - Transpose image (needs to be channels-last) 181 | # - Normalize image 182 | # - Store network output to `logits` 183 | # For hints, see what preprocessing was done during training 184 | raise NotImplementedError("TODO process the observation and run it through network") 185 | logits = None 186 | # Turn logits into probabilities 187 | probabilities = th.softmax(logits, dim=1)[0] 188 | # Into numpy 189 | probabilities = probabilities.detach().cpu().numpy() 190 | # TODO Pick an action based from the probabilities above. 191 | # The `probabilities` vector tells the probability of choosing one of the agent actions. 192 | # You have two options: 193 | # 1) Pick action with the highest probability 194 | # 2) Sample action based on probabilities 195 | # Option 2 works better emperically. 196 | agent_action = None 197 | 198 | noop_action = env.action_space.noop() 199 | environment_action = agent_action_to_environment(noop_action, agent_action) 200 | 201 | obs, reward, done, info = env.step(environment_action) 202 | reward_sum += reward 203 | print("Game {}, total reward {}".format(game_i, reward_sum)) 204 | 205 | env.close() 206 | 207 | 208 | if __name__ == "__main__": 209 | # First train the model... 210 | train() 211 | # ... then play it on the environment to see how it does 212 | enjoy() 213 | -------------------------------------------------------------------------------- /getting_familiar_with_minerl_and_gym.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | import cv2 4 | import gym 5 | import minerl 6 | 7 | 8 | SLEEP_TIME = 0.1 9 | 10 | """ 11 | The “step-loop” is common way do to agent-environment interaction. Implement this missing loop in this code. See this for documentation: https://gym.openai.com/ 12 | First, use environment "CartPole-v0" to use it to see how random agent plays the game. 13 | Get familiar with the environment CartPole-v0. Important things you need to figure out: 14 | What is the goal? 15 | What is the state information (what does the state from env.step(action) mean)? 16 | What are actions (what does the action in env.step(action) do)? What are the different actions? 17 | What is reward? 18 | What is the starting state? Does it change between different episodes (games)? 19 | Is environment deterministic or stochastic? Environment is deterministic if you can perfectly predict what happens with every action in every state. 20 | Now that you know how CartPole-v0 works, change to "MineRLObtainDiamond-v0", repeat the above steps by changing the environment in `gym.make` 21 | """ 22 | 23 | 24 | def render(observation, environment): 25 | """A function for rendering MineRL environments. You do not need to worry about this function""" 26 | if isinstance(environment.unwrapped, minerl.env._singleagent._SingleAgentEnv): 27 | # Environment is a MineRL one, use OpenCV image showing to show image 28 | # Make it larger for easier reading 29 | image = observation["pov"] 30 | image = cv2.resize(image, (256, 256)) 31 | cv2.imshow("minerl-image", image[..., ::-1]) 32 | # Refresh image 33 | _ = cv2.waitKey(1) 34 | else: 35 | # Regular render 36 | environment.render() 37 | 38 | 39 | def main(): 40 | # Create environment 41 | # Start by using CartPole-v0 for fast debugging and running! 42 | # Once code works, change to "MineRLObtainDiamond-v0" 43 | environment = gym.make("CartPole-v0") 44 | for episode_counter in range(3): 45 | # Play three episodes 46 | 47 | # Reset the environment (NOTE: With MineRL, this will take time, but with Cartpole is fast) 48 | observation = environment.reset() 49 | 50 | # Show the game situation for us to see what is going on 51 | # (Note: Normally you would use `environment.render()`, but because of MineRL 52 | # we have a different setup) 53 | render(observation, environment) 54 | # Wait a moment to give slow brains some time to process the information 55 | sleep(SLEEP_TIME) 56 | 57 | raise NotImplementedError("Implement 'step-loop' here to play one episode") 58 | 59 | # TODO step-loop 60 | # A while-loop until game returns done == True: 61 | # - Pick a random action: `environment.action_space` tells what kind actions are available. 62 | # You can use `environment.action_space.sample()` to get a random action 63 | # - Step game with `environment.step(action)`. See documentation: http://gym.openai.com/docs/ 64 | # - Print what kind of values you got from the game (observation, reward, done) 65 | # - Render current state of the game (see the use of `render` function few lines above) 66 | # - Sleep a little bit with `sleep(SLEEP_TIME)` to slow down game 67 | 68 | # Close environment properly 69 | environment.close() 70 | 71 | 72 | # Curious why this is needed? 73 | # See https://stackoverflow.com/questions/419163/what-does-if-name-main-do 74 | if __name__ == "__main__": 75 | main() 76 | -------------------------------------------------------------------------------- /playing_with_minerl.py: -------------------------------------------------------------------------------- 1 | # Import necessary libraries 2 | import pprint 3 | 4 | # We use opencv/cv2 to draw things and get keypresses 5 | import cv2 6 | import gym 7 | import numpy as np 8 | import minerl 9 | 10 | 11 | # Keymapping from keys to MineRL actions. 12 | # All actions are zeros by default ("no-op"), 13 | # and they will be updated with keys presented here. 14 | # NOTE: Only one button can be down at a time 15 | KEYBINDINGS = { 16 | "w": {"forward": 1}, 17 | "s": {"backward": 1}, 18 | "a": {"left": 1}, 19 | "d": {"right": 1}, 20 | # Arrow keys are not registered by cv2.waitKey 21 | "u": {"camera": [-5.0, 0.0]}, 22 | "j": {"camera": [5.0, 0.0]}, 23 | "h": {"camera": [0.0, -5.0]}, 24 | "k": {"camera": [0.0, 5.0]}, 25 | 26 | " ": {"jump": 1}, 27 | "b": {"attack": 1}, 28 | 29 | "1": {"craft": "planks"}, 30 | "2": {"craft": "stick"}, 31 | "3": {"craft": "crafting_table"}, 32 | "4": {"nearbyCraft": "wooden_axe"}, 33 | 34 | "c": {"place": "crafting_table"}, 35 | "e": {"equip": "wooden_axe"} 36 | } 37 | 38 | DEFAULT_BUTTON_INFO = """ 39 | INSTRUCTIONS: 40 | 41 | Control player by focusing on the image window and using controls below. 42 | The command line window will show the current inventory. 43 | 44 | Default buttons 45 | --------------- 46 | 47 | W U 48 | A-S-D H-J-K 49 | Movement Camera 50 | 51 | Space = Jump 52 | [b] = Attack 53 | 54 | [1] = Craft planks 55 | [2] = Craft sticks 56 | [3] = Craft a crafting table 57 | [4] = Craft a wooden axe (while nearby crafting table) 58 | [c] = Place crafting table 59 | [e] = Equip wooden axe (if any) 60 | --------------- 61 | """ 62 | 63 | 64 | def show_observation_and_get_action(env, observation): 65 | """Show observation to human observer and wait for a keypress""" 66 | # Print out the current inventory and item in hand 67 | # For more documentation, see https://minerl.readthedocs.io/en/latest/environments/index.html#minerlobtaindiamond-v0 68 | main_hand_item = observation["equipped_items"]["mainhand"] 69 | inventory = observation["inventory"] 70 | # Clean up inventory info a bit: if no item in inventory, remove its print 71 | for key in list(inventory.keys()): 72 | if inventory[key] == 0: 73 | _ = inventory.pop(key) 74 | else: 75 | # Remove numpy array and just replace with int 76 | inventory[key] = inventory[key].item() 77 | print("Main hand item: {}".format(main_hand_item["type"])) 78 | print("Inventory:\n", pprint.pformat(inventory, indent=4, width=10)) 79 | 80 | # Show image 81 | image = observation["pov"] 82 | # Make it larger for easier reading 83 | image = cv2.resize(image, (256, 256)) 84 | 85 | # Flip color channels (because OpenCV/cv2 wants BGR instead of RGB) 86 | cv2.imshow("image", image[..., ::-1]) 87 | # Now wait for a keypress for the action 88 | key_id = cv2.waitKey(0) 89 | # key_id is an ASCI code of the pressed character 90 | key_char = chr(key_id) 91 | 92 | # Create empty action 93 | action = env.action_space.noop() 94 | # If pressed key matches one in keybindings, 95 | # update action. 96 | if key_char in KEYBINDINGS: 97 | action.update(KEYBINDINGS[key_char]) 98 | 99 | return action 100 | 101 | 102 | def main(): 103 | """Entry point to the code. Start here""" 104 | 105 | print(DEFAULT_BUTTON_INFO) 106 | print("Now launching MineRL... This will take a while.") 107 | 108 | # Create MineRL environment 109 | # This version has basic crafting options available 110 | env = gym.make("MineRLObtainDiamondDense-v0") 111 | while True: 112 | # Play until user says otherwise 113 | # Reset environment (create a new world) 114 | # NOTE: This will take a long time, especially on the first time running MineRL! 115 | observation = env.reset() 116 | done = False 117 | while not done: 118 | # Play until player is dead 119 | # Ask human player for an action 120 | action = show_observation_and_get_action(env, observation) 121 | # Execute action on the environment and proceed to next frame 122 | observation, reward, done, info = env.step(action) 123 | 124 | # Close environment properly 125 | env.close() 126 | 127 | 128 | # Curious why this is needed? 129 | # See https://stackoverflow.com/questions/419163/what-does-if-name-main-do 130 | if __name__ == "__main__": 131 | main() 132 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | torch 2 | minerl 3 | gym 4 | tqdm 5 | opencv-python 6 | --------------------------------------------------------------------------------