Full Code of openai/universe for AI

master cc9ce6ec2418 cached
136 files
1.1 MB
335.7k tokens
1141 symbols
1 requests
Download .txt
Showing preview only (1,223K chars total). Download the full file or copy to clipboard to get everything.
Repository: openai/universe
Branch: master
Commit: cc9ce6ec2418
Files: 136
Total size: 1.1 MB

Directory structure:
gitextract_4uz9ods7/

├── .dockerignore
├── .gitignore
├── .travis.yml
├── CODE_OF_CONDUCT.rst
├── Dockerfile
├── ISSUE_TEMPLATE
├── LICENSE
├── Makefile
├── README.rst
├── doc/
│   ├── env_semantics.rst
│   ├── protocols.rst
│   └── remotes.rst
├── example/
│   ├── diagnostic-agent/
│   │   └── diagnostic-agent.py
│   ├── random-agent/
│   │   └── random-agent.py
│   ├── recorders/
│   │   ├── botaction_recorder.py
│   │   ├── reward_recorder.py
│   │   └── vnc_recorder.py
│   ├── starter-cluster/
│   │   ├── starter-cluster
│   │   ├── starter-cluster-cf.json
│   │   └── starter-cluster-requirements.txt
│   └── system-diagnostics/
│       └── system_diagnostics_logger.py
├── setup.py
├── test.dockerfile
├── tests/
│   └── functional/
│       ├── test_core_envs_semantics.py
│       └── test_envs.py
├── tox.ini
└── universe/
    ├── __init__.py
    ├── configuration.py
    ├── envs/
    │   ├── __init__.py
    │   ├── diagnostics.py
    │   ├── dummy_vnc_env.py
    │   ├── tests/
    │   │   ├── __init__.py
    │   │   └── test_semantics.py
    │   ├── vnc_core_env/
    │   │   ├── __init__.py
    │   │   ├── key.py
    │   │   ├── translator.py
    │   │   └── vnc_core_env.py
    │   ├── vnc_env.py
    │   ├── vnc_flashgames.py
    │   ├── vnc_gtav.py
    │   ├── vnc_internet.py
    │   ├── vnc_starcraft.py
    │   └── vnc_wog.py
    ├── error.py
    ├── kube/
    │   ├── __init__.py
    │   └── discovery.py
    ├── pyprofile/
    │   └── __init__.py
    ├── remotes/
    │   ├── __init__.py
    │   ├── allocator_remote.py
    │   ├── build.py
    │   ├── compose/
    │   │   ├── __init__.py
    │   │   ├── colors.py
    │   │   ├── container.py
    │   │   ├── log_printer.py
    │   │   ├── progress_stream.py
    │   │   ├── signals.py
    │   │   └── utils.py
    │   ├── docker_remote.py
    │   ├── hardcoded_addresses.py
    │   ├── healthcheck.py
    │   └── remote.py
    ├── rewarder/
    │   ├── __init__.py
    │   ├── connection_timer.py
    │   ├── env_status.py
    │   ├── merge.py
    │   ├── remote.py
    │   ├── reward_buffer.py
    │   ├── reward_proxy_server.py
    │   ├── rewarder_client.py
    │   ├── rewarder_session.py
    │   └── tests/
    │       └── test_reward_buffer.py
    ├── runtimes/
    │   ├── .agignore
    │   ├── __init__.py
    │   ├── flashgames.json
    │   └── registration.py
    ├── runtimes.yml
    ├── scoreboard/
    │   └── __init__.py
    ├── spaces/
    │   ├── __init__.py
    │   ├── diagnostics.py
    │   ├── hardcoded.py
    │   ├── joystick_action_space.py
    │   ├── joystick_event.py
    │   ├── vnc_action_space.py
    │   ├── vnc_event.py
    │   └── vnc_observation_space.py
    ├── twisty.py
    ├── utils/
    │   ├── __init__.py
    │   └── display.py
    ├── vectorized/
    │   ├── __init__.py
    │   ├── core.py
    │   ├── multiprocessing_env.py
    │   ├── tests/
    │   │   └── test_monitoring.py
    │   └── vectorize_filter.py
    ├── vncdriver/
    │   ├── README.md
    │   ├── __init__.py
    │   ├── auth.py
    │   ├── constants.py
    │   ├── dual_proxy_server.py
    │   ├── error.py
    │   ├── fbs_reader.py
    │   ├── fbs_writer.py
    │   ├── libvnc_session.py
    │   ├── screen/
    │   │   ├── __init__.py
    │   │   ├── base.py
    │   │   ├── numpy_screen.py
    │   │   ├── pyglet_screen.py
    │   │   └── screen_buffer.py
    │   ├── server_messages.py
    │   ├── vendor/
    │   │   ├── __init__.py
    │   │   └── pydes.py
    │   ├── vnc_client.py
    │   ├── vnc_proxy_server.py
    │   └── vnc_session.py
    └── wrappers/
        ├── __init__.py
        ├── action_space.py
        ├── blocking_reset.py
        ├── diagnostics.py
        ├── experimental/
        │   ├── __init__.py
        │   ├── action_space.py
        │   ├── observation.py
        │   └── random_env.py
        ├── gym_core.py
        ├── gym_core_sync.py
        ├── joint.py
        ├── logger.py
        ├── monitoring.py
        ├── multiprocessing_env.py
        ├── recording.py
        ├── render.py
        ├── tests/
        │   ├── test_joint.py
        │   └── test_time_limit.py
        ├── throttle.py
        ├── time_limit.py
        ├── timer.py
        ├── vectorize.py
        └── vision.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
vncdriver/logs
.git
*.pyc


================================================
FILE: .gitignore
================================================
.DS_Store
.ropeproject
*.pyc
tags
*.swo
*.swp
*.sqlite
upload/
venv
dist
*.egg-info
.idea
/logs
/dist
build/
/.gitfiles
/.tox
/.cache


================================================
FILE: .travis.yml
================================================
language: python
python:
  - "3.5"
services:
  - docker
before_install:
  - docker build -f test.dockerfile -t quay.io/openai/universe:test .
script:
  - docker run -v /usr/bin/docker:/usr/bin/docker -v /root/.docker:/root/.docker -v /var/run/docker.sock:/var/run/docker.sock --net=host quay.io/openai/universe:test
notifications:
  slack:
    secure: HtkwTGU+cQbpQuRaMuC2ZcuaaJfUBEZxSaChkj74lFulHAc6g/Xj1ztzj/roR/kMl3dycYPl5QL5AkxPPD/x8BweOJmgabe9boPbU9+80tpa0ueZnt0q6vX23ZA7EcqIAOwQqHiaklxoCkSflpV2N9GP20yBf5YNneHWsbFc8RDuJmNsg8s+1sZIrT3aOcvAJmu8WrNVclKvnpH/qCtvkK6npXZvdMvGpQPT/uCYOyPcbURqelk7qzNpT0oJmkrutbkT3Hp03NRDEQgS47pTPMC5pklea5zDkyh++ETEMpXU75UgN3CURKhuf/oyq7JorG/lXQaz6HBYbcT9EhPVpTzPZEczk50VAp3RWWcN6NczJJ9rVL0h+bGZmcOlJz9igNl838ziL6nxMFO9W3psXQUoBvEDo+vXPDEOUxeBrtLqUN1vfQmMw7KKiGIimInWigW19WfVQhSt47+xKKmbvBKtQ/w8lCDlwO5h7QbApv6TiaGzxtzdJMAyhNOZE7KxqvtFCJgKL4ZfmVzziLlbdbr582Cc0wxvGLDC341+CqkYVv83oimM8Ks3wHRT/ABoO1uXOSsZniUU/+oU/mzyrhrkGNNSDCwdJ0mVEWRGTYZs26IcBIeYGsLJrv3J9ZgfiyD2Knl4/yVI0IbTs7qAzhBzsXvt9aH7kH7tXYZH9QQ=
  webhooks:
    urls:
      - https://hooks.zapier.com/hooks/catch/1711022/6ztmzh/
      - https://hooks.zapier.com/hooks/catch/1711022/6zhc8p/
    on_success: always
    on_failure: always
after_success:
  - export BRANCH=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi)
  - echo "TRAVIS_BRANCH=$TRAVIS_BRANCH, PR=$PR, BRANCH=$BRANCH"
  - docker login quay.io -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"
  - docker tag quay.io/openai/universe:test quay.io/openai/universe-travis:passed-ci
  - if [ "$BRANCH" == "master" ]; then ( while true; do echo '.'; sleep 60; done ) & docker push quay.io/openai/universe-travis:passed-ci; fi # This repo is used by universe-envs to run integration test. We echo in order to keep travis alive during a slow push


================================================
FILE: CODE_OF_CONDUCT.rst
================================================
OpenAI is dedicated to providing a harassment-free experience for
everyone, regardless of gender, gender identity and expression, sexual
orientation, disability, physical appearance, body size, age, race, or
religion. We do not tolerate harassment of participants in any form.

This code of conduct applies to all OpenAI spaces both online and
off. Anyone who violates this code of conduct may be sanctioned or
expelled from these spaces at the discretion of the OpenAI team.

We may add additional rules over time, which will be made clearly
available to participants. Participants are responsible for knowing
and abiding by these rules.


================================================
FILE: Dockerfile
================================================
FROM ubuntu:16.04

RUN apt-get update \
    && apt-get install -y libav-tools \
    python3-numpy \
    python3-scipy \
    python3-setuptools \
    python3-pip \
    libpq-dev \
    libjpeg-dev \
    curl \
    cmake \
    swig \
    python3-opengl \
    libboost-all-dev \
    libsdl2-dev \
    wget \
    unzip \
    git \
    golang \
    net-tools \
    iptables \
    libvncserver-dev \
    software-properties-common \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

RUN ln -sf /usr/bin/pip3 /usr/local/bin/pip \
    && ln -sf /usr/bin/python3 /usr/local/bin/python \
    && pip install -U pip

# Install gym
RUN pip install gym[all]

# Get the faster VNC driver
RUN pip install go-vncdriver>=0.4.0

# Install pytest (for running test cases)
RUN pip install pytest

# Force the container to use the go vnc driver
ENV UNIVERSE_VNCDRIVER='go'

WORKDIR /usr/local/universe/

# Cachebusting
COPY ./setup.py ./
COPY ./tox.ini ./

RUN pip install -e .

# Upload our actual code
COPY . ./

# Just in case any python cache files were carried over from the source directory, remove them
RUN py3clean .


================================================
FILE: ISSUE_TEMPLATE
================================================

(First, please check https://github.com/openai/universe/wiki/Solutions-to-common-problems for solutions to many common problems)

### Expected behavior

### Actual behavior

### Versions
Please include the result of running
```
$ uname -a ; python --version; pip show universe gym tensorflow numpy go-vncdriver Pillow
```


================================================
FILE: LICENSE
================================================
The MIT License

Copyright (c) 2016 OpenAI (http://openai.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: Makefile
================================================
upload:
	rm -rf dist
	python setup.py sdist
	twine upload dist/*

test:
	find . -name '*.pyc' -delete
	docker build -f test.dockerfile -t quay.io/openai/universe:test .
	docker run -v /usr/bin/docker:/usr/bin/docker -v /root/.docker:/root/.docker -v /var/run/docker.sock:/var/run/docker.sock --net=host quay.io/openai/universe:test

build:
	find . -name '*.pyc' -delete
	docker build -t quay.io/openai/universe .
	docker build -f test.dockerfile -t quay.io/openai/universe:test .

push:
	find . -name '*.pyc' -delete
	docker build -t quay.io/openai/universe .
	docker build -f test.dockerfile -t quay.io/openai/universe:test .

	docker push quay.io/openai/universe
	docker push quay.io/openai/universe:test

test-push:
	docker build -f test.dockerfile -t quay.io/openai/universe:test .
	docker push quay.io/openai/universe:test


================================================
FILE: README.rst
================================================
**This repository has been deprecated in favor of the Retro (https://github.com/openai/retro) library. See our Retro Contest (https://blog.openai.com/retro-contest) blog post for detalis.**

universe
***************

`Universe <https://openai.com/blog/universe/>`_ is a software
platform for measuring and training an AI's general intelligence
across the world's supply of games, websites and other
applications. This is the ``universe`` open-source library, which
provides a simple `Gym <https://github.com/openai/gym>`__
interface to each Universe environment.

Universe allows anyone to train and evaluate AI agents on an extremely
wide range of real-time, complex environments.

Universe makes it possible for any existing program to become an
OpenAI Gym environment, without needing special access to the
program's internals, source code, or APIs. It does this by packaging
the program into a Docker container, and presenting the AI with the
same interface a human uses: sending keyboard and mouse events, and
receiving screen pixels. Our initial release contains over 1,000
environments in which an AI agent can take actions and gather
observations.

Additionally, some environments include a reward signal sent to the
agent, to guide reinforcement learning. We've included a few hundred
environments with reward signals. These environments also include
automated start menu clickthroughs, allowing your agent to skip to the
interesting part of the environment.

We'd like the community's `help <https://openai.com/blog/universe/#help>`_
to grow the number of available environments, including integrating
increasingly large and complex games.

The following classes of tasks are packaged inside of
publicly-available Docker containers, and can be run today with no
work on your part:

- Atari and CartPole environments over VNC: ``gym-core.Pong-v3``, ``gym-core.CartPole-v0``, etc.
- Flashgames over VNC: ``flashgames.DuskDrive-v0``, etc.
- Browser tasks ("World of Bits") over VNC: ``wob.mini.TicTacToe-v0``, etc.

We've scoped out integrations for many other games, including
completing a high-quality GTA V integration (thanks to `Craig Quiter <http://deepdrive.io/>`_ and NVIDIA), but these aren't included in today's release.

.. contents:: **Contents of this document**
   :depth: 2


Getting started
===============

Installation
------------

Supported systems
~~~~~~~~~~~~~~~~~

We currently support Linux and OSX running Python 2.7 or 3.5.

We recommend setting up a `conda environment <http://conda.pydata.org/docs/using/envs.html>`__
before getting started, to keep all your Universe-related packages in the same place.

Install Universe
~~~~~~~~~~~~~~~~
To get started, first install ``universe``:

.. code:: shell

    git clone https://github.com/openai/universe.git
    cd universe
    pip install -e .

If this errors out, you may be missing some required packages. Here's
the list of required packages we know about so far (please let us know
if you had to install any others).

On Ubuntu 16.04:

.. code:: shell

    pip install numpy
    sudo apt-get install golang libjpeg-turbo8-dev make

On Ubuntu 14.04:

.. code:: shell

    sudo add-apt-repository ppa:ubuntu-lxc/lxd-stable  # for newer golang
    sudo apt-get update
    sudo apt-get install golang libjpeg-turbo8-dev make

On OSX:

You might need to install Command Line Tools by running:

.. code:: shell

    xcode-select --install

Or ``numpy``, ``libjpeg-turbo`` and ``incremental`` packages:

.. code:: shell

    pip install numpy incremental
    brew install golang libjpeg-turbo

Install Docker
~~~~~~~~~~~~~~

The majority of the environments in Universe run inside Docker
containers, so you will need to `install Docker
<https://docs.docker.com/engine/installation/>`__ (on OSX, we
recommend `Docker for Mac
<https://docs.docker.com/docker-for-mac/>`__). You should be able to
run ``docker ps`` and get something like this:

.. code:: shell

     $ docker ps
     CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

Alternate configuration - running the agent in docker
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The above instructions result in an agent that runs as a regular python process in your OS, and launches docker containers as needed for the remotes.
Alternatively, you can build a docker image for the agent and run it as a container as well.
You can do this in any operating system that has a recent version of docker installed, and the git client.

To get started, clone the ``universe`` repo:

.. code:: shell

    git clone https://github.com/openai/universe.git
    cd universe
	
Build a docker image, tag it as 'universe':

.. code:: shell

    docker build -t universe .

This may take a while the first time, as the docker image layers are pulled from docker hub.

Once the image is built, you can do a quick run of the test cases to make sure everything is working:

.. code:: shell

    docker run --privileged --rm -e DOCKER_NET_HOST=172.17.0.1 -v /var/run/docker.sock:/var/run/docker.sock universe pytest

Here's a breakdown of that command:

* ``docker run`` - launch a docker container
* ``--rm`` - delete the container once the launched process finishes
* ``-e DOCKER_NET_HOST=172.17.0.1`` - tells the universe remote (when launched) to make its VNC connection back to this docker-allocated IP
* ``-v /var/run/docker.sock:/var/run/docker.sock`` - makes the docker unix socket from the host available to the container. This is a common technique used to allow containers to launch other containers alongside itself.
* ``universe`` - use the imaged named 'universe' built above
* ``pytest`` - run 'pytest' in the container, which runs all the tests

At this point, you'll see a bunch of tests run and hopefully all pass.

To do some actual development work, you probably want to do another volume map from the universe repo on your host into the container, then shell in interactively:

.. code:: shell

    docker run --privileged --rm -it -e DOCKER_NET_HOST=172.17.0.1 -v /var/run/docker.sock:/var/run/docker.sock -v (full path to cloned repo above):/usr/local/universe universe python

As you edit the files in your cloned git repo, they will be changed in your docker container and you'll be able to run them in python.

Note if you are using docker for Windows, you'll need to enable the relevant shared drive for this to work.


Notes on installation
~~~~~~~~~~~~~~~~~~~~~

* When installing ``universe``, you may see ``warning`` messages.  These lines occur when installing numpy and are normal.
* You'll need a ``go version`` of at least 1.5. Ubuntu 14.04 has an older Go, so you'll need to `upgrade <https://golang.org/doc/install>`_ your Go installation.
* We run Python 3.5 internally, so the Python 3.5 variants will be much more thoroughly performance tested. Please let us know if you see any issues on 2.7.
* While we don't officially support Windows, we expect our code to be very close to working there. We'd be happy to take pull requests that take our Windows compatibility to 100%. In the meantime, the easiest way for Windows users to run universe is to use the alternate configuration described above.

System overview
---------------

A Universe **environment** is similar to any other Gym environment:
the agent submits actions and receives observations using the ``step()``
method.

Internally, a Universe environment consists of two pieces: a **client** and a **remote**:

* The **client** is a `VNCEnv
  <https://github.com/openai/universe/blob/master/universe/envs/vnc_env.py>`_
  instance which lives in the same process as the agent. It performs
  functions like receiving the agent's actions, proxying them to the
  **remote**, queuing up rewards for the agent, and maintaining a
  local view of the current episode state.
* The **remote** is the running environment dynamics, usually a
  program running inside of a Docker container. It can run anywhere --
  locally, on a remote server, or in the cloud. (We have a separate
  page describing how to manage `remotes <doc/remotes.rst>`__.)
* The client and the remote communicate with one another using the
  `VNC <https://en.wikipedia.org/wiki/Virtual_Network_Computing>`__
  remote desktop system, as well as over an auxiliary WebSocket
  channel for reward, diagnostic, and control messages. (For more
  information on client-remote communication, see the separate page on
  the `Universe internal communication protocols
  <doc/protocols.rst>`__.)

The code in this repository corresponds to the **client** side of the
Universe environments. Additionally, you can freely access the Docker
images for the **remotes**. We'll release the source repositories for
the remotes in the future, along with tools to enable users to
integrate new environments. Please sign up for our `beta
<https://docs.google.com/forms/d/e/1FAIpQLScAiW-kIS0mz6hdzzFZJJFlXlicDvQs1TX9XMEkipNwjV5VlA/viewform>`_
if you'd like early access.

Run your first agent
--------------------

Now that you've installed the ``universe`` library, you should make
sure it actually works. You can paste the example below into your
``python`` REPL. (You may need to press enter an extra time to make
sure the ``while`` loop is executing.)

.. code:: python

  import gym
  import universe  # register the universe environments

  env = gym.make('flashgames.DuskDrive-v0')
  env.configure(remotes=1)  # automatically creates a local docker container
  observation_n = env.reset()

  while True:
    action_n = [[('KeyEvent', 'ArrowUp', True)] for ob in observation_n]  # your agent here
    observation_n, reward_n, done_n, info = env.step(action_n)
    env.render()

The example will instantiate a client in your Python process,
automatically pull the ``quay.io/openai/universe.flashgames`` image,
and will start that image as the remote. (In our `remotes
<doc/remotes.rst>`__ documentation page, we explain other ways you can run
remotes.)

It will take a few minutes for the image to pull the first time. After that,
if all goes well, a window like the one below will soon pop up. Your
agent, which is just pressing the up arrow repeatedly, is now
playing a Flash racing game called `Dusk Drive
<http://www.kongregate.com/games/longanimals/dusk-drive>`__. Your agent
is programmatically controlling a VNC client, connected to a VNC
server running inside of a Docker container in the cloud, rendering a
headless Chrome with Flash enabled:

.. image:: https://github.com/openai/universe/blob/master/doc/dusk-drive.png?raw=true
     :width: 600px

You can even connect your own VNC client to the environment, either
just to observe or to interfere with your agent. Our ``flashgames``
and ``gym-core`` images conveniently bundle a browser-based VNC
client, which can be accessed at
``http://localhost:15900/viewer/?password=openai``. If you're on Mac,
connecting to a VNC server is as easy as running: ``open
vnc://localhost:5900``.

(If using docker-machine, you'll need to replace "localhost" with the
IP address of your Docker daemon, and use ``openai`` as the password.)

Breaking down the example
~~~~~~~~~~~~~~~~~~~~~~~~~

So we managed to run an agent, what did all the code actually
mean? We'll go line-by-line through the example.

* First, we import the `gym <https://github.com/openai/gym>`__ library,
  which is the base on which Universe is built. We also import
  ``universe``, which `registers
  <https://github.com/openai/universe/blob/master/universe/__init__.py>`__
  all the Universe environments.

.. code:: python

  import gym
  import universe # register the universe environments

* Next, we create the environment instance. Behind the scenes, ``gym``
  looks up the `registration
  <https://github.com/openai/universe/blob/master/universe/__init__.py>`__
  for ``flashgames.DuskDrive-v0``, and instantiates a `VNCEnv
  <https://github.com/openai/universe/blob/master/universe/envs/vnc_env.py#L88>`__
  object which has been `wrapped
  <https://github.com/openai/universe/blob/master/universe/wrappers/__init__.py#L42>`__
  to add a few useful diagnostics and utilities. The ``VNCEnv`` object
  is the *client* part of the environment, and it is not yet connected
  to a *remote*.

.. code:: python

  env = gym.make('flashgames.DuskDrive-v0')

* The call to ``configure()`` connects the client to a remote
  environment server. When called with ``configure(remotes=1)``,
  Universe will automatically create a Docker image running locally on
  your computer. The local client connects to the remote using VNC.
  (More information on client-remote communication can be found in the
  page on `universe internal communication protocols
  <doc/protocols.rst>`__. More on configuring remotes is at `remotes <doc/remotes.rst>`__.)

.. code:: python

  env.configure(remotes=1)

* When starting a new environment, you call ``env.reset()``. Universe
  environments run in real-time, rather than stepping synchronously
  with the agent's actions, so ``reset`` is asynchronous and returns
  immediately. Since the environment will not have waited to finish
  connecting to the VNC server before returning, the initial observations
  from ``reset`` will be ``None`` to indicate that there is
  not yet a valid observation.

  Similarly, the environment keeps running in the background even
  if the agent does not call ``env.step()``.  This means that an agent
  that successfully learns from a Universe environment cannot take
  "thinking breaks":  it must keep sending actions to the environment at all times.

  Additionally, Universe introduces the *vectorized* Gym
  API. Rather than controlling a single environment at a time, the agent
  can control a fixed-size vector of ``n`` environments, each with its
  own remote. The return value from ``reset`` is therefore a *vector*
  of observations. For more information, see the separate page on
  `environment semantics <doc/env_semantics.rst>`__)

.. code:: python

  observation_n = env.reset()

* At each ``step()`` call, the agent submits a vector of actions; one for
  each environment instance it is controlling. Each VNC action is a
  list of events; above, each action is the single event "press the
  ``ArrowUp`` key". The agent could press and release the key in one
  action by instead submitting ``[('KeyEvent', 'ArrowUp', True),
  ('KeyEvent', 'ArrowUp', False)]`` for each observation.

  In fact, the agent could largely have the same effect by just
  submitting ``('KeyEvent', 'ArrowUp', True)`` once and then calling
  ``env.step([[] for ob in observation_n])`` thereafter, without ever
  releasing the key using ``('KeyEvent', 'ArrowUp', False)``. The
  browser running inside the remote would continue to statefully
  represent the arrow key as being pressed. Sending other unrelated
  keypresses would not disrupt the up arrow keypress; only explicitly
  releasing the key would cancel it.  There's one slight subtlety:
  when the episode resets, the browser will reset, and will forget
  about the keypress; you'd need to submit a new ``ArrowUp`` at the
  start of each episode.

.. code:: python

  action_n = [[('KeyEvent', 'ArrowUp', True)] for ob in observation_n]

* After we submit the action to the environment and render one frame,
  ``step()`` returns a list of *observations*, a list of *rewards*, a
  list of *"done" booleans* indicating whether the episode has ended,
  and then finally an *info dictionary* of the form ``{'n': [{},
  ...]}``, in which you can access the info for environment ``i`` as
  ``info['n'][i]``.

  Each environment's ``info`` message contains useful diagnostic
  information, including latency data, client and remote timings,
  VNC update counts, and reward message counts.

.. code:: python

    observation_n, reward_n, done_n, info = env.step(action_n)
    env.render()

* We call ``step`` in what looks like a busy loop. In reality, there
  is a `Throttle
  <https://github.com/openai/universe/blob/master/universe/wrappers/__init__.py#L18>`__
  wrapper on the client which defaults to a target frame rate of 60fps, or one
  frame every 16.7ms. If you call it more frequently than that,
  ``step`` will `sleep
  <https://github.com/openai/universe/blob/master/universe/wrappers/throttle.py>`__
  with any leftover time.


Testing
=======

We are using `pytest <http://doc.pytest.org/en/latest/>`__ for tests. You can run them via:

.. code:: shell

    pytest

Run ``pytest --help`` for useful options, such as ``pytest -s`` (disables output capture) or ``pytest -k <expression>`` (runs only specific tests).

Additional documentation
========================

More documentation not covered in this README can be found in the
`doc folder <doc>`__ of this repository.

Getting help
============

If you encounter a problem that is not addressed in this README page
or in the `extra docs <doc>`__, then try our wiki page of `solutions
to common problems
<https://github.com/openai/universe/wiki/Solutions-to-common-problems>`__ -
and add to it if your solution isn't there!

You can also search through the `issues
<https://github.com/openai/universe/issues?utf8=%E2%9C%93&q=is%3Aissue>`__
on this repository and our `discussion board
<https://discuss.openai.com/c/Universe>`__ to see if another user has posted
about the same problem or to ask for help from the community.

If you still can't solve your problem after trying all of the above
steps, please post an issue on this repository.

What's next?
============

* Get started training RL algorithms! You can try out the `Universe Starter Agent <https://github.com/openai/universe-starter-agent>`_, an implementation of the `A3C algorithm <https://arxiv.org/abs/1602.01783>`_ that can solve several VNC environments.

* For more information on how to manage remotes, see the separate documentation page on `remotes <doc/remotes.rst>`__.

* Sign up for a `beta <https://docs.google.com/forms/d/e/1FAIpQLScAiW-kIS0mz6hdzzFZJJFlXlicDvQs1TX9XMEkipNwjV5VlA/viewform>`_ to get early access to upcoming Universe releases, such as tools to integrate new Universe environments or a dataset of recorded human demonstrations.


Changelog
---------
- 2017-02-08: The old location for wrappers.SafeActionSpace has been moved to wrappers.experimental.SafeActionSpace. SoftmaxClickMouse has also been moved to wrappers.experimental.SoftmaxClickMouse
- 2017-01-08: The wrappers.SafeActionSpace has been moved to wrappers.experimental.SafeActionSpace. The old location will remain with a deprecation warning until 2017-02-08.
- 2016-12-27: BACKWARDS INCOMPATIBILITY: The gym monitor is now a
  wrapper. Rather than starting monitoring as
  `env.monitor.start(directory)`, envs are now wrapped as follows:
  `env = wrappers.Monitor(env, directory)`. This change is on master
  and will be released with 0.21.0.


================================================
FILE: doc/env_semantics.rst
================================================
Environment semantics
*********************
  
Real-time environments
======================

Universe environments differ from other Gym environments in that the
environment keeps running in real-time, even when the agent does not
call ``step``. This has a few important implications:

* Actions and observations can no longer be considered to
  occur on a "clock tick".
* An explicit call to ``reset`` is asynchronous and returns
  immediately, even though the environment has not yet finished
  resetting. (If you would prefer the ``reset`` call to block
  until the reset has finished, you can wrap
  the client-side environment with a `BlockingReset <https://github.com/openai/universe/blob/master/universe/wrappers/blocking_reset.py>`__ wrapper)
* Since the environment will not have waited to finish
  connecting to the VNC server before returning, the initial return
  values from ``reset`` will be ``None`` to indicate that there is
  not yet a valid observation.
* An agent that successfully learns from a Universe environment cannot
  take "thinking breaks": it must keep sending actions to the
  environment at all times.
* Lag and latency play a major role in your agent's ability to
  successfully learn in a given environment. The latency and profiling
  numbers returned in the ``info`` dictionary can provide important
  information for training.

Vectorized API
==============

The vectorized Gym API allows a single client-side environment to
control a vector of remotes. The main difference with the
non-vectorized Gym API is that individual environments will
automatically reset upon reaching the end of an episode. (An episode
is defined as ending when an agent has concretely succeeded or failed
at the task, such as after clearing a level of a game, or losing the
game. Some environments without clearly delineated success and
failure conditions may not have episodes.)

There are two API methods, ``reset`` and ``step``. The semantics are:

- ``reset`` takes no arguments and returns a vector of observations:

.. code:: python

  observation_n = env.reset()

- ``step`` consumes a vector of actions, and returns a vector of
  observations, vector of rewards, vector of done booleans, and an
  info dictionary. The info dictionary has an ``n`` key, which
  contains a vector of infos specific to each env:

.. code:: python

  observation_n, reward_n, done_n, info = env.step(action_n)
  # len(info['n']) == len(observation_n)

Some important notes:

- At any given moment, some of the environments may be
  resetting. Resetting environments will have a ``None`` value for
  their observation. For example, an ``observation_n`` of ``[None,
  {'vision': ...}, {'vision': ...}]`` indicates that the environment
  at index 0 is resetting.
- When an index returns ``done=True``, the corresponding environment
  will automatically start resetting.
- The user must call ``reset`` once before calling ``step``; undefined
  behavior will result if ``reset`` is not called. Further ``reset``
  calls are allowed, but generally are used only if the environment has
  been idle for a while (such as with periodic evaluation), or when it
  is important to start at the beginning 

Versioning
==========

The remote is versioned and has fixed semantics, assuming sufficient
compute resources are applied (i.e. if you don't have enough CPU, your
flash environments will likely behave differently). The client's exact
semantics will depend on the version of universe you have installed,
and you should track the version of that together with the rest of
your agent code.



================================================
FILE: doc/protocols.rst
================================================
Universe internal communication protocols
*****************************************

Network architecture
====================

A Universe environment consists of two components that run in
separate processes and communicate over the network.  The agent's
machine runs the environment **client** code, which connects
to the **remote** environment server.

Many related environments can be served from the same **runtime**,
usually packaged as a Docker container. For example, all the flash
games in Universe are served from the ``flashgames`` runtime, which
consists of the ``quay.io/openai/universe.flashgames`` Docker image
and runs with its corresponding set of configuration flags.

Each remote exposes two ports:

- A VNC port (5900 by default). The remote runs an off-the-shelf VNC
  server (usually TigerVNC), so that users can connect their own
  VNC viewers to the environments for interactive use. VNC delivers
  pixel observations to the agent, and the agent submits keyboard and
  mouse inputs over VNC as well.

- A rewarder port (15900 by default). The rewarder protocol is a
  bi-directional JSON protocol runs over WebSockets. The rewarder
  channel provides more than just a reward signal; in addition, it allows the
  agent to submit control commands (such as to indicating which of
  the available environments should be active for a given runtime) and
  to receive structured information from the environment (such as latencies
  and performance timings).

VNC system and Remote Frame Buffer protocol
===========================================
 
Keyboard and mouse actions and pixel observations are sent between the
client and the remote using the `VNC
<https://en.wikipedia.org/wiki/Virtual_Network_Computing>`__
system. VNC is a pervasive standard for remote desktop operation. Many
implementations of VNC are available online, including VNC viewers
that make it easy to observe a running agent.

To achieve the performance we needed in order to train an
agent on dozens of simultaneous remote environments at 60FPS, we wrote a
`custom client-side VNC driver <https://github.com/openai/go-vncdriver>`__
in go. The remote VNC server that we use in most of our runtimes is `TigerVNC <http://tigervnc.org/>`__

More information about the Remote Frame Buffer protocol can be found
in the official `IETF RFC <https://tools.ietf.org/html/rfc6143>`__
spec, and in other tutorials elsewhere on the internet.

Rewarder protocol
=================

The Rewarder protocol is a Universe-specific bi-directional JSON
protocol run over WebSockets. In addition to the actions and
observations provided by the VNC connection, the rewarder connection
allows the agent to submit control commands to the environment, and to
receive rewards and other informational messages. This section details
the format of the Rewarder protocol.

Message format
--------------

Each message is serialized as a JSON object with the following
structure:

.. code::
		  
    {
      "method": [string],
      "headers": [object],
      "body": [object]
    }

For example, a ``v0.env.describe`` message might look as follows:

.. code::

    {
      "method": "v0.env.describe",
      "headers": {
        "sent_at": 1479493678.1937322617,
        "message_id": 15,
        "episode_id": "1.2",
      },
      "body": {
        "env_id": "internet.SlitherIO-v0",
        "env_state": "running",
        "fps": 60
      }
    }


Each message should have a unique ``message_id`` header and a ``sent_at``
header (which should be the current UNIX timestamp with at least
millisecond precision).

Server to client messages
-------------------------

env.describe
~~~~~~~~~~~~

.. code:: 
		  
    {
      "method": "v0.env.describe",
      "headers": {
        "sent_at": 1479493678.1937322617,
        "message_id": 15,
        "episode_id": "1.2",
      },
      "body": {
        "env_id": "internet.SlitherIO-v0",
        "env_state": "running",
      }
    }

env.reward
~~~~~~~~~~

.. code::
		  
    {
      "method": "v0.env.reward",
      "headers": {
        "sent_at": 1479493678.1937322617,
        "message_id": 15,
        "episode_id": "1.2",
      },
      "body": {
        "reward": -3,
        "done": False,
    	"info": {},
      }
    }

env.text
~~~~~~~~

.. code::
		  
    {
      "method": "v0.env.text",
      "headers": {
        "sent_at": 1479493678.1937322617,
        "message_id": 15,
        "episode_id": "1.2",
      },
      "body": {
        "text": "this is some text"
      }
    }

env.observation
~~~~~~~~~~~~~~~

.. code::
		  
    {
      "method": "v0.env.observation",
      "headers": {
        "sent_at": 1479493678.1937322617,
        "message_id": 15,
        "episode_id": "1.2"
      },
      "body": {
        "observation": [0.12, 0.51, 2, 12]
      }
    }

connection.close
~~~~~~~~~~~~~~~~

.. code::
		  
    {
      "method": "v0.connection.close",
      "headers": {
        "sent_at": 1479493678.1937322617,
        "message_id": 15
      },
      "body": {
        "message": "Disconnected since time limit reached"
      }
    }

reply.error
~~~~~~~~~~~

.. code::
		  
    {
      "method": "v0.reply.error",
      "headers": {
        "sent_at": 1479493678.1937322617,
        "message_id": 15,
    	"parent_message_id": "26"
      },
      "body": {
        "message": "No such environment: llama"
      }
    }

reply.env.reset
~~~~~~~~~~~~~~~

.. code::
		  
    {
      "method": "v0.reply.env.reset",
      "headers": {
        "sent_at": 1479493678.1937322617,
        "message_id": 15,
    	"parent_message_id": "26",
    	"episode_id": "1.2"
    	
      },
      "body": {}
    }
    
reply.control.ping
~~~~~~~~~~~~~~~~~~

.. code::
		  
    {
      "method": "v0.reply.control.ping",
      "headers": {
        "sent_at": 1479493678.1937322617,
        "message_id": 15,
    	"parent_message_id": "26"
      },
      "body": {}
    }

Client to server messages
-------------------------

agent.action
~~~~~~~~~~~~

.. code::
		  
    {
      "method": "v0.agent.action",
      "headers": {
        "sent_at": 1479493678.1937322617,
        "message_id": 15
      },
      "body": {
        "action: [["JoystickAxisXEvent", 0.1],
                  ["JoystickAxisZEvent", 0.1]]
      }
    }

env.reset
~~~~~~~~~

.. code::
		  
    {
      "method": "v0.env.reset",
      "headers": {
        "sent_at": 1479493678.1937322617,
        "message_id": 15
      },
      "body": {
        "env_id': "flashgames.DuskDrive-v0"
      }
    }

control.ping
~~~~~~~~~~~~

.. code::
		  
    {
      "method": "v0.control.ping",
      "headers": {
        "sent_at": 1479493678.1937322617,
        "message_id": 15
      },
      "body": {}
    }


================================================
FILE: doc/remotes.rst
================================================
Remotes
*******

Since the remote part of the environment runs in its own server
process, managing remotes is an important task. The remote can run
anywhere - locally, or in the cloud. This section will explain
three ways to set up remotes.

.. contents:: **Contents of this document**
   :depth: 2

Docker installation
===================

The majority of the remotes for Universe environments run inside
Docker containers, so the first step to running your own remotes is
to `install Docker <https://docs.docker.com/engine/installation/>`__ (on
OSX, we recommend `Docker for Mac
<https://docs.docker.com/docker-for-mac/>`__). You should be able to
run ``docker ps`` and get something like this:

.. code:: shell

     $ docker ps
     CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES


How to start a remote
=====================

There are currently three ways to start a remote:

- Create an **automatic local remote** using ``env.configure(remotes=1)``.
  In this case, ``universe`` automatically creates a remote locally by spinning
  up a docker container for you.

- Create a **manual remote** by spinning up your own Docker container,
  locally or on a server you control.

- Create a **starter cluster** in AWS, which will automatically provide you
  with cloud-hosted remotes.


Automatic local remotes
-----------------------

To create an **automatic local remote**, call
``env.configure(remotes=1)`` (or ``4`` if you'd like 4 remotes).
This will download the ``quay.io/openai/universe.flashgames`` docker
container and start 1 copy of it locally.

.. code:: python

    import gym
    import universe # register the universe environments

    env = gym.make('flashgames.DuskDrive-v0')
    env.configure(remotes=1) # downloads and starts a flashgames runtime
    observation_n = env.reset()

    while True:
            action_n = [[('KeyEvent', 'ArrowUp', True)] for ob in observation_n] # your agent here
            observation_n, reward_n, done_n, info = env.step(action_n)
            env.render()


Agents inside Docker
~~~~~~~~~~~~~~~~~~~~
If you're running your agent inside a Docker container, it can still create automatic remotes by connecting
to the docker daemon on the host. To do this, mount the docker binary and socket inside the agent container like this:

.. code:: shell

    $ docker run --privileged \
        -v /usr/bin/docker:/usr/bin/docker \
        -v /root/.docker:/root/.docker \
        -v /var/run/docker.sock:/var/run/docker.sock \
        -e DOCKER_NET_HOST=172.17.0.1 \
        ... \
        my/agent:latest


The Universe remote will use ``$DOCKER_NET_HOST`` when connecting to the VNC and rewarder ports.


Manual remotes
--------------

To create a **manual remote**, start the remote Docker container
manually on the command line. Remotes can run locally on the same machine as
the client, or you can start them on servers you control.

To find the appropriate Docker command-line invocation for each
environment, you can look at where we `register
<https://github.com/openai/universe/blob/master/universe/runtimes/__init__.py>`__
the runtime for each environment. The command is also printed out
conveniently when you run with ``remotes=1``:

.. code:: shell

    [2016-11-25 23:51:04,223] [0] Creating container:
	image=quay.io/openai/universe.flashgames:0.19.19. Run the same thing by hand as:
	docker run -p 10000:5900 -p 10001:15900 --cap-add NET_ADMIN --cap-add SYS_ADMIN
	--ipc host quay.io/openai/universe.flashgames:0.19.19

Once you have started the docker container, configure your agent to
  connect to the VNC server (port 5900 by default) and the reward/info channel
  (port 15900 by default):

.. code:: python

    env.configure(remotes='vnc://localhost:5900+15900')

To connect manually to multiple remotes, separate them by commas:

.. code:: python

    env.configure(remotes='vnc://localhost:5900+15900,vnc://localhost:5901+15901')

If your docker container is running on a server rather than on localhost,
just plug in the appropriate URL or IP address:

.. code:: python

    env.configure(remotes='vnc://your.host.here:5900+15900')

VNC compression settings
-----------------------------------------------

The VNC connection supports multiple compression settings that control the tradeoff
between a fast but highly compressed, low quality data stream and slow, uncompressed
data stream. These can be configured by using the ``vnc_kwargs`` argument to
``env.configure``. The default arguments are:

.. code:: python

    env.configure(vnc_kwargs={'encoding':'tight', 'fine_quality_level':50, 'subsample_level':2})

Here, ``tight`` is a lossy encoding that uses JPEG for compression. We also support ``zrle`` instead, which is lossless.
The ``fine_quality_level`` controls the compression strength from high compression / low quality (0) to low compression / high quality (100).
For ``subsample_level``, 0 is highest quality, 2 is low quality and 3 is greyscale. You can investigate the effects
of many of these options on the visual fidelity by connecting to an environment using TurboVNC, which allows you to
tune these settings in the user interface.

Note that the codecs always operate on deltas of the screen, so if large portions of your screen are not changing then
you might be able to afford higher quality settings. Conversely, if you're playing a racing game that takes up a large
portion of the screen you should be more worried about bandwidth. The call to ``step`` is asynchronous with respect to
new frames arriving, so if the connection is too slow the environments will lag.

Automatic cloud-hosted remotes: starter cluster
-----------------------------------------------

If you have an AWS account, you can spin up a **starter Docker cluster** to host your own remotes. First click the "Launch Stack" button and follow the steps on the AWS console to deploy your cluster.

  .. image:: https://s3.amazonaws.com/cloudformation-examples/cloudformation-launch-stack.png
     :target: https://console.aws.amazon.com/cloudformation/home#/stacks/new?stackName=OpenAI-Universe&templateURL=thttps://s3-us-west-2.amazonaws.com/openai-public/universe/starter-cluster-cf-0.1.0.json

Once your stack on AWS is ready, run `starter-cluster` to start your environments

  .. code:: shell

    $ example/starter-cluster/starter-cluster start -s [stack-name] -i [path-to-ssh-key] \
        --runtime [universe-runtime] -n [number-of-envs]

or example, the follow will start two flashgames remotes:

  .. code:: shell

    $ pip install -r bin/starter-cluster-requirements.txt
    $ bin/starter-cluster -v start -s OpenAI-Universe -i my-ec2-key.pem -r flashgames -n 2
    Creating network "flashgames_default" with the default driver
    Pulling flashgames-0 (quay.io/openai/universe.flashgames:0.19.36)...
    ip-172-33-1-4: Pulling quay.io/openai/universe.flashgames:0.19.36... : downloaded
    ip-172-33-28-242: Pulling quay.io/openai/universe.flashgames:0.19.36... : downloaded
    Creating flashgames_flashgames-0_1
    Creating flashgames_flashgames-1_1
    Environments started.
    Remotes:
      vnc://54.245.154.123:5013+5015
      vnc://54.245.154.123:5006+5008

Now you can pass the IP address and ports for your remotes to your agent,
as was described in the previous section on manual remotes. For example:

  .. code:: shell

    $ python bin/random_agent.py -e flashgames.DuskDrive-v0 -r vnc://54.245.154.123:5013+5015,54.245.154.123:5006+5008

Running ``bin/starter-cluster start`` again will restart your remotes. To stop them, run:

  .. code:: shell

    $ bin/starter-cluster stop -s OpenAI-Universe -i my-ec2-key.pem -r flashgames
    Stopping flashgames_flashgames-1_1 ... done
    Stopping flashgames_flashgames-0_1 ... done
    Removing flashgames_flashgames-1_1 ... done
    Removing flashgames_flashgames-0_1 ... done
    Removing network flashgames_default
    Environments stopped.

Region
~~~~~~

By default, starter cluster remotes are spawned in AWS's ``us-west-2``
region. In our experience, the latencies of training over the public
internet are acceptable, but if you have trouble, it may make sense to
try running your agent code on an AWS server in the same region as the
remote.

Scaling Up
~~~~~~~~~~

If you encounter the following

.. code:: shell

  $ bin/starter-cluster -v start -s OpenAI-Universe -i my-ec2-key.pem -r flashgames   -n 2
    Creating network "flashgames_default" with the default driver
    Pulling flashgames-0 (quay.io/openai/universe.flashgames:0.19.36)...
    ip-172-33-1-4: Pulling quay.io/openai/universe.flashgames:0.19.36... : downloaded
    ip-172-33-28-242: Pulling quay.io/openai/universe.flashgames:0.19.36... :   downloaded
    ip-172-33-9-51: Pulling quay.io/openai/universe.flashgames:0.19.36... :   downloaded
    ip-172-33-27-141: Pulling quay.io/openai/universe.flashgames:0.19.36... :   downloaded
    Creating flashgames_flashgames-2_1
    Creating flashgames_flashgames-3_1
    Creating flashgames_flashgames-0_1
    Creating flashgames_flashgames-1_1
    Creating flashgames_flashgames-4_1

    ERROR: for flashgames-0  no resources available to schedule container

then it means you've run out of computing resources on your cluster, and
have to add more worker nodes. You can do so by going to the AWS
Cloudformation console:

1. Select your stack
2. Click "Update Stack" in the "Actions" dropdown
3. Hit "Next" on the "Select Template" page
4. Input the new swarm size and hit "Next"
5. Hit "Next" on the "Options" page
6. Hit "Update" on the "Review" page


Reusing remotes
===============

If a consistent ``client_id`` is supplied to ``configure()``, then the
client will attempt to reuse the same remote for the new environment
rather than spinning up a new one each time.

Switching between environments in the same *runtime*
(i.e. environments that run on the same underlying docker container)
is possible without creating a new remote; however, if you want to
switch to an environment in a different runtime, you will need to create
a new remote. For example, you can switch between
``flashgames.DuskDrive-v0`` and ``flashgames.NeonRace-v0`` without
starting a new remote, because they both run in the ``flashgames``
runtime, but if you want to switch to ``wob.mini.UseColorwheel2-v0``
you cannot re-use the same remote.

The configuration for the runtimes is defined in
`universe/runtimes/__init__.py <https://github.com/openai/universe/blob/master/universe/runtimes/__init__.py>`__,
and the specific version number tags for the corresponding Docker
images are specified in
`runtimes.yml <https://github.com/openai/universe/blob/master/universe/runtimes.yml>`__.


================================================
FILE: example/diagnostic-agent/diagnostic-agent.py
================================================
#!/usr/bin/env python
import argparse
import logging
import time

import gym
import numpy as np
import universe
from universe import pyprofile, wrappers, spaces
from gym import wrappers as gym_wrappers

# if not os.getenv("PYPROFILE_FREQUENCY"):
#     pyprofile.profile.print_frequency = 5
from universe import vectorized

logger = logging.getLogger()

CHROME_X_OFFSET = 18
CHROME_Y_OFFSET = 84

class NoopSpace(gym.Space):
    """ Null action space """
    def sample(self, seed=0):
        return []
    def contains(self, x):
        return x == []

class ForwardSpace(gym.Space):
    """ Only move forward action space """
    def __init__(self, key='w'):
        self.key = [spaces.KeyEvent.by_name(key, down=True)]
    def sample(self, seed=0):
        return self.key
    def contains(self, x):
        return x == self.key

# The world's simplest agent!
class RandomAgent(object):
    """
    Example usage:

        bin/random_agent.py -e gym-core.Pong-v3 --remote localhost:5900+15900

    """
    def __init__(self, action_space, n, vectorized):
        self.action_space = action_space
        self.n = n
        self.vectorized = vectorized

    def __call__(self, observation, reward, done):
        if self.vectorized:
            return [self.action_space.sample() for _ in range(self.n)]
        else:
            return self.action_space.sample()

if __name__ == '__main__':
    # You can optionally set up the logger. Also fine to set the level
    # to logging.DEBUG or logging.WARN if you want to change the
    # amount of output.
    logger.setLevel(logging.INFO)
    universe.configure_logging()

    # Actions this agent will take, 'random' is the default
    action_choices = ['random', 'noop', 'forward', 'click']

    parser = argparse.ArgumentParser(description=None)
    parser.add_argument('-e', '--env_id', default='gym-core.Pong-v3', help='Which environment to run on.')
    parser.add_argument('-m', '--monitor', action='store_true', help='Whether to activate the monitor.')
    parser.add_argument('-r', '--remote', default=None, help='The number of environments to create (e.g. -r 20), or the address of pre-existing VNC servers and rewarders to use (e.g. -r vnc://localhost:5900+15900,localhost:5901+15901)')
    parser.add_argument('-c', '--client-id', default='0', help='Set client id.')
    parser.add_argument('-v', '--verbose', action='count', dest='verbosity', default=0, help='Set verbosity.')
    parser.add_argument('-R', '--no-render', action='store_true', help='Do not render the environment locally.')
    parser.add_argument('-A', '--actions', choices=action_choices, default='random', help='How to sample actions to send to remote environment')
    parser.add_argument('-d', '--docker-image', help='Force a version of the docker_image used with --remote <int>. e.g --docker-image quay.io/openai/universe.gym-core:0.3')
    parser.add_argument('-s', '--reuse', default=False, action='store_true', help='Reuse existing Docker container if present, and leave this one running after (only for "-r n")')
    parser.add_argument('-f', '--fps', default=60., type=float, help='Desired frames per second')
    parser.add_argument('-N', '--max-steps', type=int, default=10**7, help='Maximum number of steps to take')
    parser.add_argument('-E', '--max-episodes', type=int, default=10**7, help='Maximum number of episodes')
    parser.add_argument('-T', '--start-timeout', type=int, default=None, help='Rewarder session connection timeout (seconds)')
    args = parser.parse_args()

    logging.getLogger('gym').setLevel(logging.NOTSET)
    logging.getLogger('universe').setLevel(logging.NOTSET)
    if args.verbosity == 0:
        logger.setLevel(logging.INFO)
    elif args.verbosity >= 1:
        logger.setLevel(logging.DEBUG)

    if args.env_id is not None:
        env = gym.make(args.env_id)
    else:
        env = wrappers.WrappedVNCEnv()
    # env = wrappers.BlockingReset(env)
    if not isinstance(env, wrappers.GymCoreAction):
        # The GymCoreSyncEnv's try to mimic their core counterparts,
        # and thus came pre-wrapped wth an action space
        # translator. Everything else probably wants a SafeActionSpace
        # wrapper to shield them from random-agent clicking around
        # everywhere.
        env = wrappers.experimental.SafeActionSpace(env)
    else:
        # Only gym-core are seedable
        env.seed([0])
    env = wrappers.Logger(env)

    if args.monitor:
        env = wrappers.Monitor(env, '/tmp/vnc_random_agent', force=True)

    if args.actions == 'random':
        action_space = env.action_space
    elif args.actions == 'noop':
        action_space = NoopSpace()
    elif args.actions == 'forward':
        action_space = ForwardSpace()
    elif args.actions == 'click':
        spec = universe.runtime_spec('flashgames').server_registry[args.env_id]
        height = spec["height"]
        width = spec["width"]
        noclick_regions = [r['coordinates'] for r in spec['regions'] if r['type'] == 'noclick'] if spec.get('regions') else []
        active_region = (CHROME_X_OFFSET, CHROME_Y_OFFSET, CHROME_X_OFFSET + width, CHROME_Y_OFFSET + height)
        env = wrappers.SoftmaxClickMouse(env, active_region=active_region, noclick_regions=noclick_regions)
        action_space = env.action_space
    else:
        logger.error("Invalid action choice: {}".format(args.actions))
        exit(1)

    env.configure(
        fps=args.fps,
        # print_frequency=None,
        # ignore_clock_skew=True,
        remotes=args.remote,
        client_id=args.client_id,
        start_timeout=args.start_timeout,

        # remotes=remote, docker_image=args.docker_image, reuse=args.reuse, ignore_clock_skew=True,
        # vnc_session_driver='go', vnc_session_kwargs={
        #     'compress_level': 0,
        # },

        vnc_driver='go', vnc_kwargs={
            # 'encoding': 'tight', 'compress_level': 0, 'fine_quality_level': 50, 'subsample_level': 2,
            'encoding': 'tight', 'compress_level': 0, 'fine_quality_level': 50, 'subsample_level': 0, 'quality_level': 5,
        },
    )

    agent = RandomAgent(action_space, n=env.n, vectorized=env.metadata['runtime.vectorized'])

    render = not args.no_render
    observation_n = env.reset()
    target = time.time()
    reward_n = [0] * env.n
    done_n = [False] * env.n

    observation_count = np.zeros(env.n)
    episode_length = np.zeros(env.n)
    episode_score = np.zeros(env.n)

    episodes_completed = 0

    for i in range(args.max_steps):
        # print(observation_n)
        # user_input.handle_events()

        if render:
            # Note the first time you call render, it'll be relatively
            # slow and you'll have some aggregated rewards. We could
            # open the render() window before `reset()`, but that's
            # confusing since it pops up a black window for the
            # duration of the reset.
            env.render()

        action_n = agent(observation_n, reward_n, done_n)

        # Take an action
        with pyprofile.push('env.step'):
            observation_n, reward_n, done_n, info = env.step(action_n)

        episode_length += 1
        if not all(r is None for r in reward_n): # checks if we connected the rewarder
            episode_score += np.array(reward_n)
        for i, ob in enumerate(observation_n):
            if ob is not None and (not isinstance(ob, dict) or ob['vision'] is not None):
                observation_count[i] += 1

        scores = {}
        lengths = {}
        observations = {}
        for i, done in enumerate(done_n):
            if not done:
                continue
            scores[i] = episode_score[i]
            lengths[i] = episode_length[i]
            observations[i] = observation_count[i]

            episode_score[i] = 0
            episode_length[i] = 0
            observation_count[i] = 0
        if len(scores) > 0:
            logger.info('Total for completed episodes: reward=%s length=%s observations=%s', scores, lengths, observations)

        errored = [i for i, info_i in enumerate(info['n']) if 'error' in info_i]
        if errored:
            logger.info('had errored indexes: %s: %s', errored, info)

        episodes_completed += len([d for d in done_n if d])
        if episodes_completed >= args.max_episodes:
            break

        # if info.get('n') and info['n'][0].get('env_status.instruction'):
        #     logger.info('received instruction = %s', info['n'][0]['env_status.instruction'])

        # if observation_n[0].get('text'):
        #     logger.info('message_n=%s', [observation['text'] for observation in observation_n])

        # if any(done_n) or any(r != 0.0 and r is not None for r in reward_n):
        #     logger.info('reward_n=%s done_n=%s info=%s', reward_n, done_n, info)

    # We're done! clean up
    env.close()


================================================
FILE: example/random-agent/random-agent.py
================================================
#!/usr/bin/env python
import argparse
import logging
import sys

import gym
import universe # register the universe environments

from universe import wrappers

logger = logging.getLogger()

def main():
    parser = argparse.ArgumentParser(description=None)
    parser.add_argument('-v', '--verbose', action='count', dest='verbosity', default=0, help='Set verbosity.')
    args = parser.parse_args()

    if args.verbosity == 0:
        logger.setLevel(logging.INFO)
    elif args.verbosity >= 1:
        logger.setLevel(logging.DEBUG)


    env = gym.make('flashgames.NeonRace-v0')
    env.configure(remotes=1)  # automatically creates a local docker container
    
    # Restrict the valid random actions. (Try removing this and see
    # what happens when the agent is given full control of the
    # keyboard/mouse.)
    env = wrappers.experimental.SafeActionSpace(env)
    observation_n = env.reset()

    while True:
        # your agent here
        #
        # Try sending this instead of a random action: ('KeyEvent', 'ArrowUp', True)
        action_n = [env.action_space.sample() for ob in observation_n]
        observation_n, reward_n, done_n, info = env.step(action_n)
        env.render()

    return 0

if __name__ == '__main__':
    sys.exit(main())


================================================
FILE: example/recorders/botaction_recorder.py
================================================
#!/usr/bin/env python
"""
  This is a small server that accepts connections on a websocket port and writes it to a file.

  The purpose is to allow a universe-env with a built-in bot to record the actions it's taking
  as a demonstration. So the demonstration includes a botactions.jsonl file that gets used instead
  of the vnc client log. (The vnc client log is still recorded and needed to fully parse the VNC
  protocol.)

  It's much simpler than reward_recorder.py, because it doesn't have to also talk to the agent.
  It just takes json messages over a websocket and appends them separated by newlines to the log file.

  The ws port is 15986 unless overridden with --listen-address
  The log file is /tmp/demo/botactions.jsonl unless overridden with --botaction-logfile
"""
import argparse
import logging
import sys
import json
from autobahn.twisted import websocket
from universe.twisty import reactor
logger = logging.getLogger()

class BotactionRecordingServer(websocket.WebSocketServerProtocol, object):

    _next_id = 1
    @classmethod
    def next_id(cls):
        id = cls._next_id
        cls._next_id += 1
        return id

    logfile_path='/tmp/demo/botactions.jsonl'

    def __init__(self):
        super(BotactionRecordingServer, self).__init__()
        self.id = self.next_id()
        self._closed = False
        self.file = None

        logger.info("[BotactionRecordingServer] [%d] Wrote version number", self.id)

    def _emit(self, rec):
        if self.file:
            self.file.write(json.dumps(rec) + '\n');
            self.file.flush()

    def onConnect(self, request):
        logger.info('[BotactionRecordingServer] [%d] Client connecting: %s. Writing to %s', self.id, request.peer, self.logfile_path)
        self.file = open(self.logfile_path, 'w', encoding='utf-8')
        self._emit({
            'version': 1,
            'session_id': self.id,
            '_debug_version': '0.0.1',  # Give this an internal version for debugging corrupt reward.demo files # TODO, pull this from setup.py or the host docker image
        })

    def onOpen(self):
        logger.info("[BotactionRecordingServer] [%d] Websocket connection established", self.id)

    def onClose(self, wasClean, code, reason):
        logger.info('[BotactionRecordingServer] [%d] Client connection closed: %s', self.id, reason)
        if self.file:
            self.file.close()
            self.file = None

        self._closed = True

    def onMessage(self, msg, binary):
        logger.debug('[BotactionRecordingServer] [%d] Received message from client: %s', self.id, msg)

        self._emit(json.loads(msg.decode('utf-8')));

def main():
    parser = argparse.ArgumentParser(description=None)
    parser.add_argument('-v', '--verbose', action='count', dest='verbosity', default=0, help='Set verbosity.')
    parser.add_argument('-l', '--listen-address', default='127.0.0.1:15896', help='Address to listen on')
    parser.add_argument('-o', '--botaction-logfile', default='/tmp/demo/botactions.jsonl', help='Filename for timestamped log of bot actions.')
    args = parser.parse_args()

    BotactionRecordingServer.logfile_path = args.botaction_logfile

    if args.verbosity == 0:
        logger.setLevel(logging.INFO)
    elif args.verbosity >= 1:
        logger.setLevel(logging.DEBUG)

    factory = websocket.WebSocketServerFactory()
    factory.protocol = BotactionRecordingServer

    host, port = args.listen_address.split(':')
    port = int(port)
    logger.info('Listening on %s:%s', host, port)
    reactor.listenTCP(port, factory)
    reactor.run()
    return 0

if __name__ == '__main__':
    sys.exit(main())


================================================
FILE: example/recorders/reward_recorder.py
================================================
#!/usr/bin/env python
import argparse
import logging
import sys

from autobahn.twisted import websocket
from universe.rewarder import reward_proxy_server
from universe.twisty import reactor

logger = logging.getLogger()


def main():
    parser = argparse.ArgumentParser(description=None)
    parser.add_argument('-v', '--verbose', action='count', dest='verbosity', default=0, help='Set verbosity.')
    parser.add_argument('-l', '--listen-address', default='0.0.0.0:15898', help='Address to listen on')
    parser.add_argument('-s', '--rewarder-address', default='127.0.0.1:15900', help='Address of the reward server to run on.')
    parser.add_argument('-d', '--logfile-dir', default=None, help='Base directory to write logs for each connection')
    args = parser.parse_args()

    if args.verbosity == 0:
        logger.setLevel(logging.INFO)
    elif args.verbosity >= 1:
        logger.setLevel(logging.DEBUG)

    factory = websocket.WebSocketServerFactory()
    factory.protocol = reward_proxy_server.RewardProxyServer
    factory.rewarder_address = args.rewarder_address
    factory.logfile_dir = args.logfile_dir
    factory.setProtocolOptions(maxConnections=1)  # We only write reward logs to one place, so only allow one connection

    host, port = args.listen_address.split(':')
    port = int(port)
    logger.info('Listening on %s:%s', host, port)
    reactor.listenTCP(port, factory)
    reactor.run()
    return 0

if __name__ == '__main__':
    sys.exit(main())


================================================
FILE: example/recorders/vnc_recorder.py
================================================
#!/usr/bin/env python
import argparse
import logging
import os
import re
import sys

from universe import utils
from universe.vncdriver import vnc_proxy_server
from twisted.internet import protocol, reactor

logger = logging.getLogger()

def main():
    parser = argparse.ArgumentParser(description=None)
    parser.add_argument('-v', '--verbose', action='count', dest='verbosity', default=0, help='Set verbosity.')
    parser.add_argument('-l', '--listen-address', default='0.0.0.0:5899', help='Address to listen on')
    parser.add_argument('-s', '--vnc-address', default='127.0.0.1:5900', help='Address of the VNC server to run on.')
    parser.add_argument('-d', '--logfile-dir', default=None, help='Base directory to write logs for each connection')
    args = parser.parse_args()

    if args.verbosity == 0:
        logger.setLevel(logging.INFO)
    elif args.verbosity >= 1:
        logger.setLevel(logging.DEBUG)

    factory = protocol.ServerFactory()
    factory.protocol = vnc_proxy_server.VNCProxyServer
    factory.vnc_address = 'tcp:{}'.format(args.vnc_address)
    factory.logfile_dir = args.logfile_dir
    factory.recorder_id = utils.random_alphanumeric().lower()

    host, port = args.listen_address.split(':')
    port = int(port)

    logger.info('Listening on %s:%s', host, port)
    reactor.listenTCP(port, factory, interface=host)
    reactor.run()
    return 0

if __name__ == '__main__':
    sys.exit(main())


================================================
FILE: example/starter-cluster/starter-cluster
================================================
#!/usr/bin/env python
from contextlib import contextmanager
import logging
import math
import os
import os.path
import subprocess
import sys

import boto3
import click
import docker
import yaml

import universe

logger = logging.getLogger('cluster')

DEBUG_LOGGING_MAP = {
    0: logging.WARNING,
    1: logging.INFO,
    2: logging.DEBUG
}

VNC_PORT = 5900
REWARDER_PORT = 15900


def get_ports(cli, n):
    """
    returns a list of n ports that are available in the docker cluster
    """
    used_ports = set()

    containers = cli.containers()
    for container in containers:
        for port in container.get('Ports', []):
            used_ports.add(port.get('PublicPort'))

    ports = []
    obtained = 0
    for i in range(5000, 10000):
        if i not in used_ports:
            ports.append(i)
            obtained += 1

        if obtained == n:
            break

    return ports


def start_ssh_tunnel(host, local_port, remote_path, key_path):
    cmd = [
        'ssh', '-L', 'localhost:{}:{}'.format(local_port, remote_path),
        '-o', 'stricthostkeychecking=no', '-o', 'UserKnownHostsFile=/dev/null']
    if key_path:
        cmd += ['-i', key_path]
    cmd.append('ec2-user@{}'.format(host))
    cmd.append('echo tunnel-ready; sleep 3600')

    logger.debug('Starting SSH tunnel: %s', cmd)

    process = subprocess.Popen(cmd, stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE)
    return process


@contextmanager
def docker_cli(host, local_port, remote_path='localhost:4000',
               key_path=None):
    ssh_tunnel = start_ssh_tunnel(host, local_port, remote_path, key_path)
    for line in iter(ssh_tunnel.stdout.readline, ''):
        if line.strip() == b'tunnel-ready':
            break
    logger.debug('SSH tunnel ready [pid: %s]', ssh_tunnel.pid)
    try:
        yield docker.Client(base_url='localhost:{}'.format(local_port))
    finally:
        logger.debug('SSH tunnel terminating')
        ssh_tunnel.terminate()
        for line in iter(ssh_tunnel.stderr.readline, ''):
            line = line.strip()
            if not line:
                break
            logger.debug('[SSH tunnel stderr] %s', line)


def get_compose_file(runtime):
    dir_path = os.path.dirname(os.path.realpath(__file__))
    return os.path.join(dir_path, 'gen', runtime, 'docker-compose.yaml')


def build_compose(cli, runtime, n):
    spec = universe.runtime_spec(runtime)
    expose = [VNC_PORT-1, VNC_PORT, REWARDER_PORT-1, REWARDER_PORT]
    usable_ports = get_ports(cli, len(expose) * n)

    output = {
        'version': '2'
    }

    services = {}
    for i in range(n):
        service = {
            'image': spec.image,
            'command': spec.command,
            'cap_add': spec.host_config.get('cap_add', [])
        }
        if spec.host_config.get('ipc_mode'):
            service['ipc'] = spec.host_config['ipc_mode']

        service['cpu_shares'] = int(math.ceil(spec.default_params.get('cpu', 4)))

        service['ports'] = ['{host}:{container}'.format(container=port, host=usable_ports[i*len(expose)+j])
                            for j, port in enumerate(expose)]

        service['labels'] = {
            'universe.runtime': runtime,
            'universe.index': str(i)
        }

        services['{}-{}'.format(runtime, i)] = service

    output['services'] = services
    content = yaml.dump(output)

    filepath = get_compose_file(runtime)

    directory = os.path.dirname(filepath)
    if not os.path.exists(directory):
        logger.info('Creating directory: %s', directory)
        os.makedirs(directory)

    logger.info('Writing compose file to %s', filepath)
    with open(filepath, 'w') as f:
        f.write(content)

    return filepath


def start_compose(cli, filepath):
    subprocess.check_call(['docker-compose', '-H', cli.base_url, '-f', filepath, 'up', '-d', '--remove-orphans'])


def stop_compose(cli, filepath):
    subprocess.check_call(['docker-compose', '-H', cli.base_url, '-f', filepath, 'down', '--remove-orphans'])


class Stack(object):
    def __init__(self, data):
        self.name = data['StackName']

        outputs = {}
        for output in data['Outputs']:
            outputs[output['OutputKey']] = output['OutputValue']
        self.docker_ip = outputs['DockerIP']
        self.worker_asg = outputs['ASGName']


def get_stack(name):
    client = boto3.client('cloudformation')
    response = client.describe_stacks(StackName=name)
    if len(response['Stacks']) == 0:
        raise Exception('Failed to find CloudFormation stack {}'.format(name))

    return Stack(response['Stacks'][0])


def get_worker_instances(stack_name):
    instances = {}

    client = boto3.client('ec2')
    response = client.describe_instances(
        Filters=[
            {
                'Name': 'tag:aws:cloudformation:stack-name',
                'Values': [
                    stack_name,
                ]
            },
            {
                'Name': 'instance-state-name',
                'Values': [
                    'running'
                ]
            }
        ]
    )
    for reservation in response['Reservations']:
        for instance in reservation['Instances']:
            instances[instance['PrivateIpAddress']] = {
                'id': instance['InstanceId'],
                'public_ip': instance.get('PublicIpAddress')
            }

    return instances


def get_runtime_containers(cli, runtime):
    containers_map = {}
    filters = {
        'label': ['universe.runtime={}'.format(runtime)]
    }
    containers = cli.containers(filters=filters)
    for container in containers:
        labels = container['Labels']
        addr = None
        for name in container['Names']:
            if name.startswith('/ip-'):
                addr = name.split('/')[1][3:].replace('-', '.')
        containers_map[labels['com.docker.compose.service']] = {
            'labels': labels,
            'ports': container['Ports'],
            'host': addr
        }

    return containers_map


@click.group()
@click.option('--verbose', '-v',
              help='Sets the debug noise level, specify multiple times for more verbosity.',
              type=click.IntRange(0, 3, clamp=True),
              count=True)
def cli(verbose):
    logger_handler = logging.StreamHandler(sys.stderr)
    logger_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
    logger.addHandler(logger_handler)
    logger.setLevel(DEBUG_LOGGING_MAP.get(verbose, logging.DEBUG))


@cli.command()
@click.option('--stack', '-s', 'stack_name', required=True,
              help='AWS CloudFormation Stack name.')
@click.option('--port', '-P', default=2374,
              help='Local port to use for remote docker connection')
@click.option('--key-path', '-i',
              help='Path to private key for SSH connection to docker host')
@click.option('--runtime', default='flashgames',
              help='Runtime ID to start. (See universe/runtimes/__init__ for a starting list)')
@click.option('-n', default=1,
              help='Number of environments to start')
def start(stack_name, port, key_path, runtime, n):
    stack = get_stack(stack_name)
    with docker_cli(stack.docker_ip, port, key_path=key_path) as cli:
        filepath = build_compose(cli, runtime, n)
        start_compose(cli, filepath)

        containers = get_runtime_containers(cli, runtime)
        instances = get_worker_instances(stack.name)

        endpoints = []
        for name, container in containers.items():
            for port in container['ports']:
                if port['PrivatePort'] == VNC_PORT:
                    vnc_port = port['PublicPort']
                elif port['PrivatePort'] == REWARDER_PORT:
                    rewarder_port = port['PublicPort']
            if container['host'] in instances:
                host_ip = instances[container['host']]['public_ip']
                endpoints.append(
                    'vnc://{}:{}+{}'.format(host_ip, vnc_port, rewarder_port))
            else:
                logger.warn(
                    'Container %s on unknown host %s', name, container['host'])

        print('Environments started.')
        print('Remotes:')
        for endpoint in endpoints:
            print('\t{}'.format(endpoint))


@cli.command()
@click.option('--stack', '-s', 'stack_name', required=True,
              help='AWS CloudFormation Stack name.')
@click.option('--port', '-P', default=2374,
              help='Local port to use for remote docker connection')
@click.option('--key-path', '-i',
              help='Path to private key for SSH connection to docker host')
@click.option('--runtime', default='flashgames',
              help='Runtime ID to stop. (See universe/runtimes/__init__ for a starting list)')
def stop(stack_name, port, key_path, runtime):
    stack = get_stack(stack_name)
    with docker_cli(stack.docker_ip, port, key_path=key_path) as cli:
        filepath = get_compose_file(runtime)
        stop_compose(cli, filepath)

        print('Environments stopped.')

if __name__ == '__main__':
    cli()


================================================
FILE: example/starter-cluster/starter-cluster-cf.json
================================================
{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Description": "Docker cluster for OpenAI Universe runtimes",
    "Mappings": {
        "AWSInstanceType2Arch": {
            "c3.2xlarge": {
                "Arch": "HVM64"
            },
            "c3.4xlarge": {
                "Arch": "HVM64"
            },
            "c3.8xlarge": {
                "Arch": "HVM64"
            },
            "c3.large": {
                "Arch": "HVM64"
            },
            "c3.xlarge": {
                "Arch": "HVM64"
            },
            "c4.2xlarge": {
                "Arch": "HVM64"
            },
            "c4.4xlarge": {
                "Arch": "HVM64"
            },
            "c4.8xlarge": {
                "Arch": "HVM64"
            },
            "c4.large": {
                "Arch": "HVM64"
            },
            "c4.xlarge": {
                "Arch": "HVM64"
            },
            "cc2.8xlarge": {
                "Arch": "HVM64"
            },
            "cr1.8xlarge": {
                "Arch": "HVM64"
            },
            "d2.2xlarge": {
                "Arch": "HVM64"
            },
            "d2.4xlarge": {
                "Arch": "HVM64"
            },
            "d2.8xlarge": {
                "Arch": "HVM64"
            },
            "d2.xlarge": {
                "Arch": "HVM64"
            },
            "g2.2xlarge": {
                "Arch": "HVMG2"
            },
            "hi1.4xlarge": {
                "Arch": "HVM64"
            },
            "hs1.8xlarge": {
                "Arch": "HVM64"
            },
            "i2.2xlarge": {
                "Arch": "HVM64"
            },
            "i2.4xlarge": {
                "Arch": "HVM64"
            },
            "i2.8xlarge": {
                "Arch": "HVM64"
            },
            "i2.xlarge": {
                "Arch": "HVM64"
            },
            "m3.2xlarge": {
                "Arch": "HVM64"
            },
            "m3.large": {
                "Arch": "HVM64"
            },
            "m3.medium": {
                "Arch": "HVM64"
            },
            "m3.xlarge": {
                "Arch": "HVM64"
            },
            "m4.10xlarge": {
                "Arch": "HVM64"
            },
            "m4.2xlarge": {
                "Arch": "HVM64"
            },
            "m4.4xlarge": {
                "Arch": "HVM64"
            },
            "m4.large": {
                "Arch": "HVM64"
            },
            "m4.xlarge": {
                "Arch": "HVM64"
            },
            "r3.2xlarge": {
                "Arch": "HVM64"
            },
            "r3.4xlarge": {
                "Arch": "HVM64"
            },
            "r3.8xlarge": {
                "Arch": "HVM64"
            },
            "r3.large": {
                "Arch": "HVM64"
            },
            "r3.xlarge": {
                "Arch": "HVM64"
            },
            "t2.large": {
                "Arch": "HVM64"
            },
            "t2.medium": {
                "Arch": "HVM64"
            },
            "t2.micro": {
                "Arch": "HVM64"
            },
            "t2.small": {
                "Arch": "HVM64"
            }
        },
        "AWSRegionArch2AMI" : {
          "us-east-1"        : {"PV64" : "ami-2a69aa47", "HVM64" : "ami-6869aa05", "HVMG2" : "ami-a41a3fb3"},
          "us-west-2"        : {"PV64" : "ami-7f77b31f", "HVM64" : "ami-7172b611", "HVMG2" : "ami-caf253aa"},
          "us-west-1"        : {"PV64" : "ami-a2490dc2", "HVM64" : "ami-31490d51", "HVMG2" : "ami-00347e60"},
          "eu-west-1"        : {"PV64" : "ami-4cdd453f", "HVM64" : "ami-f9dd458a", "HVMG2" : "ami-e2f7bd91"},
          "eu-central-1"     : {"PV64" : "ami-6527cf0a", "HVM64" : "ami-ea26ce85", "HVMG2" : "ami-d2ff04bd"},
          "ap-northeast-1"   : {"PV64" : "ami-3e42b65f", "HVM64" : "ami-374db956", "HVMG2" : "ami-4c78d52d"},
          "ap-northeast-2"   : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-2b408b45", "HVMG2" : "NOT_SUPPORTED"},
          "ap-southeast-1"   : {"PV64" : "ami-df9e4cbc", "HVM64" : "ami-a59b49c6", "HVMG2" : "ami-f3f95990"},
          "ap-southeast-2"   : {"PV64" : "ami-63351d00", "HVM64" : "ami-dc361ebf", "HVMG2" : "ami-3a122e59"},
          "ap-south-1"       : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-ffbdd790", "HVMG2" : "ami-21a7d34e"},
          "us-east-2"        : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-f6035893", "HVMG2" : "NOT_SUPPORTED"},
          "sa-east-1"        : {"PV64" : "ami-1ad34676", "HVM64" : "ami-6dd04501", "HVMG2" : "NOT_SUPPORTED"},
          "cn-north-1"       : {"PV64" : "ami-77559f1a", "HVM64" : "ami-8e6aa0e3", "HVMG2" : "NOT_SUPPORTED"}
        },
        "VpcCidrs": {
            "pubsubnet1": {
                "cidr": "172.33.0.0/20"
            },
            "pubsubnet2": {
                "cidr": "172.33.16.0/20"
            },
            "pubsubnet3": {
                "cidr": "172.33.32.0/20"
            },
            "pubsubnet4": {
                "cidr": "172.33.48.0/20"
            },
            "vpc": {
                "cidr": "172.33.0.0/16"
            }
        }
    },
    "Metadata": {
        "AWS::CloudFormation::Interface": {
            "ParameterGroups": [
                {
                    "Label": {
                        "default": "Swarm Size"
                    },
                    "Parameters": [
                        "ClusterSize"
                    ]
                },
                {
                    "Label": {
                        "default": "Swarm Properties"
                    },
                    "Parameters": [
                        "KeyName"
                    ]
                },
                {
                    "Label": {
                        "default": "Swarm Manager Properties"
                    },
                    "Parameters": [
                        "ManagerInstanceType",
                        "ManagerDiskSize",
                        "ManagerDiskType"
                    ]
                },
                {
                    "Label": {
                        "default": "Swarm Worker Properties"
                    },
                    "Parameters": [
                        "InstanceType",
                        "WorkerDiskSize",
                        "WorkerDiskType"
                    ]
                }
            ],
            "ParameterLabels": {
                "ClusterSize": {
                    "default": "Number of Swarm worker nodes?"
                },
                "InstanceType": {
                    "default": "Agent worker instance type?"
                },
                "KeyName": {
                    "default": "Which SSH key to use?"
                },
                "ManagerDiskSize": {
                    "default": "Manager ephemeral storage volume size?"
                },
                "ManagerDiskType": {
                    "default": "Manager ephemeral storage volume type"
                },
                "ManagerInstanceType": {
                    "default": "Swarm manager instance type?"
                },
                "WorkerDiskSize": {
                    "default": "Worker ephemeral storage volume size?"
                },
                "WorkerDiskType": {
                    "default": "Worker ephemeral storage volume type"
                }
            }
        }
    },
    "Outputs": {
        "ASGName": {
            "Description": "Name of the worker AutoScalingGroup",
            "Value": {
                "Ref": "NodeAsg"
            }
        },
        "DockerIP": {
            "Description": "Public IP of the manager node that can be SSH'd into",
            "Value": {
                "Fn::GetAtt": [
                    "ManagerInstance",
                    "PublicIp"
                ]
            }
        }
    },
    "Parameters": {
        "ClusterSize": {
            "Default": "4",
            "Description": "Number of worker nodes in the Swarm (1-1000).",
            "MaxValue": "1000",
            "MinValue": "1",
            "Type": "Number"
        },
        "InstanceType": {
            "AllowedValues": [
                "t2.micro",
                "t2.small",
                "t2.medium",
                "t2.large",
                "m4.large",
                "m4.xlarge",
                "m4.2xlarge",
                "m4.4xlarge",
                "m4.10xlarge",
                "m3.medium",
                "m3.large",
                "m3.xlarge",
                "m3.2xlarge",
                "c4.large",
                "c4.xlarge",
                "c4.2xlarge",
                "c4.4xlarge",
                "c4.8xlarge",
                "c3.large",
                "c3.xlarge",
                "c3.2xlarge",
                "c3.4xlarge",
                "c3.8xlarge",
                "r3.large",
                "r3.xlarge",
                "r3.2xlarge",
                "r3.4xlarge",
                "r3.8xlarge",
                "i2.xlarge",
                "i2.2xlarge",
                "i2.4xlarge",
                "i2.8xlarge"
            ],
            "ConstraintDescription": "Must be a valid EC2 HVM instance type.",
            "Default": "c4.xlarge",
            "Description": "EC2 HVM instance type (t2.micro, m3.medium, etc).",
            "Type": "String"
        },
        "KeyName": {
            "ConstraintDescription": "must be the name of an existing EC2 KeyPair.",
            "Description": "Name of an existing EC2 KeyPair to enable SSH access to the instances",
            "MinLength": "1",
            "Type": "AWS::EC2::KeyPair::KeyName"
        },
        "ManagerDiskSize": {
            "Default": "20",
            "Description": "Size of Manager's ephemeral storage volume in GiB",
            "MaxValue": "1024",
            "MinValue": "20",
            "Type": "Number"
        },
        "ManagerDiskType": {
            "AllowedValues": [
                "standard",
                "gp2"
            ],
            "Default": "standard",
            "Description": "Manager ephemeral storage volume type",
            "Type": "String"
        },
        "ManagerInstanceType": {
            "AllowedValues": [
                "t2.micro",
                "t2.small",
                "t2.medium",
                "t2.large",
                "m4.large",
                "m4.xlarge",
                "m4.2xlarge",
                "m4.4xlarge",
                "m4.10xlarge",
                "m3.medium",
                "m3.large",
                "m3.xlarge",
                "m3.2xlarge",
                "c4.large",
                "c4.xlarge",
                "c4.2xlarge",
                "c4.4xlarge",
                "c4.8xlarge",
                "c3.large",
                "c3.xlarge",
                "c3.2xlarge",
                "c3.4xlarge",
                "c3.8xlarge",
                "r3.large",
                "r3.xlarge",
                "r3.2xlarge",
                "r3.4xlarge",
                "r3.8xlarge",
                "i2.xlarge",
                "i2.2xlarge",
                "i2.4xlarge",
                "i2.8xlarge"
            ],
            "ConstraintDescription": "Must be a valid EC2 HVM instance type.",
            "Default": "t2.small",
            "Description": "EC2 HVM instance type (t2.micro, m3.medium, etc).",
            "Type": "String"
        },
        "WorkerDiskSize": {
            "Default": "50",
            "Description": "Size of Workers's ephemeral storage volume in GiB",
            "MaxValue": "1024",
            "MinValue": "20",
            "Type": "Number"
        },
        "WorkerDiskType": {
            "AllowedValues": [
                "standard",
                "gp2"
            ],
            "Default": "standard",
            "Description": "Worker ephemeral storage volume type",
            "Type": "String"
        }
    },
    "Resources": {
        "AttachGateway": {
            "DependsOn": [
                "Vpc",
                "InternetGateway"
            ],
            "Properties": {
                "InternetGatewayId": {
                    "Ref": "InternetGateway"
                },
                "VpcId": {
                    "Ref": "Vpc"
                }
            },
            "Type": "AWS::EC2::VPCGatewayAttachment"
        },
        "DockerLogGroup": {
            "Properties": {
                "LogGroupName": {
                    "Fn::Join": [
                        "-",
                        [
                            {
                                "Ref": "AWS::StackName"
                            },
                            "lg"
                        ]
                    ]
                },
                "RetentionInDays": 7
            },
            "Type": "AWS::Logs::LogGroup"
        },
        "InternetGateway": {
            "DependsOn": "Vpc",
            "Properties": {
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "-",
                                [
                                    {
                                        "Ref": "AWS::StackName"
                                    },
                                    "IGW"
                                ]
                            ]
                        }
                    }
                ]
            },
            "Type": "AWS::EC2::InternetGateway"
        },
        "ManagerInstance": {
            "DependsOn": [
                "PubSubnetAz1",
                "PubSubnetAz2"
            ],
            "Properties": {
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "-",
                                [
                                    {
                                        "Ref": "AWS::StackName"
                                    },
                                    "Manager"
                                ]
                            ]
                        }
                    },
                    {
                        "Key": "swarm-node-type",
                        "Value": "manager"
                    },
                    {
                        "Key": "swarm-stack-id",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }
                ],
                "BlockDeviceMappings": [
                    {
                        "DeviceName": "/dev/xvdb",
                        "Ebs": {
                            "VolumeSize": {
                                "Ref": "ManagerDiskSize"
                            },
                            "VolumeType": {
                                "Ref": "ManagerDiskType"
                            }
                        }
                    }
                ],
                "IamInstanceProfile": {
                    "Ref": "ProxyInstanceProfile"
                },
                "ImageId": {
                    "Fn::FindInMap": [
                        "AWSRegionArch2AMI",
                        {
                            "Ref": "AWS::Region"
                        },
                        {
                            "Fn::FindInMap": [
                                "AWSInstanceType2Arch",
                                {
                                    "Ref": "ManagerInstanceType"
                                },
                                "Arch"
                            ]
                        }
                    ]
                },
                "InstanceType": {
                    "Ref": "ManagerInstanceType"
                },
                "KeyName": {
                    "Ref": "KeyName"
                },
                "SecurityGroupIds": [
                    {
                        "Ref": "ManagerVpcSG"
                    },
                    {
                        "Ref": "SwarmWideSG"
                    }
                ],
                "SubnetId": {
                    "Ref": "PubSubnetAz1"
                },
                "UserData": {
                    "Fn::Base64": {
                        "Fn::Join": [
                            "",
                            [
                                "#!/bin/sh\n",
                                "sudo yum update -y\n",
                                "curl -sSL https://get.docker.com/ | sh\n",
                                "sed -i 's/OPTIONS=\"/OPTIONS=\"-H tcp:\\/\\/0\\.0\\.0\\.0:2375 -H unix:\\/\\/\\/var\\/run\\/docker\\.sock /' /etc/sysconfig/docker\n",
                                "sudo /etc/init.d/docker start\n",
                                "sudo usermod -aG docker ec2-user\n",
                                "\n",
                                "export LOCAL_IP=$(wget -qO- http://169.254.169.254/latest/meta-data/local-ipv4)\n",
                                "sleep 5\n",

                                "docker run -d -p 8500:8500 --name=consul progrium/consul -server -bootstrap -advertise=$LOCAL_IP\n",
                                "docker run -d -p 4000:4000 swarm manage -H :4000 --replication --advertise $LOCAL_IP:4000 consul://$LOCAL_IP:8500\n"
                            ]
                        ]
                    }
                }
            },
            "Type": "AWS::EC2::Instance"
        },
        "ManagerVpcSG": {
            "DependsOn": "NodeVpcSG",
            "Properties": {
                "GroupDescription": "Manager SecurityGroup",
                "SecurityGroupIngress": [
                    {
                        "CidrIp": "0.0.0.0/0",
                        "FromPort": "22",
                        "IpProtocol": "tcp",
                        "ToPort": "22"
                    },
                    {
                        "FromPort": "2377",
                        "IpProtocol": "tcp",
                        "SourceSecurityGroupId": {
                            "Fn::GetAtt": [
                                "NodeVpcSG",
                                "GroupId"
                            ]
                        },
                        "ToPort": "2377"
                    },
                    {
                        "FromPort": "4789",
                        "IpProtocol": "udp",
                        "SourceSecurityGroupId": {
                            "Fn::GetAtt": [
                                "NodeVpcSG",
                                "GroupId"
                            ]
                        },
                        "ToPort": "4789"
                    },
                    {
                        "FromPort": "7946",
                        "IpProtocol": "tcp",
                        "SourceSecurityGroupId": {
                            "Fn::GetAtt": [
                                "NodeVpcSG",
                                "GroupId"
                            ]
                        },
                        "ToPort": "7946"
                    },
                    {
                        "FromPort": "7946",
                        "IpProtocol": "udp",
                        "SourceSecurityGroupId": {
                            "Fn::GetAtt": [
                                "NodeVpcSG",
                                "GroupId"
                            ]
                        },
                        "ToPort": "7946"
                    }
                ],
                "VpcId": {
                    "Ref": "Vpc"
                }
            },
            "Type": "AWS::EC2::SecurityGroup"
        },
        "NodeAsg": {
            "DependsOn": "ManagerInstance",
            "Properties": {
                "DesiredCapacity": {
                    "Ref": "ClusterSize"
                },
                "LaunchConfigurationName": {
                    "Ref": "NodeLaunchConfigBeta12"
                },
                "MaxSize": "1000",
                "MinSize": "0",
                "Tags": [
                    {
                        "Key": "Name",
                        "PropagateAtLaunch": "true",
                        "Value": {
                            "Fn::Join": [
                                "-",
                                [
                                    {
                                        "Ref": "AWS::StackName"
                                    },
                                    "worker"
                                ]
                            ]
                        }
                    },
                    {
                        "Key": "swarm-node-type",
                        "PropagateAtLaunch": "true",
                        "Value": "worker"
                    },
                    {
                        "Key": "swarm-stack-id",
                        "PropagateAtLaunch": "true",
                        "Value": {
                            "Ref": "AWS::StackId"
                        }
                    }
                ],
                "VPCZoneIdentifier": [
                    {
                        "Fn::Join": [
                            ",",
                            [
                                {
                                    "Ref": "PubSubnetAz1"
                                },
                                {
                                    "Ref": "PubSubnetAz2"
                                }
                            ]
                        ]
                    }
                ]
            },
            "Type": "AWS::AutoScaling::AutoScalingGroup",
            "UpdatePolicy": {
                "AutoScalingRollingUpdate": {
                    "MaxBatchSize": "1",
                    "MinInstancesInService": "1"
                }
            }
        },
        "NodeLaunchConfigBeta12": {
            "DependsOn": "ManagerInstance",
            "Properties": {
                "AssociatePublicIpAddress": "true",
                "BlockDeviceMappings": [
                    {
                        "DeviceName": "/dev/xvdb",
                        "Ebs": {
                            "VolumeSize": {
                                "Ref": "WorkerDiskSize"
                            },
                            "VolumeType": {
                                "Ref": "WorkerDiskType"
                            }
                        }
                    }
                ],
                "IamInstanceProfile": {
                    "Ref": "ProxyInstanceProfile"
                },
                "ImageId": {
                    "Fn::FindInMap": [
                        "AWSRegionArch2AMI",
                        {
                            "Ref": "AWS::Region"
                        },
                        {
                            "Fn::FindInMap": [
                                "AWSInstanceType2Arch",
                                {
                                    "Ref": "InstanceType"
                                },
                                "Arch"
                            ]
                        }
                    ]
                },
                "InstanceType": {
                    "Ref": "InstanceType"
                },
                "KeyName": {
                    "Ref": "KeyName"
                },
                "SecurityGroups": [
                    {
                        "Ref": "NodeVpcSG"
                    },
                    {
                        "Ref": "SwarmWideSG"
                    }
                ],
                "UserData": {
                    "Fn::Base64": {
                        "Fn::Join": [
                            "",
                            [
                                "#!/bin/sh\n",
                                "sudo yum update\n",
                                "curl -sSL https://get.docker.com/ | sh\n",
                                "export LOCAL_IP=$(wget -qO- http://169.254.169.254/latest/meta-data/local-ipv4)\n",
                                "sed -i \"s/OPTIONS=\\\"/OPTIONS=\\\"--cluster-store consul:\\/\\/",
                                {
                                    "Fn::GetAtt": [
                                        "ManagerInstance",
                                        "PrivateIp"
                                    ]
                                },
                                ":8500 --cluster-advertise=$LOCAL_IP:2375 -H tcp:\\/\\/0\\.0\\.0\\.0:2375 -H unix:\\/\\/\\/var\\/run\\/docker\\.sock /\" /etc/sysconfig/docker\n",

                                "sudo /etc/init.d/docker start\n",
                                "sudo usermod -aG docker ec2-user\n",
                                "\n",

                                "docker run -d swarm join --advertise=$LOCAL_IP:2375 consul://",
                                {
                                    "Fn::GetAtt": [
                                        "ManagerInstance",
                                        "PrivateIp"
                                    ]
                                },
                                ":8500\n"
                            ]
                        ]
                    }
                }
            },
            "Type": "AWS::AutoScaling::LaunchConfiguration"
        },
        "NodeVpcSG": {
            "DependsOn": "Vpc",
            "Properties": {
                "GroupDescription": "Node SecurityGroup",
                "SecurityGroupEgress": [
                    {
                        "CidrIp": "0.0.0.0/0",
                        "FromPort": "8",
                        "IpProtocol": "icmp",
                        "ToPort": "0"
                    },
                    {
                        "CidrIp": "0.0.0.0/0",
                        "FromPort": "0",
                        "IpProtocol": "udp",
                        "ToPort": "65535"
                    },
                    {
                        "CidrIp": "0.0.0.0/0",
                        "FromPort": "0",
                        "IpProtocol": "tcp",
                        "ToPort": "2374"
                    },
                    {
                        "CidrIp": "0.0.0.0/0",
                        "FromPort": "2376",
                        "IpProtocol": "tcp",
                        "ToPort": "65535"
                    }
                ],
                "SecurityGroupIngress": [
                    {
                        "CidrIp": {
                            "Fn::FindInMap": [
                                "VpcCidrs",
                                "vpc",
                                "cidr"
                            ]
                        },
                        "FromPort": "0",
                        "IpProtocol": "-1",
                        "ToPort": "65535"
                    }
                ],
                "VpcId": {
                    "Ref": "Vpc"
                }
            },
            "Type": "AWS::EC2::SecurityGroup"
        },
        "ProxyInstanceProfile": {
            "Properties": {
                "Path": "/",
                "Roles": [
                    {
                        "Ref": "ProxyRole"
                    }
                ]
            },
            "Type": "AWS::IAM::InstanceProfile"
        },
        "ProxyPolicies": {
            "Properties": {
                "PolicyDocument": {
                    "Statement": [
                        {
                            "Action": "elasticloadbalancing:*",
                            "Effect": "Allow",
                            "Resource": "*"
                        }
                    ],
                    "Version": "2012-10-17"
                },
                "PolicyName": "elb-update",
                "Roles": [
                    {
                        "Ref": "ProxyRole"
                    }
                ]
            },
            "Type": "AWS::IAM::Policy"
        },
        "ProxyRole": {
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Statement": [
                        {
                            "Action": [
                                "sts:AssumeRole"
                            ],
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "ec2.amazonaws.com",
                                    "autoscaling.amazonaws.com"
                                ]
                            }
                        }
                    ],
                    "Version": "2012-10-17"
                },
                "Path": "/"
            },
            "Type": "AWS::IAM::Role"
        },
        "PubSubnet1RouteTableAssociation": {
            "DependsOn": [
                "PubSubnetAz1",
                "RouteViaIgw"
            ],
            "Properties": {
                "RouteTableId": {
                    "Ref": "RouteViaIgw"
                },
                "SubnetId": {
                    "Ref": "PubSubnetAz1"
                }
            },
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        },
        "PubSubnet2RouteTableAssociation": {
            "DependsOn": [
                "PubSubnetAz2",
                "RouteViaIgw"
            ],
            "Properties": {
                "RouteTableId": {
                    "Ref": "RouteViaIgw"
                },
                "SubnetId": {
                    "Ref": "PubSubnetAz2"
                }
            },
            "Type": "AWS::EC2::SubnetRouteTableAssociation"
        },
        "PubSubnetAz1": {
            "DependsOn": "Vpc",
            "Properties": {
                "AvailabilityZone": {
                    "Fn::Select": [
                        "0",
                        {
                            "Fn::GetAZs": {
                                "Ref": "AWS::Region"
                            }
                        }
                    ]
                },
                "CidrBlock": {
                    "Fn::FindInMap": [
                        "VpcCidrs",
                        "pubsubnet1",
                        "cidr"
                    ]
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "-",
                                [
                                    {
                                        "Ref": "AWS::StackName"
                                    },
                                    "Subnet1"
                                ]
                            ]
                        }
                    }
                ],
                "VpcId": {
                    "Ref": "Vpc"
                },
                "MapPublicIpOnLaunch": "true"
            },
            "Type": "AWS::EC2::Subnet"
        },
        "PubSubnetAz2": {
            "DependsOn": "Vpc",
            "Properties": {
                "AvailabilityZone": {
                    "Fn::Select": [
                        "1",
                        {
                            "Fn::GetAZs": {
                                "Ref": "AWS::Region"
                            }
                        }
                    ]
                },
                "CidrBlock": {
                    "Fn::FindInMap": [
                        "VpcCidrs",
                        "pubsubnet2",
                        "cidr"
                    ]
                },
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "-",
                                [
                                    {
                                        "Ref": "AWS::StackName"
                                    },
                                    "Subnet2"
                                ]
                            ]
                        }
                    }
                ],
                "VpcId": {
                    "Ref": "Vpc"
                },
                "MapPublicIpOnLaunch": "true"
            },
            "Type": "AWS::EC2::Subnet"
        },
        "PublicRouteViaIgw": {
            "DependsOn": [
                "AttachGateway",
                "RouteViaIgw"
            ],
            "Properties": {
                "DestinationCidrBlock": "0.0.0.0/0",
                "GatewayId": {
                    "Ref": "InternetGateway"
                },
                "RouteTableId": {
                    "Ref": "RouteViaIgw"
                }
            },
            "Type": "AWS::EC2::Route"
        },
        "RouteViaIgw": {
            "DependsOn": "Vpc",
            "Properties": {
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "-",
                                [
                                    {
                                        "Ref": "AWS::StackName"
                                    },
                                    "RT"
                                ]
                            ]
                        }
                    }
                ],
                "VpcId": {
                    "Ref": "Vpc"
                }
            },
            "Type": "AWS::EC2::RouteTable"
        },
        "SwarmAPIPolicy": {
            "DependsOn": "ProxyRole",
            "Properties": {
                "PolicyDocument": {
                    "Statement": [
                        {
                            "Action": [
                                "ec2:DescribeInstances",
                                "ec2:DescribeVpcAttribute",
                                "logs:CreateLogStream",
                                "logs:PutLogEvents"
                            ],
                            "Effect": "Allow",
                            "Resource": "*"
                        }
                    ],
                    "Version": "2012-10-17"
                },
                "PolicyName": "swarm-policy",
                "Roles": [
                    {
                        "Ref": "ProxyRole"
                    }
                ]
            },
            "Type": "AWS::IAM::Policy"
        },
        "SwarmAutoscalePolicy": {
            "Properties": {
                "PolicyDocument": {
                    "Statement": [
                        {
                            "Action": "autoscaling:*",
                            "Effect": "Allow",
                            "Resource": "*"
                        }
                    ],
                    "Version": "2012-10-17"
                },
                "PolicyName": "swarm-autoscale-policy",
                "Roles": [
                    {
                        "Ref": "ProxyRole"
                    }
                ]
            },
            "Type": "AWS::IAM::Policy"
        },
        "SwarmWideSG": {
            "DependsOn": "Vpc",
            "Properties": {
                "GroupDescription": "Swarm wide access",
                "SecurityGroupIngress": [
                    {
                        "CidrIp": {
                            "Fn::FindInMap": [
                                "VpcCidrs",
                                "vpc",
                                "cidr"
                            ]
                        },
                        "FromPort": "0",
                        "IpProtocol": "-1",
                        "ToPort": "65535"
                    },
                    {
                        "CidrIp": "0.0.0.0/0",
                        "FromPort": "5000",
                        "IpProtocol": "tcp",
                        "ToPort": "10000"
                    }
                ],
                "VpcId": {
                    "Ref": "Vpc"
                }
            },
            "Type": "AWS::EC2::SecurityGroup"
        },
        "Vpc": {
            "Properties": {
                "CidrBlock": {
                    "Fn::FindInMap": [
                        "VpcCidrs",
                        "vpc",
                        "cidr"
                    ]
                },
                "EnableDnsHostnames": "true",
                "EnableDnsSupport": "true",
                "Tags": [
                    {
                        "Key": "Name",
                        "Value": {
                            "Fn::Join": [
                                "-",
                                [
                                    {
                                        "Ref": "AWS::StackName"
                                    },
                                    "VPC"
                                ]
                            ]
                        }
                    }
                ]
            },
            "Type": "AWS::EC2::VPC"
        }
    }
}

================================================
FILE: example/starter-cluster/starter-cluster-requirements.txt
================================================
boto3>=1.4.2
click>=6.6
docker-py==1.10.6
PyYAML>=3.12
universe>=0.1.0
docker-compose>=1.9.0


================================================
FILE: example/system-diagnostics/system_diagnostics_logger.py
================================================
#!/usr/bin/env python

import json
import psutil
import time

class DiagnosticsLogger(object):
    def __init__(self, interval=5):
        self.interval = interval
        self.last_cpu_times = {}  # pid -> (user, sys)

    def run(self):
        while True:
            cpu_times, chrome_reset = self.cpu_times()
            print(json.dumps({
                'time': time.time(),
                'cpu_times': cpu_times,
                'cpu_percent': psutil.cpu_percent(percpu=True),
                'chrome_reset': chrome_reset,
            }), flush=True)
            self.chrome_reset = False
            time.sleep(self.interval)

    def get_chrome_procs(self):
        def is_chrome(proc):
            try:
                return proc.name() == 'chrome'
            except psutil.ZombieProcess:
                return False
        return [p for p in psutil.process_iter() if is_chrome(p)]

    def cpu_times(self):
        ''' return {pid: {'user': 0.0, 'sys': 0.0}}, chrome_reset '''
        chrome_procs = self.get_chrome_procs()
        new_pids = {p.pid for p in chrome_procs}
        old_pids = {pid for pid in self.last_cpu_times}
        try:
            cpu_times = {p.pid: p.cpu_times() for p in chrome_procs}
        except psutil.NoSuchProcess:
            # Chrome restarted since fetching the new pids above. Better luck next time.
            return {}, True
        if new_pids != old_pids:
            # We don't know when the Chrome procs were restarted, so don't
            # return elapsed time until next run.
            self.last_cpu_times = cpu_times
            return {}, True
        # Same chrome pids as last run: measure the elapsed cpu times
        ordered_old_times = (self.last_cpu_times[p.pid] for p in chrome_procs)
        ordered_new_times = (cpu_times[p.pid] for p in chrome_procs)
        cpu_times_diff = {p.pid: {'user': (t[0] - l[0]) / self.interval, 'sys': (t[1] - l[1]) / self.interval}
                for (p, t, l) in zip(chrome_procs, ordered_new_times, ordered_old_times)}
        self.last_cpu_times = cpu_times
        return cpu_times_diff, False

if __name__ == '__main__':
    DiagnosticsLogger().run()



================================================
FILE: setup.py
================================================
from setuptools import setup, find_packages

setup(name='universe',
      version='0.21.5',
      description="Universe: a software platform for measuring and training an AI's general intelligence across the world's supply of games, websites and other applications.",
      url='https://github.com/openai/universe',
      author='OpenAI',
      author_email='universe@openai.com',
      packages=[package for package in find_packages()
                if package.startswith('universe')],
      install_requires=[
          'autobahn>=0.16.0',
          'docker-py==1.10.3',
          'docker-pycreds==0.2.1',
          'fastzbarlight>=0.0.13',
          'go-vncdriver>=0.4.8',
          'gym>=0.8.1',
          'Pillow>=3.3.0',
          'PyYAML>=3.12',
          'six>=1.10.0',
          'twisted>=16.5.0',
          'ujson>=1.35',
      ],
      package_data={'universe': ['runtimes.yml', 'runtimes/flashgames.json']},
      tests_require=['pytest'],
      extras_require={
          'atari': 'gym[atari]',
      }
      )


================================================
FILE: test.dockerfile
================================================
FROM quay.io/openai/universe

RUN pip install tox

# Upload our actual code
WORKDIR /usr/local/universe/
COPY . ./

# Run tox. Keep printing so Travis knows we're alive.
CMD ["bash", "-c", "( while true; do echo '.'; sleep 60; done ) & tox"]


================================================
FILE: tests/functional/test_core_envs_semantics.py
================================================
import logging
import pytest

import gym
import numpy as np
from PIL import Image
from gym import spaces
from universe import wrappers
from universe.envs.vnc_core_env import translator

def show(obs):
    Image.fromarray(obs).show()

class AtariMatcher(object):
    def translator(self, env):
        return translator.AtariTranslator(env)

    def crop(self, obs):
        return obs[20:210, :160, :]

    def assert_match(self, obs, vnc_obs, extra_info=None, stage=None):
        # Crop out the mouse
        vnc_obs_cropped = self.crop(vnc_obs)
        obs_cropped = self.crop(obs)

        if not np.all(vnc_obs_cropped == obs_cropped):
            show(vnc_obs_cropped)
            show(obs_cropped)
            show(vnc_obs_cropped - obs_cropped)
            assert False, '[{}] Observations do not match: vnc_obs_cropped={} obs_cropped={} extra_info={}'.format(stage, vnc_obs_cropped, obs_cropped, extra_info)

# Wraps an Atari-over-VNC env so that it behaves like a vectorized vanilla Atari env
def atari_vnc_wrapper(env):
    env = wrappers.Vision(env)
    env = wrappers.GymCoreAction(env)
    return env

class CartPoleLowDMatcher(object):
    def translator(self, env):
        return translator.CartPoleTranslator(env)

    def assert_match(self, obs, vnc_obs, extra_info=None, stage=None):
        assert np.all(np.isclose(obs, vnc_obs)), '[{}] Observations do not match: vnc_obs={} obs={}'.format(stage, vnc_obs, obs)

def reset(matcher, env, vnc_env, stage=None):
    obs = env.reset()
    vnc_obs = vnc_env.reset()
    matcher.assert_match(obs, vnc_obs, stage=stage)

def rollout(matcher, env, vnc_env, timestep_limit=None, stage=None):
    count = 0
    actions = matcher.translator(env)

    done = None
    while True:
        action = env.action_space.sample()

        obs, reward, done, info = env.step(action)
        if done:
            # Account for remote auto-reset
            obs = env.reset()

        vnc_obs, vnc_reward, vnc_done, vnc_info = vnc_env.step(action)
        assert reward == vnc_reward
        assert done == vnc_done
        assert vnc_info['stats.reward.count'] == 1
        matcher.assert_match(obs, vnc_obs, {'reward': reward, 'done': done}, stage=stage)

        count += 1
        if done or (timestep_limit is not None and count >= timestep_limit):
            break

# TODO: we should have auto-env spinup
specs = [
    (gym.spec('gym-core.PongDeterministicSync-v3'), AtariMatcher(), atari_vnc_wrapper),
    (gym.spec('gym-core.PitfallDeterministicSync-v3'), AtariMatcher(), atari_vnc_wrapper),

    # This test is still broken. Looks like we're not piping the seed
    # to the CartPole env behind VNC
#    (gym.spec('gym-core.CartPoleLowDSync-v0'), CartPoleLowDMatcher())
]

@pytest.mark.parametrize("spec,matcher,wrapper", specs)
def test_nice_vnc_semantics_match(spec, matcher, wrapper):
    # Check that when running over VNC or using the raw environment,
    # semantics match exactly.
    gym.undo_logger_setup()
    logging.getLogger().setLevel(logging.INFO)

    spaces.seed(0)

    vnc_env = spec.make()
    if vnc_env.metadata.get('configure.required', False):
        vnc_env.configure(remotes=1)
    vnc_env = wrapper(vnc_env)
    vnc_env = wrappers.Unvectorize(vnc_env)

    env = gym.make(spec._kwargs['gym_core_id'])

    env.seed(0)
    vnc_env.seed(0)

    # Check that reset observations work
    reset(matcher, env, vnc_env, stage='initial reset')

    # Check a full rollout
    rollout(matcher, env, vnc_env, timestep_limit=50, stage='50 steps')

    # Reset to start a new episode
    reset(matcher, env, vnc_env, stage='reset to new episode')

    # Check that a step into the next episode works
    rollout(matcher, env, vnc_env, timestep_limit=1, stage='1 step in new episode')

    # Make sure env can be reseeded
    env.seed(1)
    vnc_env.seed(1)
    reset(matcher, env, vnc_env, 'reseeded reset')
    rollout(matcher, env, vnc_env, timestep_limit=1, stage='reseeded step')


================================================
FILE: tests/functional/test_envs.py
================================================
import logging
import os
import pytest
import re

import gym
from universe import wrappers
from universe.runtimes import registration

logger = logging.getLogger(__name__)

# Choose a sample from each category
# TODO: Add more comprehensive test that runs all envs
test_envs = [
    # 'gym-core.PongShortSync-v3',
    # 'gym-core.CartPoleLowDSync-v0',
    'flashgames.DuskDrive-v0',
    'internet.SlitherIO-v0',
    # 'wob.DragBox-v0',
]

@pytest.mark.parametrize('env_id', test_envs)
def test_smoke(env_id):
    """Check that environments start up without errors and that we can extract rewards and observations"""
    gym.undo_logger_setup()
    logging.getLogger().setLevel(logging.INFO)

    env = gym.make(env_id)
    if env.metadata.get('configure.required', False):
        if os.environ.get('FORCE_LATEST_UNIVERSE_DOCKER_RUNTIMES'):  # Used to test universe-envs in CI
            configure_with_latest_docker_runtime_tag(env)
        else:
            env.configure(remotes=1)

    env = wrappers.Unvectorize(env)

    env.reset()
    _rollout(env, timestep_limit=60*30) # Check a rollout

def _rollout(env, timestep_limit=None):
    """
    Test that a rollout follows our desired format. Includes the following checks:

    1. The environment resets and provides an observation within our timestep_limit
    2. Done signals map to the following:

        done=True => Episode over (sent once at end of episode)
        done=None => Resetting, agent takes no actions until done=False again
        done=False => Episode is running, agent should take actions
    """
    count = 0
    episode_state = "resetting"

    while True:
        obs, reward, done, info = env.step([])  # Step with noop action
        count += 1

        if episode_state == 'resetting':
            if done is None:  # Still resetting
                assert obs is None
                continue
            elif done is False:
                episode_state = 'running'

        if episode_state == 'running':
            assert done is False
            assert isinstance(reward, float)
            assert isinstance(done, bool), "Received done=None before done=True"
            # TODO: Remove this None check after we fix done=None semantics
            if obs is not None:
                assert obs['vision'].shape == (768, 1024, 3)
            break

        if timestep_limit is not None and count >= timestep_limit:
            assert episode_state == 'running', "Failed to finish resetting in timestep limit"
            break

        # if timestep_limit is not None and count >= timestep_limit:
        #     self.assertTrue(completed_full_episode, "Failed to complete a full episode in timestep limit")
        #     break

def configure_with_latest_docker_runtime_tag(env):
    original_image = registration.runtime_spec(env.spec.tags['runtime']).image
    latest_image = re.sub(r':.*', ':latest', original_image)
    logger.info("Using latest image: {}".format(latest_image))
    env.configure(remotes=1, docker_image=latest_image)


================================================
FILE: tox.ini
================================================
# Tox (http://tox.testrun.org/) is a tool for running tests
# in multiple virtualenvs. This configuration file will run the
# test suite on all supported python versions. To use it, "pip install tox"
# and then run "tox" from this directory.

[tox]
envlist = py27, py35
skipsdist=True

[testenv]
passenv=DISPLAY DOCKER_USERNAME DOCKER_PASSWORD FORCE_LATEST_UNIVERSE_DOCKER_RUNTIMES TRAVIS*
deps =
    pytest
    gym[atari]<0.9
    docker-py==1.10.3
    Pillow
    autobahn
    twisted
    ujson
    boto
commands =
    pip install -e /usr/local/universe
    pytest {posargs}


================================================
FILE: universe/__init__.py
================================================
# Welcome to Universe!
#
# This file contains the client-side registry of environments.

import logging
import os

# Suppress Twisted's warning about service_identity not being installed.
# We don't need service_identity right now and don't want to take it on
# as a dependency just to suppress this warning.
import warnings
warnings.filterwarnings(
    'ignore',
    message='You do not have a working installation of the service_identity'
)


from gym.envs.registration import register

import universe.scoreboard
import universe.configuration
from universe import error, envs
from universe.remotes import docker_remote
from universe.rewarder import merge_infos
from universe.runtimes.registration import runtime_spec

__all__ = [
    'configuration', 'envs', 'error', 'kube', 'pyprofile', 'remotes', 'rewarder', 'runtimes',
    'scoreboard', 'spaces', 'twisty', 'utils', 'vectorized', 'vncdriver', 'wrappers',
    'configure_logging', 'docker_image', 'enable_logfile',
    'logger', 'extra_logger']

def docker_image(runtime_id):
    logger.warn('DEPRECATION WARNING: universe.docker_image(runtime_id) is deprecated and will be removed soon. Use runtime_spec(runtime_id).image instead. ')
    return runtime_spec(runtime_id).image


#################### Logging configuration ####################

logger = logging.getLogger(__name__)
extra_logger = logging.getLogger('universe.extra.'+__name__)

_logging_configured = False

def enable_logfile(path=None):
    raise error.Error('Renamed to "universe.configure_logging()"')

def configure_logging(path=None):
    """
    Set up log levels, and split verbose logs to a file

        Configure the client-side environment logs to print
        to stdout at "info" level, and also to print to a
        verbose log file located at /tmp/universe-<pid>.log
        or another path you specify at "debug" level.
        We suggest calling this method at the beginning of
        your script.
    """

    global _logging_configured
    if _logging_configured:
        return
    _logging_configured = True

    if path is False:
        # Disable logfile
        return
    elif path is None:
        path = '/tmp/universe-{}.log'.format(os.getpid())

    logger.info('Writing logs to file: %s', path)
    # Turn up extra_logger level
    extra_logger.setLevel(logging.DEBUG)
    if path == '-':
        return

    # Add file handler to root logger
    root_logger = logging.getLogger()
    formatter = logging.Formatter('[%(asctime)s] %(message)s')
    handler = logging.FileHandler(path, 'w', encoding='UTF-8')
    handler.setFormatter(formatter)
    root_logger.addHandler(handler)

    # Set extra_logger to *only* use file handler
    extra_logger.propagate = False
    extra_logger.addHandler(handler)

############### Environment registration and runtime specification ###############
#
#    Universe environments are registered with the gym
#    environment registry when the universe module
#    is imported. We use the "tags" field to store
#    additional data specific to Universe.


#------------------------ Gym core environments -----------------------#
#     Asynchronous VNC versions of core gym environments,
#     such as CartPole and Pong

# Note on metadata:
#    Environments send on-screen metadata: the current time, and the
#    time the last action was received from the agent. This timestamp
#    data is used to compute action and observation lags. For core
#    environments, this data is sent using on-screen pixels that encode
#    timestamps.

metadata_pixels = {
    'type': 'pixels',
}

# Should be exactly the same as CartPole-v0
register(
    id='gym-core.CartPoleLowDSync-v0',
    entry_point='universe.wrappers:WrappedGymCoreSyncEnv',
    max_episode_steps=500,
    tags={
        'vnc': True,
        'runtime': 'gym-core',
        'metadata_encoding': metadata_pixels,
    },
    kwargs={
        'rewarder_observation': True,
        'gym_core_id': 'CartPole-v0',
},
    trials=2,
)

# Dynamics should match CartPole-v0, but have pixel observations
register(
    id='gym-core.CartPoleSync-v0',
    entry_point='universe.wrappers:WrappedGymCoreSyncEnv',
    max_episode_steps=500,
    tags={
        'vnc': True,
        'runtime': 'gym-core',
        'metadata_encoding': metadata_pixels,
    },
    kwargs={
        'gym_core_id': 'CartPole-v0',
    },
    trials=2,
)

# Async cartpole with 4-d observations
register(
    id='gym-core.CartPoleLowD-v0',
    entry_point='universe.wrappers:WrappedGymCoreEnv',
    max_episode_steps=500,
    tags={
        'vnc': True,
        'runtime': 'gym-core',
        'metadata_encoding': metadata_pixels,
    },
    kwargs={
        'rewarder_observation': True,
        'gym_core_id': 'CartPole-v0',
    },
    trials=2,
)

register(
    id='gym-core.CartPole-v0',
    entry_point='universe.wrappers:WrappedGymCoreEnv',
    max_episode_steps=500,
    tags={
        'vnc': True,
        'runtime': 'gym-core',
        'metadata_encoding': metadata_pixels,
    },
    kwargs={
        'gym_core_id': 'CartPole-v0',
    },
    trials=2,
)

# gym-core.Atari
for game in ['air_raid', 'alien', 'amidar', 'assault', 'asterix',
             'asteroids', 'atlantis', 'bank_heist', 'battle_zone',
             'beam_rider', 'berzerk', 'bowling', 'boxing', 'breakout',
             'carnival', 'centipede', 'chopper_command', 'crazy_climber',
             'demon_attack', 'double_dunk', 'elevator_action', 'enduro',
             'fishing_derby', 'freeway', 'frostbite', 'gopher', 'gravitar',
             'ice_hockey', 'jamesbond', 'journey_escape', 'kangaroo', 'krull',
             'kung_fu_master', 'montezuma_revenge', 'ms_pacman',
             'name_this_game', 'phoenix', 'pitfall', 'pong', 'pooyan',
             'private_eye', 'qbert', 'riverraid', 'road_runner', 'robotank',
             'seaquest', 'skiing', 'solaris', 'space_invaders', 'star_gunner',
             'tennis', 'time_pilot', 'tutankham', 'up_n_down', 'venture',
             'video_pinball', 'wizard_of_wor', 'yars_revenge', 'zaxxon']:
    # space_invaders should yield SpaceInvaders-v0 and SpaceInvaders-ram-v0
    base = ''.join([g.capitalize() for g in game.split('_')]) # SpaceInvaders

    for version in [0, 3]:
        gym_core_id = '{}-v{}'.format(base, version) # e.g. SpaceInvaders-v3
        register(
            id='gym-core.{}'.format(gym_core_id),
            entry_point='universe.wrappers:WrappedGymCoreEnv',
            max_episode_steps=100000,
            tags={
                'vnc': True,
                'atari': True,
                'runtime': 'gym-core',
                'metadata_encoding': metadata_pixels,
            },
            kwargs={
                'gym_core_id': gym_core_id,
            },
        )

        register(
            id='gym-core.{}Sync-v{}'.format(base, version),
            entry_point='universe.wrappers:WrappedGymCoreSyncEnv',
            max_episode_steps=100000,
            tags={
                'vnc': True,
                'atari': True,
                'runtime': 'gym-core',
                'metadata_encoding': metadata_pixels,
            },
            kwargs={
                'gym_core_id': gym_core_id,
            },
        )

        register(
            id='gym-core.{}30FPS-v{}'.format(base, version),
            entry_point='universe.wrappers:WrappedGymCoreEnv',
            max_episode_steps=100000,
            tags={
                'vnc': True,
                'atari': True,
                'runtime': 'gym-core',
                'metadata_encoding': metadata_pixels,
            },
            kwargs={
                'gym_core_id': gym_core_id,
                'fps': 30,
            },
        )

        register(
            id='gym-core.{}Slow-v{}'.format(base, version),
            entry_point='universe.wrappers:WrappedGymCoreEnv',
            max_episode_steps=100000,
            tags={
                'vnc': True,
                'atari': True,
                'runtime': 'gym-core',
                'metadata_encoding': metadata_pixels,
            },
            kwargs={
                'gym_core_id': gym_core_id,
                'fps': 15,
            },
        )

        deterministic_gym_core_id = '{}Deterministic-v{}'.format(base, version) # e.g. SpaceInvadersDeterministic-v3

        register(
            id='gym-core.{}Deterministic-v{}'.format(base, version),
            entry_point='universe.wrappers:WrappedGymCoreEnv',
            max_episode_steps=100000,
            tags={
                'vnc': True,
                'atari': True,
                'runtime': 'gym-core',
                'metadata_encoding': metadata_pixels,
            },
            kwargs={
                'gym_core_id': deterministic_gym_core_id,
            },
        )
        register(
            id='gym-core.{}DeterministicSlow-v{}'.format(base, version),
            entry_point='universe.wrappers:WrappedGymCoreEnv',
            max_episode_steps=75000,
            tags={
                'vnc': True,
                'atari': True,
                'runtime': 'gym-core',
                'metadata_encoding': metadata_pixels,
            },
            kwargs={
                'gym_core_id': deterministic_gym_core_id,
                'fps': 15,
            },
        )
        register(
            id='gym-core.{}DeterministicSync-v{}'.format(base, version),
            entry_point='universe.wrappers:WrappedGymCoreSyncEnv',
            max_episode_steps=75000,
            tags={
                'vnc': True,
                'atari': True,
                'runtime': 'gym-core',
                'metadata_encoding': metadata_pixels,
            },
            kwargs={
                'gym_core_id': deterministic_gym_core_id,
            },
        )

        no_frameskip_gym_core_id = '{}NoFrameskip-v{}'.format(base, version) # e.g. SpaceInvadersNoFrameskip-v3
        register(
            id='gym-core.{}NoFrameskip-v{}'.format(base, version),
            entry_point='universe.wrappers:WrappedGymCoreEnv',
            max_episode_steps=400000,
            tags={
                'vnc': True,
                'atari': True,
                'runtime': 'gym-core',
                'metadata_encoding': metadata_pixels,
            },
            kwargs={
                'gym_core_id': no_frameskip_gym_core_id,
            },
        )

#------------------------ Flash game environments ------------------------#
#     Browser-based flash games, run locally
#     in Chrome within a Docker container

# Note on metadata: flashgames send time metadata using
# an on-screen QR code

metadata_v1 = {
    'type': 'qrcode',
    'x': 914,
    'y': 658,
    'width': 100,
    'height': 100,
}

# Please keep this registry mirrored with the benchmarks in universe-envs/flashgames/gym_flashgames/__init__.py
# You can use universe-envs/flashgames/bin/manage export_env_ids_for_registration to generate this list.
for game in [
    'flashgames.1001ArabianNights-v0',
    'flashgames.21Balloons-v0',
    'flashgames.30Seconds-v0',
    'flashgames.3FootNinja-v0',
    'flashgames.3FootNinjaIi-v0',
    'flashgames.3dBuggyRacing-v0',
    'flashgames.3dClassicRacing-v0',
    'flashgames.3dFlashRacer-v0',
    'flashgames.3dFuriousDriver-v0',
    'flashgames.3dLaSupercars-v0',
    'flashgames.3dLaSupercars2-v0',
    'flashgames.3dMuscleCarRacer-v0',
    'flashgames.3dRallyFever-v0',
    'flashgames.3dRookieCop-v0',
    'flashgames.3dSpeedFever-v0',
    'flashgames.3dSportRampage-v0',
    'flashgames.3dSuperRide-v0',
    'flashgames.3dTestDrive-v0',
    'flashgames.3dTruckInTheWoods-v0',
    'flashgames.3dUrbanMadness-v0',
    'flashgames.3dUrbanMadness2-v0',
    'flashgames.4x4Monster3-v0',
    'flashgames.99BricksTheLegendOfGarry-v0',
    'flashgames.AWeekendAtTweetys-v0',
    'flashgames.AbductionGrannysVersion-v0',
    'flashgames.AchilliaTheGame-v0',
    'flashgames.AcidFactory-v0',
    'flashgames.AdrenalineChaser-v0',
    'flashgames.AdventuresOfBloo-v0',
    'flashgames.AeroDefense-v0',
    'flashgames.AerobaticMaster2-v0',
    'flashgames.Aerorumble-v0',
    'flashgames.AirWar1941-v0',
    'flashgames.AircraftRace-v0',
    'flashgames.AladdinAndTheWonderLamp-v0',
    'flashgames.AlchemySwap-v0',
    'flashgames.AliceNixsAdventure-v0',
    'flashgames.Alien-v0',
    'flashgames.AlienAssault-v0',
    'flashgames.AlienTransporter-v0',
    'flashgames.AmericanRacing-v0',
    'flashgames.AmericanRacingLvl2-v0',
    'flashgames.AmericanRacingLvl3-v0',
    'flashgames.AmericanRacingLvl4-v0',
    'flashgames.AmericanRacingLvl5-v0',
    'flashgames.AmericanRacingLvl6-v0',
    'flashgames.AmericanRacingLvl7-v0',
    'flashgames.AmericanRacingLvl8-v0',
    'flashgames.AmericanRacingLvl9-v0',
    'flashgames.AmericanRacingLvl10-v0',
    'flashgames.AmericanRacingLvl11-v0',
    'flashgames.AmericanRacingLvl12-v0',
    'flashgames.AmericanRacingLvl13-v0',
    'flashgames.AmericanRacingLvl14-v0',
    'flashgames.AmericanRacingLvl15-v0',
    'flashgames.AmericanRacingLvl16-v0',
    'flashgames.AmericanRacingLvl17-v0',
    'flashgames.AmericanRacingLvl18-v0',
    'flashgames.AmericanRacingLvl19-v0',
    'flashgames.AmericanRacingLvl20-v0',
    'flashgames.AmericanRacingLvl21-v0',
    'flashgames.AmericanRacingLvl22-v0',
    'flashgames.AmericanRacingLvl23-v0',
    'flashgames.AmericanRacingLvl24-v0',
    'flashgames.AmericanRacingLvl25-v0',
    'flashgames.AmericanRacing2-v0',
    'flashgames.AmigoPancho-v0',
    'flashgames.AmigoPancho3SheriffSancho-v0',
    'flashgames.AmigoPancho4Travel-v0',
    'flashgames.AmigoPanchoInAfghanistan-v0',
    'flashgames.AngryNewsVan-v0',
    'flashgames.AnimeClicker2-v0',
    'flashgames.AnotherLife2-v0',
    'flashgames.AntsGlider-v0',
    'flashgames.AnywayFish-v0',
    'flashgames.ArkanoidGame-v0',
    'flashgames.ArmyPursuit-v0',
    'flashgames.ArmySpeeder-v0',
    'flashgames.AspenSecret-v0',
    'flashgames.AsphaltMadness-v0',
    'flashgames.AssembleBots-v0',
    'flashgames.Astroman-v0',
    'flashgames.AtvRide-v0',
    'flashgames.Autoattack-v0',
    'flashgames.Avalancher-v0',
    'flashgames.AwesomeRun2-v0',
    'flashgames.BackHome-v0',
    'flashgames.BaldEagleJigsawPuzzle-v0',
    'flashgames.BalloonGods-v0',
    'flashgames.BalloonHero-v0',
    'flashgames.BalloonsPop-v0',
    'flashgames.Basement-v0',
    'flashgames.BeachCrazy-v0',
    'flashgames.BearInSuperActionAdventure-v0',
    'flashgames.BigWheelsTrial-v0',
    'flashgames.BikeTrial-v0',
    'flashgames.BikeTrial2-v0',
    'flashgames.BikeTrial3-v0',
    'flashgames.BikeTrial4-v0',
    'flashgames.Bimmin2-v0',
    'flashgames.BirdSlice-v0',
    'flashgames.BirdsFeeding-v0',
    'flashgames.BlackAndWhiteEscapeTheOffice-v0',
    'flashgames.BlackForce-v0',
    'flashgames.BlackInk-v0',
    'flashgames.BlackRacerJigsawPuzzle-v0',
    'flashgames.BlacksmithLab-v0',
    'flashgames.BlastTheMooks-v0',
    'flashgames.BlastTheMooksLevelPack-v0',
    'flashgames.Blix-v0',
    'flashgames.BlobsStory-v0',
    'flashgames.BlockysEscape-v0',
    'flashgames.BloodbathBay-v0',
    'flashgames.BloodyMonstersPack2-v0',
    'flashgames.Blosics2-v0',
    'flashgames.Blosics2LevelPack-v0',
    'flashgames.Blosics3-v0',
    'flashgames.BoatDrive-v0',
    'flashgames.BobbyNutcaseMotoJumping-v0',
    'flashgames.BoltThrough-v0',
    'flashgames.BombIt4-v0',
    'flashgames.BombIt6-v0',
    'flashgames.BombThePiratePigs-v0',
    'flashgames.BottleCaps-v0',
    'flashgames.BouncyCannon-v0',
    'flashgames.BoxBlocks-v0',
    'flashgames.BoxRacers-v0',
    'flashgames.BoxingLiveRound2-v0',
    'flashgames.BraveAstronaut-v0',
    'flashgames.BraveHeads-v0',
    'flashgames.BubbleAdventures-v0',
    'flashgames.BubbleBlubbs-v0',
    'flashgames.BubbleGlee-v0',
    'flashgames.BubbleHit-v0',
    'flashgames.BubbleHitChristmas-v0',
    'flashgames.BubbleHitHalloween-v0',
    'flashgames.BubbleHitPonyParade-v0',
    'flashgames.BubbleHitValentine-v0',
    'flashgames.BubbleMover-v0',
    'flashgames.BubblePop-v0',
    'flashgames.BubblePopAdventure-v0',
    'flashgames.BubbleRubble-v0',
    'flashgames.BubbleRubbleTheIsland-v0',
    'flashgames.BubbleShooterChallenge-v0',
    'flashgames.BubbleSlasher-v0',
    'flashgames.BubbleTanksTd15-v0',
    'flashgames.BubbleTub-v0',
    'flashgames.BubblesInSpace-v0',
    'flashgames.BugsGotGuns-v0',
    'flashgames.BuildBalance2-v0',
    'flashgames.BulletFury-v0',
    'flashgames.BulletHeaven-v0',
    'flashgames.BulletHeaven2-v0',
    'flashgames.Bullets-v0',
    'flashgames.BullfrogJigsawPuzzle-v0',
    'flashgames.BumbleTumble-v0',
    'flashgames.BunnyAndSquirt-v0',
    'flashgames.BunnyCannon-v0',
    'flashgames.BurgerBar-v0',
    'flashgames.BushRoyalRampage-v0',
    'flashgames.Business-v0',
    'flashgames.BusinessmanSimulator-v0',
    'flashgames.CableCapers2-v0',
    'flashgames.CakeQuest-v0',
    'flashgames.CandyMatch-v0',
    'flashgames.CandyMatchCrush-v0',
    'flashgames.CandySlider-v0',
    'flashgames.Canopy-v0',
    'flashgames.CanyonValleyRally-v0',
    'flashgames.CaptainNutty-v0',
    'flashgames.CaptainSteelbounce-v0',
    'flashgames.CardinalQuest2-v0',
    'flashgames.CarrotFantasy-v0',
    'flashgames.CarrotFantasy2Desert-v0',
    'flashgames.CarrotFantasy2Undersea-v0',
    'flashgames.CarrotFantasyExtreme2-v0',
    'flashgames.CarrotFantasyExtreme3-v0',
    'flashgames.CarsVsRobots-v0',
    'flashgames.CartoonCandy-v0',
    'flashgames.CastleRush-v0',
    'flashgames.CastleSolitaire-v0',
    'flashgames.CatGodVsSunKing2-v0',
    'flashgames.CatchTheStar-v0',
    'flashgames.Cattlepult-v0',
    'flashgames.CattlepultPlayerPack-v0',
    'flashgames.CavemanEscape-v0',
    'flashgames.CemeteryRoad-v0',
    'flashgames.CharlieTheDuck-v0',
    'flashgames.Chefday-v0',
    'flashgames.ChickCannont-v0',
    'flashgames.ChickInduce-v0',
    'flashgames.ChockABox-v0',
    'flashgames.ChristmasBubbles-v0',
    'flashgames.ChromaticTowerDefense-v0',
    'flashgames.ChuteAcademy-v0',
    'flashgames.CircuitSuperCarsRacing-v0',
    'flashgames.CitySiege3FubarLevelPack-v0',
    'flashgames.CitySkyTyping-v0',
    'flashgames.ClaustrophobiumFourStepsFromDeath-v0',
    'flashgames.Cleopatra-v0',
    'flashgames.ClickerMonsters-v0',
    'flashgames.ClimbOrDrown2-v0',
    'flashgames.ClimberGuy-v0',
    'flashgames.ClimbingSanta-v0',
    'flashgames.CloseCombat-v0',
    'flashgames.Cloud9-v0',
    'flashgames.ClubNitro-v0',
    'flashgames.Clusterobot-v0',
    'flashgames.CoastRunners-v0',
    'flashgames.CoasterCars2Contact-v0',
    'flashgames.CoasterCars2Megacross-v0',
    'flashgames.CoasterCarsBridgesTrack-v0',
    'flashgames.CoasterCarsCJackTrack-v0',
    'flashgames.CoasterRacer-v0',
    'flashgames.CoasterRacerLvl2-v0',
    'flashgames.CoasterRacerLvl3-v0',
    'flashgames.CoasterRacerLvl4-v0',
    'flashgames.CoasterRacerLvl5-v0',
    'flashgames.CoasterRacerLvl6-v0',
    'flashgames.CoasterRacerLvl7-v0',
    'flashgames.CoasterRacerLvl8-v0',
    'flashgames.CoasterRacer2-v0',
    'flashgames.CoasterRacer2Lvl2-v0',
    'flashgames.CoasterRacer2Lvl3-v0',
    'flashgames.CoasterRacer2Lvl4-v0',
    'flashgames.CoasterRacer2Lvl5-v0',
    'flashgames.CoasterRacer2Lvl6-v0',
    'flashgames.CoasterRacer2Lvl7-v0',
    'flashgames.CoasterRacer2Lvl8-v0',
    'flashgames.CoasterRacer2Lvl9-v0',
    'flashgames.CoasterRacer2Lvl10-v0',
    'flashgames.CoasterRacer2Bike-v0',
    'flashgames.CoasterRacer3-v0',
    'flashgames.CoffeeClicker-v0',
    'flashgames.ColorZapper-v0',
    'flashgames.Colordefense-v0',
    'flashgames.Colorfill-v0',
    'flashgames.Coloruid-v0',
    'flashgames.Colorwars-v0',
    'flashgames.Commando-v0',
    'flashgames.Commando2-v0',
    'flashgames.Conjure-v0',
    'flashgames.Connect2-v0',
    'flashgames.Conquerium-v0',
    'flashgames.Contra3TheAlienWars-v0',
    'flashgames.Cooliobeat-v0',
    'flashgames.Cooliodj-v0',
    'flashgames.CopperheadJigsawPuzzle-v0',
    'flashgames.CosmicSwitch-v0',
    'flashgames.CosmoGravity2-v0',
    'flashgames.CoverOrangeJourneyGangsters-v0',
    'flashgames.CowboyVsUfos-v0',
    'flashgames.Crane-v0',
    'flashgames.CrapImBroke-v0',
    'flashgames.CrazyDarts-v0',
    'flashgames.Crazycle-v0',
    'flashgames.CruiseAdventure-v0',
    'flashgames.Cruisin-v0',
    'flashgames.Crumbs2-v0',
    'flashgames.CrystalCurse-v0',
    'flashgames.CrystalStoryIi-v0',
    'flashgames.CupidBubbles-v0',
    'flashgames.CursedTreasureDontTouchMyGems-v0',
    'flashgames.CurveFever-v0',
    'flashgames.DaleAndPeakot-v0',
    'flashgames.DanceBattle-v0',
    'flashgames.DancingWithShadows-v0',
    'flashgames.DartsSim-v0',
    'flashgames.DaymareInvaders-v0',
    'flashgames.DeadHungry2-v0',
    'flashgames.DeathCabin-v0',
    'flashgames.DeathDiceOverdose-v0',
    'flashgames.DeepForest3dRace-v0',
    'flashgames.DeepFreeze-v0',
    'flashgames.Deliveryman-v0',
    'flashgames.DetectiveConrad-v0',
    'flashgames.Devilment-v0',
    'flashgames.DiamondCrashMania-v0',
    'flashgames.DigToChina-v0',
    'flashgames.DinoBubble-v0',
    'flashgames.DinoMeatHunt3Extra-v0',
    'flashgames.DirkValentine-v0',
    'flashgames.DisasterWillStrikeDefender-v0',
    'flashgames.DisasterWillStrikeUltimateDisaster-v0',
    'flashgames.DiscoverEurope-v0',
    'flashgames.Ditloid-v0',
    'flashgames.DnaLabRush-v0',
    'flashgames.Dodge-v0',
    'flashgames.DodgeAndCrash-v0',
    'flashgames.DolphinVolleyball-v0',
    'flashgames.DontPanic-v0',
    'flashgames.DoodleGod2Walkthrough-v0',
    'flashgames.DotGrowth-v0',
    'flashgames.Dots-v0',
    'flashgames.DotsRevamped-v0',
    'flashgames.DoubleEdged-v0',
    'flashgames.DoughSnake-v0',
    'flashgames.DragonChain-v0',
    'flashgames.DragonChronicles-v0',
    'flashgames.DragonFortress-v0',
    'flashgames.DragonFunflap-v0',
    'flashgames.DragonVsMonster-v0',
    'flashgames.DrawGems-v0',
    'flashgames.DreamChristmasLink-v0',
    'flashgames.DriftRunners-v0',
    'flashgames.DriftRunners2-v0',
    'flashgames.DriftRunners3d-v0',
    'flashgames.Drifters-v0',
    'flashgames.DrinkBeerNeglectFamily-v0',
    'flashgames.DriveToWreck-v0',
    'flashgames.DriveToWreck2-v0',
    'flashgames.DriveToWreck3-v0',
    'flashgames.Dropblox-v0',
    'flashgames.DualDimension-v0',
    'flashgames.DumperRush-v0',
    'flashgames.DungeonBlocks-v0',
    'flashgames.DuskDrive-v0',
    'flashgames.DuskRacers-v0',
    'flashgames.EasterBubbles-v0',
    'flashgames.EasterBunnyCollectCarrots-v0',
    'flashgames.EasterBunnyEggs-v0',
    'flashgames.EasterEggSlider-v0',
    'flashgames.EasterEggsChallenge-v0',
    'flashgames.EatToWin-v0',
    'flashgames.EctoHarvest-v0',
    'flashgames.EffingWorms-v0',
    'flashgames.EggzBlast-v0',
    'flashgames.EiffelTowerAtNight-v0',
    'flashgames.ElClassico-v0',
    'flashgames.ElainesBakery-v0',
    'flashgames.EmpireBusiness2Beta-v0',
    'flashgames.Enhanced-v0',
    'flashgames.EpicBattleFantasy4-v0',
    'flashgames.EpicDefender-v0',
    'flashgames.EpicDerbyRace-v0',
    'flashgames.EpicTimePirates-v0',
    'flashgames.EscapeTheRedGiant-v0',
    'flashgames.EuroKicks2016-v0',
    'flashgames.EvasiveRacers-v0',
    'flashgames.EvilMinion-v0',
    'flashgames.EvilSun-v0',
    'flashgames.EvolutionRacing-v0',
    'flashgames.EvolutionRacingLvl2-v0',
    'flashgames.EvolutionRacingLvl3-v0',
    'flashgames.EvolutionRacingLvl4-v0',
    'flashgames.EvolutionRacingLvl5-v0',
    'flashgames.EvolutionRacingLvl6-v0',
    'flashgames.EvolutionRacingLvl7-v0',
    'flashgames.EvolutionRacingLvl8-v0',
    'flashgames.EvolutionRacingLvl9-v0',
    'flashgames.EvolutionRacingLvl10-v0',
    'flashgames.EvolutionRacingLvl11-v0',
    'flashgames.EvolutionRacingLvl12-v0',
    'flashgames.EvolutionRacingLvl13-v0',
    'flashgames.EvolutionRacingLvl14-v0',
    'flashgames.EvolutionRacingLvl15-v0',
    'flashgames.EvolutionRacingLvl16-v0',
    'flashgames.ExperimentalShooter2-v0',
    'flashgames.ExploreTheCandies-v0',
    'flashgames.ExtremeAirWars-v0',
    'flashgames.ExtremeSkiing-v0',
    'flashgames.F1RacingChallenge-v0',
    'flashgames.FairyDefense-v0',
    'flashgames.FallDamage-v0',
    'flashgames.FarmRush-v0',
    'flashgames.FasterMiterMaster-v0',
    'flashgames.FeedMeMoar-v0',
    'flashgames.FeedOurDoughnutOverlords-v0',
    'flashgames.Filler-v0',
    'flashgames.Filler2-v0',
    'flashgames.FinalNinjaZero-v0',
    'flashgames.FinalSiege-v0',
    'flashgames.FindTheCandy3Kids-v0',
    'flashgames.Firebug-v0',
    'flashgames.FirefighterCannon-v0',
    'flashgames.FireworksGame-v0',
    'flashgames.FishAndDestroy-v0',
    'flashgames.FishEatFish-v0',
    'flashgames.FitItQuick-v0',
    'flashgames.FiveTil-v0',
    'flashgames.Fizzion-v0',
    'flashgames.Flagman-v0',
    'flashgames.FlappyAdventure-v0',
    'flashgames.FlappyBat-v0',
    'flashgames.FlappyCopter-v0',
    'flashgames.FlappyPanda-v0',
    'flashgames.FlashBombs-v0',
    'flashgames.FlashDrive-v0',
    'flashgames.FlashRace-v0',
    'flashgames.FlashRacer-v0',
    'flashgames.Flashcycle2-v0',
    'flashgames.FlashsBounty-v0',
    'flashgames.FlowerGuardian-v0',
    'flashgames.FlowerSolitaire-v0',
    'flashgames.FluffRush-v0',
    'flashgames.FlyAwayRabbit2-v0',
    'flashgames.FlyPlane-v0',
    'flashgames.FlyingCookieQuest-v0',
    'flashgames.FlyingKiwi-v0',
    'flashgames.FlyingTest-v0',
    'flashgames.Foosball2Player-v0',
    'flashgames.FootballHeads201314Ligue1-v0',
    'flashgames.FormulaRacer-v0',
    'flashgames.FormulaRacerLvl2-v0',
    'flashgames.FormulaRacerLvl3-v0',
    'flashgames.FormulaRacerLvl4-v0',
    'flashgames.FormulaRacerLvl5-v0',
    'flashgames.FormulaRacerLvl6-v0',
    'flashgames.FormulaRacerLvl7-v0',
    'flashgames.FormulaRacerLvl8-v0',
    'flashgames.FormulaRacer2012-v0',
    'flashgames.FormulaRacer2012Lvl2-v0',
    'flashgames.FormulaRacer2012Lvl3-v0',
    'flashgames.FormulaRacer2012Lvl4-v0',
    'flashgames.FormulaRacer2012Lvl5-v0',
    'flashgames.FormulaRacer2012Lvl6-v0',
    'flashgames.FormulaRacer2012Lvl7-v0',
    'flashgames.FormulaRacer2012Lvl8-v0',
    'flashgames.FormulaRacer2012Lvl9-v0',
    'flashgames.FormulaRacer2012Lvl10-v0',
    'flashgames.FormulaRacer2012Lvl11-v0',
    'flashgames.FormulaRacer2012Lvl12-v0',
    'flashgames.FormulaXspeed3d-v0',
    'flashgames.FoxSnakeJigsawPuzzle-v0',
    'flashgames.FpaWorld1Remix-v0',
    'flashgames.FreakyRun-v0',
    'flashgames.FredFigglehorn-v0',
    'flashgames.FreeSouls-v0',
    'flashgames.Free_to_use-v0',
    'flashgames.FreecellDuplex-v0',
    'flashgames.FrogEatFlies-v0',
    'flashgames.Frogged-v0',
    'flashgames.FrozenImps-v0',
    'flashgames.FrozenIslandsNewHorizons-v0',
    'flashgames.Funkostroll-v0',
    'flashgames.FunnyEaster-v0',
    'flashgames.GSwitch-v0',
    'flashgames.GalacticCats-v0',
    'flashgames.GalacticGems-v0',
    'flashgames.GalacticGems2-v0',
    'flashgames.GalacticGems2Accelerated-v0',
    'flashgames.GalacticGems2LevelPack-v0',
    'flashgames.GalacticGems2NewFrontiers-v0',
    'flashgames.GalaxyDefender-v0',
    'flashgames.GalaxyEvo2-v0',
    'flashgames.GalaxyMission-v0',
    'flashgames.GalleonFight-v0',
    'flashgames.GameInit-v0',
    'flashgames.Gameinit-v0',
    'flashgames.GamerMemoryTest-v0',
    'flashgames.GardenRush-v0',
    'flashgames.GasSand-v0',
    'flashgames.GemMania-v0',
    'flashgames.GemPop-v0',
    'flashgames.Gemclix-v0',
    'flashgames.Gemcraft-v0',
    'flashgames.GemstoneCastle-v0',
    'flashgames.GhostClimb2Player-v0',
    'flashgames.GiantsAndDwarvesTd-v0',
    'flashgames.GlobalRallyRacer-v0',
    'flashgames.Gloom-v0',
    'flashgames.Gluey2-v0',
    'flashgames.Go-v0',
    'flashgames.GoGreenGo-v0',
    'flashgames.GoKart3d-v0',
    'flashgames.Goldextraction-v0',
    'flashgames.GolfRun-v0',
    'flashgames.GonAndMon-v0',
    'flashgames.GrandPrixGo-v0',
    'flashgames.GrandPrixGo2-v0',
    'flashgames.GrappleCat-v0',
    'flashgames.GravityBall-v0',
    'flashgames.GravityGuy-v0',
    'flashgames.GravityThruster-v0',
    'flashgames.GroundBattles-v0',
    'flashgames.Growbox-v0',
    'flashgames.GsSoccerWorldCup-v0',
    'flashgames.GunExpress-v0',
    'flashgames.GunnerMayhem-v0',
    'flashgames.GunpowderAndFeathers-v0',
    'flashgames.HalloweenAdventureRun-v0',
    'flashgames.HalloweenExplorer-v0',
    'flashgames.HalloweenJam-v0',
    'flashgames.HammerBall-v0',
    'flashgames.Hamsterball-v0',
    'flashgames.HandsOff-v0',
    'flashgames.HappyBallz-v0',
    'flashgames.HappyBees-v0',
    'flashgames.HappyEasterEggs-v0',
    'flashgames.Harvest-v0',
    'flashgames.HarvestDay-v0',
    'flashgames.Hash-v0',
    'flashgames.Hearts-v0',
    'flashgames.HeatRushFuture-v0',
    'flashgames.HeatRushFutureLvl2-v0',
    'flashgames.HeatRushFutureLvl3-v0',
    'flashgames.HeatRushFutureLvl4-v0',
    'flashgames.HeatRushFutureLvl5-v0',
    'flashgames.HeatRushFutureLvl6-v0',
    'flashgames.HeatRushFutureLvl7-v0',
    'flashgames.HeatRushFutureLvl8-v0',
    'flashgames.HeatRushFutureLvl9-v0',
    'flashgames.HeatRushFutureLvl10-v0',
    'flashgames.HeatRushFutureLvl11-v0',
    'flashgames.HeatRushFutureLvl12-v0',
    'flashgames.HeatRushFutureLvl13-v0',
    'flashgames.HeatRushFutureLvl14-v0',
    'flashgames.HeatRushFutureLvl15-v0',
    'flashgames.HeatRushUsa-v0',
    'flashgames.HeatRushUsaLvl2-v0',
    'flashgames.HeatRushUsaLvl3-v0',
    'flashgames.HeatRushUsaLvl4-v0',
    'flashgames.HeatRushUsaLvl5-v0',
    'flashgames.HeatRushUsaLvl6-v0',
    'flashgames.HeatRushUsaLvl7-v0',
    'flashgames.HeatRushUsaLvl8-v0',
    'flashgames.HeatRushUsaLvl9-v0',
    'flashgames.HeatRushUsaLvl10-v0',
    'flashgames.HeatRushUsaLvl11-v0',
    'flashgames.HeatRushUsaLvl12-v0',
    'flashgames.HeatRushUsaLvl13-v0',
    'flashgames.HeatRushUsaLvl14-v0',
    'flashgames.HeatRushUsaLvl15-v0',
    'flashgames.HeatRushUsaLvl16-v0',
    'flashgames.HeavenAndHell-v0',
    'flashgames.HeavyLegion2-v0',
    'flashgames.HeliVsTower-v0',
    'flashgames.HelicopsTerritories-v0',
    'flashgames.Helicrane-v0',
    'flashgames.Helixteus-v0',
    'flashgames.HelmetBombers3-v0',
    'flashgames.HeroRoofTop-v0',
    'flashgames.HeroSimulator-v0',
    'flashgames.HeroesOfMangaraTheFrostCrown-v0',
    'flashgames.HexBattles-v0',
    'flashgames.HeySummer-v0',
    'flashgames.HighSpeedChase-v0',
    'flashgames.HighwayRevenge-v0',
    'flashgames.HiredHeroes-v0',
    'flashgames.HoldTheFort-v0',
    'flashgames.HoleInOne-v0',
    'flashgames.Hotspot-v0',
    'flashgames.HowDareYou-v0',
    'flashgames.HungerHunter-v0',
    'flashgames.HungryLittlePenguins-v0',
    'flashgames.HungryPiranha-v0',
    'flashgames.HunterForDismantlers-v0',
    'flashgames.HyperTravel-v0',
    'flashgames.IceBlock-v0',
    'flashgames.IceCreamFromSpace-v0',
    'flashgames.IceRun-v0',
    'flashgames.IceSlide-v0',
    'flashgames.Ics2-v0',
    'flashgames.IcyGifts2-v0',
    'flashgames.IdleChop-v0',
    'flashgames.IdleFarmer-v0',
    'flashgames.IdleLifting-v0',
    'flashgames.IdlePlanet-v0',
    'flashgames.ImitationNationSnakeGame-v0',
    'flashgames.IncrementalAcceleration-v0',
    'flashgames.Indefinite-v0',
    'flashgames.IndependenceDaySlacking2015-v0',
    'flashgames.InfectonatorSurvivorsAlphaDemo-v0',
    'flashgames.InfernalMess-v0',
    'flashgames.Infinitix-v0',
    'flashgames.InsaneCircle-v0',
    'flashgames.IntoSpace-v0',
    'flashgames.IslandDefense-v0',
    'flashgames.IsoblockerMaster-v0',
    'flashgames.ItsDarkInHell-v0',
    'flashgames.JakeTheSnake-v0',
    'flashgames.JamesTheCircusZebra-v0',
    'flashgames.JamesTheDeepSeaZebra-v0',
    'flashgames.JamesThePirateZebra-v0',
    'flashgames.JamesTheSpaceZebra-v0',
    'flashgames.JelliesFun-v0',
    'flashgames.JellyFriend-v0',
    'flashgames.JellySnake-v0',
    'flashgames.JetpackJackride-v0',
    'flashgames.JollySwipe-v0',
    'flashgames.JollySwipeLevelPack-v0',
    'flashgames.JonnyBackflip-v0',
    'flashgames.JumpOverTheRings-v0',
    'flashgames.Jumprunner-v0',
    'flashgames.Jumpz-v0',
    'flashgames.JungleCrash-v0',
    'flashgames.JungleEagle-v0',
    'flashgames.KamikazeRace-v0',
    'flashgames.KangoIslands-v0',
    'flashgames.KartOn-v0',
    'flashgames.KartRacing-v0',
    'flashgames.KartingSuperGo-v0',
    'flashgames.Kawairun-v0',
    'flashgames.KeeperOfTheGrove3-v0',
    'flashgames.Kinetikz-v0',
    'flashgames.Kinetikz2-v0',
    'flashgames.Kinetikz3-v0',
    'flashgames.KingRolla-v0',
    'flashgames.KitchenRestaurantCleanUp-v0',
    'flashgames.KnightsOfRock-v0',
    'flashgames.Knighttron-v0',
    'flashgames.Knockers-v0',
    'flashgames.Krome-v0',
    'flashgames.LaserCannon3LevelsPack-v0',
    'flashgames.LawnmowerRacing3d-v0',
    'flashgames.LaxAirbusParking-v0',
    'flashgames.Lazerman-v0',
    'flashgames.LearnToFlyIdle-v0',
    'flashgames.Legor9-v0',
    'flashgames.LessQuick-v0',
    'flashgames.LetsFall-v0',
    'flashgames.LevelEditor3-v0',
    'flashgames.LilyFighters-v0',
    'flashgames.LineGameLimeEdition-v0',
    'flashgames.LlamasInDistress-v0',
    'flashgames.LonelyEscapeAsylum-v0',
    'flashgames.LongJump-v0',
    'flashgames.Long_short-v0',
    'flashgames.LooneyAndJohny-v0',
    'flashgames.LuckyBalls-v0',
    'flashgames.LuxUltimate-v0',
    'flashgames.Madburger3-v0',
    'flashgames.MadpetSkateboarder2-v0',
    'flashgames.MagicSafari-v0',
    'flashgames.ManicRallyGo-v0',
    'flashgames.MapTurtleJigsawPuzzle-v0',
    'flashgames.MarblesShooter-v0',
    'flashgames.MarsColonyTd-v0',
    'flashgames.MarshmallowsEscape-v0',
    'flashgames.MashaCollectsButterflies-v0',
    'flashgames.MasterDifference-v0',
    'flashgames.Match2Collapse-v0',
    'flashgames.Match3Adventure-v0',
    'flashgames.Match3ChristmasPack-v0',
    'flashgames.Match3PresentBoxSaga-v0',
    'flashgames.MatchAndCrash-v0',
    'flashgames.MatchAndSpell-v0',
    'flashgames.MatchAroundTheWorld-v0',
    'flashgames.MatchCraft-v0',
    'flashgames.MatchCrypt-v0',
    'flashgames.MatchJong-v0',
    'flashgames.MatchMonsters-v0',
    'flashgames.MatchStars-v0',
    'flashgames.MatchTheBugz-v0',
    'flashgames.MatchTheFruits-v0',
    'flashgames.MatchToEnjoy-v0',
    'flashgames.MatchToEnjoyLevelPack-v0',
    'flashgames.MatchingSweetHearts-v0',
    'flashgames.MazeEye-v0',
    'flashgames.MedievalShark-v0',
    'flashgames.MeerkatMission-v0',
    'flashgames.MexicoRex-v0',
    'flashgames.MiceVsHammers-v0',
    'flashgames.Michimind-v0',
    'flashgames.MidnightCanine-v0',
    'flashgames.MidnightMiner-v0',
    'flashgames.MightyTower-v0',
    'flashgames.Mimelet-v0',
    'flashgames.MindImpulse-v0',
    'flashgames.MineDrop-v0',
    'flashgames.MineHero-v0',
    'flashgames.MinedigJourneyToHollowEarth-v0',
    'flashgames.MiniMachines-v0',
    'flashgames.MiniSportsChallenge-v0',
    'flashgames.MinicarHunt-v0',
    'flashgames.Minicarting-v0',
    'flashgames.MissionEscapeTheDojo-v0',
    'flashgames.ModelCarRacing-v0',
    'flashgames.MonkeyBlast-v0',
    'flashgames.MonkeyGems-v0',
    'flashgames.MonkeyGoHappyNinjaHunt2-v0',
    'flashgames.MonkeyManic-v0',
    'flashgames.MonsterChains-v0',
    'flashgames.MonsterLabFeedThemAll-v0',
    'flashgames.MonsterRun-v0',
    'flashgames.MonsterTroubles-v0',
    'flashgames.MonsterTruckFever-v0',
    'flashgames.MonsterTruckRally-v0',
    'flashgames.Moosters-v0',
    'flashgames.MotherLoad-v0',
    'flashgames.MotoMadness-v0',
    'flashgames.MotoTrialMania-v0',
    'flashgames.MotorWheels-v0',
    'flashgames.Mrbirdie-v0',
    'flashgames.MultiballMadness-v0',
    'flashgames.Multitask-v0',
    'flashgames.MummyMadness-v0',
    'flashgames.Mushbooms-v0',
    'flashgames.MushboomsLevelPack-v0',
    'flashgames.MushboomsLevelPack2-v0',
    'flashgames.MushroomFarmDefender-v0',
    'flashgames.MushyMishy-v0',
    'flashgames.MusicSmash-v0',
    'flashgames.MusicStomp-v0',
    'flashgames.MusicZap-v0',
    'flashgames.MysteriousPirateJewels-v0',
    'flashgames.MysticIndiaPop-v0',
    'flashgames.MysticalAncientTreasure-v0',
    'flashgames.NOfficialWebVersion-v0',
    'flashgames.NadiasRage-v0',
    'flashgames.NanoKingdoms2JokersRevenge-v0',
    'flashgames.NeonRace-v0',
    'flashgames.NeonRaceLvl2-v0',
    'flashgames.NeonRaceLvl3-v0',
    'flashgames.NeonRaceLvl4-v0',
    'flashgames.NeonRaceLvl5-v0',
    'flashgames.NeonRaceLvl6-v0',
    'flashgames.NeonRaceLvl7-v0',
    'flashgames.NeonRaceLvl8-v0',
    'flashgames.NeonRace2-v0',
    'flashgames.NeonRace2Lvl2-v0',
    'flashgames.NeonRace2Lvl3-v0',
    'flashgames.NeonRace2Lvl4-v0',
    'flashgames.NeonRace2Lvl5-v0',
    'flashgames.NeonRace2Lvl6-v0',
    'flashgames.NeonRace2Lvl7-v0',
    'flashgames.NeonRace2Lvl8-v0',
    'flashgames.NeonRace2Lvl9-v0',
    'flashgames.NeonRace2Lvl10-v0',
    'flashgames.NeonRace2Lvl11-v0',
    'flashgames.NeonRace2Lvl12-v0',
    'flashgames.NeonRace2Lvl13-v0',
    'flashgames.NeonRace2Lvl14-v0',
    'flashgames.NeonRace2Lvl15-v0',
    'flashgames.Neopods-v0',
    'flashgames.NervousLadybug-v0',
    'flashgames.NewSiberianSupercarsRacing-v0',
    'flashgames.NewSplitterPals-v0',
    'flashgames.NightDrivin-v0',
    'flashgames.NightRaceRally-v0',
    'flashgames.NinjaPainter-v0',
    'flashgames.NinjaPandaArena-v0',
    'flashgames.NinjaPandaCouple-v0',
    'flashgames.NinjaTrainingWorlds-v0',
    'flashgames.Nook-v0',
    'flashgames.NoughtsAndCrosses-v0',
    'flashgames.NoughtsAndCrossesExtreme-v0',
    'flashgames.NukeDefense-v0',
    'flashgames.Numz-v0',
    'flashgames.NuttyBoom-v0',
    'flashgames.ObamaAlienDefense-v0',
    'flashgames.OceanMatch-v0',
    'flashgames.Oddball2-v0',
    'flashgames.OffRoaders3d-v0',
    'flashgames.OfficeTrap-v0',
    'flashgames.Offroaders-v0',
    'flashgames.Offroaders2-v0',
    'flashgames.OkParking-v0',
    'flashgames.OldTv-v0',
    'flashgames.OozingForever-v0',
    'flashgames.OswaldTheAngryDwarf-v0',
    'flashgames.Overheat-v0',
    'flashgames.PaintWars-v0',
    'flashgames.Paintwars-v0',
    'flashgames.PanikInChocoland-v0',
    'flashgames.PapaLouie3WhenSundaesAttack-v0',
    'flashgames.PaperDefense-v0',
    'flashgames.ParachuteRetrospect-v0',
    'flashgames.ParallelLevels-v0',
    'flashgames.ParkingFury-v0',
    'flashgames.Parkour-v0',
    'flashgames.ParticleWarsExtreme-v0',
    'flashgames.Pathillogical-v0',
    'flashgames.PaulVaulting-v0',
    'flashgames.Peakart-v0',
    'flashgames.PearlBreaking-v0',
    'flashgames.Pel-v0',
    'flashgames.PenguinCubes-v0',
    'flashgames.PenguinHeroes-v0',
    'flashgames.PenguinSkate2-v0',
    'flashgames.PerilousJourney2-v0',
    'flashgames.Phit-v0',
    'flashgames.PickAndDig2-v0',
    'flashgames.PickUpTruckRacing-v0',
    'flashgames.PicnicPanicTd-v0',
    'flashgames.PigDestroyer-v0',
    'flashgames.PiggyWiggy-v0',
    'flashgames.PiggysCupcakeQuest-v0',
    'flashgames.PinBalls-v0',
    'flashgames.PinataWarriors-v0',
    'flashgames.PingPongSurvival-v0',
    'flashgames.PirateRunAway-v0',
    'flashgames.PiratesAndCannons-v0',
    'flashgames.PixelBasher-v0',
    'flashgames.PixelFighta-v0',
    'flashgames.PixelPurge-v0',
    'flashgames.PixelQuest-v0',
    'flashgames.PlaneRace-v0',
    'flashgames.PlaneRace2-v0',
    'flashgames.PlopPlopLite-v0',
    'flashgames.PocketRocket-v0',
    'flashgames.Pointer-v0',
    'flashgames.Pointless-v0',
    'flashgames.PoliceChaseCrackdown-v0',
    'flashgames.PoliceHotRacing-v0',
    'flashgames.PoliceInterceptor-v0',
    'flashgames.PolygonalFury-v0',
    'flashgames.Popopop-v0',
    'flashgames.Popopop2-v0',
    'flashgames.PouJetpack-v0',
    'flashgames.PouThanksgivingDaySlacking-v0',
    'flashgames.PowerCopter-v0',
    'flashgames.PowerSwing-v0',
    'flashgames.Primary-v0',
    'flashgames.PrincessBubblesRescuePrince-v0',
    'flashgames.PrincessToTheRescue-v0',
    'flashgames.ProjectMonochrome-v0',
    'flashgames.PuddingPie-v0',
    'flashgames.PufferFish-v0',
    'flashgames.PumpkinCollector-v0',
    'flashgames.PumpkinMan-v0',
    'flashgames.PumpkinsInZombieTown-v0',
    'flashgames.PunchBallJump-v0',
    'flashgames.PurifyTheLegendOfZ-v0',
    'flashgames.PuzzleMonsters-v0',
    'flashgames.PuzzleRescuePrime-v0',
    'flashgames.PyramidApocalypse-v0',
    'flashgames.Pyro-v0',
    'flashgames.Qoosh-v0',
    'flashgames.QuashBoard-v0',
    'flashgames.QubedMysteriousIsland-v0',
    'flashgames.QubeyTheCube-v0',
    'flashgames.Quick-v0',
    'flashgames.RabbitPlanetEscape-v0',
    'flashgames.RabbitRustler-v0',
    'flashgames.RacerKartz-v0',
    'flashgames.RacingSupercarChampionship-v0',
    'flashgames.RainbowDrops-v0',
    'flashgames.RapaNui-v0',
    'flashgames.Raze3-v0',
    'flashgames.Rb2-v0',
    'flashgames.Rbots-v0',
    'flashgames.ReachTheGoal-v0',
    'flashgames.RedBeard-v0',
    'flashgames.RedCode3-v0',
    'flashgames.RedFuryRacing-v0',
    'flashgames.ReleaseTheMooks-v0',
    'flashgames.ReleaseTheMooks2-v0',
    'flashgames.ReleaseTheMooks3-v0',
    'flashgames.Resonance-v0',
    'flashgames.RetroRunner-v0',
    'flashgames.Retron-v0',
    'flashgames.ReverseBoots-v0',
    'flashgames.RhythmBlasterV2-v0',
    'flashgames.RhythmRockets-v0',
    'flashgames.RhythmSnake-v0',
    'flashgames.RingsideHero-v0',
    'flashgames.RiseOfChampions-v0',
    'flashgames.RoadRacing-v0',
    'flashgames.RoadblockAttack-v0',
    'flashgames.RoboPop-v0',
    'flashgames.RobotDuelFight-v0',
    'flashgames.RobotWantsFishy-v0',
    'flashgames.RocketBootsInc-v0',
    'flashgames.Rocketeer-v0',
    'flashgames.RollTheCluster-v0',
    'flashgames.RollerRider-v0',
    'flashgames.RollingHills-v0',
    'flashgames.Rose-v0',
    'flashgames.RubbleRacer-v0',
    'flashgames.RunFaustoRun-v0',
    'flashgames.RunNGun-v0',
    'flashgames.RunRamRun-v0',
    'flashgames.RunRunRan-v0',
    'flashgames.RunSoldierRun-v0',
    'flashgames.RushOfTanks-v0',
    'flashgames.RussianTruck-v0',
    'flashgames.SafariTime-v0',
    'flashgames.SandcastleShowdown-v0',
    'flashgames.SantaClimbHere-v0',
    'flashgames.SantaMan-v0',
    'flashgames.SantaSituation-v0',
    'flashgames.SapphireClix-v0',
    'flashgames.SaveTheDummyHolidays-v0',
    'flashgames.SavingLittleAlien-v0',
    'flashgames.SchoolBusRacing-v0',
    'flashgames.Scribble-v0',
    'flashgames.Scribble2-v0',
    'flashgames.SeaPong-v0',
    'flashgames.ShamelessClone2-v0',
    'flashgames.Sheepster-v0',
    'flashgames.Sheepy-v0',
    'flashgames.ShimmyChute-v0',
    'flashgames.ShootTheCircle-v0',
    'flashgames.ShortCircuit-v0',
    'flashgames.SiegeHeroPiratePillage-v0',
    'flashgames.Sieger2LevelPack-v0',
    'flashgames.SiegerRebuiltToDestroy-v0',
    'flashgames.Sirtet-v0',
    'flashgames.SistersOfNoMercy-v0',
    'flashgames.SkiSim-v0',
    'flashgames.SkyIsland-v0',
    'flashgames.SkyKnight2-v0',
    'flashgames.SkyQuest-v0',
    'flashgames.Skytrip-v0',
    'flashgames.SliceTheBox-v0',
    'flashgames.SliceTheBoxRemaster-v0',
    'flashgames.SlingBaby-v0',
    'flashgames.SlipSlideSloth-v0',
    'flashgames.SmashTheSwine-v0',
    'flashgames.SmileyJumpFest-v0',
    'flashgames.SmileyPuzzle-v0',
    'flashgames.SmileyPuzzle2-v0',
    'flashgames.SmileyPuzzleGirlEdition-v0',
    'flashgames.SmileyShowdown-v0',
    'flashgames.SnackOnLittleCreatures-v0',
    'flashgames.SnailBob4-v0',
    'flashgames.Snake-v0',
    'flashgames.SnakeClassic-v0',
    'flashgames.SnakeFightArena-v0',
    'flashgames.SneakyScubaEscape-v0',
    'flashgames.SnowPrincessMakeup-v0',
    'flashgames.SnowQueen-v0',
    'flashgames.SnowQueen3-v0',
    'flashgames.SnowQueen4-v0',
    'flashgames.Solarsaurs-v0',
    'flashgames.SonicBubbles-v0',
    'flashgames.SpaceBounty-v0',
    'flashgames.SpaceColony-v0',
    'flashgames.SpaceMadness-v0',
    'flashgames.SpacePunkRacer-v0',
    'flashgames.SpacePunkRacerLvl2-v0',
    'flashgames.SpacePunkRacerLvl3-v0',
    'flashgames.SpacePunkRacerLvl4-v0',
    'flashgames.SpacePunkRacerLvl5-v0',
    'flashgames.SpacePunkRacerLvl6-v0',
    'flashgames.SpacePunkRacerLvl7-v0',
    'flashgames.SpacePunkRacerLvl8-v0',
    'flashgames.SpacemanMax-v0',
    'flashgames.SpanishLiga2016-v0',
    'flashgames.Sparks-v0',
    'flashgames.Spectrum-v0',
    'flashgames.SpectrumHeist-v0',
    'flashgames.SpectrumRunner-v0',
    'flashgames.SpeedBusters-v0',
    'flashgames.SpellIdle2-v0',
    'flashgames.SpinClimbGreen-v0',
    'flashgames.SpinSoar-v0',
    'flashgames.SpinSprint-v0',
    'flashgames.SpunkyVsAliens-v0',
    'flashgames.Stalingrad-v0',
    'flashgames.Stalingrad2-v0',
    'flashgames.Stalingrad3-v0',
    'flashgames.Stand-v0',
    'flashgames.StarCars-v0',
    'flashgames.Stardrops-v0',
    'flashgames.Stargrazer-v0',
    'flashgames.Stars-v0',
    'flashgames.Stealthbound-v0',
    'flashgames.StealthboundLevelPack-v0',
    'flashgames.StickBlender-v0',
    'flashgames.StickyNinjaMissions-v0',
    'flashgames.Stickylinky-v0',
    'flashgames.StitchlandConflict-v0',
    'flashgames.StormRage-v0',
    'flashgames.Stratega-v0',
    'flashgames.StreetRace-v0',
    'flashgames.StreetRace2Nitro-v0',
    'flashgames.StreetRace3-v0',
    'flashgames.Streetrace2Nitro-v0',
    'flashgames.StrikeForceKitty-v0',
    'flashgames.SubmarineFighter-v0',
    'flashgames.Sundrops-v0',
    'flashgames.SuperAdventurePalsBattleArena-v0',
    'flashgames.SuperBattleCity2-v0',
    'flashgames.SuperBomb-v0',
    'flashgames.SuperBoxotron2000-v0',
    'flashgames.SuperCandyGems-v0',
    'flashgames.SuperCarRacing-v0',
    'flashgames.SuperDash-v0',
    'flashgames.SuperIdleMaster-v0',
    'flashgames.SuperK9-v0',
    'flashgames.SuperPuzzlePlatformer-v0',
    'flashgames.SuperRally3d-v0',
    'flashgames.SuperRallyChallenge-v0',
    'flashgames.SuperRallyChallenge2-v0',
    'flashgames.SuperRallyExtreme-v0',
    'flashgames.SuperShinyheadHarderThanFlappyBird-v0',
    'flashgames.SuperXtreme5MinuteShootEmUp-v0',
    'flashgames.SuperbikeExtreme-v0',
    'flashgames.SuperbikeRacer-v0',
    'flashgames.SupercarDomination-v0',
    'flashgames.SupergirlGo-v0',
    'flashgames.SurfBuggy-v0',
    'flashgames.SurvivalLab-v0',
    'flashgames.SurvivorMissionD-v0',
    'flashgames.SushiCatTheHoneymoon-v0',
    'flashgames.SwagMan-v0',
    'flashgames.SwampTreck-v0',
    'flashgames.SwapTheDots-v0',
    'flashgames.SweetTooth-v0',
    'flashgames.SwimmingRace-v0',
    'flashgames.SwingTriangle-v0',
    'flashgames.TableTennisChallenge-v0',
    'flashgames.TamusMitta-v0',
    'flashgames.TankStorm-v0',
    'flashgames.TankStorm2-v0',
    'flashgames.TankStorm3-v0',
    'flashgames.TankStorm4-v0',
    'flashgames.TapRocket-v0',
    'flashgames.TastyFruits-v0',
    'flashgames.TattooArtist-v0',
    'flashgames.TaxiInc-v0',
    'flashgames.TaxiRacers-v0',
    'flashgames.TechnoMania-v0',
    'flashgames.TempleRunKnight-v0',
    'flashgames.TerrestrialConflict-v0',
    'flashgames.ThatRedButton-v0',
    'flashgames.Thaw-v0',
    'flashgames.TheBigEscape-v0',
    'flashgames.TheBoomlandsWorldWars-v0',
    'flashgames.TheBravestHunter-v0',
    'flashgames.TheCaseOfScaryShadow-v0',
    'flashgames.TheCubicMonkeyAdventures2-v0',
    'flashgames.TheGreatSiege-v0',
    'flashgames.TheOneForkRestaurantDx-v0',
    'flashgames.ThePretenderPartThree-v0',
    'flashgames.TheProfessionals3-v0',
    'flashgames.TheSilentPlanet-v0',
    'flashgames.TheThreeTowers-v0',
    'flashgames.TheTowerman-v0',
    'flashgames.Thundercars-v0',
    'flashgames.TinyCastle-v0',
    'flashgames.TinyRacers-v0',
    'flashgames.Titanic-v0',
    'flashgames.TokyoGuineaPop-v0',
    'flashgames.ToonEscapeMaze-v0',
    'flashgames.ToonEscapeSpookHouse-v0',
    'flashgames.Tosuta-v0',
    'flashgames.TouchTheBubbles4-v0',
    'flashgames.TouchTheSky-v0',
    'flashgames.TowerCollapseDeluxe-v0',
    'flashgames.TowerEmpire-v0',
    'flashgames.TowerEmpire2-v0',
    'flashgames.TowerMoon-v0',
    'flashgames.TowerOfPisa-v0',
    'flashgames.ToyRacers-v0',
    'flashgames.ToyWarAngryRobotDog-v0',
    'flashgames.TractorTrial-v0',
    'flashgames.TractorTrial2-v0',
    'flashgames.TrafficCollision-v0',
    'flashgames.TrickOrToad-v0',
    'flashgames.TrickyRick-v0',
    'flashgames.Trizzle-v0',
    'flashgames.TrollingLionJump-v0',
    'flashgames.TtRacer-v0',
    'flashgames.TumbleTiles-v0',
    'flashgames.Tumblestump2-v0',
    'flashgames.TurboCrew-v0',
    'flashgames.TurboRally-v0',
    'flashgames.TurtleBreak-v0',
    'flashgames.TutiFruti-v0',
    'flashgames.TwinkleStarRush-v0',
    'flashgames.Typeasaurus-v0',
    'flashgames.UdderChaos-v0',
    'flashgames.UltimateEscape-v0',
    'flashgames.UltimateLegend-v0',
    'flashgames.Underrun-v0',
    'flashgames.UnderwaterSecrets-v0',
    'flashgames.UnfreezeMe3-v0',
    'flashgames.UrbanFatburner-v0',
    'flashgames.UrbanMicroRacers-v0',
    'flashgames.V8MuscleCars-v0',
    'flashgames.V8MuscleCars2-v0',
    'flashgames.V8MuscleCars3-v0',
    'flashgames.V8RacingChampion-v0',
    'flashgames.VanguardWars-v0',
    'flashgames.VectorRunner-v0',
    'flashgames.Velocity-v0',
    'flashgames.VengeanceRider-v0',
    'flashgames.VideoGameMonster-v0',
    'flashgames.ViewtifulFightClub2-v0',
    'flashgames.Viridia-v0',
    'flashgames.VirtualRacer-v0',
    'flashgames.VolcanoPanicInIsland-v0',
    'flashgames.VolleyBomb-v0',
    'flashgames.WackyStrike-v0',
    'flashgames.WarBerlinIdle-v0',
    'flashgames.WarHeroes-v0',
    'flashgames.WarOfTheShard-v0',
    'flashgames.WastelandSiege-v0',
    'flashgames.WaveLucha-v0',
    'flashgames.Weirdville-v0',
    'flashgames.WhatsInsideTheBox-v0',
    'flashgames.Wheelers-v0',
    'flashgames.WhistleAndMice-v0',
    'flashgames.WildWestConflict-v0',
    'flashgames.WilliamTell-v0',
    'flashgames.WindowShooter-v0',
    'flashgames.WinterSlider-v0',
    'flashgames.WishTotems-v0',
    'flashgames.WishTotemsLevelPack-v0',
    'flashgames.WizkidEscape-v0',
    'flashgames.WolfSpiderJigsawPuzzle-v0',
    'flashgames.WonderRocket-v0',
    'flashgames.WoollyBearJigsawPuzzle-v0',
    'flashgames.WorldsGuard2-v0',
    'flashgames.WormHappy-v0',
    'flashgames.WreckRoad-v0',
    'flashgames.XChains-v0',
    'flashgames.XmasChains-v0',
    'flashgames.Xmatch2016-v0',
    'flashgames.Xnake-v0',
    'flashgames.YepisJourney-v0',
    'flashgames.YummyyummyMonsterShooter-v0',
    'flashgames.Zed-v0',
    'flashgames.Zevil2-v0',
    'flashgames.ZodiacMatch-v0',
    'flashgames.Zombality-v0',
    'flashgames.ZombieDemolisher3-v0',
    'flashgames.ZombieMatch3-v0',
    'flashgames.ZombieTdReborn-v0',
    'flashgames.ZombieTowerDefenseReborn-v0',
    'flashgames.ZombiesAndDonuts-v0',
    'flashgames.ZombiesMustDie-v0',
    'flashgames.ZombiesVsBrains-v0',
    'flashgames.Zombonarium-v0',
    'flashgames.ZooRacer-v0',
    ]:
    register(
        id=game,
        entry_point='universe.wrappers:WrappedFlashgamesEnv',
        max_episode_steps=20000,
        tags={
            'vnc': True,
            'flashgames': True,
            'runtime': 'flashgames',
            'metadata_encoding': metadata_v1,
            'action_probe': {
                'type': 'key',
                'value': 0x60,
            }
        },
    )

register(
    id='VNCNoopFlashgamesEnv-v0',  # Special noop flashgame env
    entry_point='universe.vnc:WrappedFlashgamesEnv',
    max_episode_steps=10**7,
    tags={
        'vnc': True,
        'flashgames': True,
        'runtime': 'flashgames',
    },
)

#------------------------ World of Bits and MiniWoB ------------------------#
#     "World of Bits" comprises a series of browser tasks,
#     including a series of simple "MiniWoB" tasks such
#     as using buttons and sliders, as well as more complex
#     tasks such as booking flights on actual websites.

vnc_world_of_bits = [
    'wob.MiniWorldOfBits-v0',
    'wob.mini.BisectAngle-v0',
    'wob.mini.BookFlight-v0',
    'wob.mini.ChaseCircle-v0',
    'wob.mini.ChooseDate-v0',
    'wob.mini.ChooseList-v0',
    'wob.mini.CircleCenter-v0',
    'wob.mini.ClickButton-v0',
    'wob.mini.ClickButtonSequence-v0',
    'wob.mini.ClickCheckboxes-v0',
    'wob.mini.ClickCollapsible-v0',
    'wob.mini.ClickCollapsible2-v0',
    'wob.mini.ClickColor-v0',
    'wob.mini.ClickDialog-v0',
    'wob.mini.ClickDialog2-v0',
    'wob.mini.ClickLink-v0',
    'wob.mini.ClickMenu-v0',
    'wob.mini.ClickMenu2-v0',
    'wob.mini.ClickOption-v0',
    'wob.mini.ClickPie-v0',
    'wob.mini.ClickScrollList-v0',
    'wob.mini.ClickShades-v0',
    'wob.mini.ClickShape-v0',
    'wob.mini.ClickTab-v0',
    'wob.mini.ClickTab2-v0',
    'wob.mini.ClickTest-v0',
    'wob.mini.ClickTest2-v0',
    'wob.mini.ClickWidget-v0',
    'wob.mini.CopyPaste-v0',
    'wob.mini.CopyPaste2-v0',
    'wob.mini.CountShape-v0',
    'wob.mini.CountSides-v0',
    'wob.mini.DragBox-v0',
    'wob.mini.DragCube-v0',
    'wob.mini.DragItem-v0',
    'wob.mini.DragItems-v0',
    'wob.mini.DragItemsGrid-v0',
    'wob.mini.DragShapes-v0',
    'wob.mini.DragSortNumbers-v0',
    'wob.mini.EmailInbox-v0',
    'wob.mini.EnterDate-v0',
    'wob.mini.EnterPassword-v0',
    'wob.mini.EnterText-v0',
    'wob.mini.EnterText2-v0',
    'wob.mini.EnterTextDynamic-v0',
    'wob.mini.EnterTime-v0',
    'wob.mini.FindMidpoint-v0',
    'wob.mini.FindWord-v0',
    'wob.mini.FocusText-v0',
    'wob.mini.FocusText2-v0',
    'wob.mini.GridCoordinate-v0',
    'wob.mini.GuessNumber-v0',
    'wob.mini.HighlightText-v0',
    'wob.mini.HighlightText2-v0',
    'wob.mini.IdentifyShape-v0',
    'wob.mini.LoginUser-v0',
    'wob.mini.MovingItems-v0',
    'wob.mini.NavigateTree-v0',
    'wob.mini.NumberCheckboxes-v0',
    'wob.mini.ReadTable-v0',
    'wob.mini.ReadTable2-v0',
    'wob.mini.ResizeTextarea-v0',
    'wob.mini.RightAngle-v0',
    'wob.mini.ScrollText-v0',
    'wob.mini.ScrollText2-v0',
    'wob.mini.SearchEngine-v0',
    'wob.mini.SimonSays-v0',
    'wob.mini.SimpleAlgebra-v0',
    'wob.mini.SimpleArithmetic-v0',
    'wob.mini.SocialMedia-v0',
    'wob.mini.Terminal-v0',
    'wob.mini.TextEditor-v0',
    'wob.mini.TextTransform-v0',
    'wob.mini.TicTacToe-v0',
    'wob.mini.UseAutocomplete-v0',
    'wob.mini.UseColorwheel-v0',
    'wob.mini.UseColorwheel2-v0',
    'wob.mini.UseSlider-v0',
    'wob.mini.UseSlider2-v0',
    'wob.mini.UseSpinner-v0',
    'wob.mini.VisualAddition-v0',
]

# signup forms.
for _id in range(20):
    vnc_world_of_bits.append('wob.real.Signup-{}-v0'.format(_id))

for _site in ['Jetblue', 'Kayak', 'AA', 'VirginAmerica',
               'United',  'Delta',  'Alaska']:
    vnc_world_of_bits.append('wob.real.BookFlight-{}-v0'.format(_site))

for _site in ['Airfrance', 'Craigslist', 'Chase']:
    vnc_world_of_bits.append('wob.real.ClickButton-{}-v0'.format(_site))

for _task in ['Learn', 'Test']:
    for _name in ['Geography', 'Planet', 'Universe', 'Comet', 'Moon', 'Mars', 'Solar-System']:
        vnc_world_of_bits.append('wob.real.Quizlet-{}-{}-v0'.format(_name, _task))

vnc_world_of_bits.append('wob.real.Duolingo-French-Basic-1-v0')

for game in vnc_world_of_bits:
    register(
        id=game,
        entry_point='universe.wrappers:WrappedVNCEnv',
        max_episode_steps=10**7,
        tags={
            'vnc': True,
            'wob': True,
            'runtime': 'world-of-bits',
        },
    )

#-------------------------- Complex Games ------------------------#
#     Any game, program, app, or website can be a
#     Universe environment. Here we include
#     a handful of sample "complex" games
#     such as World of Bits, GTA V, and StarCraft.
#     Adding more games is straightforward, and
#     we welcome contributions of environments
#     from the community!

for id in ['starcraft.TerranAstralBalance-v0']:
    register(
        id=id,
        entry_point='universe.wrappers:WrappedStarCraftEnv',
        max_episode_steps=10**7,
        tags={
            'vnc': True,
            'starcraft': True,
            'runtime': 'starcraft',
        },
    )

for gtav_game in ['gtav.SaneDriving-v0', 'gtav.Speed-v0']:
    register(
        id=gtav_game,
        entry_point='universe.wrappers:WrappedGTAVEnv',
        max_episode_steps=10**7,
        tags={
            'vnc': True,
            'gtav': True,
            'runtime': 'vnc-windows',
        },
    )

register(
    id='world.WorldOfGoo-v0',
    entry_point='universe.wrappers:WrappedWorldOfGooEnv',
    max_episode_steps=10**7,
    tags={
        'vnc': True,
        'wog': True,
        'runtime': 'vnc-world-of-goo',
    },
)

for slith_game in ['SlitherIO-v0', 'SlitherIONoSkins-v0', 'SlitherIOEasy-v0']:
    register(
        id='internet.' + slith_game,
        entry_point='universe.wrappers:WrappedInternetEnv',
        max_episode_steps=10**7,
        tags={
            'vnc': True,
            'internet': True,
            'slither': True,
            'runtime': 'flashgames',
            'metadata_encoding': metadata_v1,
            'action_probe': {
                'type': 'key',
                'value': 0x60,
            }
        },
    )

register(
    id='test.DummyVNCEnv-v0',
    entry_point='universe.envs:DummyVNCEnv',
    max_episode_steps= 10**7,
    tags={
        'vnc': True,
        'metadata_encoding': metadata_v1,
        'action_probe': {
            'type': 'key',
            'value': 0x60,
            }
        },
    )


================================================
FILE: universe/configuration.py
================================================
import logging
from gym import configuration

universe_logger = logging.getLogger('universe')
universe_logger.setLevel(logging.INFO)

extra_logger = logging.getLogger('universe.extra')
extra_logger.setLevel(logging.INFO)

if hasattr(configuration, '_extra_loggers'):
    configuration._extra_loggers.append(universe_logger)
    configuration._extra_loggers.append(extra_logger)


================================================
FILE: universe/envs/__init__.py
================================================
import universe.envs.vnc_env
from universe.envs.vnc_env import VNCEnv
from universe.envs.vnc_core_env import GymCoreEnv, GymCoreSyncEnv
from universe.envs.vnc_flashgames import FlashgamesEnv
from universe.envs.vnc_internet import InternetEnv
from universe.envs.vnc_starcraft import StarCraftEnv
from universe.envs.vnc_gtav import GTAVEnv
from universe.envs.vnc_wog import WorldOfGooEnv
from universe.envs.dummy_vnc_env import DummyVNCEnv


================================================
FILE: universe/envs/diagnostics.py
================================================
import collections
import fastzbarlight
import itertools
import logging
from multiprocessing import pool
import numpy as np
import time
import threading
# import psutil
import sys
from collections import namedtuple
from gym.utils import reraise

import re
from universe import error, pyprofile, spaces

# TODO: prefix the loggers

logger = logging.getLogger(__name__)
extra_logger = logging.getLogger('universe.extra.'+__name__)

def show(ob):
    from PIL import Image
    Image.fromarray(ob).show()

def standard_error(ary, axis, scale=1):
    ary = np.array(ary) * scale
    if len(ary) > 1:
        return np.std(ary, axis=axis) / np.sqrt(len(ary) - 1)
    else:
        return np.std(ary, axis=axis)

def extract_timestamp(observation):
    total = 0
    for byte in observation[0]:
        total = 256 * total + byte
    for byte in observation[1]:
        total = 256 * total + byte

    timestamp = total/1000.
    return timestamp

class MetadataDecoder(object):
    @classmethod
    def build(cls, metadata_encoding, pool, qr_pool, label):
        metadata_encoding = metadata_encoding.copy()
        type = metadata_encoding.pop('type')
        if type == 'qrcode':
            return QRCodeMetadataDecoder(label=label, pool=pool, qr_pool=qr_pool, **metadata_encoding)
        elif type == 'pixels':
            return PixelsMetadataDecoder(label=label)
        else:
            raise error.Error('Invalid encoding: {}'.format(type))

class AsyncDecode(object):
    pool = None

    def __init__(self, pool, qr_pool, method, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height

        self._last_img = None

        self.method = method
        self.results = []
        self.deque = collections.deque()
        self.pool = pool
        self.qr_pool = qr_pool

    def __call__(self, img, available_at):
        # Choose the return value
        if len(self.deque) > 0 and self.deque[0].ready():
            last = self.deque.popleft()
            res = last.get()
            if res is not None:
                pyprofile.timing('vnc_env.diagnostics.async_decode.latency', time.time() - res['available_at'])
        else:
            res = False

        pyprofile.gauge('vnc_env.diagnostics.async_decode.queue_depth', len(self.deque))

        # Just grayscale it by keeping only one component. Should be
        # good enough as this region is black and white anyway.
        grayscale = img[self.y:self.y+self.height, self.x:self.x+self.width, 0]

        # Apply processing if needed
        match = np.array_equal(self._last_img, grayscale)
        if not match:
            pyprofile.incr('vnc_env.diagnostics.async_decode.schedule')
            # sneakily copy if numpy hasn't, so it can be cached
            self._last_img = np.ascontiguousarray(grayscale)
            async = self.qr_pool.apply_async(self.method, (self._last_img, time.time(), available_at))
            self.deque.append(async)
        else:
            pyprofile.incr('vnc_env.diagnostics.async_decode.cache_hit')

        return res

class QRCodeMetadataDecoder(MetadataDecoder):
    def __init__(self, pool, qr_pool, x, y, width, height, label):
        self.flag_synchronous = False

        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.label = label

        self.decode = AsyncDecode(pool, qr_pool, self._decode, x, y, width, height)

    def _decode(self, observation, start, available_at):
        # This method gets wrapped by AsyncDecode.__call__
        with pyprofile.push('vnc_env.diagnostics.QRCodeMetadataDecoder.qr_code_scanner'):

            encoded = fastzbarlight.qr_code_scanner(observation.tobytes(), self.width, self.height)
        if encoded is None:
            # Failed to parse!
            return
        if encoded.startswith(b'v1:'):
            encoded = encoded.decode('utf-8')
            if len(encoded) != len('v1:') + 12 + 12:
                raise error.Error('Bad length for metadata from enviroment: {}'.format(encoded))

            encoded = encoded[len('v1:'):]
            last_update = int(encoded[:12], 16) / 1000.0
            last_action = int(encoded[12:24], 16) / 1000.

            return {
                # Timestamp on the image
                'now': last_update,
                # When the last probe was received
                'probe_received_at': last_action,
                'processing_start': start,
                'processing_end': time.time(),
                'available_at': available_at,
            }
        else:
            raise error.Error('Bad version string for metadata from environment: {}'.format(encoded))


class PixelsMetadataDecoder(MetadataDecoder):
    def __init__(self, label):
        self.flag_synchronous = True

        self.anchor = np.array([
            [(0x12, 0x34, 0x56), (0x78, 0x90, 0xab)],
            [(0x23, 0x45, 0x67), (0x89, 0x0a, 0xbc)],
        ], dtype=np.uint8)

        self.location = None
        self.last_search_metadata = 0
        self.label = label

    def _check_location(self, observation, location):
        y, x = location
        return np.all(observation[y:y+2, x:x+2] == self.anchor)

    def _find_metadata_location(self, observation):
        ys, xs = np.where(np.all(observation == self.anchor[0, 0], axis=-1))
        if len(ys) == 0:
            extra_logger.info('[%s] Could not find metadata anchor pixel', self.label)
            return False

        # TODO: handle multiple hits
        assert len(ys) == 1
        location = (ys[0], xs[0])

        assert self._check_location(observation, location)
        extra_logger.info('[%s] Found metadata anchor pixel: %s', self.label, location)
        return location

    def _should_search_metadata(self):
       return time.time() - self.last_search_metadata > 1

    def decode(self, observation, available_at=None):
        start = time.time()

        # metadata pixel location hasn't been initialized or it has moved
        if not self.location or not self._check_location(observation,
                                                         self.location):
            # only search for metadata occasionally
            if self._should_search_metadata():
                self.location = self._find_metadata_location(observation)
                self.last_search_metadata = time.time()

        if not self.location:
            return False  # False translates to None in DiagnosticsInstance

        y, x = self.location
        now = extract_timestamp(observation[y, x+2:x+4])
        probe_received_at = extract_timestamp(observation[y, x+4:x+6])

        return {
            'now': now,
            'probe_received_at': probe_received_at,
            'processing_start': start,
            'processing_end': time.time(),
            'available_at': available_at,
        }

class Diagnostics(object):
    def __init__(self, n, probe_key, ignore_clock_skew=False, metadata_encoding=None, disable_action_probes=False):
        # Each QR code takes about 1ms (and updates at 5fps). We do
        # our best to ensure the QR is processed in time for the next
        # step call (n/16 would put us right at the threshold).
        self.pool = pool.ThreadPool(max(int(n/4), 1))
        self.qr_pool = pool.ThreadPool(max(int(n/8), 1))
        self.lock = threading.RLock()

        self.instance_n = [None] * n
        self.ignore_clock_skew = ignore_clock_skew
        self.disable_action_probes = disable_action_probes

        self.metadata_encoding = metadata_encoding

        self.update(probe_key=probe_key, metadata_encoding=metadata_encoding)

    # only used in flashgames right now
    def update(self, probe_key, metadata_encoding):
        self.probe_key = probe_key
        self.metadata_encoding = metadata_encoding

        for instance in self.instance_n:
            if instance is not None:
                instance.update(probe_key=self.probe_key, metadata_encoding=self.metadata_encoding)

    def connect(self, i, network=None, label=None):
        # This should technically be synchronized
        self.instance_n[i] = DiagnosticsInstance(i, network, self.probe_key, self.ignore_clock_skew, self.metadata_encoding, disable_action_probes=self.disable_action_probes, qr_pool=self.qr_pool, pool=self.pool, label=label)

    def close(self, i=None):
        if i is not None:
            self.instance_n[i] = None
        else:
            self.pool.close()
            self.qr_pool.close()
            for i in range(len(self.instance_n)):
                self.close(i)
            self.instance_n = None

    def add_probe(self, action_n, mask_n):
        if self.disable_action_probes or self.instance_n is None:
            return

        for instance, action, mask in zip(self.instance_n, action_n, mask_n):
            # Important that masking prevents us from adding probes. (This
            # avoids us e.g. filling in backticks into text boxes as the
            # environment boots.)
            if mask and instance:
                instance.add_probe(action)

    def add_metadata(self, observation_n, info_n, available_at=None):
        """Mutates the info_n dictionary."""
        if self.instance_n is None:
            return

        with pyprofile.push('vnc_env.diagnostics.Diagnostics.add_metadata'):
            async = self.pool.imap_unordered(
                self._add_metadata_i,
                zip(self.instance_n, observation_n, info_n, [available_at] * len(observation_n)))
            list(async)

    def _add_metadata_i(self, args):
        instance, observation, info, now = args
        if instance is None or observation is None:
            return
        instance.add_metadata(observation, info, now)

    def extract_metadata(self, observation_n):
        return [instance._extract_metadata(observation)
                for instance, observation in zip(self.instance_n, observation_n)]

    def clear_probes_when_done(self, done_n):
        if self.instance_n is None: # if we've been closed there's nothing to do
            return
        for instance, done in zip(self.instance_n, done_n):
            if done:
                instance.clear_probe()

class DiagnosticsInstance(object):
    anchor = np.array([
        [(0x12, 0x12, 0x12), (0x78, 0x78, 0x78)],
        [(0x23, 0x23, 0x23), (0x89, 0x89, 0x89)],
    ], dtype=np.uint8)
    zero_clock_skew = np.zeros([2])

    def __init__(self, i, network, probe_key, ignore_clock_skew, metadata_encoding, disable_action_probes, pool, qr_pool, label=None):
        '''
        network - either Network() object used to get clock skew, or None.

                  If None, we skip measuring clock skew, and skip measuring
                  diagnostics which rely on clock skew.
        '''
        if network is None:
            assert ignore_clock_skew
        self.ignore_clock_skew = ignore_clock_skew

        self.label = label
        self.i = i
        self.network = network

        self.probe_sent_at = None # local time
        self.probe_received_at = None # remote time
        self.action_latency_skewed = None
        self.last_observation_timestamp = None
        self.disable_action_probes = disable_action_probes

        self.pool = pool
        self.qr_pool = qr_pool
        self.could_read_metadata = None
        self.update(probe_key=probe_key, metadata_encoding=metadata_encoding)

    def update(self, probe_key, metadata_encoding):
        self.probe = [
                spaces.KeyEvent(probe_key, down=True).compile(),
                spaces.KeyEvent(probe_key, down=False).compile(),
        ]

        if metadata_encoding is not None:
            self.metadata_decoder = MetadataDecoder.build(metadata_encoding, pool=self.pool, qr_pool=self.qr_pool, label=self.label)
        else:
            self.metadata_decoder = None

    def clear_probe(self):
        self.probe_sent_at = None
        self.probe_received_at = None

    def add_probe(self, action):
        if self.network is not None and not self.network.active():
            return

        if self.probe_sent_at is not None and self.probe_sent_at + 10 < time.time():
            extra_logger.warn('[%s] Probe to determine action latency timed out (was sent %s). (This is harmless, but worth knowing about.)', self.label, self.probe_sent_at)
            self.probe_sent_at = None
        if self.probe_sent_at is None:
            extra_logger.debug('[%s] Sending out new action probe: %s', self.label, self.probe)
            self.probe_sent_at = time.time()
            action += self.probe
        assert self.probe_sent_at is not None

    def add_metadata(self, observation, info, available_at=None):
        """Extract metadata from a pixel observation and add it to the info
        """
        observation = observation['vision']
        if observation is None: return
        if self.network is not None and not self.network.active():
            return
        elif self.metadata_decoder is None:
            return
        elif observation is None:
            return
        # should return a dict with now/probe_received_at keys
        with pyprofile.push('vnc_env.diagnostics.DiagnosticsInstance.add_metadata.decode'):
            metadata = self.metadata_decoder.decode(observation, available_at=available_at)

        if metadata is False:
            # No metadata ready, though it doesn't mean parsing failed
            metadata = None
        elif metadata is None:
            if self.could_read_metadata:
                self.could_read_metadata = False
                extra_logger.info('[%s] Stopped being able to read metadata (expected when environment resets)', self.label)
        elif not self.could_read_metadata:
            self.could_read_metadata = True
            extra_logger.info('[%s] Started being able to read metadata', self.label)

        if self.metadata_decoder.flag_synchronous and metadata is not None:
            info['diagnostics.image_remote_time'] = metadata['now']

        local_now = time.time()

        if self.network is None:
            # Assume the clock skew is zero. Should only be run on the
            # same machine as the VNC server, such as the universe
            # instance inside of the environmenth containers.
            real_clock_skew = self.zero_clock_skew
        else:
            # Note: this is a 2-length vector of (min, max), so anything added to
            # it is also going to be a 2-length vector.
            # Most of the diagnostics below are, but you have to look carefully.
            real_clock_skew = self.network.reversed_clock_skew()

        # Store real clock skew here
        info['stats.gauges.diagnostics.clock_skew'] = real_clock_skew
        if self.ignore_clock_skew:
            clock_skew = self.zero_clock_skew
        else:
            clock_skew = real_clock_skew

        if metadata is not None:
            # We'll generally update the observation timestamp infrequently
            if self.last_observation_timestamp == metadata['now']:
                delta = None
            else:
                # We just got a new timestamp in the observation!
                self.last_observation_timestamp = metadata['now']
                observation_now = metadata['now']
                delta = observation_now - metadata['available_at']

                # Subtract *local* time it was received from the *remote* time
                # displayed. Negate and reverse order to fix time ordering.
                info['stats.gauges.diagnostics.lag.observation'] = -(delta + clock_skew)[[1, 0]]

            # if self.network is None:
            #     # The rest of diagnostics need the network, so we're done here
            #     return

            probe_received_at = metadata['probe_received_at']
            if probe_received_at == 0 or self.disable_action_probes:
                # Happens when the env first starts
                self.probe_received_at = None
            elif self.probe_received_at is None: # this also would work for the equality case
                self.probe_received_at = probe_received_at
            elif self.probe_received_at != probe_received_at and self.probe_sent_at is None:
                logger.info('[%s] Probe is marked as received at %s, but probe_sent_at is None. This is surprising. (HINT: do you have multiple universe instances talking to the same environment?)', self.label, probe_received_at)
            elif self.probe_received_at != probe_received_at:
                extra_logger.debug('[%s] Next probe received: old=%s new=%s', self.label, self.probe_received_at, probe_received_at)
                self.probe_received_at = probe_received_at
                # Subtract the *local* time we sent it from the *remote* time it was received
                self.action_latency_skewed = probe_received_at - self.probe_sent_at
                self.probe_sent_at = None

            if self.action_latency_skewed:
                action_lag = self.action_latency_skewed + clock_skew
                self.action_latency_skewed = None
            else:
                action_lag = None
            info['stats.gauges.diagnostics.lag.action'] = action_lag

        local_now = time.time()
        # Look at when the remote believed it parsed the score (not
        # all envs send this currently).
        #
        # Also, if we received no new rewards, then this values is
        # None. This could indicate a high reward latency (bad,
        # uncommon), or that the agent is calling step faster than new
        # rewards are coming in (good, common).
        remote_score_now = info.get('rewarder.lag.observation.timestamp')
        if remote_score_now is not None:
            delta = remote_score_now - local_now
            info['stats.gauges.diagnostics.lag.reward'] = -(delta + clock_skew)[[1, 0]]

        # L
Download .txt
gitextract_4uz9ods7/

├── .dockerignore
├── .gitignore
├── .travis.yml
├── CODE_OF_CONDUCT.rst
├── Dockerfile
├── ISSUE_TEMPLATE
├── LICENSE
├── Makefile
├── README.rst
├── doc/
│   ├── env_semantics.rst
│   ├── protocols.rst
│   └── remotes.rst
├── example/
│   ├── diagnostic-agent/
│   │   └── diagnostic-agent.py
│   ├── random-agent/
│   │   └── random-agent.py
│   ├── recorders/
│   │   ├── botaction_recorder.py
│   │   ├── reward_recorder.py
│   │   └── vnc_recorder.py
│   ├── starter-cluster/
│   │   ├── starter-cluster
│   │   ├── starter-cluster-cf.json
│   │   └── starter-cluster-requirements.txt
│   └── system-diagnostics/
│       └── system_diagnostics_logger.py
├── setup.py
├── test.dockerfile
├── tests/
│   └── functional/
│       ├── test_core_envs_semantics.py
│       └── test_envs.py
├── tox.ini
└── universe/
    ├── __init__.py
    ├── configuration.py
    ├── envs/
    │   ├── __init__.py
    │   ├── diagnostics.py
    │   ├── dummy_vnc_env.py
    │   ├── tests/
    │   │   ├── __init__.py
    │   │   └── test_semantics.py
    │   ├── vnc_core_env/
    │   │   ├── __init__.py
    │   │   ├── key.py
    │   │   ├── translator.py
    │   │   └── vnc_core_env.py
    │   ├── vnc_env.py
    │   ├── vnc_flashgames.py
    │   ├── vnc_gtav.py
    │   ├── vnc_internet.py
    │   ├── vnc_starcraft.py
    │   └── vnc_wog.py
    ├── error.py
    ├── kube/
    │   ├── __init__.py
    │   └── discovery.py
    ├── pyprofile/
    │   └── __init__.py
    ├── remotes/
    │   ├── __init__.py
    │   ├── allocator_remote.py
    │   ├── build.py
    │   ├── compose/
    │   │   ├── __init__.py
    │   │   ├── colors.py
    │   │   ├── container.py
    │   │   ├── log_printer.py
    │   │   ├── progress_stream.py
    │   │   ├── signals.py
    │   │   └── utils.py
    │   ├── docker_remote.py
    │   ├── hardcoded_addresses.py
    │   ├── healthcheck.py
    │   └── remote.py
    ├── rewarder/
    │   ├── __init__.py
    │   ├── connection_timer.py
    │   ├── env_status.py
    │   ├── merge.py
    │   ├── remote.py
    │   ├── reward_buffer.py
    │   ├── reward_proxy_server.py
    │   ├── rewarder_client.py
    │   ├── rewarder_session.py
    │   └── tests/
    │       └── test_reward_buffer.py
    ├── runtimes/
    │   ├── .agignore
    │   ├── __init__.py
    │   ├── flashgames.json
    │   └── registration.py
    ├── runtimes.yml
    ├── scoreboard/
    │   └── __init__.py
    ├── spaces/
    │   ├── __init__.py
    │   ├── diagnostics.py
    │   ├── hardcoded.py
    │   ├── joystick_action_space.py
    │   ├── joystick_event.py
    │   ├── vnc_action_space.py
    │   ├── vnc_event.py
    │   └── vnc_observation_space.py
    ├── twisty.py
    ├── utils/
    │   ├── __init__.py
    │   └── display.py
    ├── vectorized/
    │   ├── __init__.py
    │   ├── core.py
    │   ├── multiprocessing_env.py
    │   ├── tests/
    │   │   └── test_monitoring.py
    │   └── vectorize_filter.py
    ├── vncdriver/
    │   ├── README.md
    │   ├── __init__.py
    │   ├── auth.py
    │   ├── constants.py
    │   ├── dual_proxy_server.py
    │   ├── error.py
    │   ├── fbs_reader.py
    │   ├── fbs_writer.py
    │   ├── libvnc_session.py
    │   ├── screen/
    │   │   ├── __init__.py
    │   │   ├── base.py
    │   │   ├── numpy_screen.py
    │   │   ├── pyglet_screen.py
    │   │   └── screen_buffer.py
    │   ├── server_messages.py
    │   ├── vendor/
    │   │   ├── __init__.py
    │   │   └── pydes.py
    │   ├── vnc_client.py
    │   ├── vnc_proxy_server.py
    │   └── vnc_session.py
    └── wrappers/
        ├── __init__.py
        ├── action_space.py
        ├── blocking_reset.py
        ├── diagnostics.py
        ├── experimental/
        │   ├── __init__.py
        │   ├── action_space.py
        │   ├── observation.py
        │   └── random_env.py
        ├── gym_core.py
        ├── gym_core_sync.py
        ├── joint.py
        ├── logger.py
        ├── monitoring.py
        ├── multiprocessing_env.py
        ├── recording.py
        ├── render.py
        ├── tests/
        │   ├── test_joint.py
        │   └── test_time_limit.py
        ├── throttle.py
        ├── time_limit.py
        ├── timer.py
        ├── vectorize.py
        └── vision.py
Download .txt
SYMBOL INDEX (1141 symbols across 97 files)

FILE: example/diagnostic-agent/diagnostic-agent.py
  class NoopSpace (line 21) | class NoopSpace(gym.Space):
    method sample (line 23) | def sample(self, seed=0):
    method contains (line 25) | def contains(self, x):
  class ForwardSpace (line 28) | class ForwardSpace(gym.Space):
    method __init__ (line 30) | def __init__(self, key='w'):
    method sample (line 32) | def sample(self, seed=0):
    method contains (line 34) | def contains(self, x):
  class RandomAgent (line 38) | class RandomAgent(object):
    method __init__ (line 45) | def __init__(self, action_space, n, vectorized):
    method __call__ (line 50) | def __call__(self, observation, reward, done):

FILE: example/random-agent/random-agent.py
  function main (line 13) | def main():

FILE: example/recorders/botaction_recorder.py
  class BotactionRecordingServer (line 24) | class BotactionRecordingServer(websocket.WebSocketServerProtocol, object):
    method next_id (line 28) | def next_id(cls):
    method __init__ (line 35) | def __init__(self):
    method _emit (line 43) | def _emit(self, rec):
    method onConnect (line 48) | def onConnect(self, request):
    method onOpen (line 57) | def onOpen(self):
    method onClose (line 60) | def onClose(self, wasClean, code, reason):
    method onMessage (line 68) | def onMessage(self, msg, binary):
  function main (line 73) | def main():

FILE: example/recorders/reward_recorder.py
  function main (line 13) | def main():

FILE: example/recorders/vnc_recorder.py
  function main (line 14) | def main():

FILE: example/system-diagnostics/system_diagnostics_logger.py
  class DiagnosticsLogger (line 7) | class DiagnosticsLogger(object):
    method __init__ (line 8) | def __init__(self, interval=5):
    method run (line 12) | def run(self):
    method get_chrome_procs (line 24) | def get_chrome_procs(self):
    method cpu_times (line 32) | def cpu_times(self):

FILE: tests/functional/test_core_envs_semantics.py
  function show (line 11) | def show(obs):
  class AtariMatcher (line 14) | class AtariMatcher(object):
    method translator (line 15) | def translator(self, env):
    method crop (line 18) | def crop(self, obs):
    method assert_match (line 21) | def assert_match(self, obs, vnc_obs, extra_info=None, stage=None):
  function atari_vnc_wrapper (line 33) | def atari_vnc_wrapper(env):
  class CartPoleLowDMatcher (line 38) | class CartPoleLowDMatcher(object):
    method translator (line 39) | def translator(self, env):
    method assert_match (line 42) | def assert_match(self, obs, vnc_obs, extra_info=None, stage=None):
  function reset (line 45) | def reset(matcher, env, vnc_env, stage=None):
  function rollout (line 50) | def rollout(matcher, env, vnc_env, timestep_limit=None, stage=None):
  function test_nice_vnc_semantics_match (line 84) | def test_nice_vnc_semantics_match(spec, matcher, wrapper):

FILE: tests/functional/test_envs.py
  function test_smoke (line 23) | def test_smoke(env_id):
  function _rollout (line 40) | def _rollout(env, timestep_limit=None):
  function configure_with_latest_docker_runtime_tag (line 82) | def configure_with_latest_docker_runtime_tag(env):

FILE: universe/__init__.py
  function docker_image (line 33) | def docker_image(runtime_id):
  function enable_logfile (line 45) | def enable_logfile(path=None):
  function configure_logging (line 48) | def configure_logging(path=None):

FILE: universe/envs/diagnostics.py
  function show (line 22) | def show(ob):
  function standard_error (line 26) | def standard_error(ary, axis, scale=1):
  function extract_timestamp (line 33) | def extract_timestamp(observation):
  class MetadataDecoder (line 43) | class MetadataDecoder(object):
    method build (line 45) | def build(cls, metadata_encoding, pool, qr_pool, label):
  class AsyncDecode (line 55) | class AsyncDecode(object):
    method __init__ (line 58) | def __init__(self, pool, qr_pool, method, x, y, width, height):
    method __call__ (line 72) | def __call__(self, img, available_at):
  class QRCodeMetadataDecoder (line 101) | class QRCodeMetadataDecoder(MetadataDecoder):
    method __init__ (line 102) | def __init__(self, pool, qr_pool, x, y, width, height, label):
    method _decode (line 113) | def _decode(self, observation, start, available_at):
  class PixelsMetadataDecoder (line 143) | class PixelsMetadataDecoder(MetadataDecoder):
    method __init__ (line 144) | def __init__(self, label):
    method _check_location (line 156) | def _check_location(self, observation, location):
    method _find_metadata_location (line 160) | def _find_metadata_location(self, observation):
    method _should_search_metadata (line 174) | def _should_search_metadata(self):
    method decode (line 177) | def decode(self, observation, available_at=None):
  class Diagnostics (line 203) | class Diagnostics(object):
    method __init__ (line 204) | def __init__(self, n, probe_key, ignore_clock_skew=False, metadata_enc...
    method update (line 221) | def update(self, probe_key, metadata_encoding):
    method connect (line 229) | def connect(self, i, network=None, label=None):
    method close (line 233) | def close(self, i=None):
    method add_probe (line 243) | def add_probe(self, action_n, mask_n):
    method add_metadata (line 254) | def add_metadata(self, observation_n, info_n, available_at=None):
    method _add_metadata_i (line 265) | def _add_metadata_i(self, args):
    method extract_metadata (line 271) | def extract_metadata(self, observation_n):
    method clear_probes_when_done (line 275) | def clear_probes_when_done(self, done_n):
  class DiagnosticsInstance (line 282) | class DiagnosticsInstance(object):
    method __init__ (line 289) | def __init__(self, i, network, probe_key, ignore_clock_skew, metadata_...
    method update (line 315) | def update(self, probe_key, metadata_encoding):
    method clear_probe (line 326) | def clear_probe(self):
    method add_probe (line 330) | def add_probe(self, action):
    method add_metadata (line 343) | def add_metadata(self, observation, info, available_at=None):
  function extract_n_m (line 453) | def extract_n_m(dict_n_m, key):

FILE: universe/envs/dummy_vnc_env.py
  class DummyVNCEnv (line 11) | class DummyVNCEnv(vectorized.Env):
    method __init__ (line 33) | def __init__(self):
    method configure (line 39) | def configure(self, remotes=None,
    method _reset (line 52) | def _reset(self):
    method _step (line 55) | def _step(self, action_n):
    method __str__ (line 74) | def __str__(self):

FILE: universe/envs/tests/test_semantics.py
  function get_rewarder_session (line 21) | def get_rewarder_session(env):
  function get_vnc_session (line 24) | def get_vnc_session(env):
  function get_rewarder_client (line 27) | def get_rewarder_client(env):
  function get_reward_buffer (line 31) | def get_reward_buffer(env):
  function setup_module (line 35) | def setup_module(module):
  class FakeVNCConnection (line 38) | class FakeVNCConnection(object):
    method __init__ (line 39) | def __init__(self, name, address, password, encoding=None, fine_qualit...
    method step (line 50) | def step(self, action):
    method _to_dict (line 54) | def _to_dict(self):
  class FakeVNCSession (line 65) | class FakeVNCSession(object):
    method __init__ (line 66) | def __init__(self):
    method connect (line 69) | def connect(self, name, **kwargs):
    method close (line 72) | def close(self, name=None):
    method step (line 78) | def step(self, action_d):
    method _to_dict (line 88) | def _to_dict(self):
  class FakeRewarderConnection (line 91) | class FakeRewarderConnection(object):
    method __init__ (line 92) | def __init__(self, name, address, label, password, env_id=None, seed=N...
    method reset (line 114) | def reset(self, seed=None):
    method pop (line 117) | def pop(self, peek=False):
    method _to_dict (line 120) | def _to_dict(self):
  class FakeRewarder (line 134) | class FakeRewarder(object):
    method __init__ (line 135) | def __init__(self):
    method reset (line 138) | def reset(self, seed=None, **kwargs):
    method connect (line 142) | def connect(self, name, **kwargs):
    method close (line 146) | def close(self, name=None):
    method pop (line 152) | def pop(self, peek_d):
    method _to_dict (line 164) | def _to_dict(self):
  function test_connect (line 167) | def test_connect():
  function test_describe_handling (line 176) | def test_describe_handling():
  function test_vnc_env (line 198) | def test_vnc_env():
  function test_boundary_simple (line 229) | def test_boundary_simple():
  function test_boundary_multiple (line 249) | def test_boundary_multiple():
  function test_peek (line 281) | def test_peek():

FILE: universe/envs/vnc_core_env/key.py
  class KeyStateHandler (line 68) | class KeyStateHandler(dict):
    method on_key_press (line 86) | def on_key_press(self, symbol, modifiers):
    method on_key_release (line 88) | def on_key_release(self, symbol, modifiers):
    method __getitem__ (line 90) | def __getitem__(self, key):
  function modifiers_string (line 93) | def modifiers_string(modifiers):
  function symbol_string (line 128) | def symbol_string(symbol):
  function motion_string (line 147) | def motion_string(motion):
  function user_key (line 163) | def user_key(scancode):

FILE: universe/envs/vnc_core_env/translator.py
  class AtariKeyState (line 8) | class AtariKeyState(object):
    method __init__ (line 15) | def __init__(self, env):
    method apply_vnc_actions (line 19) | def apply_vnc_actions(self, vnc_actions):
    method to_keysyms (line 36) | def to_keysyms(self):
    method to_index (line 40) | def to_index(self):
  class AtariTranslator (line 45) | class AtariTranslator(object):
    method __init__ (line 49) | def __init__(self, env):
    method keysyms_to_vnc_actions (line 59) | def keysyms_to_vnc_actions(self, keysyms):
    method keysyms_to_index (line 67) | def keysyms_to_index(self, keysyms):
    method index_to_keysyms (line 71) | def index_to_keysyms(self, i):
    method _name_to_index (line 86) | def _name_to_index(self, name):
    method _index_to_name (line 89) | def _index_to_name(self, i):
    method _keysyms_to_name (line 92) | def _keysyms_to_name(self, keysyms):
  class CartPoleTranslator (line 106) | class CartPoleTranslator(object):
    method __init__ (line 107) | def __init__(self, env):
    method keysyms_to_vnc_actions (line 110) | def keysyms_to_vnc_actions(self, keysyms):
    method keysyms_to_index (line 114) | def keysyms_to_index(self, keys):
    method index_to_keysyms (line 120) | def index_to_keysyms(self, i):

FILE: universe/envs/vnc_core_env/vnc_core_env.py
  class GymCoreEnv (line 10) | class GymCoreEnv(vnc_env.VNCEnv):
    method __init__ (line 11) | def __init__(self, gym_core_id, fps=60):
  class GymCoreSyncEnv (line 22) | class GymCoreSyncEnv(GymCoreEnv):
    method __init__ (line 31) | def __init__(self, gym_core_id, fps=60, vnc_pixels=True):
    method _flip_past (line 44) | def _flip_past(self, when_n):
    method _reset (line 67) | def _reset(self):
    method _observation (line 85) | def _observation(self, observation_n):
    method _step (line 93) | def _step(self, action_n):

FILE: universe/envs/vnc_env.py
  function default_client_id (line 30) | def default_client_id():
  function rewarder_session (line 33) | def rewarder_session(which):
  function go_vncdriver (line 42) | def go_vncdriver():
  function py_vncdriver (line 46) | def py_vncdriver():
  function libvnc_vncdriver (line 49) | def libvnc_vncdriver():
  function vnc_session (line 52) | def vnc_session(which=None):
  function build_observation_n (line 89) | def build_observation_n(visual_observation_n, info_n):
  class VNCEnv (line 102) | class VNCEnv(vectorized.Env):
    method __init__ (line 112) | def __init__(self, fps=None, probe_key=None):
    method _seed (line 134) | def _seed(self, seed):
    method configure (line 138) | def configure(self, remotes=None,
    method connect (line 257) | def connect(self, i, name, vnc_address, rewarder_address, vnc_password...
    method _close (line 313) | def _close(self, i=None):
    method _reset (line 335) | def _reset(self):
    method _reset_mask (line 350) | def _reset_mask(self):
    method _pop_rewarder_session (line 353) | def _pop_rewarder_session(self, peek_d):
    method _step_vnc_session (line 368) | def _step_vnc_session(self, compiled_d):
    method _compile_actions (line 388) | def _compile_actions(self, action_n):
    method _action_d (line 409) | def _action_d(self, action_n):
    method _step (line 415) | def _step(self, action_n):
    method _handle_initial_n (line 468) | def _handle_initial_n(self, observation_n, reward_n):
    method _handle_err_n (line 478) | def _handle_err_n(self, err_n, vnc_err_n, info_n, observation_n=None, ...
    method _handle_connect (line 508) | def _handle_connect(self, n=None):
    method _handle_crashed_n (line 521) | def _handle_crashed_n(self, info_n):
    method _propagate_obs_info (line 539) | def _propagate_obs_info(self, info_n, obs_info_n):
    method _render (line 545) | def _render(self, mode='human', close=False):
    method __str__ (line 554) | def __str__(self):
  class Mask (line 561) | class Mask(object):
    method __init__ (line 581) | def __init__(self, connection_labels, initially_masked=True):
    method close (line 591) | def close(self, i):
    method maintain_mask (line 595) | def maintain_mask(self, done_n, info_n):
    method apply_to_actions (line 629) | def apply_to_actions(self, action_n, info_n, mask):
    method apply_to_return (line 638) | def apply_to_return(self, observation_n, reward_n, done_n, info_n, obs...
  function compile_action (line 655) | def compile_action(event):

FILE: universe/envs/vnc_flashgames.py
  class FlashgamesEnv (line 3) | class FlashgamesEnv(vnc_env.VNCEnv):
    method __init__ (line 4) | def __init__(self):

FILE: universe/envs/vnc_gtav.py
  class GTAVEnv (line 5) | class GTAVEnv(vnc_env.VNCEnv):
    method __init__ (line 6) | def __init__(self):

FILE: universe/envs/vnc_internet.py
  class InternetEnv (line 3) | class InternetEnv(vnc_env.VNCEnv):
    method __init__ (line 4) | def __init__(self):

FILE: universe/envs/vnc_starcraft.py
  class StarCraftEnv (line 14) | class StarCraftEnv(vnc_env.VNCEnv):
    method __init__ (line 15) | def __init__(self):

FILE: universe/envs/vnc_wog.py
  class WorldOfGooEnv (line 5) | class WorldOfGooEnv(vnc_env.VNCEnv):
    method __init__ (line 6) | def __init__(self):

FILE: universe/error.py
  class Error (line 3) | class Error(Exception):
  class RPCError (line 6) | class RPCError(Error):
  class ConnectionError (line 9) | class ConnectionError(Error):
  class TimeoutError (line 12) | class TimeoutError(Error):
  class AuthenticationError (line 15) | class AuthenticationError(Error):

FILE: universe/kube/discovery.py
  class Error (line 6) | class Error(Exception):
  function pretty_command (line 11) | def pretty_command(command):
  function log_command (line 14) | def log_command(command, prefix=''):
  function check_call (line 17) | def check_call(command, *args, **kwargs):
  function popen (line 21) | def popen(command, *args, **kwargs):
  function check_with_output (line 25) | def check_with_output(command, *args, **kwargs):
  function interpret_ready (line 33) | def interpret_ready(pod):
  function interpret_ports (line 51) | def interpret_ports(containers):
  class VNCEnvDiscovery (line 72) | class VNCEnvDiscovery(object):
    method __init__ (line 73) | def __init__(self):
    method discover_batches (line 78) | def discover_batches(self):
    method discover (line 94) | def discover(self, batch, force_ready=False):

FILE: universe/pyprofile/__init__.py
  class Error (line 19) | class Error(Exception):
  class ExponentialAverage (line 22) | class ExponentialAverage(object):
    method __init__ (line 23) | def __init__(self, decay=0.1):
    method add (line 29) | def add(self, data):
    method avg (line 51) | def avg(self):
  class RunningVariance (line 54) | class RunningVariance(object):
    method __init__ (line 79) | def __init__(self):
    method add (line 84) | def add(self,x):
    method mean (line 92) | def mean(self):
    method meanfull (line 94) | def meanfull(self):
    method std (line 96) | def std(self):
    method __repr__ (line 100) | def __repr__(self):
  function pretty (line 103) | def pretty(d, unit):
  function pretty_bytes (line 113) | def pretty_bytes(b):
  function pretty_seconds (line 125) | def pretty_seconds(t):
  function thread_id (line 134) | def thread_id():
  class StackProfile (line 137) | class StackProfile(object):
    method __init__ (line 138) | def __init__(self, profile):
    method __enter__ (line 144) | def __enter__(self):
    method __exit__ (line 147) | def __exit__(self, type, value, tb):
    method push (line 150) | def push(self, event):
    method pop (line 158) | def pop(self):
    method _current_stack (line 171) | def _current_stack(self):
  class Profile (line 183) | class Profile(object):
    method __init__ (line 184) | def __init__(self, print_frequency=None, print_filter=None):
    method reset (line 199) | def reset(self):
    method add_export_hook (line 204) | def add_export_hook(self, hook):
    method __enter__ (line 207) | def __enter__(self):
    method __exit__ (line 212) | def __exit__(self, type, value, tb):
    method timing (line 217) | def timing(self, event, time):
    method incr (line 233) | def incr(self, event, amount=1, unit=None):
    method gauge (line 252) | def gauge(self, event, value, delta=False, unit=None):
    method _print_if_needed (line 271) | def _print_if_needed(self):
    method export (line 281) | def export(self, log=True, reset=True):
    method _print_export (line 333) | def _print_export(self, export):

FILE: universe/remotes/allocator_remote.py
  class Stop (line 31) | class Stop(Exception):
  class RequestError (line 34) | class RequestError(Exception):
    method __init__ (line 35) | def __init__(self, message, status_code=None):
  class FatalError (line 41) | class FatalError(RequestError):
  class AllocatorManager (line 44) | class AllocatorManager(threading.Thread):
    method __init__ (line 47) | def __init__(self, client_id, base_url=allocator_base,
    method from_remotes (line 105) | def from_remotes(cls, client_id, remotes, runtime_id, runtime_tag, sta...
    method pop (line 136) | def pop(self, n=None):
    method allocate (line 166) | def allocate(self, handles, initial=False, params={}):
    method close (line 171) | def close(self):
    method run (line 174) | def run(self):
    method _run (line 182) | def _run(self):
    method _process_requests (line 187) | def _process_requests(self):
    method _allocate (line 200) | def _allocate(self, handles, initial, params):
    method _poll (line 237) | def _poll(self):
    method _handle_allocation (line 267) | def _handle_allocation(self, allocation, pop=False):
    method with_retries (line 294) | def with_retries(self, method, *args, **kwargs):
  class AllocatorClient (line 316) | class AllocatorClient(object):
    method __init__ (line 317) | def __init__(self, label, api_key, base_url):
    method _handle_resp (line 325) | def _handle_resp(self, resp):
    method _post_request (line 345) | def _post_request(self, route, data, description):
    method _delete_request (line 354) | def _delete_request(self, route):
    method _get_request (line 360) | def _get_request(self, route):
    method allocation_create (line 366) | def allocation_create(self, client_id, runtime_id, handles, params={},...
    method allocation_refresh (line 373) | def allocation_refresh(self, id, names):
    method allocation_delete (line 378) | def allocation_delete(self, id, names):

FILE: universe/remotes/build.py
  function build (line 7) | def build(client_id, remotes, runtime=None, start_timeout=None, **kwargs):

FILE: universe/remotes/compose/colors.py
  function get_pairs (line 15) | def get_pairs():
  function ansi (line 21) | def ansi(code):
  function ansi_color (line 25) | def ansi_color(code, s):
  function make_color_fn (line 29) | def make_color_fn(code):
  function rainbow (line 37) | def rainbow():

FILE: universe/remotes/compose/container.py
  class Container (line 15) | class Container(object):
    method __init__ (line 20) | def __init__(self, client, dictionary, has_been_inspected=False):
    method from_ps (line 27) | def from_ps(cls, client, dictionary, **kwargs):
    method from_id (line 43) | def from_id(cls, client, id):
    method create (line 47) | def create(cls, client, **options):
    method id (line 52) | def id(self):
    method image (line 56) | def image(self):
    method image_config (line 60) | def image_config(self):
    method short_id (line 64) | def short_id(self):
    method name (line 68) | def name(self):
    method service (line 72) | def service(self):
    method name_without_project (line 76) | def name_without_project(self):
    method number (line 85) | def number(self):
    method ports (line 93) | def ports(self):
    method human_readable_ports (line 98) | def human_readable_ports(self):
    method labels (line 109) | def labels(self):
    method stop_signal (line 113) | def stop_signal(self):
    method log_config (line 117) | def log_config(self):
    method human_readable_state (line 121) | def human_readable_state(self):
    method human_readable_command (line 132) | def human_readable_command(self):
    method environment (line 138) | def environment(self):
    method exit_code (line 146) | def exit_code(self):
    method is_running (line 150) | def is_running(self):
    method is_restarting (line 154) | def is_restarting(self):
    method is_paused (line 158) | def is_paused(self):
    method log_driver (line 162) | def log_driver(self):
    method has_api_logs (line 166) | def has_api_logs(self):
    method attach_log_stream (line 170) | def attach_log_stream(self):
    method get (line 177) | def get(self, key):
    method get_local_port (line 190) | def get_local_port(self, port, protocol='tcp'):
    method get_mount (line 194) | def get_mount(self, mount_dest):
    method start (line 200) | def start(self, **options):
    method stop (line 203) | def stop(self, **options):
    method pause (line 206) | def pause(self, **options):
    method unpause (line 209) | def unpause(self, **options):
    method kill (line 212) | def kill(self, **options):
    method restart (line 215) | def restart(self, **options):
    method remove (line 218) | def remove(self, **options):
    method create_exec (line 221) | def create_exec(self, command, **options):
    method start_exec (line 224) | def start_exec(self, exec_id, **options):
    method rename_to_tmp_name (line 227) | def rename_to_tmp_name(self):
    method inspect_if_not_inspected (line 236) | def inspect_if_not_inspected(self):
    method wait (line 240) | def wait(self):
    method logs (line 243) | def logs(self, *args, **kwargs):
    method inspect (line 246) | def inspect(self):
    method attach (line 251) | def attach(self, *args, **kwargs):
    method __repr__ (line 254) | def __repr__(self):
    method __eq__ (line 257) | def __eq__(self, other):
    method __hash__ (line 262) | def __hash__(self):
  function get_container_name (line 266) | def get_container_name(container):

FILE: universe/remotes/compose/log_printer.py
  function build (line 21) | def build(containers, service_names, **kwargs):
  class LogPresenter (line 27) | class LogPresenter(object):
    method __init__ (line 29) | def __init__(self, prefix_width, color_func):
    method present (line 33) | def present(self, container, line):
  function build_log_presenters (line 40) | def build_log_presenters(service_names, monochrome):
  function max_name_width (line 54) | def max_name_width(service_names, max_index_width=3):
  class LogPrinter (line 64) | class LogPrinter(threading.Thread):
    method __init__ (line 69) | def __init__(self,
    method run (line 82) | def run(self):
  function remove_stopped_threads (line 109) | def remove_stopped_threads(thread_map):
  function build_thread (line 115) | def build_thread(container, presenter, queue, log_args):
  function build_thread_map (line 124) | def build_thread_map(initial_containers, presenters, thread_args):
  class QueueItem (line 131) | class QueueItem(namedtuple('_QueueItem', 'item is_stop exc')):
    method new (line 134) | def new(cls, item):
    method exception (line 138) | def exception(cls, exc):
    method stop (line 142) | def stop(cls):
  function tail_container_logs (line 146) | def tail_container_logs(container, presenter, queue, log_args):
  function get_log_generator (line 161) | def get_log_generator(container):
  function build_no_log_generator (line 167) | def build_no_log_generator(container, log_args):
  function build_log_generator (line 175) | def build_log_generator(container, log_args):
  function wait_on_exit (line 186) | def wait_on_exit(container):
  function start_producer_thread (line 191) | def start_producer_thread(thread_args):
  function watch_events (line 197) | def watch_events(thread_map, event_stream, presenters, thread_args):
  function consume_queue (line 217) | def consume_queue(queue, cascade_stop):

FILE: universe/remotes/compose/progress_stream.py
  class StreamOutputError (line 7) | class StreamOutputError(Exception):
  function stream_output (line 11) | def stream_output(output, stream):
  function print_output_event (line 56) | def print_output_event(event, stream, is_terminal):
  function get_digest_from_pull (line 96) | def get_digest_from_pull(events):
  function get_digest_from_push (line 107) | def get_digest_from_push(events):

FILE: universe/remotes/compose/signals.py
  class ShutdownException (line 7) | class ShutdownException(Exception):
  function shutdown (line 11) | def shutdown(signal, frame):
  function set_signal_handler (line 15) | def set_signal_handler(handler):
  function set_signal_handler_to_shutdown (line 20) | def set_signal_handler_to_shutdown():

FILE: universe/remotes/compose/utils.py
  function get_output_stream (line 15) | def get_output_stream(stream):
  function stream_as_text (line 21) | def stream_as_text(stream):
  function line_splitter (line 34) | def line_splitter(buffer, separator=u'\n'):
  function split_buffer (line 41) | def split_buffer(stream, splitter=None, decoder=lambda a: a):
  function json_splitter (line 66) | def json_splitter(buffer):
  function json_stream (line 78) | def json_stream(stream):
  function json_hash (line 86) | def json_hash(obj):
  function microseconds_from_time_nano (line 93) | def microseconds_from_time_nano(time_nano):
  function build_string_dict (line 97) | def build_string_dict(source_dict):

FILE: universe/remotes/docker_remote.py
  function random_alphanumeric (line 24) | def random_alphanumeric(length=14):
  function pretty_command (line 32) | def pretty_command(command):
  class DockerManager (line 35) | class DockerManager(object):
    method __init__ (line 36) | def __init__(self, runtime, n, reuse=False, start_timeout=None):
    method allocate (line 57) | def allocate(self, handles, initial=False, params={}):
    method pop (line 60) | def pop(self, n=None):
    method _start (line 79) | def _start(self):
    method close (line 87) | def close(self):
    method start_logging (line 91) | def start_logging(self, instances):
    method healthcheck (line 105) | def healthcheck(self, instances):
  function get_client (line 113) | def get_client():
  class PortAssigner (line 159) | class PortAssigner(object):
    method __init__ (line 160) | def __init__(self, reuse=False):
    method _refresh_ports (line 167) | def _refresh_ports(self):
    method allocate_ports (line 177) | def allocate_ports(self, num):
  class DockerInstance (line 205) | class DockerInstance(object):
    method __init__ (line 206) | def __init__(self, assigner, runtime, label='main'):
    method start (line 226) | def start(self, attempts=None):
    method _spawn (line 246) | def _spawn(self):
    method _pull_image (line 287) | def _pull_image(self):
    method _spawn_container (line 300) | def _spawn_container(self):
    method _start (line 319) | def _start(self):
    method _remove (line 338) | def _remove(self):
    method __del__ (line 360) | def __del__(self):
    method close (line 363) | def close(self):
    method client (line 377) | def client(self):

FILE: universe/remotes/hardcoded_addresses.py
  class HardcodedAddresses (line 11) | class HardcodedAddresses(object):
    method build (line 13) | def build(cls, remotes, **kwargs):
    method __init__ (line 27) | def __init__(self, vnc_addresses, rewarder_addresses, vnc_password, re...
    method pop (line 51) | def pop(self, n=None):
    method allocate (line 80) | def allocate(self, handles, initial=False, params={}):
    method close (line 86) | def close(self):
  function parse_remotes (line 89) | def parse_remotes(remotes):

FILE: universe/remotes/healthcheck.py
  function run (line 12) | def run(vnc_addresses, rewarder_addresses, timeout=None, start_timeout=N...
  function host_port (line 16) | def host_port(address, default_port=None):
  class Healthcheck (line 26) | class Healthcheck(object):
    method __init__ (line 27) | def __init__(self, vnc_addresses, rewarder_addresses, timeout=None, st...
    method _register_vnc (line 39) | def _register_vnc(self, address, start_time=None):
    method _register_rewarder (line 67) | def _register_rewarder(self, address, start_time=None):
    method run (line 101) | def run(self):

FILE: universe/remotes/remote.py
  class Remote (line 1) | class Remote(object):
    method __init__ (line 2) | def __init__(self, handle, vnc_address, vnc_password, rewarder_address...
    method __str__ (line 10) | def __str__(self):
    method __repr__ (line 13) | def __repr__(self):

FILE: universe/rewarder/connection_timer.py
  class ConnectionTimer (line 15) | class ConnectionTimer(protocol.Protocol):
    method connectionMade (line 16) | def connectionMade(self):
  function start (line 19) | def start(endpoint):
  function measure_clock_skew (line 25) | def measure_clock_skew(label, host):
  class Clockskew (line 43) | class Clockskew(protocol.ProcessProtocol):
    method __init__ (line 44) | def __init__(self, label, cmd):
    method outReceived (line 52) | def outReceived(self, data):
    method errReceived (line 55) | def errReceived(self, data):
    method processExited (line 58) | def processExited(self, reason):
  class ConnectionTimerException (line 71) | class ConnectionTimerException(Exception):

FILE: universe/rewarder/env_status.py
  function parse_episode_id (line 6) | def parse_episode_id(episode_id):
  function generate_episode_id (line 11) | def generate_episode_id(parsed):
  function compare_ids (line 16) | def compare_ids(a, b):
  class EnvStatus (line 28) | class EnvStatus(object):
    method __init__ (line 29) | def __init__(self, label=None, primary=True):
    method env_info (line 38) | def env_info(self):
    method set_env_info (line 47) | def set_env_info(self, env_state=None, env_id=None, episode_id=None, b...
    method episode_id (line 86) | def episode_id(self):
    method env_state (line 91) | def env_state(self):
    method env_state (line 96) | def env_state(self, value):
    method env_id (line 101) | def env_id(self):
    method env_id (line 106) | def env_id(self, value):
    method fps (line 110) | def fps(self):
    method wait_for_env_state_change (line 114) | def wait_for_env_state_change(self, start_state):

FILE: universe/rewarder/merge.py
  function merge_infos (line 4) | def merge_infos(info1, info2):
  function merge_reward_n (line 30) | def merge_reward_n(accum_reward_n, reward_n):
  function merge_done_n (line 36) | def merge_done_n(accum_done_n, done_n):
  function _merge_observation (line 42) | def _merge_observation(accum_observation, observation):
  function merge_observation_n (line 60) | def merge_observation_n(accum_observation_n, observation_n):
  function merge_n (line 65) | def merge_n(

FILE: universe/rewarder/remote.py
  class Exit (line 24) | class Exit(Exception):
  class RewarderProtocol (line 27) | class RewarderProtocol(websocket.WebSocketServerProtocol):
    method onConnect (line 30) | def onConnect(self, request):
    method authenticate (line 43) | def authenticate(self, request):
    method onOpen (line 61) | def onOpen(self):
    method onMessage (line 75) | def onMessage(self, payload, isBinary):
    method onClose (line 105) | def onClose(self, wasClean, code, reason):
    method send_message (line 109) | def send_message(self, method, body, headers):
    method reject (line 135) | def reject(self, message):
  class ControlBuffer (line 140) | class ControlBuffer(object):
    method __init__ (line 141) | def __init__(self, cv):
    method recv_rpc (line 145) | def recv_rpc(self, context, payload):
    method client_disconnect (line 152) | def client_disconnect(self, conn, stats):
    method get (line 155) | def get(self, *args, **kwargs):
  class AgentConn (line 161) | class AgentConn(object):
    method __init__ (line 162) | def __init__(self, env_status, cv, control_buffer, error_buffer, idle_...
    method active_clients (line 175) | def active_clients(self):
    method listen (line 178) | def listen(self, port=15900):
    method check_message (line 186) | def check_message(self, conn):
    method _register (line 220) | def _register(self, conn, observer=False):
    method _unregister (line 225) | def _unregister(self, conn):
    method _broadcast (line 243) | def _broadcast(self, method, body, headers=None, conn=None):
    method send_env_text (line 252) | def send_env_text(self, text, episode_id):
    method _send_env_text (line 256) | def _send_env_text(self, text, episode_id):
    method send_env_observation (line 261) | def send_env_observation(self, observation, episode_id):
    method _send_env_observation (line 264) | def _send_env_observation(self, observation, episode_id, conn=None):
    method send_env_reward (line 269) | def send_env_reward(self, reward, done, info, episode_id):
    method _send_env_reward (line 276) | def _send_env_reward(self, reward, done, info, episode_id):
    method send_env_describe_from_env_info (line 283) | def send_env_describe_from_env_info(self, env_info):
    method send_env_describe (line 287) | def send_env_describe(self, env_id, env_state, episode_id, fps, header...
    method _send_env_describe (line 290) | def _send_env_describe(self, env_id, env_state, episode_id, fps, heade...
    method send_reply_error (line 310) | def send_reply_error(self, *args, **kwargs):
    method _send_reply_error (line 313) | def _send_reply_error(self, message, parent_message_id, parent_context):
    method send_reply_env_reset (line 324) | def send_reply_env_reset(self, *args, **kwargs):
    method _send_reply_env_reset (line 327) | def _send_reply_env_reset(self, parent_message_id, parent_context, epi...
    method check_status (line 337) | def check_status(self):
  class RewardLogger (line 361) | class RewardLogger(object):
    method __init__ (line 362) | def __init__(self):
    method reset (line 365) | def reset(self, log=True, episode_stats=True):
    method record (line 385) | def record(self, reward, done, info):
    method _log_reset (line 398) | def _log_reset(self):
    method _log (line 401) | def _log(self):

FILE: universe/rewarder/reward_buffer.py
  class RewardState (line 11) | class RewardState(object):
    method __init__ (line 12) | def __init__(self, label, episode_id):
    method push_time (line 25) | def push_time(self, remote_time, local_time):
    method set_env_info (line 30) | def set_env_info(self, env_state):
    method push_text (line 33) | def push_text(self, text):
    method push_done (line 36) | def push_done(self, done, info):
    method push_info (line 44) | def push_info(self, info):
    method push (line 47) | def push(self, reward, done, info):
    method pop_text (line 56) | def pop_text(self):
    method pop_info (line 61) | def pop_info(self):
    method pop (line 73) | def pop(self):
    method set_observation (line 88) | def set_observation(self, observation):
  class RewardBuffer (line 92) | class RewardBuffer(object):
    method __init__ (line 93) | def __init__(self, label):
    method reward_state (line 107) | def reward_state(self, episode_id):
    method set_env_info (line 131) | def set_env_info(self, env_state, env_id, episode_id, fps):
    method set_observation (line 145) | def set_observation(self, episode_id, observation):
    method push_time (line 149) | def push_time(self, episode_id, remote_time, local_time):
    method push_text (line 153) | def push_text(self, episode_id, text):
    method push_info (line 158) | def push_info(self, episode_id, info):
    method push (line 163) | def push(self, episode_id, reward, done, info):
    method pop (line 168) | def pop(self, peek=False):
    method mask (line 219) | def mask(self):
    method reset (line 225) | def reset(self, episode_id):
    method _max_id (line 233) | def _max_id(self):
    method _valid_ids (line 241) | def _valid_ids(self):
    method _advance (line 244) | def _advance(self):
    method _drop_below (line 264) | def _drop_below(self, episode_id, quiet=False):
    method wait_for_step (line 279) | def wait_for_step(self, error_buffer=None, timeout=None):

FILE: universe/rewarder/reward_proxy_server.py
  class RewardServerClient (line 12) | class RewardServerClient(websocket.WebSocketClientProtocol, object):
    method __init__ (line 13) | def __init__(self):
    method onConnect (line 20) | def onConnect(self, request):
    method onOpen (line 31) | def onOpen(self):
    method onMessage (line 34) | def onMessage(self, msg, isBinary):
    method onClose (line 49) | def onClose(self, wasClean, code, reason):
    method close (line 52) | def close(self):
  class RewardProxyServer (line 57) | class RewardProxyServer(websocket.WebSocketServerProtocol, object):
    method next_id (line 62) | def next_id(cls):
    method __init__ (line 67) | def __init__(self):
    method pop_buffer (line 76) | def pop_buffer(self):
    method begin_recording (line 83) | def begin_recording(self):
    method onConnect (line 119) | def onConnect(self, request):
    method onOpen (line 123) | def onOpen(self):
    method connect_upstream (line 127) | def connect_upstream(self, tries=1, max_attempts=7):
    method close (line 168) | def close(self):
    method onClose (line 172) | def onClose(self, wasClean, code, reason):
    method onMessage (line 181) | def onMessage(self, msg, binary):
    method record_message (line 192) | def record_message(self, msg, from_rewarder):

FILE: universe/rewarder/rewarder_client.py
  class RemoteError (line 14) | class RemoteError(error.Error):
  class RewarderClient (line 17) | class RewarderClient(websocket.WebSocketClientProtocol):
    method __init__ (line 18) | def __init__(self):
    method send_reset (line 31) | def send_reset(self, env_id, seed, fps, episode_id):
    method _finish_reset (line 45) | def _finish_reset(self, episode_id):
    method onConnect (line 49) | def onConnect(self, request):
    method waitForWebsocketConnection (line 59) | def waitForWebsocketConnection(self):
    method send (line 62) | def send(self, method, body, headers=None, expect_reply=False):
    method _manual_recv (line 100) | def _manual_recv(self, method, body, headers={}):
    method recv (line 105) | def recv(self, context, response):
    method _make_context (line 176) | def _make_context(self):
    method onMessage (line 179) | def onMessage(self, payload, isBinary):
    method onClose (line 196) | def onClose(self, wasClean, code, reason):
    method close (line 216) | def close(self, code=1000, reason=None):

FILE: universe/rewarder/rewarder_session.py
  function _ping (line 19) | def _ping(client):
  class RewarderSession (line 22) | class RewarderSession(object):
    method __init__ (line 23) | def __init__(self):
    method close (line 37) | def close(self, name=None, reason=u'closed by RewarderSession.close'):
    method connect (line 64) | def connect(self, name, address, label, password, env_id=None, seed=No...
    method _already_closed (line 94) | def _already_closed(self, i):
    method _connect (line 102) | def _connect(self, name, address, env_id, seed, fps, i, network, env_s...
    method pop_errors (line 221) | def pop_errors(self):
    method reset (line 231) | def reset(self, seed=None, env_id=None):
    method _reset (line 237) | def _reset(self, seed=None, env_id=None):
    method _send_env_reset (line 250) | def _send_env_reset(self, client, seed=None, episode_id=None, env_id=N...
    method pop (line 260) | def pop(self, warn=True, peek_d=None):
    method wait (line 281) | def wait(self, timeout=None):
    method send_action (line 292) | def send_action(self, action_n, env_id):
    method _send_action (line 296) | def _send_action(self, env_id, action_n):
    method _send_env_action (line 301) | def _send_env_action(self, client, env_id, action_n):
    method rewards_count (line 311) | def rewards_count(self):
    method pop_observation (line 315) | def pop_observation(self):
  class Network (line 329) | class Network(object):
    method __init__ (line 330) | def __init__(self):
    method active (line 343) | def active(self):
    method reversed_clock_skew (line 348) | def reversed_clock_skew(self):
    method _report (line 355) | def _report(self):
    method _start (line 370) | def _start(self):
    method close (line 380) | def close(self):
    method calibrate (line 388) | def calibrate(self, client):
    method _start_measure_connection_time (line 420) | def _start_measure_connection_time(self, d):
    method _measure_connection_time (line 424) | def _measure_connection_time(self, d, connection_time_m, i):
    method _start_measure_application_ping (line 441) | def _start_measure_application_ping(self, d=None):
    method _measure_application_ping (line 449) | def _measure_application_ping(self, d, clock_skew_m, request_overhead_...
    method _update_exposed_metrics (line 507) | def _update_exposed_metrics(self):
    method _start_measure_clock_skew (line 513) | def _start_measure_clock_skew(self):

FILE: universe/rewarder/tests/test_reward_buffer.py
  function test_prereset (line 3) | def test_prereset():
  function test_mask_peek (line 11) | def test_mask_peek():
  function test_single (line 21) | def test_single():
  function test_multiple (line 33) | def test_multiple():
  function test_double_reset (line 59) | def test_double_reset():

FILE: universe/runtimes/registration.py
  class UnregisteredRuntime (line 8) | class UnregisteredRuntime(error.Unregistered):
  class DockerRuntime (line 14) | class DockerRuntime(object):
    method __init__ (line 16) | def __init__(self, id=id, image=None, command=None, host_config=None, ...
    method server_registry (line 36) | def server_registry(self):
    method _cli_flags (line 43) | def _cli_flags(self):
    method cli_command (line 68) | def cli_command(self, vnc_port, rewarder_port, extra_flags=[]):
  class WindowsRuntime (line 77) | class WindowsRuntime(object):
    method __init__ (line 79) | def __init__(self, id=id, default_params=None):
  class Registry (line 88) | class Registry(object):
    method __init__ (line 89) | def __init__(self):
    method register_runtime (line 92) | def register_runtime(self, id, kind, **kwargs):
    method runtime_spec (line 100) | def runtime_spec(self, id):

FILE: universe/spaces/diagnostics.py
  class DiagnosticEvent (line 1) | class DiagnosticEvent(object):

FILE: universe/spaces/hardcoded.py
  class Hardcoded (line 3) | class Hardcoded(object):
    method __init__ (line 4) | def __init__(self, actions):
    method contains (line 7) | def contains(self, action):
    method sample (line 10) | def sample(self):
    method __getitem__ (line 14) | def __getitem__(self, i):

FILE: universe/spaces/joystick_action_space.py
  class JoystickActionSpace (line 8) | class JoystickActionSpace(gym.Space):
    method __init__ (line 12) | def __init__(self, axis_x=False, axis_y=False, axis_z=False, axis_rx=F...
    method contains (line 43) | def contains(self, action):
    method sample (line 53) | def sample(self):
  class JoystickActionSpaceException (line 63) | class JoystickActionSpaceException(Exception):
  function box_axis (line 67) | def box_axis():

FILE: universe/spaces/joystick_event.py
  class JoystickEvent (line 1) | class JoystickEvent(object):
  class JoystickAxisEvent (line 5) | class JoystickAxisEvent(JoystickEvent):
    method __init__ (line 6) | def __init__(self, amount):
    method __repr__ (line 9) | def __repr__(self):
    method __str__ (line 12) | def __str__(self):
    method __hash__ (line 15) | def __hash__(self):
    method __eq__ (line 18) | def __eq__(self, other):
    method compile (line 22) | def compile(self):
  class JoystickAxisXEvent (line 26) | class JoystickAxisXEvent(JoystickAxisEvent):
  class JoystickAxisYEvent (line 30) | class JoystickAxisYEvent(JoystickAxisEvent):
  class JoystickAxisZEvent (line 34) | class JoystickAxisZEvent(JoystickAxisEvent):
  class JoystickAxisRxEvent (line 38) | class JoystickAxisRxEvent(JoystickAxisEvent):
  class JoystickAxisRyEvent (line 42) | class JoystickAxisRyEvent(JoystickAxisEvent):
  class JoystickAxisRzEvent (line 46) | class JoystickAxisRzEvent(JoystickAxisEvent):
  class JoystickSlider0Event (line 50) | class JoystickSlider0Event(JoystickAxisEvent):
  class JoystickSlider1Event (line 54) | class JoystickSlider1Event(JoystickAxisEvent):

FILE: universe/spaces/vnc_action_space.py
  class VNCActionSpace (line 9) | class VNCActionSpace(gym.Space):
    method __init__ (line 28) | def __init__(self, keys=None, buttonmasks=None, screen_shape=(1024, 72...
    method contains (line 48) | def contains(self, action):
    method sample (line 69) | def sample(self):

FILE: universe/spaces/vnc_event.py
  class VNCEvent (line 5) | class VNCEvent(object):
  function keycode (line 8) | def keycode(key):
  class KeyEvent (line 16) | class KeyEvent(VNCEvent):
    method build (line 24) | def build(cls, keys, down=None):
    method by_name (line 45) | def by_name(cls, key, down=None):
    method __init__ (line 48) | def __init__(self, key, down=True):
    method compile (line 53) | def compile(self):
    method __repr__ (line 56) | def __repr__(self):
    method __str__ (line 68) | def __str__(self):
    method __hash__ (line 71) | def __hash__(self):
    method __eq__ (line 74) | def __eq__(self, other):
    method key_name (line 80) | def key_name(self):
  class PointerEvent (line 84) | class PointerEvent(VNCEvent):
    method __init__ (line 85) | def __init__(self, x, y, buttonmask=0):
    method compile (line 90) | def compile(self):
    method __repr__ (line 93) | def __repr__(self):
    method __str__ (line 96) | def __str__(self):

FILE: universe/spaces/vnc_observation_space.py
  class VNCObservationSpace (line 3) | class VNCObservationSpace(gym.Space):
    method contains (line 6) | def contains(self, x):

FILE: universe/twisty.py
  function _get_reactor (line 9) | def _get_reactor(platform):
  class TwistedThread (line 32) | class TwistedThread(threading.Thread):
    method start_once (line 37) | def start_once(cls):
    method run (line 45) | def run(self):

FILE: universe/utils/__init__.py
  class ErrorBuffer (line 16) | class ErrorBuffer(object):
    method __init__ (line 17) | def __init__(self):
    method __enter__ (line 20) | def __enter__(self):
    method __exit__ (line 23) | def __exit__(self, type, value, traceback):
    method __call__ (line 27) | def __call__(self, error, wrap=True):
    method record (line 30) | def record(self, error, wrap=True):
    method check (line 40) | def check(self, timeout=None):
    method blocking_check (line 51) | def blocking_check(self, timeout=None):
  function format_error (line 64) | def format_error(e):
  function queue_get (line 84) | def queue_get(local_queue):
  function blockingCallFromThread (line 93) | def blockingCallFromThread(f, *a, **kw):
  function repeat_space (line 109) | def repeat_space(space, n):
  function random_alphanumeric (line 114) | def random_alphanumeric(length=14):
  function best_effort (line 123) | def best_effort(function, *args, **kwargs):
  function basic_auth_encode (line 136) | def basic_auth_encode(username, password=''):
  function basic_auth_decode (line 140) | def basic_auth_decode(header):
  function default_password (line 150) | def default_password():
  class PeriodicLog (line 159) | class PeriodicLog(object):
    method log (line 160) | def log(self, obj, name, msg, *args, **kwargs):
    method log_debug (line 176) | def log_debug(self, obj, name, msg, *args, **kwargs):
  function thread_name (line 195) | def thread_name():
  function exit_on_signal (line 198) | def exit_on_signal():

FILE: universe/utils/display.py
  function fmt_plusminus (line 10) | def fmt_plusminus(mean, dev):
  function compute_timestamps_pair_max (line 17) | def compute_timestamps_pair_max(time_m_2, flat=True):
  function display_timestamps_pair_compact (line 41) | def display_timestamps_pair_compact(time_m_2):
  function display_timestamps_pair (line 61) | def display_timestamps_pair(time_m_2):
  function compute_timestamps_sigma_n (line 74) | def compute_timestamps_sigma_n(time_m):
  function compute_timestamps_sigma (line 85) | def compute_timestamps_sigma(time_m):
  function display_timestamps (line 94) | def display_timestamps(time_m):
  function compute_timestamps (line 101) | def compute_timestamps(time_m):
  function display_timestamps_n (line 109) | def display_timestamps_n(time_m):
  function standard_error (line 113) | def standard_error(ary, axis=0):
  function display_timestamp (line 119) | def display_timestamp(time):
  function pick_time_units (line 124) | def pick_time_units(time):

FILE: universe/vectorized/core.py
  class Env (line 5) | class Env(gym.Env):
  class Wrapper (line 19) | class Wrapper(Env, gym.Wrapper):
    method __init__ (line 27) | def __init__(self, env):
    method n (line 40) | def n(self):
    method configure (line 43) | def configure(self, **kwargs):
  class ObservationWrapper (line 46) | class ObservationWrapper(Wrapper, gym.ObservationWrapper):
  class RewardWrapper (line 49) | class RewardWrapper(Wrapper, gym.RewardWrapper):
  class ActionWrapper (line 52) | class ActionWrapper(Wrapper, gym.ActionWrapper):

FILE: universe/vectorized/multiprocessing_env.py
  class Error (line 13) | class Error(Exception):
  function display_name (line 16) | def display_name(exception):
  function render_dict (line 24) | def render_dict(error):
  class Worker (line 31) | class Worker(object):
    method __init__ (line 32) | def __init__(self, env_m, worker_idx):
    method _clear_state (line 49) | def _clear_state(self):
    method start (line 54) | def start(self):
    method _parent_recv (line 57) | def _parent_recv(self):
    method _child_send (line 63) | def _child_send(self, msg):
    method _parent_send (line 66) | def _parent_send(self, msg):
    method close_start (line 77) | def close_start(self):
    method close_finish (line 80) | def close_finish(self):
    method reset_start (line 83) | def reset_start(self):
    method reset_finish (line 86) | def reset_finish(self):
    method step_start (line 89) | def step_start(self, action_m):
    method step_finish (line 93) | def step_finish(self):
    method mask_start (line 96) | def mask_start(self, i):
    method seed_start (line 99) | def seed_start(self, seed_m):
    method render_start (line 102) | def render_start(self, mode, close):
    method render_finish (line 105) | def render_finish(self):
    method run (line 108) | def run(self):
    method do_run (line 116) | def do_run(self):
    method step_m (line 155) | def step_m(self, action_m):
  function step_n (line 178) | def step_n(worker_n, action_n):
  function reset_n (line 199) | def reset_n(worker_n):
  function seed_n (line 210) | def seed_n(worker_n, seed_n):
  function mask (line 218) | def mask(worker_n, i):
  function render_n (line 227) | def render_n(worker_n, mode, close):
  function close_n (line 242) | def close_n(worker_n):
  class MultiprocessingEnv (line 261) | class MultiprocessingEnv(core.Env):
    method __init__ (line 267) | def __init__(self, env_id):
    method configure (line 282) | def configure(self, n=1, pool_size=None, episode_limit=None):
    method _seed (line 299) | def _seed(self, seed):
    method _reset (line 303) | def _reset(self):
    method _step (line 306) | def _step(self, action_n):
    method _render (line 309) | def _render(self, mode='human', close=False):
    method mask (line 312) | def mask(self, i):
    method _close (line 315) | def _close(self):

FILE: universe/vectorized/tests/test_monitoring.py
  function test_multiprocessing_env_monitoring (line 8) | def test_multiprocessing_env_monitoring():
  function test_vnc_monitoring (line 23) | def test_vnc_monitoring():

FILE: universe/vectorized/vectorize_filter.py
  class Filter (line 3) | class Filter(object):
    method _after_reset (line 4) | def _after_reset(self, observation):
    method _after_step (line 7) | def _after_step(self, observation, reward, done, info):
  class VectorizeFilter (line 10) | class VectorizeFilter(core.Wrapper):
    method __init__ (line 18) | def __init__(self, env, filter_factory, *args, **kwargs):
    method _reset (line 25) | def _reset(self):
    method _step (line 32) | def _step(self, action_n):
    method __str__ (line 48) | def __str__(self):

FILE: universe/vncdriver/auth.py
  class RFBDes (line 7) | class RFBDes(pydes.des):
    method setKey (line 8) | def setKey(self, key):
  function challenge (line 31) | def challenge():
  function challenge_response (line 39) | def challenge_response(challenge, password=None):

FILE: universe/vncdriver/dual_proxy_server.py
  class DualProxyServer (line 18) | class DualProxyServer(VNCProxyServer):
    method __init__ (line 19) | def __init__(self, action_queue=None, error_buffer=None, enable_loggin...
    method _log_info (line 25) | def _log_info(self, msg, *args, **kwargs):
    method recv_ClientInit (line 28) | def recv_ClientInit(self, block):
    method close (line 47) | def close(self):

FILE: universe/vncdriver/error.py
  class Error (line 1) | class Error(Exception):

FILE: universe/vncdriver/fbs_reader.py
  class InvalidFBSFileError (line 7) | class InvalidFBSFileError(error.Error):
  class FBSReader (line 10) | class FBSReader(object):
    method __init__ (line 11) | def __init__(self, path):
    method __iter__ (line 24) | def __iter__(self):
    method read_safe (line 27) | def read_safe(self, size=None):
    method next (line 45) | def next(self):
    method __next__ (line 48) | def __next__(self):
    method close (line 67) | def close(self):

FILE: universe/vncdriver/fbs_writer.py
  class FBSWriter (line 9) | class FBSWriter(object):
    method __init__ (line 10) | def __init__(self, path):
    method write (line 27) | def write(self, data):
    method _write_metadata (line 54) | def _write_metadata(self):
    method close (line 61) | def close(self):
    method __del__ (line 71) | def __del__(self):

FILE: universe/vncdriver/libvnc_session.py
  function load_pygame (line 11) | def load_pygame():
  class LibVNCSession (line 25) | class LibVNCSession(object):
    method __init__ (line 26) | def __init__(self, remotes, error_buffer, encoding=None, compress_leve...
    method flip (line 71) | def flip(self):
    method step (line 74) | def step(self, action):
    method render (line 77) | def render(self):
    method _guard (line 80) | def _guard(self, fn):
    method _render (line 86) | def _render(self):
    method before_render (line 103) | def before_render(self):
    method close (line 116) | def close(self):

FILE: universe/vncdriver/screen/base.py
  class Screen (line 6) | class Screen(object):

FILE: universe/vncdriver/screen/numpy_screen.py
  class NumpyScreen (line 14) | class NumpyScreen(object):
    method __init__ (line 15) | def __init__(self, width, height):
    method set_paint_cursor (line 49) | def set_paint_cursor(self, paint_cursor):
    method peek (line 52) | def peek(self):
    method flip (line 56) | def flip(self):
    method apply_action (line 80) | def apply_action(self, action):
    method apply (line 92) | def apply(self, framebuffer_update):
    method _apply (line 102) | def _apply(self, framebuffer_update):
    method update_back (line 116) | def update_back(self):
    method _update_back (line 120) | def _update_back(self):
    method _update_rectangle (line 134) | def _update_rectangle(self, x, y, width, height, data):
    method _update_cursor_shape (line 138) | def _update_cursor_shape(self, hotx, hoty, width, height, image, mask):
    method _paint_cursor (line 142) | def _paint_cursor(self):
    method _unpaint_cursor (line 178) | def _unpaint_cursor(self):

FILE: universe/vncdriver/screen/pyglet_screen.py
  class PygletScreen (line 12) | class PygletScreen(object):
    method __init__ (line 13) | def __init__(self, bitmap=None):
    method flip (line 20) | def flip(self):
    method _initialize (line 31) | def _initialize(self):
    method update_rectangle (line 40) | def update_rectangle(self, x, y, width, height, data):
    method apply (line 49) | def apply(self, framebuffer_update):

FILE: universe/vncdriver/screen/screen_buffer.py
  class ScreenBuffer (line 9) | class ScreenBuffer(object):
    method __init__ (line 10) | def __init__(self):
    method apply_format (line 15) | def apply_format(self, attrs):
    method update_rectangle (line 21) | def update_rectangle(self, x, y, width, height, data):
    method copy_rectangle (line 31) | def copy_rectangle(self, src_x, src_y, x, y, width, height):
    method fill_rectangle (line 42) | def fill_rectangle(self, x, y, width, height, color):
    method framebuffer_update_finish (line 52) | def framebuffer_update_finish(self):
    method _push (line 57) | def _push(self, update):
    method pop (line 61) | def pop(self):
    method peek (line 70) | def peek(self):

FILE: universe/vncdriver/server_messages.py
  class FramebufferUpdate (line 16) | class FramebufferUpdate(object):
    method __init__ (line 17) | def __init__(self, rectangles):
  class Rectangle (line 20) | class Rectangle(object):
    method __init__ (line 21) | def __init__(self, x, y, width, height, encoding):
  class PseudoCursorEncoding (line 28) | class PseudoCursorEncoding(object):
    method __init__ (line 29) | def __init__(self, image, mask):
    method parse_rectangle (line 34) | def parse_rectangle(cls, client, x, y, width, height, data):
  class RAWEncoding (line 46) | class RAWEncoding(object):
    method __init__ (line 47) | def __init__(self, data):
    method parse_rectangle (line 51) | def parse_rectangle(cls, client, x, y, width, height, data):
  class ZlibEncoding (line 57) | class ZlibEncoding(object):
    method __init__ (line 58) | def __init__(self, data):
    method parse_rectangle (line 62) | def parse_rectangle(cls, client, x, y, width, height, data):
  class ZRLEEncoding (line 70) | class ZRLEEncoding(object):
    method __init__ (line 71) | def __init__(self, data):
    method parse_rectangle (line 75) | def parse_rectangle(cls, client, x, y, width, height, data):
    method _read (line 91) | def _read(cls, x, y, width, height, buf, bytes_per_pixel):
    method _read_tile (line 105) | def _read_tile(cls, tile, buf, tile_width, tile_height, bytes_per_pixel):

FILE: universe/vncdriver/vendor/pydes.py
  class _baseDes (line 107) | class _baseDes(object):
    method __init__ (line 108) | def __init__(self, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
    method getKey (line 126) | def getKey(self):
    method setKey (line 130) | def setKey(self, key):
    method getMode (line 135) | def getMode(self):
    method setMode (line 139) | def setMode(self, mode):
    method getPadding (line 143) | def getPadding(self):
    method setPadding (line 147) | def setPadding(self, pad):
    method getPadMode (line 153) | def getPadMode(self):
    method setPadMode (line 157) | def setPadMode(self, mode):
    method getIV (line 161) | def getIV(self):
    method setIV (line 165) | def setIV(self, IV):
    method _padData (line 172) | def _padData(self, data, pad, padmode):
    method _unpadData (line 201) | def _unpadData(self, data, pad, padmode):
    method _guardAgainstUnicode (line 228) | def _guardAgainstUnicode(self, data):
  class des (line 247) | class des(_baseDes):
    method __init__ (line 397) | def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
    method setKey (line 411) | def setKey(self, key):
    method __String_to_BitList (line 416) | def __String_to_BitList(self, data):
    method __BitList_to_String (line 437) | def __BitList_to_String(self, data):
    method __permutate (line 454) | def __permutate(self, table, block):
    method __create_sub_keys (line 460) | def __create_sub_keys(self):
    method __des_crypt (line 485) | def __des_crypt(self, block, crypt_type):
    method crypt (line 564) | def crypt(self, data, crypt_type):
    method encrypt (line 642) | def encrypt(self, data, pad=None, padmode=None):
    method decrypt (line 661) | def decrypt(self, data, pad=None, padmode=None):
  class triple_des (line 687) | class triple_des(_baseDes):
    method __init__ (line 708) | def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
    method setKey (line 712) | def setKey(self, key):
    method setMode (line 739) | def setMode(self, mode):
    method setPadding (line 745) | def setPadding(self, pad):
    method setPadMode (line 751) | def setPadMode(self, mode):
    method setIV (line 757) | def setIV(self, IV):
    method encrypt (line 763) | def encrypt(self, data, pad=None, padmode=None):
    method decrypt (line 807) | def decrypt(self, data, pad=None, padmode=None):

FILE: universe/vncdriver/vnc_client.py
  class UnknownEncoding (line 26) | class UnknownEncoding(Exception):
  function peer_address (line 29) | def peer_address(peer):
  class Framebuffer (line 32) | class Framebuffer(object):
    method __init__ (line 33) | def __init__(self, width, height, server_pixel_format, name):
    method apply_format (line 43) | def apply_format(self, server_pixel_format):
  class VNCClient (line 68) | class VNCClient(protocol.Protocol, object):
    method __init__ (line 69) | def __init__(self):
    method connectionLost (line 93) | def connectionLost(self, reason):
    method sendMessage (line 98) | def sendMessage(self, data):
    method dataReceived (line 104) | def dataReceived(self, data):
    method flush (line 114) | def flush(self):
    method handle (line 139) | def handle(self, type, block):
    method recv_ProtocolVersion_Handshake (line 148) | def recv_ProtocolVersion_Handshake(self, block):
    method recv_Security_Handshake (line 157) | def recv_Security_Handshake(self, block):
    method recv_SecurityResult_Handshake (line 168) | def recv_SecurityResult_Handshake(self, block):
    method recv_SecurityResult_Handshake_failed_length (line 180) | def recv_SecurityResult_Handshake_failed_length(self, block):
    method recv_SecurityResult_Handshake_failed_reason (line 184) | def recv_SecurityResult_Handshake_failed_reason(self, block):
    method recv_VNC_Authentication (line 187) | def recv_VNC_Authentication(self, block):
    method send_ClientInit (line 192) | def send_ClientInit(self):
    method recv_ServerInit (line 197) | def recv_ServerInit(self, block):
    method recv_ServerInit_name (line 202) | def recv_ServerInit_name(self, block, width, height, server_pixel_form...
    method recv_ServerToClient (line 221) | def recv_ServerToClient(self, block):
    method recv_FramebufferUpdate (line 239) | def recv_FramebufferUpdate(self, block):
    method _process_rectangles (line 249) | def _process_rectangles(self):
    method recv_Rectangle (line 266) | def recv_Rectangle(self, block):
    method recv_DecodePseudoCursor (line 286) | def recv_DecodePseudoCursor(self, block, x, y, width, height):
    method recv_DecodeRAW (line 292) | def recv_DecodeRAW(self, block, x, y, width, height):
    method recv_DecodeZRLE (line 299) | def recv_DecodeZRLE(self, block, x, y, width, height):
    method recv_DecodeZRLE_value (line 306) | def recv_DecodeZRLE_value(self, block, x, y, width, height):
    method recv_DecodeZlib (line 312) | def recv_DecodeZlib(self, block, x, y, width, height):
    method recv_DecodeZlib_value (line 319) | def recv_DecodeZlib_value(self, block, x, y, width, height):
    method recv_SetColorMapEntries (line 325) | def recv_SetColorMapEntries(self, block):
    method _handle_SetColorMapEntries (line 331) | def _handle_SetColorMapEntries(self, first_color, number_of_colors, co...
    method recv_SetColorMapEntries_color (line 338) | def recv_SetColorMapEntries_color(self, block, first_color, number_of_...
    method recv_ServerCutText (line 345) | def recv_ServerCutText(self, block):
    method recv_ServerCutText_value (line 350) | def recv_ServerCutText_value(self, block):
    method send_SetEncodings (line 355) | def send_SetEncodings(self, encodings):
    method send_PixelFormat (line 360) | def send_PixelFormat(self, bpp=32, depth=24, bigendian=0, truecolor=1,...
    method send_FramebufferUpdateRequest (line 370) | def send_FramebufferUpdateRequest(self, x=0, y=0, width=None, height=N...
    method send_KeyEvent (line 382) | def send_KeyEvent(self, key, down):
    method send_PointerEvent (line 389) | def send_PointerEvent(self, x, y, buttonmask=0):
    method send_ClientCutText (line 398) | def send_ClientCutText(self, message):
    method expect (line 404) | def expect(self, type, length, *args, **kwargs):
    method close (line 413) | def close(self):
    method _error (line 418) | def _error(self, e):
  function client_factory (line 427) | def client_factory(deferred, error_buffer):

FILE: universe/vncdriver/vnc_proxy_server.py
  class LogManager (line 15) | class LogManager(object):
    method __init__ (line 16) | def __init__(self, base_logfile_dir, recorder_id, id):
    method global_rewards_logfile (line 30) | def global_rewards_logfile(self):
    method global_botaction_logfile (line 38) | def global_botaction_logfile(self):
    method global_env_id_file (line 47) | def global_env_id_file(self):
    method server_logfile (line 55) | def server_logfile(self):
    method client_logfile (line 59) | def client_logfile(self):
    method close (line 62) | def close(self):
  class VNCProxyServer (line 92) | class VNCProxyServer(protocol.Protocol, object):
    method next_id (line 122) | def next_id(cls):
    method __init__ (line 127) | def __init__(self, action_queue=None, error_buffer=None, enable_loggin...
    method start_logging (line 150) | def start_logging(self):
    method connectionMade (line 160) | def connectionMade(self):
    method connectionLost (line 185) | def connectionLost(self, reason):
    method dataReceived (line 190) | def dataReceived(self, data):
    method sendData (line 198) | def sendData(self, data):
    method flush (line 205) | def flush(self):
    method handle (line 219) | def handle(self, type, block):
    method send_ProtocolVersion_Handshake (line 226) | def send_ProtocolVersion_Handshake(self):
    method recv_ProtocolVersion_Handshake (line 229) | def recv_ProtocolVersion_Handshake(self, block):
    method send_SecurityTypes (line 243) | def send_SecurityTypes(self):
    method recv_SecurityTypesResponse (line 247) | def recv_SecurityTypesResponse(self, block):
    method send_VNC_Authentication (line 252) | def send_VNC_Authentication(self):
    method recv_VNC_Authentication_response (line 260) | def recv_VNC_Authentication_response(self, block):
    method send_SecurityResult_Handshake_success (line 269) | def send_SecurityResult_Handshake_success(self):
    method send_SecurityResult_Handshake_failed (line 274) | def send_SecurityResult_Handshake_failed(self, reason):
    method recv_ClientInit (line 280) | def recv_ClientInit(self, block):
    method recv_ClientToServer (line 302) | def recv_ClientToServer(self, block):
    method recv_SetPixelFormat (line 325) | def recv_SetPixelFormat(self, block):
    method recv_SetEncodings (line 336) | def recv_SetEncodings(self, block):
    method _handle_SetEncodings (line 343) | def _handle_SetEncodings(self, number_of_encodings, encodings):
    method recv_SetEncodings_encoding_type (line 367) | def recv_SetEncodings_encoding_type(self, block, number_of_encodings, ...
    method recv_FramebufferUpdateRequest (line 375) | def recv_FramebufferUpdateRequest(self, block):
    method recv_KeyEvent (line 381) | def recv_KeyEvent(self, block):
    method recv_PointerEvent (line 389) | def recv_PointerEvent(self, block):
    method recv_ClientCutText (line 397) | def recv_ClientCutText(self, block):
    method recv_ClientCutText_value (line 403) | def recv_ClientCutText_value(self, block):
    method expect (line 408) | def expect(self, type, length, *args, **kwargs):
    method proxyData (line 414) | def proxyData(self, data):
    method recvProxyData (line 418) | def recvProxyData(self, data):
    method close (line 425) | def close(self):
    method _error (line 435) | def _error(self, e):
  class VNCProxyClient (line 442) | class VNCProxyClient(protocol.Protocol, object):
    method __init__ (line 443) | def __init__(self):
    method start_logging (line 459) | def start_logging(self):
    method connectionMade (line 466) | def connectionMade(self):
    method connectionLost (line 471) | def connectionLost(self, reason):
    method proxyData (line 476) | def proxyData(self, data):
    method recvProxyData (line 481) | def recvProxyData(self, data):
    method sendData (line 485) | def sendData(self, data):
    method dataReceived (line 494) | def dataReceived(self, data):
    method flush (line 507) | def flush(self):
    method handle (line 525) | def handle(self, type, block):
    method recv_ProtocolVersion_Handshake (line 532) | def recv_ProtocolVersion_Handshake(self, block):
    method recv_Security_Handshake (line 541) | def recv_Security_Handshake(self, block):
    method recv_VNC_Authentication (line 552) | def recv_VNC_Authentication(self, block):
    method recv_SecurityResult_Handshake (line 557) | def recv_SecurityResult_Handshake(self, block):
    method recv_SecurityResult_Handshake_failed_length (line 569) | def recv_SecurityResult_Handshake_failed_length(self, block):
    method recv_SecurityResult_Handshake_failed_reason (line 573) | def recv_SecurityResult_Handshake_failed_reason(self, block):
    method send_ClientInit (line 576) | def send_ClientInit(self):
    method expect (line 596) | def expect(self, type, length, *args, **kwargs):
    method close (line 606) | def close(self):
    method _error (line 614) | def _error(self, e):
    method send_SetEncodings (line 619) | def send_SetEncodings(self, encodings):

FILE: universe/vncdriver/vnc_session.py
  class VNCSession (line 11) | class VNCSession(object):
    method __init__ (line 12) | def __init__(self, remotes, error_buffer):
    method connect (line 18) | def connect(self):
    method _connect (line 21) | def _connect(self):
    method flip (line 52) | def flip(self):
    method peek (line 69) | def peek(self):
    method step (line 73) | def step(self, action):
    method _step (line 77) | def _step(self, action):
    method render (line 92) | def render(self):
    method close (line 98) | def close(self):
    method _close (line 101) | def _close(self):

FILE: universe/wrappers/__init__.py
  function wrap (line 21) | def wrap(env):
  function WrappedVNCEnv (line 24) | def WrappedVNCEnv():
  function WrappedGymCoreEnv (line 27) | def WrappedGymCoreEnv(gym_core_id, fps=None, rewarder_observation=False):
  function WrappedGymCoreSyncEnv (line 35) | def WrappedGymCoreSyncEnv(gym_core_id, fps=60, rewarder_observation=False):
  function WrappedFlashgamesEnv (line 45) | def WrappedFlashgamesEnv():
  function WrappedInternetEnv (line 49) | def WrappedInternetEnv(*args, **kwargs):
  function WrappedStarCraftEnv (line 52) | def WrappedStarCraftEnv(*args, **kwargs):
  function WrappedGTAVEnv (line 55) | def WrappedGTAVEnv(*args, **kwargs):
  function WrappedWorldOfGooEnv (line 58) | def WrappedWorldOfGooEnv(*args, **kwargs):

FILE: universe/wrappers/action_space.py
  class SoftmaxClickMouse (line 1) | class SoftmaxClickMouse():
    method init (line 2) | def init(self):
  class SafeActionSpace (line 6) | class SafeActionSpace():
    method init (line 7) | def init(self):

FILE: universe/wrappers/blocking_reset.py
  class BlockingReset (line 3) | class BlockingReset(vectorized.Wrapper):
    method __init__ (line 9) | def __init__(self, *args, **kwargs):
    method _reset (line 15) | def _reset(self):
    method _step (line 36) | def _step(self, action_n):

FILE: universe/wrappers/diagnostics.py
  class Diagnostics (line 8) | class Diagnostics(vectorized.Wrapper):
    method _step (line 10) | def _step(self, action_n):

FILE: universe/wrappers/experimental/action_space.py
  function slither_vnc (line 11) | def slither_vnc(space=False, left=False, right=False):
  function racing_vnc (line 16) | def racing_vnc(up=False, left=False, right=False):
  function platform_vnc (line 21) | def platform_vnc(up=False, left=False, right=False, space=False):
  class SafeActionSpace (line 28) | class SafeActionSpace(vectorized.Wrapper):
    method __init__ (line 38) | def __init__(self, env):
  class SoftmaxClickMouse (line 65) | class SoftmaxClickMouse(vectorized.ActionWrapper):
    method __init__ (line 72) | def __init__(self, env, active_region=(10, 75 + 50, 10 + 160, 75 + 210...
    method _action (line 94) | def _action(self, action_n):
    method _discrete_to_action (line 97) | def _discrete_to_action(self, i):
    method _reverse_action (line 105) | def _reverse_action(self, action):
    method _action_to_discrete (line 121) | def _action_to_discrete(self, event):
    method is_contained (line 135) | def is_contained(cls, point, coords):

FILE: universe/wrappers/experimental/observation.py
  function CropObservations (line 9) | def CropObservations(env):
  class _CropObservations (line 23) | class _CropObservations(vectorized.ObservationWrapper):
    method __init__ (line 24) | def __init__(self, env, height, width, x=0, y=0):
    method _observation (line 34) | def _observation(self, observation_n):
    method _crop_frame (line 37) | def _crop_frame(self, frame):

FILE: universe/wrappers/experimental/random_env.py
  class RandomEnv (line 6) | class RandomEnv(vectorized.Wrapper):
    method __init__ (line 13) | def __init__(self, env, env_ids):
    method configure (line 17) | def configure(self, **kwargs):
    method _reset (line 20) | def _reset(self):
    method _step (line 24) | def _step(self, action_n):

FILE: universe/wrappers/gym_core.py
  function atari_vnc (line 16) | def atari_vnc(up=False, down=False, left=False, right=False, z=False):
  function gym_core_action_space (line 23) | def gym_core_action_space(gym_core_id):
  class CropAtari (line 45) | class CropAtari(vectorized.ObservationWrapper):
    method __init__ (line 50) | def __init__(self, env):
    method _observation (line 54) | def _observation(self, observation_n):
  function one_hot (line 57) | def one_hot(indices, depth):
  class GymCoreAction (line 60) | class GymCoreAction(vectorized.ActionWrapper):
    method __init__ (line 61) | def __init__(self, env, gym_core_id=None):
    method _action (line 81) | def _action(self, action_n):
    method _reverse_action (line 86) | def _reverse_action(self, action_n):
  class GymCoreObservation (line 91) | class GymCoreObservation(vectorized.Wrapper):
    method __init__ (line 92) | def __init__(self, env, gym_core_id=None):
    method _reset (line 107) | def _reset(self):
    method _step (line 119) | def _step(self, action_n):
    method _observation (line 129) | def _observation(self, done_n, info):

FILE: universe/wrappers/gym_core_sync.py
  class GymCoreSync (line 7) | class GymCoreSync(vectorized.Wrapper):
    method __init__ (line 16) | def __init__(self, env):
    method _reset (line 25) | def _reset(self):
    method _step (line 36) | def _step(self, action_n):
    method _flip_past (line 71) | def _flip_past(self, observation_n, reward_n, done_n, info):

FILE: universe/wrappers/joint.py
  class Joint (line 4) | class Joint(vectorized.Wrapper):
    method __init__ (line 5) | def __init__(self, env_m):
    method n (line 20) | def n(self):
    method _close (line 23) | def _close(self):
    method _render (line 27) | def _render(self, mode='human', close=False):
    method _reset (line 30) | def _reset(self):
    method _step (line 43) | def _step(self, action_n):

FILE: universe/wrappers/logger.py
  function stats (line 14) | def stats(count):
  class Logger (line 25) | class Logger(vectorized.Wrapper):
    method __init__ (line 29) | def __init__(self, env, print_frequency=5):
    method configure (line 37) | def configure(self, **kwargs):
    method _clear_step_state (line 41) | def _clear_step_state(self):
    method _step (line 61) | def _step(self, action_n):

FILE: universe/wrappers/monitoring.py
  class _UniverseMonitor (line 9) | class _UniverseMonitor(core.Wrapper):
    method __init__ (line 10) | def __init__(self, env, directory, video_callable=None, force=False,
    method _start_monitor (line 24) | def _start_monitor(self):
    method _step (line 60) | def _step(self, action_n):
    method _reset (line 66) | def _reset(self):
    method _close (line 72) | def _close(self):
    method set_monitor_mode (line 76) | def set_monitor_mode(self, mode):
  function Monitor (line 80) | def Monitor(env, directory, video_callable=None, force=False, resume=False,

FILE: universe/wrappers/multiprocessing_env.py
  function WrappedMultiprocessingEnv (line 8) | def WrappedMultiprocessingEnv(env_id):
  class RemoveNones (line 11) | class RemoveNones(vectorized.Wrapper):
    method __init__ (line 18) | def __init__(self, env):
    method _reset (line 22) | def _reset(self):
    method _step (line 27) | def _step(self, action_n):
  class EpisodeID (line 32) | class EpisodeID(vectorized.Wrapper):
    method configure (line 40) | def configure(self, episode_limit=None, **kwargs):
    method _clear_state (line 45) | def _clear_state(self):
    method _set_done_to (line 50) | def _set_done_to(self):
    method _reset (line 59) | def _reset(self):
    method _step (line 63) | def _step(self, action_n):

FILE: universe/wrappers/recording.py
  class Recording (line 15) | class Recording(vectorized.Wrapper):
    method __init__ (line 33) | def __init__(self, env, recording_dir=None, recording_policy=None, rec...
    method _get_episode_id (line 72) | def _get_episode_id(self):
    method _get_writer (line 77) | def _get_writer(self, i):
    method _reset (line 90) | def _reset(self):
    method _step (line 108) | def _step(self, action_n):
    method _close (line 134) | def _close(self):
  class RecordingWriter (line 142) | class RecordingWriter(object):
    method __init__ (line 146) | def __init__(self, recording_dir, instance_id, channel_id, async_write...
    method close (line 159) | def close(self):
    method close_files (line 162) | def close_files(self):
    method json_encode (line 170) | def json_encode(self, obj):
    method writer_main (line 192) | def writer_main(self):
    method __call__ (line 200) | def __call__(self, **kwargs):
    method write_item (line 204) | def write_item(self, item):
  class RecordingAnnotator (line 210) | class RecordingAnnotator(object):
    method __init__ (line 211) | def __init__(self, writer, episode_id, step_id):
    method __call__ (line 215) | def __call__(self, **kwargs):

FILE: universe/wrappers/render.py
  class Render (line 8) | class Render(vectorized.Wrapper):
    method __init__ (line 12) | def __init__(self, *args, **kwargs):
    method configure (line 20) | def configure(self, **kwargs):
    method _reset (line 27) | def _reset(self):
    method _step (line 32) | def _step(self, action_n):
    method _render (line 37) | def _render(self, mode='human', *args, **kwargs):

FILE: universe/wrappers/tests/test_joint.py
  function test_joint (line 5) | def test_joint():

FILE: universe/wrappers/tests/test_time_limit.py
  function test_steps_limit_restart (line 26) | def test_steps_limit_restart():
  function test_steps_limit_restart_unused_when_not_wrapped (line 45) | def test_steps_limit_restart_unused_when_not_wrapped():
  function test_seconds_limit_restart (line 55) | def test_seconds_limit_restart():
  function test_default_time_limit (line 79) | def test_default_time_limit():

FILE: universe/wrappers/throttle.py
  class Throttle (line 7) | class Throttle(vectorized.Wrapper):
    method __init__ (line 21) | def __init__(self, env):
    method configure (line 26) | def configure(self, skip_metadata=False, fps='default', **kwargs):
    method _reset (line 35) | def _reset(self):
    method _step (line 46) | def _step(self, action_n):
    method _substep (line 128) | def _substep(self, action_n):
    method _start_timer (line 142) | def _start_timer(self):

FILE: universe/wrappers/time_limit.py
  class UniverseTimeLimit (line 11) | class UniverseTimeLimit(core.Wrapper):
    method __init__ (line 12) | def __init__(self, env):
    method _elapsed_seconds (line 24) | def _elapsed_seconds(self):
    method _past_limit (line 27) | def _past_limit(self):
    method _step (line 39) | def _step(self, action_n):
    method _reset (line 50) | def _reset(self):

FILE: universe/wrappers/timer.py
  class Timer (line 7) | class Timer(vectorized.Wrapper):
    method configure (line 13) | def configure(self, **kwargs):
    method _reset (line 16) | def _reset(self):
    method _step (line 20) | def _step(self, action_n):

FILE: universe/wrappers/vectorize.py
  class Vectorize (line 7) | class Vectorize(gym.Wrapper):
    method __init__ (line 16) | def __init__(self, env):
    method _reset (line 22) | def _reset(self):
    method _step (line 26) | def _step(self, action):
    method _seed (line 30) | def _seed(self, seed):
  class Unvectorize (line 33) | class Unvectorize(core.Wrapper):
    method _reset (line 40) | def _reset(self):
    method _step (line 45) | def _step(self, action):
    method _seed (line 50) | def _seed(self, seed):
  class WeakUnvectorize (line 53) | class WeakUnvectorize(Unvectorize):
    method __init__ (line 54) | def __init__(self, env, i):
    method _check_for_duplicate_wrappers (line 60) | def _check_for_duplicate_wrappers(self):
    method env (line 64) | def env(self):
    method env (line 75) | def env(self, value):
    method _seed (line 79) | def _seed(self, seed):
    method close (line 83) | def close(self):

FILE: universe/wrappers/vision.py
  class Vision (line 6) | class Vision(vectorized.Wrapper):
    method _reset (line 16) | def _reset(self):
    method _step (line 20) | def _step(self, action_n):
Condensed preview — 136 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,280K chars).
[
  {
    "path": ".dockerignore",
    "chars": 26,
    "preview": "vncdriver/logs\n.git\n*.pyc\n"
  },
  {
    "path": ".gitignore",
    "chars": 134,
    "preview": ".DS_Store\n.ropeproject\n*.pyc\ntags\n*.swo\n*.swp\n*.sqlite\nupload/\nvenv\ndist\n*.egg-info\n.idea\n/logs\n/dist\nbuild/\n/.gitfiles\n"
  },
  {
    "path": ".travis.yml",
    "chars": 1852,
    "preview": "language: python\npython:\n  - \"3.5\"\nservices:\n  - docker\nbefore_install:\n  - docker build -f test.dockerfile -t quay.io/o"
  },
  {
    "path": "CODE_OF_CONDUCT.rst",
    "chars": 639,
    "preview": "OpenAI is dedicated to providing a harassment-free experience for\neveryone, regardless of gender, gender identity and ex"
  },
  {
    "path": "Dockerfile",
    "chars": 1111,
    "preview": "FROM ubuntu:16.04\n\nRUN apt-get update \\\n    && apt-get install -y libav-tools \\\n    python3-numpy \\\n    python3-scipy \\\n"
  },
  {
    "path": "ISSUE_TEMPLATE",
    "chars": 323,
    "preview": "\n(First, please check https://github.com/openai/universe/wiki/Solutions-to-common-problems for solutions to many common "
  },
  {
    "path": "LICENSE",
    "chars": 1087,
    "preview": "The MIT License\n\nCopyright (c) 2016 OpenAI (http://openai.com)\n\nPermission is hereby granted, free of charge, to any per"
  },
  {
    "path": "Makefile",
    "chars": 828,
    "preview": "upload:\n\trm -rf dist\n\tpython setup.py sdist\n\ttwine upload dist/*\n\ntest:\n\tfind . -name '*.pyc' -delete\n\tdocker build -f t"
  },
  {
    "path": "README.rst",
    "chars": 18830,
    "preview": "**This repository has been deprecated in favor of the Retro (https://github.com/openai/retro) library. See our Retro Con"
  },
  {
    "path": "doc/env_semantics.rst",
    "chars": 3582,
    "preview": "Environment semantics\n*********************\n  \nReal-time environments\n======================\n\nUniverse environments diff"
  },
  {
    "path": "doc/protocols.rst",
    "chars": 6694,
    "preview": "Universe internal communication protocols\n*****************************************\n\nNetwork architecture\n=============="
  },
  {
    "path": "doc/remotes.rst",
    "chars": 10710,
    "preview": "Remotes\n*******\n\nSince the remote part of the environment runs in its own server\nprocess, managing remotes is an importa"
  },
  {
    "path": "example/diagnostic-agent/diagnostic-agent.py",
    "chars": 8851,
    "preview": "#!/usr/bin/env python\nimport argparse\nimport logging\nimport time\n\nimport gym\nimport numpy as np\nimport universe\nfrom uni"
  },
  {
    "path": "example/random-agent/random-agent.py",
    "chars": 1266,
    "preview": "#!/usr/bin/env python\nimport argparse\nimport logging\nimport sys\n\nimport gym\nimport universe # register the universe envi"
  },
  {
    "path": "example/recorders/botaction_recorder.py",
    "chars": 3649,
    "preview": "#!/usr/bin/env python\n\"\"\"\n  This is a small server that accepts connections on a websocket port and writes it to a file."
  },
  {
    "path": "example/recorders/reward_recorder.py",
    "chars": 1481,
    "preview": "#!/usr/bin/env python\nimport argparse\nimport logging\nimport sys\n\nfrom autobahn.twisted import websocket\nfrom universe.re"
  },
  {
    "path": "example/recorders/vnc_recorder.py",
    "chars": 1436,
    "preview": "#!/usr/bin/env python\nimport argparse\nimport logging\nimport os\nimport re\nimport sys\n\nfrom universe import utils\nfrom uni"
  },
  {
    "path": "example/starter-cluster/starter-cluster",
    "chars": 9174,
    "preview": "#!/usr/bin/env python\nfrom contextlib import contextmanager\nimport logging\nimport math\nimport os\nimport os.path\nimport s"
  },
  {
    "path": "example/starter-cluster/starter-cluster-cf.json",
    "chars": 37604,
    "preview": "{\n    \"AWSTemplateFormatVersion\": \"2010-09-09\",\n    \"Description\": \"Docker cluster for OpenAI Universe runtimes\",\n    \"M"
  },
  {
    "path": "example/starter-cluster/starter-cluster-requirements.txt",
    "chars": 93,
    "preview": "boto3>=1.4.2\nclick>=6.6\ndocker-py==1.10.6\nPyYAML>=3.12\nuniverse>=0.1.0\ndocker-compose>=1.9.0\n"
  },
  {
    "path": "example/system-diagnostics/system_diagnostics_logger.py",
    "chars": 2167,
    "preview": "#!/usr/bin/env python\n\nimport json\nimport psutil\nimport time\n\nclass DiagnosticsLogger(object):\n    def __init__(self, in"
  },
  {
    "path": "setup.py",
    "chars": 1025,
    "preview": "from setuptools import setup, find_packages\n\nsetup(name='universe',\n      version='0.21.5',\n      description=\"Universe:"
  },
  {
    "path": "test.dockerfile",
    "chars": 242,
    "preview": "FROM quay.io/openai/universe\n\nRUN pip install tox\n\n# Upload our actual code\nWORKDIR /usr/local/universe/\nCOPY . ./\n\n# Ru"
  },
  {
    "path": "tests/functional/test_core_envs_semantics.py",
    "chars": 3959,
    "preview": "import logging\nimport pytest\n\nimport gym\nimport numpy as np\nfrom PIL import Image\nfrom gym import spaces\nfrom universe i"
  },
  {
    "path": "tests/functional/test_envs.py",
    "chars": 3030,
    "preview": "import logging\nimport os\nimport pytest\nimport re\n\nimport gym\nfrom universe import wrappers\nfrom universe.runtimes import"
  },
  {
    "path": "tox.ini",
    "chars": 575,
    "preview": "# Tox (http://tox.testrun.org/) is a tool for running tests\n# in multiple virtualenvs. This configuration file will run "
  },
  {
    "path": "universe/__init__.py",
    "chars": 56983,
    "preview": "# Welcome to Universe!\n#\n# This file contains the client-side registry of environments.\n\nimport logging\nimport os\n\n# Sup"
  },
  {
    "path": "universe/configuration.py",
    "chars": 378,
    "preview": "import logging\nfrom gym import configuration\n\nuniverse_logger = logging.getLogger('universe')\nuniverse_logger.setLevel(l"
  },
  {
    "path": "universe/envs/__init__.py",
    "chars": 438,
    "preview": "import universe.envs.vnc_env\nfrom universe.envs.vnc_env import VNCEnv\nfrom universe.envs.vnc_core_env import GymCoreEnv,"
  },
  {
    "path": "universe/envs/diagnostics.py",
    "chars": 24197,
    "preview": "import collections\nimport fastzbarlight\nimport itertools\nimport logging\nfrom multiprocessing import pool\nimport numpy as"
  },
  {
    "path": "universe/envs/dummy_vnc_env.py",
    "chars": 2673,
    "preview": "import logging\nimport numpy as np\n\nfrom gym.utils import reraise\n\nfrom universe import error, rewarder, spaces, utils, v"
  },
  {
    "path": "universe/envs/tests/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "universe/envs/tests/test_semantics.py",
    "chars": 13920,
    "preview": "# import numpy as np\n# from universe import vectorized\n\n# class SimpleEnv(vectorized.Env):\n#     def _step(self, action_"
  },
  {
    "path": "universe/envs/vnc_core_env/__init__.py",
    "chars": 165,
    "preview": "from universe.envs.vnc_core_env.vnc_core_env import GymCoreEnv, GymCoreSyncEnv\nfrom universe.envs.vnc_core_env.translato"
  },
  {
    "path": "universe/envs/vnc_core_env/key.py",
    "chars": 10765,
    "preview": "# imported from Pyglet\n\n# ----------------------------------------------------------------------------\n# pyglet\n# Copyri"
  },
  {
    "path": "universe/envs/vnc_core_env/translator.py",
    "chars": 4025,
    "preview": "from universe import spaces\nfrom universe.envs.vnc_core_env import key\nimport logging\n\nlogger = logging.getLogger(__name"
  },
  {
    "path": "universe/envs/vnc_core_env/vnc_core_env.py",
    "chars": 4798,
    "preview": "import logging\nimport time\n\nimport gym\nfrom universe import spaces\nfrom universe.envs import vnc_env\n\nlogger = logging.g"
  },
  {
    "path": "universe/envs/vnc_env.py",
    "chars": 26783,
    "preview": "import getpass\nimport logging\nimport os\nimport random\nimport uuid\n\nimport universe\nfrom gym.utils import reraise\nfrom un"
  },
  {
    "path": "universe/envs/vnc_flashgames.py",
    "chars": 188,
    "preview": "from universe.envs import vnc_env\n\nclass FlashgamesEnv(vnc_env.VNCEnv):\n     def __init__(self):\n        super(Flashgame"
  },
  {
    "path": "universe/envs/vnc_gtav.py",
    "chars": 372,
    "preview": "from universe.envs import vnc_env\nfrom universe.spaces.joystick_action_space import JoystickActionSpace\n\n\nclass GTAVEnv("
  },
  {
    "path": "universe/envs/vnc_internet.py",
    "chars": 184,
    "preview": "from universe.envs import vnc_env\n\nclass InternetEnv(vnc_env.VNCEnv):\n     def __init__(self):\n        super(InternetEnv"
  },
  {
    "path": "universe/envs/vnc_starcraft.py",
    "chars": 2410,
    "preview": "import string\n\nfrom universe import spaces\nfrom universe.spaces import vnc_event, VNCActionSpace\nfrom universe.spaces.vn"
  },
  {
    "path": "universe/envs/vnc_wog.py",
    "chars": 389,
    "preview": "from universe.envs import vnc_env\nfrom universe.spaces import VNCActionSpace\n\n\nclass WorldOfGooEnv(vnc_env.VNCEnv):\n    "
  },
  {
    "path": "universe/error.py",
    "chars": 199,
    "preview": "import sys\n\nclass Error(Exception):\n    pass\n\nclass RPCError(Error):\n    pass\n\nclass ConnectionError(Error):\n    pass\n\nc"
  },
  {
    "path": "universe/kube/__init__.py",
    "chars": 63,
    "preview": "from universe.kube.discovery import discover, discover_batches\n"
  },
  {
    "path": "universe/kube/discovery.py",
    "chars": 4135,
    "preview": "import json\nimport logging\nimport pipes\nimport subprocess\n\nclass Error(Exception):\n    pass\n\nlogger = logging.getLogger("
  },
  {
    "path": "universe/pyprofile/__init__.py",
    "chars": 12138,
    "preview": "# A simple in-memory stats library\n#\n# Inspired by statsd: http://statsd.readthedocs.io/en/v3.1/types.html#gauges\nimport"
  },
  {
    "path": "universe/remotes/__init__.py",
    "chars": 229,
    "preview": "from universe.remotes.hardcoded_addresses import HardcodedAddresses\nfrom universe.remotes.allocator_remote import Alloca"
  },
  {
    "path": "universe/remotes/allocator_remote.py",
    "chars": 15830,
    "preview": "import json\nimport logging\nimport os\nimport re\nimport requests\nimport six\nimport six.moves.urllib.parse as urlparse\nimpo"
  },
  {
    "path": "universe/remotes/build.py",
    "chars": 1704,
    "preview": "import re\nfrom universe import error\nfrom universe.remotes.allocator_remote import AllocatorManager\nfrom universe.remote"
  },
  {
    "path": "universe/remotes/compose/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "universe/remotes/compose/colors.py",
    "chars": 860,
    "preview": "from __future__ import absolute_import\nfrom __future__ import unicode_literals\nNAMES = [\n    'grey',\n    'red',\n    'gre"
  },
  {
    "path": "universe/remotes/compose/container.py",
    "chars": 7935,
    "preview": "from __future__ import absolute_import\nfrom __future__ import unicode_literals\n\nfrom functools import reduce\n\nimport six"
  },
  {
    "path": "universe/remotes/compose/log_printer.py",
    "chars": 6934,
    "preview": "# Forked from docker-compose\nfrom __future__ import absolute_import\nfrom __future__ import unicode_literals\n\nimport sys\n"
  },
  {
    "path": "universe/remotes/compose/progress_stream.py",
    "chars": 3036,
    "preview": "from __future__ import absolute_import\nfrom __future__ import unicode_literals\n\nfrom universe.remotes.compose import uti"
  },
  {
    "path": "universe/remotes/compose/signals.py",
    "chars": 395,
    "preview": "from __future__ import absolute_import\nfrom __future__ import unicode_literals\n\nimport signal\n\n\nclass ShutdownException("
  },
  {
    "path": "universe/remotes/compose/utils.py",
    "chars": 2691,
    "preview": "from __future__ import absolute_import\nfrom __future__ import unicode_literals\n\nimport codecs\nimport hashlib\nimport json"
  },
  {
    "path": "universe/remotes/docker_remote.py",
    "chars": 15135,
    "preview": "from __future__ import absolute_import\n\nimport base64\nimport logging\nimport os\nimport pipes\nimport sys\nimport threading\n"
  },
  {
    "path": "universe/remotes/hardcoded_addresses.py",
    "chars": 5728,
    "preview": "import logging\nimport os\nimport re\nimport six.moves.urllib.parse as urlparse\n\nfrom universe import error, utils\nfrom uni"
  },
  {
    "path": "universe/remotes/healthcheck.py",
    "chars": 6212,
    "preview": "import errno\nimport logging\nimport select\nimport socket\nimport time\n\nfrom universe import error, utils\nfrom gym.utils im"
  },
  {
    "path": "universe/remotes/remote.py",
    "chars": 499,
    "preview": "class Remote(object):\n    def __init__(self, handle, vnc_address, vnc_password, rewarder_address, rewarder_password, nam"
  },
  {
    "path": "universe/rewarder/__init__.py",
    "chars": 278,
    "preview": "from universe.rewarder.rewarder_session import RewarderSession\nfrom universe.rewarder.env_status import EnvStatus, compa"
  },
  {
    "path": "universe/rewarder/connection_timer.py",
    "chars": 2645,
    "preview": "import os\nimport re\nimport signal\nimport time\n\nfrom universe import error\nfrom universe.twisty import reactor\nfrom twist"
  },
  {
    "path": "universe/rewarder/env_status.py",
    "chars": 3690,
    "preview": "import logging\nimport threading\n\nlogger = logging.getLogger()\n\ndef parse_episode_id(episode_id):\n    if episode_id is No"
  },
  {
    "path": "universe/rewarder/merge.py",
    "chars": 2846,
    "preview": "from universe import error\nimport six\n\ndef merge_infos(info1, info2):\n    \"\"\"We often need to aggregate together multipl"
  },
  {
    "path": "universe/rewarder/remote.py",
    "chars": 16970,
    "preview": "# loaded inside of the environments\n\nimport logging\nimport os\nfrom universe import pyprofile\nimport sys\nis_py2 = sys.ver"
  },
  {
    "path": "universe/rewarder/reward_buffer.py",
    "chars": 12129,
    "preview": "import logging\nimport threading\nimport time\n\nfrom universe import error\nfrom universe.rewarder import env_status, merge\n"
  },
  {
    "path": "universe/rewarder/reward_proxy_server.py",
    "chars": 8174,
    "preview": "import json\nimport logging\nimport os\nimport time\n\nfrom autobahn.twisted import websocket\nfrom universe.twisty import rea"
  },
  {
    "path": "universe/rewarder/rewarder_client.py",
    "chars": 8326,
    "preview": "import logging\nfrom universe import pyprofile\nimport time\nimport ujson\n\nfrom autobahn.twisted import websocket\nfrom twis"
  },
  {
    "path": "universe/rewarder/rewarder_session.py",
    "chars": 21847,
    "preview": "from autobahn.twisted import websocket\nimport logging\nimport numpy as np\nimport threading\nimport time\n\nfrom twisted.pyth"
  },
  {
    "path": "universe/rewarder/tests/test_reward_buffer.py",
    "chars": 3110,
    "preview": "from universe.rewarder import reward_buffer\n\ndef test_prereset():\n    buf = reward_buffer.RewardBuffer('buf')\n    buf.pu"
  },
  {
    "path": "universe/runtimes/.agignore",
    "chars": 16,
    "preview": "flashgames.json\n"
  },
  {
    "path": "universe/runtimes/__init__.py",
    "chars": 1263,
    "preview": "import os\nimport yaml\n\nfrom universe.runtimes.registration import register_runtime\n\nwith open(os.path.join(os.path.dirna"
  },
  {
    "path": "universe/runtimes/flashgames.json",
    "chars": 541169,
    "preview": "{\"flashgames.StealthboundLevelPack-v0\": {\"readme_header\": null, \"categories\": [\"Assorted\"], \"rewarder\": false, \"autostar"
  },
  {
    "path": "universe/runtimes/registration.py",
    "chars": 3863,
    "preview": "import collections\nimport json\n\nimport six\nfrom gym import error\n\n\nclass UnregisteredRuntime(error.Unregistered):\n    \"\""
  },
  {
    "path": "universe/runtimes.yml",
    "chars": 80,
    "preview": "flashgames:\n  tag: 0.20.28\ngym-core:\n  tag: 0.20.6\nworld-of-bits:\n  tag: 0.20.0\n"
  },
  {
    "path": "universe/scoreboard/__init__.py",
    "chars": 2619,
    "preview": "from gym.benchmarks import scoring\nfrom gym.benchmarks import register_benchmark\n\nregister_benchmark(\n    id='Atari7VNC-"
  },
  {
    "path": "universe/spaces/__init__.py",
    "chars": 301,
    "preview": "from universe.spaces.hardcoded import Hardcoded\nfrom universe.spaces.vnc_action_space import VNCActionSpace\nfrom univers"
  },
  {
    "path": "universe/spaces/diagnostics.py",
    "chars": 72,
    "preview": "class DiagnosticEvent(object):\n    pass\n\nPeekReward = DiagnosticEvent()\n"
  },
  {
    "path": "universe/spaces/hardcoded.py",
    "chars": 359,
    "preview": "from gym.spaces import prng\n\nclass Hardcoded(object):\n    def __init__(self, actions):\n        self.actions = actions\n\n "
  },
  {
    "path": "universe/spaces/joystick_action_space.py",
    "chars": 2585,
    "preview": "import gym\nfrom gym.spaces import Box\nfrom universe.spaces import joystick_event\nfrom gym.spaces import prng\nfrom collec"
  },
  {
    "path": "universe/spaces/joystick_event.py",
    "chars": 1000,
    "preview": "class JoystickEvent(object):\n    pass\n\n\nclass JoystickAxisEvent(JoystickEvent):\n    def __init__(self, amount):\n        "
  },
  {
    "path": "universe/spaces/vnc_action_space.py",
    "chars": 3088,
    "preview": "import gym\nimport string\n\nfrom gym.spaces import prng\n\nfrom universe.vncdriver import constants\nfrom universe.spaces imp"
  },
  {
    "path": "universe/spaces/vnc_event.py",
    "chars": 2568,
    "preview": "import string\nfrom universe import error\nfrom universe.vncdriver import constants\n\nclass VNCEvent(object):\n    pass\n\ndef"
  },
  {
    "path": "universe/spaces/vnc_observation_space.py",
    "chars": 212,
    "preview": "import gym\n\nclass VNCObservationSpace(gym.Space):\n    # For now, we leave the VNC ObservationSpace wide open, since\n    "
  },
  {
    "path": "universe/twisty.py",
    "chars": 1528,
    "preview": "import threading\nfrom twisted.python.runtime import platform\n\n# On OSX, we should use kqueue rather than the default sel"
  },
  {
    "path": "universe/utils/__init__.py",
    "chars": 6378,
    "preview": "import logging\nimport six\nimport sys\nif six.PY2:\n    import Queue as queue\nelse:\n    import queue\nimport threading\nimpor"
  },
  {
    "path": "universe/utils/display.py",
    "chars": 3795,
    "preview": "# -*- coding: utf-8 -*-\nimport logging\n\nimport six\nimport numpy as np\n\nlogger = logging.getLogger(__name__)\n\n# We log th"
  },
  {
    "path": "universe/vectorized/__init__.py",
    "chars": 244,
    "preview": "from universe.vectorized.core import Env, Wrapper, ObservationWrapper, ActionWrapper, RewardWrapper\nfrom universe.vector"
  },
  {
    "path": "universe/vectorized/core.py",
    "chars": 1687,
    "preview": "import gym\nfrom gym import spaces\nfrom universe import error\n\nclass Env(gym.Env):\n    \"\"\"Base class capable of handling "
  },
  {
    "path": "universe/vectorized/multiprocessing_env.py",
    "chars": 9422,
    "preview": "import logging\nimport multiprocessing\nimport numpy as np\nimport traceback\n\nimport gym\nfrom gym import spaces\nfrom univer"
  },
  {
    "path": "universe/vectorized/tests/test_monitoring.py",
    "chars": 1231,
    "preview": "import glob\nimport os\n\nimport gym.monitoring\nfrom gym.monitoring.tests import helpers\nfrom universe import wrappers\n\ndef"
  },
  {
    "path": "universe/vectorized/vectorize_filter.py",
    "chars": 1736,
    "preview": "from universe.vectorized import core\n\nclass Filter(object):\n    def _after_reset(self, observation):\n        return obse"
  },
  {
    "path": "universe/vncdriver/README.md",
    "chars": 265,
    "preview": "# Python VNC driver implementation\n\nThis Python VNC driver is using an older API, and needs a small amount\nof work to on"
  },
  {
    "path": "universe/vncdriver/__init__.py",
    "chars": 259,
    "preview": "import logging\n\nfrom universe.vncdriver.vnc_session import VNCSession\nfrom universe.vncdriver.vnc_client import client_f"
  },
  {
    "path": "universe/vncdriver/auth.py",
    "chars": 1097,
    "preview": "import six\nimport uuid\n\nfrom universe import utils\nfrom universe.vncdriver.vendor import pydes\n\nclass RFBDes(pydes.des):"
  },
  {
    "path": "universe/vncdriver/constants.py",
    "chars": 3867,
    "preview": "# Encodings\nRAW_ENCODING =                  0\nCOPY_RECTANGLE_ENCODING =       1\nRRE_ENCODING =                  2\nCORRE_"
  },
  {
    "path": "universe/vncdriver/dual_proxy_server.py",
    "chars": 2271,
    "preview": "# a proxy server that handles both reward channel and vnc.\nfrom twisted.python import log\nfrom autobahn.twisted import w"
  },
  {
    "path": "universe/vncdriver/error.py",
    "chars": 33,
    "preview": "class Error(Exception):\n    pass\n"
  },
  {
    "path": "universe/vncdriver/fbs_reader.py",
    "chars": 1882,
    "preview": "import json\nimport os\nimport struct\n\nfrom universe import error\n\nclass InvalidFBSFileError(error.Error):\n    pass\n\nclass"
  },
  {
    "path": "universe/vncdriver/fbs_writer.py",
    "chars": 1739,
    "preview": "import json\nimport struct\nimport time\n\nfrom gym.utils import atomic_write, closer\n\nfbs_closer = closer.Closer()\n\nclass F"
  },
  {
    "path": "universe/vncdriver/libvnc_session.py",
    "chars": 4042,
    "preview": "import logging\nimport os\n\nfrom twisted.internet import defer, endpoints\n\nfrom universe import error, utils\nfrom universe"
  },
  {
    "path": "universe/vncdriver/screen/__init__.py",
    "chars": 243,
    "preview": "from universe.vncdriver.screen.base import Screen\nfrom universe.vncdriver.screen.numpy_screen import NumpyScreen\nfrom un"
  },
  {
    "path": "universe/vncdriver/screen/base.py",
    "chars": 97,
    "preview": "import logging\nimport time\n\nlogger = logging.getLogger(__name__)\n\nclass Screen(object):\n    pass\n"
  },
  {
    "path": "universe/vncdriver/screen/numpy_screen.py",
    "chars": 7244,
    "preview": "import logging\nimport numpy as np\nfrom universe import pyprofile\nimport threading\nimport time\n\nfrom universe import erro"
  },
  {
    "path": "universe/vncdriver/screen/pyglet_screen.py",
    "chars": 3296,
    "preview": "import logging\nimport numpy as np\nimport os\nfrom universe import pyprofile\nimport sys\n\nfrom universe import error\nfrom u"
  },
  {
    "path": "universe/vncdriver/screen/screen_buffer.py",
    "chars": 1853,
    "preview": "import logging\nimport time\nimport threading\n\nfrom universe.vncdriver.screen import numpy_screen\n\nlogger = logging.getLog"
  },
  {
    "path": "universe/vncdriver/server_messages.py",
    "chars": 13672,
    "preview": "try:\n    # In Py2, use the more efficient cStringIO implementation if it's\n    # available\n    from cStringIO import Str"
  },
  {
    "path": "universe/vncdriver/vendor/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "universe/vncdriver/vendor/pydes.py",
    "chars": 27499,
    "preview": "#############################################################################\n# \t\t\t\tDocumentation\t\t\t\t    #\n#############"
  },
  {
    "path": "universe/vncdriver/vnc_client.py",
    "chars": 17665,
    "preview": "import collections\ntry:\n    import cStringIO as StringIO\nexcept ImportError:\n    from six import StringIO\nimport logging"
  },
  {
    "path": "universe/vncdriver/vnc_proxy_server.py",
    "chars": 22147,
    "preview": "import logging\nimport os\nimport re\nimport shutil\nimport struct\nimport time\nimport traceback\n\nfrom universe import pyprof"
  },
  {
    "path": "universe/vncdriver/vnc_session.py",
    "chars": 3569,
    "preview": "import logging\n\nfrom twisted.internet import defer, endpoints\n\nfrom universe import error, utils\nfrom universe.twisty im"
  },
  {
    "path": "universe/wrappers/__init__.py",
    "chars": 2208,
    "preview": "import gym\nimport universe.wrappers.experimental\nfrom universe import envs, spaces\nfrom universe.wrappers import gym_cor"
  },
  {
    "path": "universe/wrappers/action_space.py",
    "chars": 543,
    "preview": "class SoftmaxClickMouse():\n    def init(self):\n        raise DeprecationWarning('DEPRECATION WARNING: wrappers.SoftmaxCl"
  },
  {
    "path": "universe/wrappers/blocking_reset.py",
    "chars": 2275,
    "preview": "from universe import rewarder, spaces, vectorized\n\nclass BlockingReset(vectorized.Wrapper):\n    \"\"\"\nBy default, a reset "
  },
  {
    "path": "universe/wrappers/diagnostics.py",
    "chars": 652,
    "preview": "import logging\nimport six\nfrom universe import pyprofile, vectorized\n\nlogger = logging.getLogger(__name__)\n\n# Not used i"
  },
  {
    "path": "universe/wrappers/experimental/__init__.py",
    "chars": 227,
    "preview": "from universe.wrappers.experimental.action_space import SafeActionSpace, SoftmaxClickMouse\nfrom universe.wrappers.experi"
  },
  {
    "path": "universe/wrappers/experimental/action_space.py",
    "chars": 6525,
    "preview": "import logging\n\nimport gym\nimport numpy as np\nfrom universe import spaces\nfrom universe import vectorized\nfrom universe."
  },
  {
    "path": "universe/wrappers/experimental/observation.py",
    "chars": 1724,
    "preview": "import logging\n\nfrom universe import vectorized, runtime_spec\n\nlogger = logging.getLogger(__name__)\nlogger.setLevel(logg"
  },
  {
    "path": "universe/wrappers/experimental/random_env.py",
    "chars": 904,
    "preview": "import logging\nfrom universe import vectorized\n\nlogger = logging.getLogger(__name__)\n\nclass RandomEnv(vectorized.Wrapper"
  },
  {
    "path": "universe/wrappers/gym_core.py",
    "chars": 5828,
    "preview": "import logging\nimport gym\nimport time\nimport numpy as np\nfrom universe import error\nfrom gym import spaces as gym_spaces"
  },
  {
    "path": "universe/wrappers/gym_core_sync.py",
    "chars": 3947,
    "preview": "import gym\nimport logging\nfrom universe import rewarder, spaces, vectorized\n\nlogger = logging.getLogger(__name__)\n\nclass"
  },
  {
    "path": "universe/wrappers/joint.py",
    "chars": 2342,
    "preview": "from multiprocessing import pool\nfrom universe import error, rewarder, vectorized\n\nclass Joint(vectorized.Wrapper):\n    "
  },
  {
    "path": "universe/wrappers/logger.py",
    "chars": 9413,
    "preview": "# -*- coding: utf-8 -*-\n\nimport logging\nimport numpy as np\nimport six\nimport time\n\nfrom universe import vectorized\nfrom "
  },
  {
    "path": "universe/wrappers/monitoring.py",
    "chars": 3499,
    "preview": "import logging\n\nimport gym\nfrom universe.vectorized import core  # Cannot import vectorized directly without inducing a "
  },
  {
    "path": "universe/wrappers/multiprocessing_env.py",
    "chars": 2972,
    "preview": "import logging\nimport numpy as np\nfrom universe import vectorized\nfrom universe.wrappers import render\n\nlogger = logging"
  },
  {
    "path": "universe/wrappers/recording.py",
    "chars": 8802,
    "preview": "import logging\nimport time\nimport os\nimport json\nimport numpy as np\nimport threading\nfrom six.moves import queue\nfrom un"
  },
  {
    "path": "universe/wrappers/render.py",
    "chars": 1734,
    "preview": "import logging\nimport os\nfrom twisted.python.runtime import platform\nfrom universe import vectorized\n\nlogger = logging.g"
  },
  {
    "path": "universe/wrappers/tests/test_joint.py",
    "chars": 751,
    "preview": "import gym\nimport universe\nfrom universe import wrappers\n\ndef test_joint():\n    env1 = gym.make('test.DummyVNCEnv-v0')\n "
  },
  {
    "path": "universe/wrappers/tests/test_time_limit.py",
    "chars": 2295,
    "preview": "import gym\nimport time\nimport universe\nfrom gym.envs import register\nfrom universe import wrappers\n\nregister(\n    id='te"
  },
  {
    "path": "universe/wrappers/throttle.py",
    "chars": 6180,
    "preview": "import logging\nimport time\nfrom universe import pyprofile, rewarder, spaces, vectorized\n\nlogger = logging.getLogger(__na"
  },
  {
    "path": "universe/wrappers/time_limit.py",
    "chars": 1948,
    "preview": "import logging\n\nimport time\nfrom universe import pyprofile\nfrom universe.vectorized import core\n\nlogger = logging.getLog"
  },
  {
    "path": "universe/wrappers/timer.py",
    "chars": 931,
    "preview": "import logging\nimport time\nfrom universe import pyprofile, vectorized\n\nlogger = logging.getLogger(__name__)\n\nclass Timer"
  },
  {
    "path": "universe/wrappers/vectorize.py",
    "chars": 2638,
    "preview": "import gym\nimport weakref\n\nfrom universe import error\nfrom universe.vectorized import core\n\nclass Vectorize(gym.Wrapper)"
  },
  {
    "path": "universe/wrappers/vision.py",
    "chars": 920,
    "preview": "import logging\nfrom universe import vectorized\n\nlogger = logging.getLogger(__name__)\n\nclass Vision(vectorized.Wrapper):\n"
  }
]

About this extraction

This page contains the full source code of the openai/universe GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 136 files (1.1 MB), approximately 335.7k tokens, and a symbol index with 1141 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!