From 7ac04a49822de44fefcaf76431d3ec813915cb2c Mon Sep 17 00:00:00 2001 From: Jonas Schneider Date: Wed, 27 Apr 2016 18:09:36 -0700 Subject: [PATCH 001/310] Fix Travis and tox configs --- .travis.yml | 19 +++++++++++++++++++ tox.ini | 1 + 2 files changed, 20 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6396b1d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,19 @@ +dist: trusty +sudo: required +cache: + apt: true +language: python +addons: + apt: + packages: + - python-dev +python: + - "2.7" + - "3.5" +install: pip install tox-travis +script: tox + +notifications: + slack: + secure: h/Mxm8K+avH/2W0818zCHmLloRPMFN4NJL01+VShvAkH80/acfjeq/+mMdWXXPL/oOB6kSHDk+GDhwR6+s03ZcPMn5INTFvFYqUc6UWmT+NXtOPxGTN0xda6MdYUkWQUKaMyjFrweZQOMOASFBIzPOq4XeVbM5aB8s4EJhnfAcYZhp/idwKbToVihN4KZgxlvZIFc8iEp1o9uSl5qrsaeYYYXRkb6mauacAwOo4/Chu+cOnoLUOnvhBFE3rV3doDNrbnoalO8XiExtgx5CIAYWrlMni7r2Q+LlzgwdyTH19ZtybPxJTZIIWSBQ2UtcoYdIEDcc36GcUwz1VUGg32mLJJnY2xw80CWR4ixFPpLwwP5Y99WTn8v094B4nmFTWOwNWXp3EkqtTN9XcJoRBqXB5ArucIPqrx57dOCljSKx22gL6WaF2p3stSAxIGFektGyGnisaELrFZG1C63aHoUPicj3gUlijmAoUmYaDRf6P1wnpXqBpKDAWWhAMSatvx1ekmEJgR7OQklQnnfjx9kENDUygNUWS4IQwN2qYieuzHFL3of7/30mTM43+Vt/vWN8GI7j01BXu6FNGGloHxjH1pt3bLP/+uj5BJsT2HWF+Z8XR4VE6cyVuKsQAFgCXwOkoDHALbcwsspONDIt/9ixkesgh1oFt4CzU3UuU5wYs= + on_success: change diff --git a/tox.ini b/tox.ini index 77b0842..7330eaa 100644 --- a/tox.ini +++ b/tox.ini @@ -8,6 +8,7 @@ envlist = py27, py35 [testenv:py35] whitelist_externals=make +install_command=echo {packages} deps = nose2 numpy From 53d28f9292cd3c5a635dc6dbe32dda54ad7f67c4 Mon Sep 17 00:00:00 2001 From: Jonas Schneider Date: Wed, 27 Apr 2016 18:26:24 -0700 Subject: [PATCH 002/310] Fix import path --- atari_py/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atari_py/__init__.py b/atari_py/__init__.py index 6dd7b48..f12d58d 100644 --- a/atari_py/__init__.py +++ b/atari_py/__init__.py @@ -1,4 +1,4 @@ -from ale_python_interface import * +from .ale_python_interface import * import os def _game_dir(): @@ -9,4 +9,4 @@ def get_game_path(game_name): def list_games(): files = os.listdir(_game_dir()) - return [os.path.basename(f).split(".")[0] for f in files] \ No newline at end of file + return [os.path.basename(f).split(".")[0] for f in files] From 510214295d52e41412cf0b6e39ad109034788313 Mon Sep 17 00:00:00 2001 From: Jonas Schneider Date: Wed, 27 Apr 2016 18:27:01 -0700 Subject: [PATCH 003/310] Bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3670684..f4b68c1 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.0.14', + version='0.0.15', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From 09f1cea7982fa6313c43c0e04d0a9263fdf64934 Mon Sep 17 00:00:00 2001 From: Jonas Schneider Date: Wed, 27 Apr 2016 18:52:31 -0700 Subject: [PATCH 004/310] Add smoke test --- atari_py/tests/test_smoke.py | 8 ++++++++ tox.ini | 1 + 2 files changed, 9 insertions(+) create mode 100644 atari_py/tests/test_smoke.py diff --git a/atari_py/tests/test_smoke.py b/atari_py/tests/test_smoke.py new file mode 100644 index 0000000..80fa036 --- /dev/null +++ b/atari_py/tests/test_smoke.py @@ -0,0 +1,8 @@ +import atari_py + +def test_smoke(): + pong_path = atari_py.get_game_path('pong') + ale = atari_py.ALEInterface() + ale.loadROM(pong_path) + action_set = ale.getMinimalActionSet() + ale.act(action_set[0]) diff --git a/tox.ini b/tox.ini index 7330eaa..65e5a79 100644 --- a/tox.ini +++ b/tox.ini @@ -16,6 +16,7 @@ commands = make python setup.py build pip install -e . + nose2 python setup.py clean --all make clean From d74554c0e2e611017071ccdc7720d58f71c35d6c Mon Sep 17 00:00:00 2001 From: Jonas Schneider Date: Wed, 27 Apr 2016 18:56:16 -0700 Subject: [PATCH 005/310] Ensure ROM path is a byte array --- atari_py/ale_python_interface.py | 3 ++- setup.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index fd2280a..02c812e 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -7,6 +7,7 @@ import numpy as np from numpy.ctypeslib import as_ctypes import os +import six ale_lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), 'ale_interface/build/libale_c.so')) @@ -134,7 +135,7 @@ def setFloat(self, key, value): ale_lib.setFloat(self.obj, key, value) def loadROM(self, rom_file): - ale_lib.loadROM(self.obj, rom_file) + ale_lib.loadROM(self.obj, six.b(rom_file)) def act(self, action): return ale_lib.act(self.obj, int(action)) diff --git a/setup.py b/setup.py index f4b68c1..514cc2e 100644 --- a/setup.py +++ b/setup.py @@ -29,6 +29,6 @@ def run(self): packages=['atari_py'], package_data={'atari_py': package_data}, cmdclass={'build': Build}, - install_requires=['numpy'], + install_requires=['numpy', 'six'], tests_require=['nose2'] ) From e8a5dd7906a55e48110b3889cf12b69f557f13cf Mon Sep 17 00:00:00 2001 From: Jonas Schneider Date: Wed, 27 Apr 2016 18:58:38 -0700 Subject: [PATCH 006/310] Extend the smoke test to include screen capture --- atari_py/tests/test_smoke.py | 8 ++++++++ tox.ini | 1 + 2 files changed, 9 insertions(+) diff --git a/atari_py/tests/test_smoke.py b/atari_py/tests/test_smoke.py index 80fa036..3fe28bc 100644 --- a/atari_py/tests/test_smoke.py +++ b/atari_py/tests/test_smoke.py @@ -1,8 +1,16 @@ import atari_py +import numpy as np def test_smoke(): pong_path = atari_py.get_game_path('pong') ale = atari_py.ALEInterface() ale.loadROM(pong_path) action_set = ale.getMinimalActionSet() + + # Test stepping ale.act(action_set[0]) + + # Test screen capture + (screen_width,screen_height) = ale.getScreenDims() + arr = np.zeros((screen_height, screen_width, 4), dtype=np.uint8) + ale.getScreenRGB(arr) diff --git a/tox.ini b/tox.ini index 65e5a79..80a7f32 100644 --- a/tox.ini +++ b/tox.ini @@ -8,6 +8,7 @@ envlist = py27, py35 [testenv:py35] whitelist_externals=make + echo install_command=echo {packages} deps = nose2 From 2dc7bcb6b68ecc0822301d44d0a56f01f281114f Mon Sep 17 00:00:00 2001 From: Bastiaan Quast Date: Thu, 28 Apr 2016 16:20:08 +0200 Subject: [PATCH 007/310] add colon before code block --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 76ae5f4..d0de251 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ To install via pip, run: ```pip install atari-py``` -Alternatively, you can install using setuptools using +Alternatively, you can install using setuptools using: ```python setup.py install``` From 6a961bcdc9f93db3110e3c551f3d38844747d3f9 Mon Sep 17 00:00:00 2001 From: Jonas Schneider Date: Wed, 27 Apr 2016 18:58:54 -0700 Subject: [PATCH 008/310] Bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 514cc2e..ea05943 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.0.15', + version='0.0.16', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From ef3e590f256d83828b88e01c0d15e50cef8c8615 Mon Sep 17 00:00:00 2001 From: Jonas Schneider Date: Thu, 28 Apr 2016 11:17:47 -0700 Subject: [PATCH 009/310] Install nose2 inside the virtualenv manually --- tox.ini | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tox.ini b/tox.ini index 80a7f32..fe17214 100644 --- a/tox.ini +++ b/tox.ini @@ -10,10 +10,8 @@ envlist = py27, py35 whitelist_externals=make echo install_command=echo {packages} -deps = - nose2 - numpy commands = + pip install numpy nose2 make python setup.py build pip install -e . From 298346ee3b5ce642e3f2d585e6e154602abbb6f8 Mon Sep 17 00:00:00 2001 From: Greg Brockman Date: Thu, 28 Apr 2016 14:48:38 -0700 Subject: [PATCH 010/310] Add Travis badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d0de251..97f2fb3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # atari_py +[![Build Status](https://travis-ci.org/openai/atari-py.svg?branch=master)](https://travis-ci.org/openai/atari-py) + A packaged and slightly-modified version of [https://github.com/bbitmaster/ale_python_interface](https://github.com/bbitmaster/ale_python_interface). ## Installation From 4da8e5d1d3011bb0f326365e674ea037bd25ac14 Mon Sep 17 00:00:00 2001 From: Jonas Schneider Date: Thu, 28 Apr 2016 15:06:07 -0700 Subject: [PATCH 011/310] Bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ea05943..83b00d4 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.0.16', + version='0.0.17', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From 92b85a4d1af54b86d0cdf27c5edd47fc711f1553 Mon Sep 17 00:00:00 2001 From: Greg Brockman Date: Sat, 7 May 2016 22:32:02 -0700 Subject: [PATCH 012/310] Build on more cores --- setup.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 83b00d4..3bf3c5b 100644 --- a/setup.py +++ b/setup.py @@ -1,3 +1,4 @@ +import multiprocessing import os from setuptools import setup import subprocess @@ -9,13 +10,15 @@ class Build(DistutilsBuild): def run(self): + cores_to_use = max(1, multiprocessing.cpu_count() - 1) + cmd = ['make', 'build', '-C', 'atari_py/ale_interface', '-j', str(cores_to_use)] try: - subprocess.check_call(['make', 'build', '-C', 'atari_py/ale_interface']) + subprocess.check_call(cmd) except subprocess.CalledProcessError as e: sys.stderr.write("Could not build atari-py: %s. (HINT: are you sure cmake is installed? You might also be missing a library. Atari-py requires: zlib [installable as 'apt-get install zlib1g-dev' on Ubuntu].)\n" % e) raise except OSError as e: - sys.stderr.write("Unable to execute 'make build -C atari_py/ale_interface'. HINT: are you sure `make` is installed?\n") + sys.stderr.write("Unable to execute '{}'. HINT: are you sure `make` is installed?\n".format(' '.join(cmd))) raise DistutilsBuild.run(self) From d63ced3941f25d289eb49234898f58281183d4ea Mon Sep 17 00:00:00 2001 From: Greg Brockman Date: Sat, 7 May 2016 22:32:21 -0700 Subject: [PATCH 013/310] Bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3bf3c5b..dde650f 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.0.17', + version='0.0.18', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From a8024822f7677eb0609d7912b18134d9c69445fc Mon Sep 17 00:00:00 2001 From: Trevor Blackwell Date: Tue, 14 Mar 2017 15:59:24 -0700 Subject: [PATCH 014/310] getScreenRGB allocation bugfix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In atari_py/ale_c_wrapper.h:62 it writes 4 bytes per pixel, but was allocating 3 bytes here. Gym wasn’t affected, because it pre-allocates a buffer --- atari_py/ale_python_interface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index 02c812e..b48d4fc 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -193,13 +193,13 @@ def getScreen(self, screen_data=None): def getScreenRGB(self, screen_data=None): """This function fills screen_data with the data in RGB format screen_data MUST be a numpy array of uint8. This can be initialized like so: - screen_data = np.empty((height,width,3), dtype=np.uint8) + screen_data = np.empty((height,width,4), dtype=np.uint8) If it is None, then this function will initialize it. """ if(screen_data is None): width = ale_lib.getScreenWidth(self.obj) height = ale_lib.getScreenHeight(self.obj) - screen_data = np.empty((height, width,3), dtype=np.uint8) + screen_data = np.empty((height, width,4), dtype=np.uint8) ale_lib.getScreenRGB(self.obj, as_ctypes(screen_data[:])) return screen_data From 5690e47df171a6fceabf3db549bec062b1dad133 Mon Sep 17 00:00:00 2001 From: Trevor Blackwell Date: Fri, 17 Mar 2017 16:14:12 -0700 Subject: [PATCH 015/310] Document color channels in getScreenRGB --- atari_py/ale_python_interface.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index b48d4fc..bcca793 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -191,10 +191,15 @@ def getScreen(self, screen_data=None): return screen_data def getScreenRGB(self, screen_data=None): - """This function fills screen_data with the data in RGB format + """This function fills screen_data with the data in RGB format. screen_data MUST be a numpy array of uint8. This can be initialized like so: - screen_data = np.empty((height,width,4), dtype=np.uint8) + screen_data = np.empty((height,width,4), dtype=np.uint8) If it is None, then this function will initialize it. + On little-endian machines like x86, the channels are BGRZ order: + screen_data[x, y, 0:4] is [blue, green, red, 0] + On big-endian machines (rare in 2017) the channels would be the opposite order. + There's not much error checking here: if you supply an array that's too small + this function will produce undefined behavior. """ if(screen_data is None): width = ale_lib.getScreenWidth(self.obj) From 25092d475ce5a46d379f8e4d978cea65fa832f81 Mon Sep 17 00:00:00 2001 From: Szymon Sidor Date: Sun, 19 Mar 2017 16:06:41 -0700 Subject: [PATCH 016/310] Add hero binary --- atari_py/atari_roms/hero.bin | Bin 0 -> 8192 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 atari_py/atari_roms/hero.bin diff --git a/atari_py/atari_roms/hero.bin b/atari_py/atari_roms/hero.bin new file mode 100644 index 0000000000000000000000000000000000000000..4242bd9adebcddb55d67894fca15174fef13b037 GIT binary patch literal 8192 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 Date: Wed, 22 Mar 2017 16:44:20 -0700 Subject: [PATCH 017/310] bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index dde650f..f43b6b1 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.0.18', + version='0.0.19', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From ee24180f45856a14c46f76dd7c4e039a1bf519d3 Mon Sep 17 00:00:00 2001 From: Trevor Blackwell Date: Fri, 24 Mar 2017 23:32:47 -0700 Subject: [PATCH 018/310] Accept python3 strings in filename --- atari_py/ale_python_interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index bcca793..5fabb64 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -238,7 +238,7 @@ def getRAM(self, ram=None): return ram def saveScreenPNG(self, filename): - return ale_lib.saveScreenPNG(self.obj, filename) + return ale_lib.saveScreenPNG(self.obj, six.b(filename)) def saveState(self): return ale_lib.saveState(self.obj) From 5f2a36214c3bf659210ff7062de7a89f3fc470f3 Mon Sep 17 00:00:00 2001 From: Trevor Blackwell Date: Tue, 28 Mar 2017 09:49:12 -0700 Subject: [PATCH 019/310] Add getScreenRGB2, which doesn't require channel swapping --- atari_py/ale_c_wrapper.h | 19 ++++++++++++++++++- atari_py/ale_python_interface.py | 23 ++++++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/atari_py/ale_c_wrapper.h b/atari_py/ale_c_wrapper.h index 1666591..197ab8f 100644 --- a/atari_py/ale_c_wrapper.h +++ b/atari_py/ale_c_wrapper.h @@ -58,12 +58,29 @@ extern "C" { size_t screen_size = w*h; pixel_t *ale_screen_data = ale->getScreen().getArray(); - for(int i = 0;i < w*h;i++){ + for(int i = 0;i < screen_size;i++){ output_buffer[i] = rgb_palette[ale_screen_data[i]]; } } + void getScreenRGB2(ALEInterface *ale, unsigned char *output_buffer){ + size_t w = ale->getScreen().width(); + size_t h = ale->getScreen().height(); + size_t screen_size = w*h; + pixel_t *ale_screen_data = ale->getScreen().getArray(); + + int j = 0; + for(int i = 0;i < screen_size;i++){ + unsigned int zrgb = rgb_palette[ale_screen_data[i]]; + output_buffer[j++] = (zrgb>>16)&0xff; + output_buffer[j++] = (zrgb>>8)&0xff; + output_buffer[j++] = (zrgb>>0)&0xff; + } + + } + + void getScreenGrayscale(ALEInterface *ale, unsigned char *output_buffer){ size_t w = ale->getScreen().width(); size_t h = ale->getScreen().height(); diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index 5fabb64..dd99edb 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -66,6 +66,8 @@ ale_lib.getScreenHeight.restype = c_int ale_lib.getScreenRGB.argtypes = [c_void_p, c_void_p] ale_lib.getScreenRGB.restype = None +ale_lib.getScreenRGB2.argtypes = [c_void_p, c_void_p] +ale_lib.getScreenRGB2.restype = None ale_lib.getScreenGrayscale.argtypes = [c_void_p, c_void_p] ale_lib.getScreenGrayscale.restype = None ale_lib.saveState.argtypes = [c_void_p] @@ -191,7 +193,7 @@ def getScreen(self, screen_data=None): return screen_data def getScreenRGB(self, screen_data=None): - """This function fills screen_data with the data in RGB format. + """This function fills screen_data with the data in BGRZ (not actually RGB -- see getScreenRGB2 for that) format. screen_data MUST be a numpy array of uint8. This can be initialized like so: screen_data = np.empty((height,width,4), dtype=np.uint8) If it is None, then this function will initialize it. @@ -208,6 +210,25 @@ def getScreenRGB(self, screen_data=None): ale_lib.getScreenRGB(self.obj, as_ctypes(screen_data[:])) return screen_data + + def getScreenRGB2(self, screen_data=None): + """This function fills screen_data with the data in RGB format. + screen_data MUST be a numpy array of uint8. This can be initialized like so: + screen_data = np.empty((height,width,3), dtype=np.uint8) + If it is None, then this function will initialize it. + On all architectures, the channels are RGB order: + screen_data[x, y, :] is [red, green, blue] + There's not much error checking here: if you supply an array that's too small + this function will produce undefined behavior. + """ + if(screen_data is None): + width = ale_lib.getScreenWidth(self.obj) + height = ale_lib.getScreenHeight(self.obj) + screen_data = np.empty((height, width, 3), dtype=np.uint8) + assert screen_data.strides == (480, 3, 1) + ale_lib.getScreenRGB2(self.obj, as_ctypes(screen_data[:])) + return screen_data + def getScreenGrayscale(self, screen_data=None): """This function fills screen_data with the data in grayscale screen_data MUST be a numpy array of uint8. This can be initialized like so: From 3acfc88b6a46ad809052717fca770464a081192a Mon Sep 17 00:00:00 2001 From: Trevor Blackwell Date: Tue, 28 Mar 2017 10:20:40 -0700 Subject: [PATCH 020/310] bump --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index f43b6b1..84ed77c 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.0.19', + version='0.0.20', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From 2ecb58ce2b5177dec79b2763c522c71e2e4bcca5 Mon Sep 17 00:00:00 2001 From: Trevor Blackwell Date: Tue, 28 Mar 2017 16:17:46 -0700 Subject: [PATCH 021/310] Fix getFloat, setFloat, etc. under py3 --- atari_py/ale_python_interface.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index dd99edb..536b30b 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -24,7 +24,7 @@ ale_lib.getBool.restype = c_bool ale_lib.getFloat.argtypes = [c_void_p, c_char_p] ale_lib.getFloat.restype = c_float -ale_lib.setString.argtypes = [c_void_p, c_char_p, c_int] +ale_lib.setString.argtypes = [c_void_p, c_char_p, c_char_p] ale_lib.setString.restype = None ale_lib.setInt.argtypes = [c_void_p, c_char_p, c_int] ale_lib.setInt.restype = None @@ -119,22 +119,22 @@ def __init__(self): self.obj = ale_lib.ALE_new() def getString(self, key): - return ale_lib.getString(self.obj, key) + return ale_lib.getString(self.obj, six.b(key)) def getInt(self, key): - return ale_lib.getInt(self.obj, key) + return ale_lib.getInt(self.obj, six.b(key)) def getBool(self, key): - return ale_lib.getBool(self.obj, key) + return ale_lib.getBool(self.obj, six.b(key)) def getFloat(self, key): - return ale_lib.getFloat(self.obj, key) + return ale_lib.getFloat(self.obj, six.b(key)) def setString(self, key, value): - ale_lib.setString(self.obj, key, value) + ale_lib.setString(self.obj, six.b(key), six.b(value)) def setInt(self, key, value): - ale_lib.setInt(self.obj, key, value) + ale_lib.setInt(self.obj, six.b(key), int(value)) def setBool(self, key, value): - ale_lib.setBool(self.obj, key, value) + ale_lib.setBool(self.obj, six.b(key), bool(value)) def setFloat(self, key, value): - ale_lib.setFloat(self.obj, key, value) + ale_lib.setFloat(self.obj, six.b(key), float(value)) def loadROM(self, rom_file): ale_lib.loadROM(self.obj, six.b(rom_file)) From 9226727aaa76e8498605c665ab04ce27b57dd9d2 Mon Sep 17 00:00:00 2001 From: Nicolai Czempin Date: Wed, 29 Mar 2017 17:18:35 +0200 Subject: [PATCH 022/310] Add Kaboom! and Robinett's Adventure --- atari_py/ale_interface/src/games/Roms.cpp | 4 + .../src/games/supported/Adventure.cpp | 122 ++++++++++++++++++ .../src/games/supported/Adventure.hpp | 75 +++++++++++ .../src/games/supported/Kaboom.cpp | 98 ++++++++++++++ .../src/games/supported/Kaboom.hpp | 65 ++++++++++ atari_py/atari_roms/adventure.bin | Bin 0 -> 4096 bytes atari_py/atari_roms/kaboom.bin | Bin 0 -> 2048 bytes atari_py/package_data.txt | 6 + 8 files changed, 370 insertions(+) create mode 100644 atari_py/ale_interface/src/games/supported/Adventure.cpp create mode 100644 atari_py/ale_interface/src/games/supported/Adventure.hpp create mode 100644 atari_py/ale_interface/src/games/supported/Kaboom.cpp create mode 100644 atari_py/ale_interface/src/games/supported/Kaboom.hpp create mode 100644 atari_py/atari_roms/adventure.bin create mode 100644 atari_py/atari_roms/kaboom.bin diff --git a/atari_py/ale_interface/src/games/Roms.cpp b/atari_py/ale_interface/src/games/Roms.cpp index 084ca63..ad49e44 100644 --- a/atari_py/ale_interface/src/games/Roms.cpp +++ b/atari_py/ale_interface/src/games/Roms.cpp @@ -14,6 +14,7 @@ #include "RomUtils.hpp" // include the game implementations +#include "supported/Adventure.hpp" #include "supported/AirRaid.hpp" #include "supported/Alien.hpp" #include "supported/Amidar.hpp" @@ -46,6 +47,7 @@ #include "supported/IceHockey.hpp" #include "supported/JamesBond.hpp" #include "supported/JourneyEscape.hpp" +#include "supported/Kaboom.hpp" #include "supported/Kangaroo.hpp" #include "supported/Krull.hpp" #include "supported/KungFuMaster.hpp" @@ -79,6 +81,7 @@ /* list of supported games */ static const RomSettings *roms[] = { + new AdventureSettings(), new AirRaidSettings(), new AlienSettings(), new AmidarSettings(), @@ -111,6 +114,7 @@ static const RomSettings *roms[] = { new IceHockeySettings(), new JamesBondSettings(), new JourneyEscapeSettings(), + new KaboomSettings(), new KangarooSettings(), new KrullSettings(), new KungFuMasterSettings(), diff --git a/atari_py/ale_interface/src/games/supported/Adventure.cpp b/atari_py/ale_interface/src/games/supported/Adventure.cpp new file mode 100644 index 0000000..5887f43 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Adventure.cpp @@ -0,0 +1,122 @@ +/* ***************************************************************************** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "Adventure.hpp" + +#include "../RomUtils.hpp" + +AdventureSettings::AdventureSettings() { + + reset(); +} + +/* create a new instance of the rom */ +RomSettings* AdventureSettings::clone() const { + + RomSettings* rval = new AdventureSettings(); + *rval = *this; + return rval; +} + +/* process the latest information from ALE */ +void AdventureSettings::step(const System& system) { + + int chalice_status = readRam(&system, 0xB9); + bool chalice_in_yellow_castle = chalice_status == 0x12; + + if (chalice_in_yellow_castle) { + m_reward = 1; + } + + int player_status = readRam(&system, 0xE0); + bool player_eaten = player_status == 2; + + if (player_eaten) { + m_reward = -1; + } + + m_terminal = player_eaten || chalice_in_yellow_castle; +} + +/* is end of game */ +bool AdventureSettings::isTerminal() const { + + return m_terminal; +} +; + +/* get the most recently observed reward */ +reward_t AdventureSettings::getReward() const { + + return m_reward; +} + +/* is an action part of the minimal set? */ +bool AdventureSettings::isMinimal(const Action &a) const { + + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_FIRE: + case PLAYER_A_UP: + case PLAYER_A_RIGHT: + case PLAYER_A_LEFT: + case PLAYER_A_DOWN: + case PLAYER_A_UPRIGHT: + case PLAYER_A_UPLEFT: + case PLAYER_A_DOWNRIGHT: + case PLAYER_A_DOWNLEFT: + case PLAYER_A_UPFIRE: + case PLAYER_A_RIGHTFIRE: + case PLAYER_A_LEFTFIRE: + case PLAYER_A_DOWNFIRE: + case PLAYER_A_UPRIGHTFIRE: + case PLAYER_A_UPLEFTFIRE: + case PLAYER_A_DOWNRIGHTFIRE: + case PLAYER_A_DOWNLEFTFIRE: + return true; + default: + return false; + } +} + +/* reset the state of the game */ +void AdventureSettings::reset() { + + m_reward = 0; + m_terminal = false; +} + +/* saves the state of the rom settings */ +void AdventureSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putBool(m_terminal); +} + +// loads the state of the rom settings +void AdventureSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_terminal = ser.getBool(); +} + diff --git a/atari_py/ale_interface/src/games/supported/Adventure.hpp b/atari_py/ale_interface/src/games/supported/Adventure.hpp new file mode 100644 index 0000000..ccfee50 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Adventure.hpp @@ -0,0 +1,75 @@ +/* ***************************************************************************** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __ADVENTURE_HPP__ +#define ____ADVENTURE_HPP___HPP__ + +#include "../RomSettings.hpp" + + +/* RL wrapper for Adventure settings */ +class AdventureSettings : public RomSettings { + + public: + + AdventureSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + const char* rom() const { return "adventure"; } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + virtual const int lives() { return 1; } + + private: + + bool m_terminal; + reward_t m_reward; + }; + +#endif // __ADVENTURE_HPP__ + diff --git a/atari_py/ale_interface/src/games/supported/Kaboom.cpp b/atari_py/ale_interface/src/games/supported/Kaboom.cpp new file mode 100644 index 0000000..ebe7c63 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Kaboom.cpp @@ -0,0 +1,98 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "Kaboom.hpp" + +#include "../RomUtils.hpp" +#include + +KaboomSettings::KaboomSettings() { + reset(); +} + + +/* create a new instance of the rom */ +RomSettings* KaboomSettings::clone() const { + + RomSettings* rval = new KaboomSettings(); + *rval = *this; + return rval; +} + + +/* process the latest information from ALE */ +void KaboomSettings::step(const System& system) { + + // update the reward + reward_t score = getDecimalScore(0xA5, 0xA4, 0xA3, &system); + m_reward = score - m_score; + m_score = score; + + // update terminal status + int lives = readRam(&system, 0xA1); + m_terminal = lives == 0x0 || m_score > 999991; +} + + +/* is end of game */ +bool KaboomSettings::isTerminal() const { + + return false; //m_terminal; +}; + + +/* get the most recently observed reward */ +reward_t KaboomSettings::getReward() const { + return m_reward; +} + + +/* is an action part of the minimal set? */ +bool KaboomSettings::isMinimal(const Action &a) const { + + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_RIGHT: + case PLAYER_A_LEFT: + return true; + default: + return false; + } +} + + +/* reset the state of the game */ +void KaboomSettings::reset() { + + m_reward = 0; + m_score = 0; + m_terminal = false; +} + +/* saves the state of the rom settings */ +void KaboomSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putInt(m_score); + ser.putBool(m_terminal); +} + +// loads the state of the rom settings +void KaboomSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_score = ser.getInt(); + m_terminal = ser.getBool(); +} + +ActionVect KaboomSettings::getStartingActions() { + ActionVect startingActions; + startingActions.push_back(PLAYER_A_FIRE); + return startingActions; +} diff --git a/atari_py/ale_interface/src/games/supported/Kaboom.hpp b/atari_py/ale_interface/src/games/supported/Kaboom.hpp new file mode 100644 index 0000000..fd6e54b --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Kaboom.hpp @@ -0,0 +1,65 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __KABOOM_HPP__ +#define __KABOOM_HPP__ + +#include "../RomSettings.hpp" + +/* RL wrapper for Kaboom settings */ +class KaboomSettings: public RomSettings +{ + +public: + + KaboomSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + const char* rom() const + { + return "kaboom"; + } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + ActionVect getStartingActions(); + +private: + + bool m_terminal; + reward_t m_reward; + reward_t m_score; +}; + +#endif // __KABOOM__ + diff --git a/atari_py/atari_roms/adventure.bin b/atari_py/atari_roms/adventure.bin new file mode 100644 index 0000000000000000000000000000000000000000..a092248593d105dc0f79afbb60163bfdc6925a84 GIT binary patch literal 4096 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 literal 0 HcmV?d00001 diff --git a/atari_py/atari_roms/kaboom.bin b/atari_py/atari_roms/kaboom.bin new file mode 100644 index 0000000000000000000000000000000000000000..4f18cb0bbca6359cc93b7e9ebcadfb96a3ca1b7b GIT binary patch literal 2048 zcmah}e`p)m9e;W{oz99nJ-cou*J`VP5-g{5A}~0N_Jb0eS<}K=GU)o3DNVq`e~gWl z{2^RNxvzW#3R=kpJ3pM$Sx@+EOFm^2BvrL}tWj;Tm4k*Z6vD)4jT6RtYwUCEZ1&z= zl9JLt_I=WO@B8_F-}mQxcj}gg&MN4_y1A47(><-L@hiJnS&rrd#YIzSb9s(t2P=bT z4oV8N$UmT?q}C>Z2Y*?@<^#as0YU#R1mG#vD{+!f^-Bk(L(*h*7i7TI4d|`f5UJj0 z>wo5}J4G2Hxn3y(y~RnH+*+Y^*r8VeyN4WnA4KE+`4;&v5Qh4sZHc4PaDZX7>Y$y> zWxw`9M|6(Pu6j<&34vD3ep;{&HD0xyFqz!n_}FgmH?clu2>Mt|PGJ2wMC4Zc8ROGO zT5Ye{L32#EBOUzrqazTxE+gRSHuTEN#Netsu-zgbm9w~{nw~&FM_?OR_c3+fSDFlr zz>9gT2g0LcusO=Zmi{xCloJP*N!|~*IVqc)%o2uP_e^uLCM0lkOD1;#uh~WW`c(u` z*cbQD$q$oeP#wX}T{`8Y?V@hdYKWP6XylOzI85yui>8ler)BgtAJ&n_UT(WSm_d9O zcBK2?@CN-VX---lW=l)Ri6Ih_weRF))?_!zlI(iuY)JOQ%9gXNLg}F|8SuE+Zd$cJ zvnI3fTGp^k{^Fo4ZV#9yKT`|?8aa1xyB6!uq$=A zMgFcIc;`H>OyG43OEV(fy5l3BDe?2mVd4>gv5NEj>aM{g;S-l{Z00fDgv-(I*)XMr z8vooVZ_%YdJUplSVf(tUrTk@Oy}3;` z-RGfZB`kR)#AY@Ct(`XgYcr--JUOH8v3nI4Oss~cR1}*bTzsoIBc0*TfTSk?vv5@; z$xJC_kZ8=#mH7$r{p0+dol54~b>%`4>TwFxGq6LAkr%&kaNeO|f}n;%# z{PV^UhoPbgbiu;Sh1_DTZvL%B zw)7}enica?YM8iLpd~9zCsO&RHSYI?T1hFKE49cbRfj#Gmb9~0pq0}a_v}=7)B_9J zUao8wVr9}@o?vgsa^H@Dp$ygZ`Ars9$lMow$u@X;ad;0d#>&4;(CTWZ(a#!jh-$Hm z#5=qfK5=2y%JUl1eWtMb7TfLVZ{;q+1*b97F+X{&bl(YH#ce*%Ssqy~724S13|_@k zre{UEq!U=WAEw%1x1mh4altnY zSM^g+XWru8c@i= z2L=X$_{kwMWMDwV7UESUL_sjd`NA&-AqA2H_z|w zS?C+|E)q$$4Xk;bbx*X2xHO97ou(h!8`ZpSvf~#O}O9r!p?@Of3KZ0hCE> AO8@`> literal 0 HcmV?d00001 diff --git a/atari_py/package_data.txt b/atari_py/package_data.txt index d1e27aa..2743d65 100644 --- a/atari_py/package_data.txt +++ b/atari_py/package_data.txt @@ -208,6 +208,8 @@ ale_interface/src/games/RomUtils.hpp ale_interface/src/games/Roms.cpp ale_interface/src/games/Roms.hpp ale_interface/src/games/module.mk +ale_interface/src/games/supported/Adventure.cpp +ale_interface/src/games/supported/Adventure.hpp ale_interface/src/games/supported/AirRaid.cpp ale_interface/src/games/supported/AirRaid.hpp ale_interface/src/games/supported/Alien.cpp @@ -272,6 +274,8 @@ ale_interface/src/games/supported/JamesBond.cpp ale_interface/src/games/supported/JamesBond.hpp ale_interface/src/games/supported/JourneyEscape.cpp ale_interface/src/games/supported/JourneyEscape.hpp +ale_interface/src/games/supported/Kaboom.cpp +ale_interface/src/games/supported/Kaboom.hpp ale_interface/src/games/supported/Kangaroo.cpp ale_interface/src/games/supported/Kangaroo.hpp ale_interface/src/games/supported/Krull.cpp @@ -345,6 +349,7 @@ ale_interface/src/os_dependent/SettingsWin32.hxx ale_interface/src/os_dependent/module.mk ale_interface/stellarc atari_ntsc_rgb_palette.h +atari_roms/adventure.bin atari_roms/air_raid.bin atari_roms/alien.bin atari_roms/amidar.bin @@ -376,6 +381,7 @@ atari_roms/gravitar.bin atari_roms/ice_hockey.bin atari_roms/jamesbond.bin atari_roms/journey_escape.bin +atari_roms/kaboom.bin atari_roms/kangaroo.bin atari_roms/krull.bin atari_roms/kung_fu_master.bin From 0216f13a42a574301f4ece99f7463b9e9e65c051 Mon Sep 17 00:00:00 2001 From: Trevor Blackwell Date: Thu, 30 Mar 2017 11:02:42 -0700 Subject: [PATCH 023/310] Fix py2/3/str/bytes for ALE --- atari_py/ale_python_interface.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index 536b30b..f93d7ba 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -114,30 +114,35 @@ def frame_number(self): def episode_frame_number(self): return ale_lib.ALEState_getEpisodeFrameNumber(self.obj) +def _as_bytes(s): + if hasattr(s, 'encode'): + return s.encode('utf8') + return s + class ALEInterface(object): def __init__(self): self.obj = ale_lib.ALE_new() def getString(self, key): - return ale_lib.getString(self.obj, six.b(key)) + return ale_lib.getString(self.obj, _as_bytes(key)) def getInt(self, key): - return ale_lib.getInt(self.obj, six.b(key)) + return ale_lib.getInt(self.obj, _as_bytes(key)) def getBool(self, key): - return ale_lib.getBool(self.obj, six.b(key)) + return ale_lib.getBool(self.obj, _as_bytes(key)) def getFloat(self, key): - return ale_lib.getFloat(self.obj, six.b(key)) + return ale_lib.getFloat(self.obj, _as_bytes(key)) def setString(self, key, value): - ale_lib.setString(self.obj, six.b(key), six.b(value)) + ale_lib.setString(self.obj, _as_bytes(key), _as_bytes(value)) def setInt(self, key, value): - ale_lib.setInt(self.obj, six.b(key), int(value)) + ale_lib.setInt(self.obj, _as_bytes(key), int(value)) def setBool(self, key, value): - ale_lib.setBool(self.obj, six.b(key), bool(value)) + ale_lib.setBool(self.obj, _as_bytes(key), bool(value)) def setFloat(self, key, value): - ale_lib.setFloat(self.obj, six.b(key), float(value)) + ale_lib.setFloat(self.obj, _as_bytes(key), float(value)) def loadROM(self, rom_file): - ale_lib.loadROM(self.obj, six.b(rom_file)) + ale_lib.loadROM(self.obj, _as_bytes(rom_file)) def act(self, action): return ale_lib.act(self.obj, int(action)) @@ -259,7 +264,7 @@ def getRAM(self, ram=None): return ram def saveScreenPNG(self, filename): - return ale_lib.saveScreenPNG(self.obj, six.b(filename)) + return ale_lib.saveScreenPNG(self.obj, _as_bytes(filename)) def saveState(self): return ale_lib.saveState(self.obj) From 27d891569fe15ebc3d65b25d884fb5134bc3a984 Mon Sep 17 00:00:00 2001 From: Trevor Blackwell Date: Thu, 30 Mar 2017 13:18:34 -0700 Subject: [PATCH 024/310] Updated slack notification --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index 6396b1d..8c96188 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,3 +17,9 @@ notifications: slack: secure: h/Mxm8K+avH/2W0818zCHmLloRPMFN4NJL01+VShvAkH80/acfjeq/+mMdWXXPL/oOB6kSHDk+GDhwR6+s03ZcPMn5INTFvFYqUc6UWmT+NXtOPxGTN0xda6MdYUkWQUKaMyjFrweZQOMOASFBIzPOq4XeVbM5aB8s4EJhnfAcYZhp/idwKbToVihN4KZgxlvZIFc8iEp1o9uSl5qrsaeYYYXRkb6mauacAwOo4/Chu+cOnoLUOnvhBFE3rV3doDNrbnoalO8XiExtgx5CIAYWrlMni7r2Q+LlzgwdyTH19ZtybPxJTZIIWSBQ2UtcoYdIEDcc36GcUwz1VUGg32mLJJnY2xw80CWR4ixFPpLwwP5Y99WTn8v094B4nmFTWOwNWXp3EkqtTN9XcJoRBqXB5ArucIPqrx57dOCljSKx22gL6WaF2p3stSAxIGFektGyGnisaELrFZG1C63aHoUPicj3gUlijmAoUmYaDRf6P1wnpXqBpKDAWWhAMSatvx1ekmEJgR7OQklQnnfjx9kENDUygNUWS4IQwN2qYieuzHFL3of7/30mTM43+Vt/vWN8GI7j01BXu6FNGGloHxjH1pt3bLP/+uj5BJsT2HWF+Z8XR4VE6cyVuKsQAFgCXwOkoDHALbcwsspONDIt/9ixkesgh1oFt4CzU3UuU5wYs= on_success: change + webhooks: + urls: + - https://hooks.zapier.com/hooks/catch/1711022/6ztmzh/ + - https://hooks.zapier.com/hooks/catch/1711022/6zhc8p/ + on_success: always + on_failure: always From 5853fceef626d228c9b1fd17830977bb235b9177 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Tue, 4 Apr 2017 14:58:19 -0700 Subject: [PATCH 025/310] drop remnants of old make build --- atari_py/ale_interface/common.rules | 31 --- atari_py/ale_interface/makefile.mac | 248 ------------------ atari_py/ale_interface/makefile.unix | 246 ----------------- atari_py/ale_interface/setup.sh | 3 - atari_py/ale_interface/src/common/module.mk | 18 -- .../ale_interface/src/controllers/module.mk | 12 - .../ale_interface/src/emucore/m6502/module.mk | 15 -- atari_py/ale_interface/src/emucore/module.mk | 57 ---- .../src/emucore/rsynth/module.mk | 16 -- .../ale_interface/src/environment/module.mk | 12 - atari_py/ale_interface/src/external/module.mk | 10 - atari_py/ale_interface/src/games/module.mk | 73 ------ atari_py/ale_interface/src/module.mk | 11 - .../ale_interface/src/os_dependent/module.mk | 12 - 14 files changed, 764 deletions(-) delete mode 100644 atari_py/ale_interface/common.rules delete mode 100644 atari_py/ale_interface/makefile.mac delete mode 100644 atari_py/ale_interface/makefile.unix delete mode 100755 atari_py/ale_interface/setup.sh delete mode 100644 atari_py/ale_interface/src/common/module.mk delete mode 100644 atari_py/ale_interface/src/controllers/module.mk delete mode 100644 atari_py/ale_interface/src/emucore/m6502/module.mk delete mode 100644 atari_py/ale_interface/src/emucore/module.mk delete mode 100644 atari_py/ale_interface/src/emucore/rsynth/module.mk delete mode 100644 atari_py/ale_interface/src/environment/module.mk delete mode 100644 atari_py/ale_interface/src/external/module.mk delete mode 100644 atari_py/ale_interface/src/games/module.mk delete mode 100644 atari_py/ale_interface/src/module.mk delete mode 100644 atari_py/ale_interface/src/os_dependent/module.mk diff --git a/atari_py/ale_interface/common.rules b/atari_py/ale_interface/common.rules deleted file mode 100644 index 285cd64..0000000 --- a/atari_py/ale_interface/common.rules +++ /dev/null @@ -1,31 +0,0 @@ -# Common build rules, used by the sub modules and their module.mk files - -# Copy the list of objects to a new variable. The name of the new variable -# contains the module name, a trick we use so we can keep multiple different -# module object lists, one for each module. -MODULE_OBJS-$(MODULE) := $(MODULE_OBJS) - -MODULE_LIB-$(MODULE) := $(MODULE)/lib$(notdir $(MODULE)).a - -# If not building as a plugin, add the object files to the main OBJS list -#OBJS += $(MODULE_LIB-$(MODULE)) -OBJS += $(MODULE_OBJS) - -# Convenience library target -#$(MODULE_LIB-$(MODULE)): $(MODULE_OBJS) -# -$(RM) $@ -# $(AR) $@ $+ -# $(RANLIB) $@ - -# Pseudo target for comfort, allows for "make common", "make gui" etc. -#$(MODULE): $(MODULE_LIB-$(MODULE)) - - -# Clean target, removes all object files. This looks a bit hackish, as we have to -# copy the content of MODULE_OBJS to another unique variable (the next module.mk -# will overwrite it after all). The same for the libMODULE.a library file. -clean: clean-$(MODULE) -clean-$(MODULE): clean-% : - -$(RM) $(MODULE_OBJS-$*) $(MODULE_LIB-$*) $(PLUGIN-$*) - -.PHONY: clean-$(MODULE) $(MODULE) diff --git a/atari_py/ale_interface/makefile.mac b/atari_py/ale_interface/makefile.mac deleted file mode 100644 index 3f2f179..0000000 --- a/atari_py/ale_interface/makefile.mac +++ /dev/null @@ -1,248 +0,0 @@ -##============================================================================ -# makefile for the A.L.E: Atari Learing Environment (Powered by Stella) -##============================================================================ - -srcdir ?= . -# Set this to 1 to enable SDL and display_screen -USE_SDL := 0 -# Set this to 1 to enable the RLGlue interface -USE_RLGLUE := 0 -DEFINES := -DRLGENV_NOMAINLOOP -LDFLAGS := -# /opt/local/include for MacPorts; /usr/local/include for RL-Glue -INCLUDES := -Isrc/controllers -Isrc/os_dependent -I/usr/include -I/opt/local/include -I/usr/local/include -Isrc/environment -Isrc/external -LIBS_SDL := -lSDL -lSDLmain -LIBS_RLGLUE := -lrlutils -lrlgluenetdev -LIBS := -L/opt/local/lib -OBJS := -PROF := -MODULES := -MODULE_DIRS := -DISTNAME := atari_learning_environment -DEBUG := 0 - -# -------- Generated by configure ----------- -CXX := g++ -CXXFLAGS := -LD := g++ -# LIBS += -lz -lX11 -# For the Mac -LIBS += -lz -framework Cocoa -RANLIB := ranlib -INSTALL := install -AR := ar cru -MKDIR := mkdir -p -ECHO := printf -CAT := cat -RM := rm -f -RM_REC := rm -f -r -ZIP := zip -q -CP := cp - - -# MODULES += src/unix -MODULE_DIRS += -EXEEXT := -NASM := /usr/bin/nasm -NASMFLAGS := -f elf - -PREFIX := /usr/local -BINDIR := /usr/local/bin -DOCDIR := /usr/local/share/doc/stella -DATADIR := /usr/local/share -PROFILE := - -HAVE_GCC3 = 1 -HAVE_NASM = 1 - -INCLUDES += -Isrc/games -Isrc/emucore -Isrc/emucore/m6502/src -Isrc/emucore/m6502/src/bspf/src -Isrc/common -Isrc/controllers -Isrc/environment -OBJS += -DEFINES += -DUNIX -DHAS_ALTIVEC -DUSE_NASM -DBSPF_UNIX -DHAVE_INTTYPES -DWINDOWED_SUPPORT -DHAVE_GETTIMEOFDAY -DSNAPSHOT_SUPPORT -LDFLAGS += - -ifeq ("$(USE_SDL)", "1") - CXXFLAGS+=$(shell sdl-config --cflags) - LDFLAGS+=$(shell sdl-config --libs) - DEFINES += -D__USE_SDL -DSOUND_SUPPORT -endif - -ifeq ("$(USE_RLGLUE)", "1") - DEFINES += -D__USE_RLGLUE - LIBS += $(LIBS_RLGLUE) -endif - -# Uncomment this for stricter compile time code verification -# CXXFLAGS+= -Werror - -CXXFLAGS += -Wall -Wunused -fPIC - -ifeq ("$(DEBUG)", "1") - CXXFLAGS += -g -O0 -else - CXXFLAGS += -O3 -endif - -ifdef PROFILE - PROF:= -g -pg -fprofile-arcs -ftest-coverage - CXXFLAGS+= $(PROF) -else - CXXFLAGS+= -fomit-frame-pointer -endif - -# Even more warnings... -#CXXFLAGS+= -pedantic -Wpointer-arith -Wcast-qual -Wconversion -#CXXFLAGS+= -Wshadow -Wimplicit -Wundef -Wnon-virtual-dtor -#CXXFLAGS+= -Wno-reorder -Wwrite-strings -fcheck-new -Wctor-dtor-privacy - -####################################################################### -# Misc stuff - you should never have to edit this # -####################################################################### - -EXECUTABLE := ale$(EXEEXT) -LIBRARY := libale.so - -all: tags $(EXECUTABLE) $(LIBRARY) - - -###################################################################### -# Various minor settings -###################################################################### - -# The name for the directory used for dependency tracking -DEPDIR := .deps - - -###################################################################### -# Module settings -###################################################################### - -MODULES := $(MODULES) - -# After the game specific modules follow the shared modules -MODULES += \ - src \ - src/emucore \ - src/emucore/m6502 \ - src/common \ - src/controllers \ - src/os_dependent \ - src/games \ - src/environment \ - src/external - - -###################################################################### -# The build rules follow - normally you should have no need to -# touch whatever comes after here. -###################################################################### - -# Concat DEFINES and INCLUDES to form the CPPFLAGS -CPPFLAGS:= $(DEFINES) $(INCLUDES) - -# Include the build instructions for all modules --include $(addprefix $(srcdir)/, $(addsuffix /module.mk,$(MODULES))) - -# Depdir information -DEPDIRS = $(addsuffix /$(DEPDIR),$(MODULE_DIRS)) -DEPFILES = - -# The build rule for the Stella executable -$(EXECUTABLE): $(OBJS) - $(LD) $(LDFLAGS) $(PRE_OBJS_FLAGS) $+ $(POST_OBJS_FLAGS) $(LIBS) $(PROF) -o $@ - -$(LIBRARY): $(OBJS) - $(LD) $(LDFLAGS) -shared -o $(LIBRARY) $(OBJS) $(LIBS) - -distclean: clean - $(RM_REC) $(DEPDIRS) - $(RM) build.rules config.h config.mak config.log - -clean: - $(RM) $(OBJS) $(EXECUTABLE) $(LIBRARY) - - - - -.PHONY: all clean dist distclean - -.SUFFIXES: .cxx -ifndef HAVE_GCC3 -# If you use GCC, disable the above and enable this for intelligent -# dependency tracking. -.cxx.o: - $(MKDIR) $(*D)/$(DEPDIR) - $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d2" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o - $(ECHO) "$(*D)/" > $(*D)/$(DEPDIR)/$(*F).d - $(CAT) "$(*D)/$(DEPDIR)/$(*F).d2" >> "$(*D)/$(DEPDIR)/$(*F).d" - $(RM) "$(*D)/$(DEPDIR)/$(*F).d2" - -.c.o: - $(MKDIR) $(*D)/$(DEPDIR) - $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d2" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o - $(ECHO) "$(*D)/" > $(*D)/$(DEPDIR)/$(*F).d - $(CAT) "$(*D)/$(DEPDIR)/$(*F).d2" >> "$(*D)/$(DEPDIR)/$(*F).d" - $(RM) "$(*D)/$(DEPDIR)/$(*F).d2" -else -# If you even have GCC 3.x, you can use this build rule, which is safer; the above -# rule can get you into a bad state if you Ctrl-C at the wrong moment. -# Also, with this GCC inserts additional dummy rules for the involved headers, -# which ensures a smooth compilation even if said headers become obsolete. -.cxx.o: - $(MKDIR) $(*D)/$(DEPDIR) - $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o - -.c.o: - $(MKDIR) $(*D)/$(DEPDIR) - $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o -endif - -ifdef HAVE_NASM -.SUFFIXES: .asm -.asm.o: - $(NASM) -O1 $(NASMFLAGS) -g -o $*.o $(<) -endif - -# Include the dependency tracking files. We add /dev/null at the end -# of the list to avoid a warning/error if no .d file exist --include $(wildcard $(addsuffix /*.d,$(DEPDIRS))) /dev/null - -# check if configure has been run or has been changed since last run -config.mak: $(srcdir)/configure - @echo "You need to run ./configure before you can run make" - @echo "Either you haven't run it before or it has changed." - @exit 1 - -install: all - $(INSTALL) -d "$(DESTDIR)$(BINDIR)" - $(INSTALL) -c -s -m 755 "$(srcdir)/stella$(EXEEXT)" "$(DESTDIR)$(BINDIR)/stella$(EXEEXT)" - $(INSTALL) -d "$(DESTDIR)$(DOCDIR)" - $(INSTALL) -c -m 644 "$(srcdir)/Announce.txt" "$(srcdir)/Changes.txt" "$(srcdir)/Copyright.txt" "$(srcdir)/License.txt" "$(srcdir)/README-SDL.txt" "$(srcdir)/Readme.txt" "$(srcdir)/Todo.txt" "$(srcdir)/docs/index.html" "$(srcdir)/docs/debugger.html" "$(DESTDIR)$(DOCDIR)/" - $(INSTALL) -d "$(DESTDIR)$(DOCDIR)/graphics" - $(INSTALL) -c -m 644 $(wildcard $(srcdir)/docs/graphics/*.png) "$(DESTDIR)$(DOCDIR)/graphics" - $(INSTALL) -d "$(DESTDIR)$(DATADIR)/applications" - $(INSTALL) -c -m 644 "$(srcdir)/src/unix/stella.desktop" "$(DESTDIR)$(DATADIR)/applications" - $(INSTALL) -d "$(DESTDIR)$(DATADIR)/icons" - $(INSTALL) -d "$(DESTDIR)$(DATADIR)/icons/mini" - $(INSTALL) -d "$(DESTDIR)$(DATADIR)/icons/large" - $(INSTALL) -c -m 644 "$(srcdir)/src/common/stella.png" "$(DESTDIR)$(DATADIR)/icons" - $(INSTALL) -c -m 644 "$(srcdir)/src/common/stella.png" "$(DESTDIR)$(DATADIR)/icons/mini" - $(INSTALL) -c -m 644 "$(srcdir)/src/common/stella.png" "$(DESTDIR)$(DATADIR)/icons/large" - -install-strip: install - strip stella$(EXEEXT) - -uninstall: - rm -f "$(DESTDIR)$(BINDIR)/stella$(EXEEXT)" - rm -rf "$(DESTDIR)$(DOCDIR)/" - rm -f "$(DESTDIR)$(DATADIR)/applications/stella.desktop" - rm -f "$(DESTDIR)$(DATADIR)/icons/stella.png" - rm -f "$(DESTDIR)$(DATADIR)/icons/mini/stella.png" - rm -f "$(DESTDIR)$(DATADIR)/icons/large/stella.png" - - -# Use Exuberant ctags (the one from Slackware's vim package, for instance), -# not the one from emacs! -tags: - ctags `find . -name '*.[ch]xx' -o -name '*.c' -o -name '*.y'` || true - - diff --git a/atari_py/ale_interface/makefile.unix b/atari_py/ale_interface/makefile.unix deleted file mode 100644 index 1367ba7..0000000 --- a/atari_py/ale_interface/makefile.unix +++ /dev/null @@ -1,246 +0,0 @@ -##============================================================================ -# makefile for the A.L.E: Atari Learing Environment (Powered by Stella) -##============================================================================ - -srcdir ?= . -# Set this to 1 to enable SDL, display_screen, and sound support -USE_SDL := 0 -# Set this to 1 to enable the RLGlue interface -USE_RLGLUE := 0 -DEFINES := -DRLGENV_NOMAINLOOP -LDFLAGS := -# /usr/local/include for RL-Glue -INCLUDES := -Isrc/controllers -Isrc/os_dependent -I/usr/include -I/usr/local/include -Isrc/environment -Isrc/external -LIBS_RLGLUE := -lrlutils -lrlgluenetdev -LIBS := -OBJS := -PROF := -MODULES := -MODULE_DIRS := -DISTNAME := atari_learning_environment -DEBUG := 0 - -# -------- Generated by configure ----------- -CXX := g++ -CXXFLAGS := -LD := g++ -LIBS += -lz -RANLIB := ranlib -INSTALL := install -AR := ar cru -MKDIR := mkdir -p -ECHO := printf -CAT := cat -RM := rm -f -RM_REC := rm -f -r -ZIP := zip -q -CP := cp - - -# MODULES += src/unix -MODULE_DIRS += -EXEEXT := -NASM := /usr/bin/nasm -NASMFLAGS := -f elf - -PREFIX := /usr/local -BINDIR := /usr/local/bin -DOCDIR := /usr/local/share/doc/stella -DATADIR := /usr/local/share -PROFILE := - -HAVE_GCC3 = 1 -HAVE_NASM = 1 - -INCLUDES += -Isrc/games -Isrc/emucore -Isrc/emucore/m6502/src -Isrc/emucore/m6502/src/bspf/src -Isrc/common -Isrc/controllers -Isrc/environment -OBJS += -DEFINES += -DUNIX -DHAS_ALTIVEC -DUSE_NASM -DBSPF_UNIX -DHAVE_INTTYPES -DWINDOWED_SUPPORT -DHAVE_GETTIMEOFDAY -DSNAPSHOT_SUPPORT -LDFLAGS += - -ifeq ($(strip $(USE_SDL)), 1) - CXXFLAGS+=$(shell sdl-config --cflags) - LIBS+=$(shell sdl-config --libs) - DEFINES += -D__USE_SDL -DSOUND_SUPPORT -endif - -ifeq ($(strip $(USE_RLGLUE)), 1) - DEFINES += -D__USE_RLGLUE - LIBS += $(LIBS_RLGLUE) -endif - - -# Uncomment this for stricter compile time code verification -# CXXFLAGS+= -Werror - -CXXFLAGS += -Wall -Wunused -fPIC - -ifeq ($(strip $(DEBUG)), 1) - CXXFLAGS += -g -O0 -else - CXXFLAGS += -O3 -endif - -ifdef PROFILE - PROF:= -g -pg -fprofile-arcs -ftest-coverage - CXXFLAGS+= $(PROF) -else - CXXFLAGS+= -fomit-frame-pointer -endif - -# Even more warnings... -#CXXFLAGS+= -pedantic -Wpointer-arith -Wcast-qual -Wconversion -#CXXFLAGS+= -Wshadow -Wimplicit -Wundef -Wnon-virtual-dtor -#CXXFLAGS+= -Wno-reorder -Wwrite-strings -fcheck-new -Wctor-dtor-privacy - -####################################################################### -# Misc stuff - you should never have to edit this # -####################################################################### - -EXECUTABLE := ale$(EXEEXT) -LIBRARY := libale.so - -all: tags $(EXECUTABLE) $(LIBRARY) - - -###################################################################### -# Various minor settings -###################################################################### - -# The name for the directory used for dependency tracking -DEPDIR := .deps - - -###################################################################### -# Module settings -###################################################################### - -MODULES := $(MODULES) - -# After the game specific modules follow the shared modules -MODULES += \ - src \ - src/emucore \ - src/emucore/m6502 \ - src/common \ - src/controllers \ - src/os_dependent \ - src/games \ - src/environment \ - src/external - - -###################################################################### -# The build rules follow - normally you should have no need to -# touch whatever comes after here. -###################################################################### - -# Concat DEFINES and INCLUDES to form the CPPFLAGS -CPPFLAGS:= $(DEFINES) $(INCLUDES) - -# Include the build instructions for all modules --include $(addprefix $(srcdir)/, $(addsuffix /module.mk,$(MODULES))) - -# Depdir information -DEPDIRS = $(addsuffix /$(DEPDIR),$(MODULE_DIRS)) -DEPFILES = - -# The build rule for the Stella executable -$(EXECUTABLE): $(OBJS) - $(LD) $(LDFLAGS) $(PRE_OBJS_FLAGS) $+ $(POST_OBJS_FLAGS) $(LIBS) $(PROF) -o $@ - -$(LIBRARY): $(OBJS) - $(LD) $(LDFLAGS) -shared -o $(LIBRARY) $(OBJS) $(LIBS) - -distclean: clean - $(RM_REC) $(DEPDIRS) - $(RM) build.rules config.h config.mak config.log - -clean: - $(RM) $(OBJS) $(EXECUTABLE) $(LIBRARY) - - - - -.PHONY: all clean dist distclean - -.SUFFIXES: .cxx -ifndef HAVE_GCC3 -# If you use GCC, disable the above and enable this for intelligent -# dependency tracking. -.cxx.o: - $(MKDIR) $(*D)/$(DEPDIR) - $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d2" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o - $(ECHO) "$(*D)/" > $(*D)/$(DEPDIR)/$(*F).d - $(CAT) "$(*D)/$(DEPDIR)/$(*F).d2" >> "$(*D)/$(DEPDIR)/$(*F).d" - $(RM) "$(*D)/$(DEPDIR)/$(*F).d2" - -.c.o: - $(MKDIR) $(*D)/$(DEPDIR) - $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d2" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o - $(ECHO) "$(*D)/" > $(*D)/$(DEPDIR)/$(*F).d - $(CAT) "$(*D)/$(DEPDIR)/$(*F).d2" >> "$(*D)/$(DEPDIR)/$(*F).d" - $(RM) "$(*D)/$(DEPDIR)/$(*F).d2" -else -# If you even have GCC 3.x, you can use this build rule, which is safer; the above -# rule can get you into a bad state if you Ctrl-C at the wrong moment. -# Also, with this GCC inserts additional dummy rules for the involved headers, -# which ensures a smooth compilation even if said headers become obsolete. -.cxx.o: - $(MKDIR) $(*D)/$(DEPDIR) - $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o - -.c.o: - $(MKDIR) $(*D)/$(DEPDIR) - $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o -endif - -ifdef HAVE_NASM -.SUFFIXES: .asm -.asm.o: - $(NASM) -O1 $(NASMFLAGS) -g -o $*.o $(<) -endif - -# Include the dependency tracking files. We add /dev/null at the end -# of the list to avoid a warning/error if no .d file exist --include $(wildcard $(addsuffix /*.d,$(DEPDIRS))) /dev/null - -# check if configure has been run or has been changed since last run -config.mak: $(srcdir)/configure - @echo "You need to run ./configure before you can run make" - @echo "Either you haven't run it before or it has changed." - @exit 1 - -install: all - $(INSTALL) -d "$(DESTDIR)$(BINDIR)" - $(INSTALL) -c -s -m 755 "$(srcdir)/stella$(EXEEXT)" "$(DESTDIR)$(BINDIR)/stella$(EXEEXT)" - $(INSTALL) -d "$(DESTDIR)$(DOCDIR)" - $(INSTALL) -c -m 644 "$(srcdir)/Announce.txt" "$(srcdir)/Changes.txt" "$(srcdir)/Copyright.txt" "$(srcdir)/License.txt" "$(srcdir)/README-SDL.txt" "$(srcdir)/Readme.txt" "$(srcdir)/Todo.txt" "$(srcdir)/docs/index.html" "$(srcdir)/docs/debugger.html" "$(DESTDIR)$(DOCDIR)/" - $(INSTALL) -d "$(DESTDIR)$(DOCDIR)/graphics" - $(INSTALL) -c -m 644 $(wildcard $(srcdir)/docs/graphics/*.png) "$(DESTDIR)$(DOCDIR)/graphics" - $(INSTALL) -d "$(DESTDIR)$(DATADIR)/applications" - $(INSTALL) -c -m 644 "$(srcdir)/src/unix/stella.desktop" "$(DESTDIR)$(DATADIR)/applications" - $(INSTALL) -d "$(DESTDIR)$(DATADIR)/icons" - $(INSTALL) -d "$(DESTDIR)$(DATADIR)/icons/mini" - $(INSTALL) -d "$(DESTDIR)$(DATADIR)/icons/large" - $(INSTALL) -c -m 644 "$(srcdir)/src/common/stella.png" "$(DESTDIR)$(DATADIR)/icons" - $(INSTALL) -c -m 644 "$(srcdir)/src/common/stella.png" "$(DESTDIR)$(DATADIR)/icons/mini" - $(INSTALL) -c -m 644 "$(srcdir)/src/common/stella.png" "$(DESTDIR)$(DATADIR)/icons/large" - -install-strip: install - strip stella$(EXEEXT) - -uninstall: - rm -f "$(DESTDIR)$(BINDIR)/stella$(EXEEXT)" - rm -rf "$(DESTDIR)$(DOCDIR)/" - rm -f "$(DESTDIR)$(DATADIR)/applications/stella.desktop" - rm -f "$(DESTDIR)$(DATADIR)/icons/stella.png" - rm -f "$(DESTDIR)$(DATADIR)/icons/mini/stella.png" - rm -f "$(DESTDIR)$(DATADIR)/icons/large/stella.png" - - -# Use Exuberant ctags (the one from Slackware's vim package, for instance), -# not the one from emacs! -tags: - ctags `find . -name '*.[ch]xx' -o -name '*.c' -o -name '*.y'` || true - - diff --git a/atari_py/ale_interface/setup.sh b/atari_py/ale_interface/setup.sh deleted file mode 100755 index 2d66814..0000000 --- a/atari_py/ale_interface/setup.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -set -e -mkdir -p build && cd build && cmake .. && make -j4 diff --git a/atari_py/ale_interface/src/common/module.mk b/atari_py/ale_interface/src/common/module.mk deleted file mode 100644 index 336f4fe..0000000 --- a/atari_py/ale_interface/src/common/module.mk +++ /dev/null @@ -1,18 +0,0 @@ -MODULE := src/common - -MODULE_OBJS := \ - src/common/SoundNull.o \ - src/common/SoundSDL.o \ - src/common/SoundExporter.o\ - src/common/display_screen.o \ - src/common/ColourPalette.o \ - src/common/ScreenExporter.o \ - src/common/Constants.o \ - src/common/Defaults.o \ - src/common/Log.o - -MODULE_DIRS += \ - src/common - -# Include common rules -include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/controllers/module.mk b/atari_py/ale_interface/src/controllers/module.mk deleted file mode 100644 index 6363a6c..0000000 --- a/atari_py/ale_interface/src/controllers/module.mk +++ /dev/null @@ -1,12 +0,0 @@ -MODULE := src/controllers - -MODULE_OBJS := \ - src/controllers/ale_controller.o \ - src/controllers/fifo_controller.o \ - src/controllers/rlglue_controller.o \ - -MODULE_DIRS += \ - src/controllers - -# Include common rules -include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/emucore/m6502/module.mk b/atari_py/ale_interface/src/emucore/m6502/module.mk deleted file mode 100644 index 9361d5b..0000000 --- a/atari_py/ale_interface/src/emucore/m6502/module.mk +++ /dev/null @@ -1,15 +0,0 @@ -MODULE := src/emucore/m6502 - -MODULE_OBJS := \ - src/emucore/m6502/src/Device.o \ - src/emucore/m6502/src/M6502.o \ - src/emucore/m6502/src/M6502Low.o \ - src/emucore/m6502/src/M6502Hi.o \ - src/emucore/m6502/src/NullDev.o \ - src/emucore/m6502/src/System.o - -MODULE_DIRS += \ - src/emucore/m6502/src - -# Include common rules -include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/emucore/module.mk b/atari_py/ale_interface/src/emucore/module.mk deleted file mode 100644 index 54483c2..0000000 --- a/atari_py/ale_interface/src/emucore/module.mk +++ /dev/null @@ -1,57 +0,0 @@ -MODULE := src/emucore - -MODULE_OBJS := \ - src/emucore/AtariVox.o \ - src/emucore/Booster.o \ - src/emucore/Cart2K.o \ - src/emucore/Cart3F.o \ - src/emucore/Cart3E.o \ - src/emucore/Cart4A50.o \ - src/emucore/Cart4K.o \ - src/emucore/CartAR.o \ - src/emucore/CartCV.o \ - src/emucore/Cart.o \ - src/emucore/CartDPC.o \ - src/emucore/CartE0.o \ - src/emucore/CartE7.o \ - src/emucore/CartF4.o \ - src/emucore/CartF4SC.o \ - src/emucore/CartF6.o \ - src/emucore/CartF6SC.o \ - src/emucore/CartF8.o \ - src/emucore/CartF8SC.o \ - src/emucore/CartFASC.o \ - src/emucore/CartFE.o \ - src/emucore/CartMB.o \ - src/emucore/CartMC.o \ - src/emucore/CartUA.o \ - src/emucore/Cart0840.o \ - src/emucore/Console.o \ - src/emucore/Control.o \ - src/emucore/Deserializer.o \ - src/emucore/Driving.o \ - src/emucore/Event.o \ - src/emucore/FSNode.o \ - src/emucore/Joystick.o \ - src/emucore/Keyboard.o \ - src/emucore/M6532.o \ - src/emucore/MD5.o \ - src/emucore/MediaSrc.o \ - src/emucore/OSystem.o \ - src/emucore/Paddles.o \ - src/emucore/Props.o \ - src/emucore/PropsSet.o \ - src/emucore/Random.o \ - src/emucore/Serializer.o \ - src/emucore/Settings.o \ - src/emucore/SpeakJet.o \ - src/emucore/Switches.o \ - src/emucore/TIA.o \ - src/emucore/TIASnd.o \ - src/emucore/unzip.o \ - -MODULE_DIRS += \ - src/emucore - -# Include common rules -include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/emucore/rsynth/module.mk b/atari_py/ale_interface/src/emucore/rsynth/module.mk deleted file mode 100644 index b1ad52a..0000000 --- a/atari_py/ale_interface/src/emucore/rsynth/module.mk +++ /dev/null @@ -1,16 +0,0 @@ -MODULE := src/emucore/rsynth - -MODULE_OBJS := \ - src/emucore/rsynth/darray.o \ - src/emucore/rsynth/elements.o \ - src/emucore/rsynth/holmes.o \ - src/emucore/rsynth/opsynth.o \ - src/emucore/rsynth/phones.o \ - src/emucore/rsynth/phtoelm.o \ - src/emucore/rsynth/trie.o - -MODULE_DIRS += \ - src/emucore/rsynth - -# Include common rules -include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/environment/module.mk b/atari_py/ale_interface/src/environment/module.mk deleted file mode 100644 index c35a5ab..0000000 --- a/atari_py/ale_interface/src/environment/module.mk +++ /dev/null @@ -1,12 +0,0 @@ -MODULE := src/environment - -MODULE_OBJS := \ - src/environment/ale_state.o \ - src/environment/stella_environment.o \ - src/environment/phosphor_blend.o \ - -MODULE_DIRS += \ - src/environment - -# Include common rules -include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/external/module.mk b/atari_py/ale_interface/src/external/module.mk deleted file mode 100644 index 9e25b44..0000000 --- a/atari_py/ale_interface/src/external/module.mk +++ /dev/null @@ -1,10 +0,0 @@ -MODULE := src/external - -MODULE_OBJS := \ - src/external/TinyMT/tinymt32.o \ - -MODULE_DIRS += \ - src/external/TinyMT - -# Include common rules -include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/games/module.mk b/atari_py/ale_interface/src/games/module.mk deleted file mode 100644 index 3af60e7..0000000 --- a/atari_py/ale_interface/src/games/module.mk +++ /dev/null @@ -1,73 +0,0 @@ -MODULE := src/games - -MODULE_OBJS := \ - src/games/Roms.o \ - src/games/RomSettings.o \ - src/games/RomUtils.o \ - src/games/supported/AirRaid.o \ - src/games/supported/Alien.o \ - src/games/supported/Amidar.o \ - src/games/supported/Assault.o \ - src/games/supported/Asterix.o \ - src/games/supported/Asteroids.o \ - src/games/supported/Atlantis.o \ - src/games/supported/BankHeist.o \ - src/games/supported/BattleZone.o \ - src/games/supported/BeamRider.o \ - src/games/supported/Berzerk.o \ - src/games/supported/Bowling.o \ - src/games/supported/Boxing.o \ - src/games/supported/Breakout.o \ - src/games/supported/Carnival.o \ - src/games/supported/Centipede.o \ - src/games/supported/ChopperCommand.o \ - src/games/supported/CrazyClimber.o \ - src/games/supported/Defender.o \ - src/games/supported/DemonAttack.o \ - src/games/supported/DoubleDunk.o \ - src/games/supported/ElevatorAction.o \ - src/games/supported/Enduro.o \ - src/games/supported/FishingDerby.o \ - src/games/supported/Freeway.o \ - src/games/supported/Frostbite.o \ - src/games/supported/Gopher.o \ - src/games/supported/Gravitar.o \ - src/games/supported/Hero.o \ - src/games/supported/IceHockey.o \ - src/games/supported/JamesBond.o \ - src/games/supported/JourneyEscape.o \ - src/games/supported/Kangaroo.o \ - src/games/supported/Krull.o \ - src/games/supported/KungFuMaster.o \ - src/games/supported/MontezumaRevenge.o \ - src/games/supported/MsPacman.o \ - src/games/supported/NameThisGame.o \ - src/games/supported/Phoenix.o \ - src/games/supported/Pitfall.o \ - src/games/supported/Pong.o \ - src/games/supported/Pooyan.o \ - src/games/supported/PrivateEye.o \ - src/games/supported/QBert.o \ - src/games/supported/RiverRaid.o \ - src/games/supported/RoadRunner.o \ - src/games/supported/RoboTank.o \ - src/games/supported/Seaquest.o \ - src/games/supported/Skiing.o \ - src/games/supported/Solaris.o \ - src/games/supported/SpaceInvaders.o \ - src/games/supported/StarGunner.o \ - src/games/supported/Tennis.o \ - src/games/supported/TimePilot.o \ - src/games/supported/Tutankham.o \ - src/games/supported/UpNDown.o \ - src/games/supported/Venture.o \ - src/games/supported/VideoPinball.o \ - src/games/supported/WizardOfWor.o \ - src/games/supported/YarsRevenge.o \ - src/games/supported/Zaxxon.o \ - -MODULE_DIRS += \ - src/games - -# Include common rules -include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/module.mk b/atari_py/ale_interface/src/module.mk deleted file mode 100644 index eaf33fc..0000000 --- a/atari_py/ale_interface/src/module.mk +++ /dev/null @@ -1,11 +0,0 @@ -MODULE := src/ - -MODULE_OBJS := \ - src/main.o \ - src/ale_interface.o - -MODULE_DIRS += \ - src/ - -# Include common rules -include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/os_dependent/module.mk b/atari_py/ale_interface/src/os_dependent/module.mk deleted file mode 100644 index d6adcef..0000000 --- a/atari_py/ale_interface/src/os_dependent/module.mk +++ /dev/null @@ -1,12 +0,0 @@ -MODULE := src/os_dependent - -MODULE_OBJS := \ - src/os_dependent/FSNodePOSIX.o \ - src/os_dependent/OSystemUNIX.o \ - src/os_dependent/SettingsUNIX.o \ - -MODULE_DIRS += \ - src/os_dependent - -# Include common rules -include $(srcdir)/common.rules From 1324a5b05cdf6b87b1ffc6d25a187e18efcaac1c Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Tue, 4 Apr 2017 14:34:25 -0700 Subject: [PATCH 026/310] switch to new ALE build with separated targets only build the ALE C library as required for the Python interface, instead of unnecessarily building the C++ library and CLI --- atari_py/ale_interface/CMakeLists.txt | 157 +++++++++++++++++++++++--- 1 file changed, 140 insertions(+), 17 deletions(-) diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index 140ef1b..207ceb7 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -1,9 +1,14 @@ cmake_minimum_required (VERSION 2.6) project(ale) +set(ALEVERSION "0.5") + option(USE_SDL "Use SDL" OFF) option(USE_RLGLUE "Use RL-Glue" OFF) option(BUILD_EXAMPLES "Build Example Agents" OFF) +option(BUILD_CPP_LIB "Build C++ Shared Library" OFF) +option(BUILD_CLI "Build ALE Command Line Interface" OFF) +option(BUILD_C_LIB "Build ALE C Library (needed for Python interface)" ON) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunused -fPIC -O3 -fomit-frame-pointer -D__STDC_CONSTANT_MACROS") add_definitions(-DHAVE_INTTYPES) @@ -54,8 +59,57 @@ if(WINDOWS OR MINGW) list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsWin32.cxx ${SOURCE_DIR}/os_dependent/OSystemWin32.cxx ${SOURCE_DIR}/os_dependent/FSNodeWin32.cxx) else() list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsUNIX.cxx ${SOURCE_DIR}/os_dependent/OSystemUNIX.cxx ${SOURCE_DIR}/os_dependent/FSNodePOSIX.cxx) + SET(BIN_INSTALL_DIR "bin") + SET(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) + SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE STRING "Library directory name") + SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE STRING "Headers directory name") + SET(PKGCONFIG_INSTALL_DIR "${LIB_INSTALL_DIR}/pkgconfig/" CACHE STRING "Base directory for pkgconfig files") + endif() +# List and set the install targets for the headers, generate and install the pkgconfig file +if(UNIX) + + INSTALL(FILES ${SOURCE_DIR}/os_dependent/SettingsUNIX.hxx ${SOURCE_DIR}/os_dependent/SettingsWin32.hxx ${SOURCE_DIR}/os_dependent/OSystemUNIX.hxx ${SOURCE_DIR}/os_dependent/OSystemWin32.hxx DESTINATION ${INCLUDE_INSTALL_DIR}/${PROJECT_NAME}/os_dependent) + file(GLOB module_headers ${SOURCE_DIR}/*.h?[xp]) + foreach(header ${module_headers}) + INSTALL(FILES ${header} DESTINATION ${INCLUDE_INSTALL_DIR}/${PROJECT_NAME}) + endforeach(header ${HEADERS}) + + foreach(module ${MODULES}) + file(GLOB module_headers ${SOURCE_DIR}/${module}/*.h) + foreach(header ${module_headers}) + INSTALL(FILES ${header} DESTINATION ${INCLUDE_INSTALL_DIR}/${PROJECT_NAME}/${module}/) + endforeach(header ${HEADERS}) + + file(GLOB module_headers ${SOURCE_DIR}/${module}/*.h?[xp]) + foreach(header ${module_headers}) + INSTALL(FILES ${header} DESTINATION ${INCLUDE_INSTALL_DIR}/${PROJECT_NAME}/${module}/) + endforeach(header ${HEADERS}) + endforeach(module ${MODULES}) + + ################################### + # Pkg-config stuff + ################################### + + FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc +" +Name: ${PROJECT_NAME} +Description: The Arcade Learning Environment (ALE) - a platform for AI research. +URL: http://www.arcadelearningenvironment.org/ +Version: ${ALEVERSION} +Requires: +Libs: -L${LIB_INSTALL_DIR} -lale +Cflags: -I${INCLUDE_INSTALL_DIR} +" +) + + +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc + DESTINATION ${PKGCONFIG_INSTALL_DIR}) + +endif(UNIX) + include_directories( ${SOURCE_DIR} ${SOURCE_DIR}/common @@ -71,31 +125,63 @@ include_directories( ${SOURCE_DIR}/external/TinyMT ) -add_library(ale-lib SHARED ${SOURCE_DIR}/ale_interface.cpp ${SOURCES}) -set_target_properties(ale-lib PROPERTIES OUTPUT_NAME ale) -set_target_properties(ale-lib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) -add_executable(ale-bin ${SOURCE_DIR}/main.cpp ${SOURCE_DIR}/ale_interface.cpp ${SOURCES}) -set_target_properties(ale-bin PROPERTIES OUTPUT_NAME ale) -set_target_properties(ale-bin PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) -add_library(ale-c-lib SHARED ${CMAKE_CURRENT_SOURCE_DIR}/../ale_c_wrapper.cpp ${SOURCE_DIR}/ale_interface.cpp ${SOURCES}) -set_target_properties(ale-c-lib PROPERTIES OUTPUT_NAME ale_c) -set_target_properties(ale-c-lib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) +if(BUILD_CPP_LIB) + add_library(ale-lib SHARED ${SOURCE_DIR}/ale_interface.cpp ${SOURCES}) + set_target_properties(ale-lib PROPERTIES OUTPUT_NAME ale) + set_target_properties(ale-lib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + if(UNIX) + install(TARGETS ale-lib + DESTINATION ${LIB_INSTALL_DIR}) + endif() + target_link_libraries(ale-lib ${LINK_LIBS}) +endif() + +if(BUILD_ALE_BIN) + add_executable(ale-bin ${SOURCE_DIR}/main.cpp ${SOURCE_DIR}/ale_interface.cpp ${SOURCES}) + set_target_properties(ale-bin PROPERTIES OUTPUT_NAME ale) + set_target_properties(ale-bin PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + if(UNIX) + install(TARGETS ale-bin + DESTINATION ${BIN_INSTALL_DIR}) + endif() + target_link_libraries(ale-bin ${LINK_LIBS}) +endif() -target_link_libraries(ale-lib ${LINK_LIBS}) -target_link_libraries(ale-bin ${LINK_LIBS}) -target_link_libraries(ale-c-lib ${LINK_LIBS}) +if(BUILD_C_LIB) + add_library(ale-c-lib SHARED ${CMAKE_CURRENT_SOURCE_DIR}/../ale_c_wrapper.cpp ${SOURCE_DIR}/ale_interface.cpp ${SOURCES}) + set_target_properties(ale-c-lib PROPERTIES OUTPUT_NAME ale_c) + set_target_properties(ale-c-lib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + if(UNIX) + install(TARGETS ale-c-lib + DESTINATION ${LIB_INSTALL_DIR}) + endif() + target_link_libraries(ale-c-lib ${LINK_LIBS}) +endif() if(BUILD_EXAMPLES) + # Shared library example. link_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_executable(sharedLibraryInterfaceExample ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples/sharedLibraryInterfaceExample.cpp) - set_target_properties(sharedLibraryInterfaceExample PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples) + set_target_properties(sharedLibraryInterfaceExample PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/doc/examples) + set_target_properties(sharedLibraryInterfaceExample PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-sharedLibraryInterfaceExample) target_link_libraries(sharedLibraryInterfaceExample ale) target_link_libraries(sharedLibraryInterfaceExample ${LINK_LIBS}) add_dependencies(sharedLibraryInterfaceExample ale-lib) - + + # Fifo interface example. + link_directories(${CMAKE_CURRENT_SOURCE_DIR}) + add_executable(fifoInterfaceExample ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples/fifoInterfaceExample.cpp) + set_target_properties(fifoInterfaceExample PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/doc/examples) + set_target_properties(fifoInterfaceExample PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-fifoInterfaceExample) + target_link_libraries(fifoInterfaceExample ale) + target_link_libraries(fifoInterfaceExample ${LINK_LIBS}) + add_dependencies(fifoInterfaceExample ale-lib) + + # Example showing how to record an Atari 2600 video. if (USE_SDL) add_executable(videoRecordingExample ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples/videoRecordingExample.cpp) - set_target_properties(videoRecordingExample PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples) + set_target_properties(videoRecordingExample PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/doc/examples) + set_target_properties(videoRecordingExample PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-videoRecordingExample) target_link_libraries(videoRecordingExample ale) target_link_libraries(videoRecordingExample ${LINK_LIBS}) add_dependencies(videoRecordingExample ale-lib) @@ -104,13 +190,50 @@ endif() if(USE_RLGLUE) add_executable(RLGlueAgent ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples/RLGlueAgent.c) - set_target_properties(RLGlueAgent PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples) + set_target_properties(RLGlueAgent PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/doc/examples) + set_target_properties(RLGlueAgent PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-RLGlueAgent) target_link_libraries(RLGlueAgent rlutils) target_link_libraries(RLGlueAgent rlagent) target_link_libraries(RLGlueAgent rlgluenetdev) + add_executable(RLGlueExperiment ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples/RLGlueExperiment.c) - set_target_properties(RLGlueExperiment PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples) + set_target_properties(RLGlueExperiment PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/doc/examples) + set_target_properties(RLGlueExperiment PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-RLGlueExperiment) target_link_libraries(RLGlueExperiment rlutils) target_link_libraries(RLGlueExperiment rlexperiment) target_link_libraries(RLGlueExperiment rlgluenetdev) + endif() + + +########### Add uninstall target ############### + FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake +" +IF(NOT EXISTS \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\") + MESSAGE(FATAL_ERROR \"Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\") +ENDIF(NOT EXISTS \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\") + +FILE(READ \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\" files) +STRING(REGEX REPLACE \"\\n\" \";\" files \"\${files}\") +FOREACH(file \${files}) + MESSAGE(STATUS \"Uninstalling \"\$ENV{DESTDIR}\${file}\"\") + IF(EXISTS \"\$ENV{DESTDIR}\${file}\") + EXEC_PROGRAM( + \"@CMAKE_COMMAND@\" ARGS \"-E remove \"\$ENV{DESTDIR}\${file}\"\" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + IF(NOT \"\${rm_retval}\" STREQUAL 0) + MESSAGE(FATAL_ERROR \"Problem when removing \"\$ENV{DESTDIR}\${file}\"\") + ENDIF(NOT \"\${rm_retval}\" STREQUAL 0) + ELSE(EXISTS \"\$ENV{DESTDIR}\${file}\") + MESSAGE(STATUS \"File \"\$ENV{DESTDIR}\${file}\" does not exist.\") + ENDIF(EXISTS \"\$ENV{DESTDIR}\${file}\") +ENDFOREACH(file) +") + +ADD_CUSTOM_TARGET(uninstall + "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + COMMAND rm -rf ${INCLUDE_INSTALL_DIR}/ale) + + From 1eb49e92e91a24b694ce45197ad3f637bab68497 Mon Sep 17 00:00:00 2001 From: Trevor Blackwell Date: Wed, 5 Apr 2017 21:08:57 -0700 Subject: [PATCH 027/310] Bump version to 0.0.21 after major build changes --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 84ed77c..cd22780 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.0.20', + version='0.0.21', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From eed97d1f1ffda192557325cd104a102d914ab4b5 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Wed, 12 Apr 2017 17:01:32 -0700 Subject: [PATCH 028/310] fix #10: flag naming mismatch (does not effect our build) --- atari_py/ale_interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index 207ceb7..d8f1906 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -136,7 +136,7 @@ if(BUILD_CPP_LIB) target_link_libraries(ale-lib ${LINK_LIBS}) endif() -if(BUILD_ALE_BIN) +if(BUILD_CLI) add_executable(ale-bin ${SOURCE_DIR}/main.cpp ${SOURCE_DIR}/ale_interface.cpp ${SOURCES}) set_target_properties(ale-bin PROPERTIES OUTPUT_NAME ale) set_target_properties(ale-bin PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) From 199fdf3ac3eb65889938b242bf77cfbaf9b12b24 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Wed, 12 Apr 2017 17:15:35 -0700 Subject: [PATCH 029/310] update ROMs these ALE fixes alter the semantics of the following Atari envs: - Asteroids: add score wrapping - Breakout: reduce minimal action set - Kaboom: add missing action, fix terminal (was never done?) - Kangaroo: different score(?) - QBert: fix lives/terminal issue - WizardOfWor: different score and lives(?) --- .../ale_interface/src/games/supported/Asteroids.cpp | 10 ++++++++-- .../ale_interface/src/games/supported/Breakout.cpp | 2 -- atari_py/ale_interface/src/games/supported/Kaboom.cpp | 7 ++++--- .../ale_interface/src/games/supported/Kangaroo.cpp | 2 +- atari_py/ale_interface/src/games/supported/QBert.cpp | 2 +- .../ale_interface/src/games/supported/WizardOfWor.cpp | 4 ++-- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/atari_py/ale_interface/src/games/supported/Asteroids.cpp b/atari_py/ale_interface/src/games/supported/Asteroids.cpp index 5fbab0d..b91cb9f 100644 --- a/atari_py/ale_interface/src/games/supported/Asteroids.cpp +++ b/atari_py/ale_interface/src/games/supported/Asteroids.cpp @@ -48,13 +48,19 @@ RomSettings* AsteroidsSettings::clone() const { void AsteroidsSettings::step(const System& system) { // update the reward - reward_t score = getDecimalScore(62, 61, &system); + reward_t score = getDecimalScore(0xBE, 0xBD, &system); score *= 10; m_reward = score - m_score; + // Deal with score wrapping. In truth this should be done for all games and in a more + // uniform fashion. + if (m_reward < 0) { + const int WRAP_SCORE = 100000; + m_reward += WRAP_SCORE; + } m_score = score; // update terminal status - int byte = readRam(&system, 0x3C); + int byte = readRam(&system, 0xBC); m_lives = (byte - (byte & 15)) >> 4; m_terminal = (m_lives == 0); } diff --git a/atari_py/ale_interface/src/games/supported/Breakout.cpp b/atari_py/ale_interface/src/games/supported/Breakout.cpp index c7062c1..10fb51f 100644 --- a/atari_py/ale_interface/src/games/supported/Breakout.cpp +++ b/atari_py/ale_interface/src/games/supported/Breakout.cpp @@ -84,8 +84,6 @@ bool BreakoutSettings::isMinimal(const Action &a) const { case PLAYER_A_FIRE: case PLAYER_A_RIGHT: case PLAYER_A_LEFT: - case PLAYER_A_RIGHTFIRE: - case PLAYER_A_LEFTFIRE: return true; default: return false; diff --git a/atari_py/ale_interface/src/games/supported/Kaboom.cpp b/atari_py/ale_interface/src/games/supported/Kaboom.cpp index ebe7c63..890f4ba 100644 --- a/atari_py/ale_interface/src/games/supported/Kaboom.cpp +++ b/atari_py/ale_interface/src/games/supported/Kaboom.cpp @@ -38,14 +38,14 @@ void KaboomSettings::step(const System& system) { // update terminal status int lives = readRam(&system, 0xA1); - m_terminal = lives == 0x0 || m_score > 999991; + m_terminal = lives == 0x0 || m_score == 999999; } /* is end of game */ bool KaboomSettings::isTerminal() const { - return false; //m_terminal; + return m_terminal; }; @@ -60,9 +60,10 @@ bool KaboomSettings::isMinimal(const Action &a) const { switch (a) { case PLAYER_A_NOOP: + case PLAYER_A_FIRE: case PLAYER_A_RIGHT: case PLAYER_A_LEFT: - return true; + return true; default: return false; } diff --git a/atari_py/ale_interface/src/games/supported/Kangaroo.cpp b/atari_py/ale_interface/src/games/supported/Kangaroo.cpp index aca14a3..cc3f502 100644 --- a/atari_py/ale_interface/src/games/supported/Kangaroo.cpp +++ b/atari_py/ale_interface/src/games/supported/Kangaroo.cpp @@ -48,7 +48,7 @@ RomSettings* KangarooSettings::clone() const { void KangarooSettings::step(const System& system) { // update the reward - int score = getDecimalScore(40, 39, &system); + int score = getDecimalScore(0xA8, 0xA7, &system); score *= 100; int reward = score - m_score; m_reward = reward; diff --git a/atari_py/ale_interface/src/games/supported/QBert.cpp b/atari_py/ale_interface/src/games/supported/QBert.cpp index f144f41..8897327 100644 --- a/atari_py/ale_interface/src/games/supported/QBert.cpp +++ b/atari_py/ale_interface/src/games/supported/QBert.cpp @@ -57,7 +57,7 @@ void QBertSettings::step(const System& system) { int livesAsChar = static_cast(lives_value); if (m_last_lives - 1 == livesAsChar) m_lives--; - m_last_lives = lives_value; + m_last_lives = livesAsChar; // update the reward // Ignore reward if reset the game via the fire button; otherwise the agent diff --git a/atari_py/ale_interface/src/games/supported/WizardOfWor.cpp b/atari_py/ale_interface/src/games/supported/WizardOfWor.cpp index 47ea4b9..ca89ad5 100644 --- a/atari_py/ale_interface/src/games/supported/WizardOfWor.cpp +++ b/atari_py/ale_interface/src/games/supported/WizardOfWor.cpp @@ -48,14 +48,14 @@ RomSettings* WizardOfWorSettings::clone() const { void WizardOfWorSettings::step(const System& system) { // update the reward - reward_t score = getDecimalScore(6, 8, &system); + reward_t score = getDecimalScore(0x86, 0x88, &system); if (score >= 8000) score -= 8000; // MGB score does not go beyond 999 score *= 100; m_reward = score - m_score; m_score = score; // update terminal status - int newLives = readRam(&system, 0x0D) & 15; + int newLives = readRam(&system, 0x8D) & 15; int byte1 = readRam(&system, 0xF4); bool isWaiting = (readRam(&system, 0xD7) & 0x1) == 0; From 9330c9c0a2130f3478b3e5005c689f2190d41a8b Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Wed, 12 Apr 2017 17:20:51 -0700 Subject: [PATCH 030/310] update ALE to master@e1f3bda / version 0.5.1 n.b. only the existing ROMs are updated and new ROMs are not included --- atari_py/ale_interface/src/ale_interface.cpp | 55 +++++--- atari_py/ale_interface/src/ale_interface.hpp | 28 +++- .../src/common/ColourPalette.cpp | 38 +++++- .../src/common/ColourPalette.hpp | 3 + atari_py/ale_interface/src/common/Log.cpp | 2 +- .../src/controllers/fifo_controller.cpp | 15 ++- atari_py/ale_interface/src/emucore/Cart3E.cxx | 2 +- atari_py/ale_interface/src/emucore/CartAR.cxx | 3 +- atari_py/ale_interface/src/emucore/CartCV.cxx | 3 +- atari_py/ale_interface/src/emucore/CartE7.cxx | 3 +- .../ale_interface/src/emucore/CartF4SC.cxx | 3 +- .../ale_interface/src/emucore/CartF6SC.cxx | 3 +- .../ale_interface/src/emucore/CartF8SC.cxx | 3 +- .../ale_interface/src/emucore/CartFASC.cxx | 3 +- atari_py/ale_interface/src/emucore/CartMC.cxx | 3 +- .../ale_interface/src/emucore/Console.cxx | 10 +- .../ale_interface/src/emucore/Console.hxx | 10 +- atari_py/ale_interface/src/emucore/M6532.cxx | 9 +- .../ale_interface/src/emucore/OSystem.cxx | 126 +++++------------- .../ale_interface/src/emucore/OSystem.hxx | 23 +++- atari_py/ale_interface/src/emucore/Random.cxx | 118 ++++++++++++---- atari_py/ale_interface/src/emucore/Random.hxx | 43 ++++-- .../ale_interface/src/emucore/Settings.cxx | 97 ++++++++++++-- .../ale_interface/src/emucore/Settings.hxx | 16 +++ .../src/environment/ale_screen.hpp | 2 +- .../src/environment/ale_state.cpp | 71 +++++++--- .../src/environment/ale_state.hpp | 17 ++- .../src/environment/phosphor_blend.cpp | 15 ++- .../src/environment/stella_environment.cpp | 39 +++--- .../src/environment/stella_environment.hpp | 14 +- .../src/external/TinyMT/tinymt32.c | 6 + atari_py/ale_interface/src/main.cpp | 2 - .../src/os_dependent/OSystemUNIX.cxx | 2 +- .../src/os_dependent/OSystemWin32.cxx | 2 +- doc/manual/manual.pdf | Bin 219597 -> 237670 bytes doc/manual/manual.tex | 76 +++++++---- 36 files changed, 585 insertions(+), 280 deletions(-) diff --git a/atari_py/ale_interface/src/ale_interface.cpp b/atari_py/ale_interface/src/ale_interface.cpp index f8c81b1..6218316 100644 --- a/atari_py/ale_interface/src/ale_interface.cpp +++ b/atari_py/ale_interface/src/ale_interface.cpp @@ -62,8 +62,6 @@ void ALEInterface::createOSystem(std::auto_ptr &theOSystem, theSettings.reset(new SettingsUNIX(theOSystem.get())); #endif - setDefaultSettings(theOSystem->settings()); - theOSystem->settings().loadConfig(); } @@ -91,16 +89,10 @@ void ALEInterface::loadSettings(const string& romfile, exit(1); } - // Seed random number generator - if (theOSystem->settings().getString("random_seed") == "time") { - Logger::Info << "Random Seed: Time" << endl; - Random::seed((uInt32)time(NULL)); - } else { - int seed = theOSystem->settings().getInt("random_seed"); - assert(seed >= 0); - Logger::Info << "Random Seed: " << seed << endl; - Random::seed((uInt32)seed); - } + // Must force the resetting of the OSystem's random seed, which is set before we change + // choose our random seed. + Logger::Info << "Random seed is " << theOSystem->settings().getInt("random_seed") << std::endl; + theOSystem->resetRNGSeed(); string currentDisplayFormat = theOSystem->console().getFormat(); theOSystem->colourPalette().setPalette("standard", currentDisplayFormat); @@ -196,9 +188,8 @@ void ALEInterface::reset_game() { } // Indicates if the game has ended. -bool ALEInterface::game_over() { - return (environment->isTerminal() || - (max_num_frames > 0 && getEpisodeFrameNumber() >= max_num_frames)); +bool ALEInterface::game_over() const { + return environment->isTerminal(); } // The remaining number of lives. @@ -250,7 +241,7 @@ int ALEInterface::getFrameNumber() { } // Returns the frame number since the start of the current episode -int ALEInterface::getEpisodeFrameNumber() { +int ALEInterface::getEpisodeFrameNumber() const { return environment->getEpisodeFrameNumber(); } @@ -259,6 +250,30 @@ const ALEScreen& ALEInterface::getScreen() { return environment->getScreen(); } +//This method should receive an empty vector to fill it with +//the grayscale colours +void ALEInterface::getScreenGrayscale(std::vector& grayscale_output_buffer){ + size_t w = environment->getScreen().width(); + size_t h = environment->getScreen().height(); + size_t screen_size = w*h; + + pixel_t *ale_screen_data = environment->getScreen().getArray(); + theOSystem->colourPalette().applyPaletteGrayscale(grayscale_output_buffer, ale_screen_data, screen_size); +} + +//This method should receive a vector to fill it with +//the RGB colours. The first positions contain the red colours, +//followed by the green colours and then the blue colours +void ALEInterface::getScreenRGB(std::vector& output_rgb_buffer){ + size_t w = environment->getScreen().width(); + size_t h = environment->getScreen().height(); + size_t screen_size = w*h; + + pixel_t *ale_screen_data = environment->getScreen().getArray(); + + theOSystem->colourPalette().applyPaletteRGB(output_rgb_buffer, ale_screen_data, screen_size * 3); +} + // Returns the current RAM content const ALERAM& ALEInterface::getRAM() { return environment->getRAM(); @@ -282,6 +297,14 @@ void ALEInterface::restoreState(const ALEState& state) { return environment->restoreState(state); } +ALEState ALEInterface::cloneSystemState() { + return environment->cloneSystemState(); +} + +void ALEInterface::restoreSystemState(const ALEState& state) { + return environment->restoreSystemState(state); +} + void ALEInterface::saveScreenPNG(const string& filename) { ScreenExporter exporter(theOSystem->colourPalette()); diff --git a/atari_py/ale_interface/src/ale_interface.hpp b/atari_py/ale_interface/src/ale_interface.hpp index 47a5f7a..997a3e4 100644 --- a/atari_py/ale_interface/src/ale_interface.hpp +++ b/atari_py/ale_interface/src/ale_interface.hpp @@ -37,7 +37,6 @@ #include "os_dependent/SettingsUNIX.hxx" #include "os_dependent/OSystemUNIX.hxx" #include "games/Roms.hpp" -#include "common/Defaults.hpp" #include "common/display_screen.h" #include "environment/stella_environment.hpp" #include "common/ScreenExporter.hpp" @@ -46,7 +45,7 @@ #include #include -static const std::string Version = "0.5.0"; +static const std::string Version = "0.5.1"; /** This class interfaces ALE with external code for controlling agents. @@ -83,7 +82,7 @@ class ALEInterface { reward_t act(Action action); // Indicates if the game has ended. - bool game_over(); + bool game_over() const; // Resets the game, but not the full system. void reset_game(); @@ -103,11 +102,20 @@ class ALEInterface { const int lives(); // Returns the frame number since the start of the current episode - int getEpisodeFrameNumber(); + int getEpisodeFrameNumber() const; // Returns the current game screen const ALEScreen &getScreen(); + //This method should receive an empty vector to fill it with + //the grayscale colours + void getScreenGrayscale(std::vector& grayscale_output_buffer); + + //This method should receive a vector to fill it with + //the RGB colours. The first positions contain the red colours, + //followed by the green colours and then the blue colours + void getScreenRGB(std::vector& output_rgb_buffer); + // Returns the current RAM content const ALERAM &getRAM(); @@ -117,10 +125,22 @@ class ALEInterface { // Loads the state of the system void loadState(); + // This makes a copy of the environment state. This copy does *not* include pseudorandomness, + // making it suitable for planning purposes. By contrast, see cloneSystemState. ALEState cloneState(); + // Reverse operation of cloneState(). This does not restore pseudorandomness, so that repeated + // calls to restoreState() in the stochastic controls setting will not lead to the same outcomes. + // By contrast, see restoreSystemState. void restoreState(const ALEState& state); + // This makes a copy of the system & environment state, suitable for serialization. This includes + // pseudorandomness and so is *not* suitable for planning purposes. + ALEState cloneSystemState(); + + // Reverse operation of cloneSystemState. + void restoreSystemState(const ALEState& state); + // Save the current screen as a png file void saveScreenPNG(const std::string& filename); diff --git a/atari_py/ale_interface/src/common/ColourPalette.cpp b/atari_py/ale_interface/src/common/ColourPalette.cpp index 1244c52..acf91f3 100644 --- a/atari_py/ale_interface/src/common/ColourPalette.cpp +++ b/atari_py/ale_interface/src/common/ColourPalette.cpp @@ -34,7 +34,7 @@ inline uInt32 convertGrayscale(uInt32 packedRGBValue) double g = (packedRGBValue >> 8) & 0xff; double b = (packedRGBValue >> 0) & 0xff; - uInt8 lum = (uInt8) round(r * 0.2989 + g * 0.5870 + b * 0.1140 ); + uInt8 lum = (uInt8) round(r * 0.2989 + g * 0.5870 + b * 0.1140); return packRGB(lum, lum, lum); } @@ -45,8 +45,10 @@ ColourPalette::ColourPalette(): m_palette(NULL) { void ColourPalette::getRGB(int val, int &r, int &g, int &b) const { - assert (m_palette != NULL); + assert(m_palette != NULL); assert(val >= 0 && val <= 0xFF); + // Make sure we are reading from RGB, not grayscale. + assert((val & 0x01) == 0); // Set the RGB components accordingly r = (m_palette[val] >> 16) & 0xFF; @@ -56,9 +58,10 @@ void ColourPalette::getRGB(int val, int &r, int &g, int &b) const uInt8 ColourPalette::getGrayscale(int val) const { - assert (m_palette != NULL); + assert(m_palette != NULL); assert(val >= 0 && val < 0xFF); - + assert((val & 0x01) == 1); + // Set the RGB components accordingly return (m_palette[val+1] >> 0) & 0xFF; } @@ -81,6 +84,21 @@ void ColourPalette::applyPaletteRGB(uInt8* dst_buffer, uInt8 *src_buffer, size_t } } +void ColourPalette::applyPaletteRGB(std::vector& dst_buffer, uInt8 *src_buffer, size_t src_size) +{ + dst_buffer.resize(3 * src_size); + assert(dst_buffer.size() == 3 * src_size); + + uInt8 *p = src_buffer; + + for(size_t i = 0; i < src_size * 3; i += 3, p++){ + int rgb = m_palette[*p]; + dst_buffer[i+0] = (unsigned char) ((rgb >> 16)); // r + dst_buffer[i+1] = (unsigned char) ((rgb >> 8)); // g + dst_buffer[i+2] = (unsigned char) ((rgb >> 0)); // b + } +} + void ColourPalette::applyPaletteGrayscale(uInt8* dst_buffer, uInt8 *src_buffer, size_t src_size) { uInt8 *p = src_buffer; @@ -91,6 +109,18 @@ void ColourPalette::applyPaletteGrayscale(uInt8* dst_buffer, uInt8 *src_buffer, } } +void ColourPalette::applyPaletteGrayscale(std::vector& dst_buffer, uInt8 *src_buffer, size_t src_size) +{ + dst_buffer.resize(src_size); + assert(dst_buffer.size() == src_size); + + uInt8 *p = src_buffer; + + for(size_t i = 0; i < src_size; i++, p++){ + dst_buffer[i] = (unsigned char) (m_palette[*p+1] & 0xFF); + } +} + void ColourPalette::setPalette(const string& type, const string& displayFormat) { diff --git a/atari_py/ale_interface/src/common/ColourPalette.hpp b/atari_py/ale_interface/src/common/ColourPalette.hpp index b9e4587..f769955 100644 --- a/atari_py/ale_interface/src/common/ColourPalette.hpp +++ b/atari_py/ale_interface/src/common/ColourPalette.hpp @@ -16,6 +16,7 @@ #ifndef __COLOUR_PALETTE_HPP__ #define __COLOUR_PALETTE_HPP__ +#include #include // Include obscure header file for uInt32 definition #include "../emucore/m6502/src/bspf/src/bspf.hxx" @@ -41,6 +42,7 @@ class ColourPalette { 8 bits => 24 bits */ void applyPaletteRGB(uInt8* dst_buffer, uInt8 *src_buffer, size_t src_size); + void applyPaletteRGB(std::vector& dst_buffer, uInt8 *src_buffer, size_t src_size); /** Applies the current grayscale palette to the src_buffer and returns the results in dst_buffer @@ -48,6 +50,7 @@ class ColourPalette { 8 bits => 8 bits */ void applyPaletteGrayscale(uInt8* dst_buffer, uInt8 *src_buffer, size_t src_size); + void applyPaletteGrayscale(std::vector& dst_buffer, uInt8 *src_buffer, size_t src_size); /** Loads all defined palettes with PAL color-loss data depending diff --git a/atari_py/ale_interface/src/common/Log.cpp b/atari_py/ale_interface/src/common/Log.cpp index 901f0f5..64ef888 100644 --- a/atari_py/ale_interface/src/common/Log.cpp +++ b/atari_py/ale_interface/src/common/Log.cpp @@ -2,7 +2,7 @@ #include using namespace ale; -Logger::mode Logger::current_mode = Warning; +Logger::mode Logger::current_mode = Info; void Logger::setMode(Logger::mode m){ current_mode = m; diff --git a/atari_py/ale_interface/src/controllers/fifo_controller.cpp b/atari_py/ale_interface/src/controllers/fifo_controller.cpp index bca59c4..e3da759 100644 --- a/atari_py/ale_interface/src/controllers/fifo_controller.cpp +++ b/atari_py/ale_interface/src/controllers/fifo_controller.cpp @@ -98,7 +98,10 @@ void FIFOController::handshake() { // Read in agent's response char in_buffer [1024]; - fgets (in_buffer, sizeof(in_buffer), m_fin); + if (fgets (in_buffer, sizeof(in_buffer), m_fin) == NULL) { + // If The agent hung up, stop the handshake. + return; + } // Parse response: send_screen, send_ram, , send_RL char * token = strtok (in_buffer,",\n"); @@ -232,8 +235,14 @@ void FIFOController::sendRL() { void FIFOController::readAction(Action& action_a, Action& action_b) { // Read the new action from the pipe, as a comma-separated pair char in_buffer[2048]; - fgets (in_buffer, sizeof(in_buffer), m_fin); - + if (fgets (in_buffer, sizeof(in_buffer), m_fin) == NULL) { + // If fgets returns NULL, we set the two actions to NOOP here. This is probably because the + // other side has hung up. We'll let the process terminate as usual. + action_a = PLAYER_A_NOOP; + action_b = PLAYER_B_NOOP; + return; + } + char * token = strtok (in_buffer,",\n"); action_a = (Action)atoi(token); diff --git a/atari_py/ale_interface/src/emucore/Cart3E.cxx b/atari_py/ale_interface/src/emucore/Cart3E.cxx index a2fbf1a..8d2e5fe 100644 --- a/atari_py/ale_interface/src/emucore/Cart3E.cxx +++ b/atari_py/ale_interface/src/emucore/Cart3E.cxx @@ -40,7 +40,7 @@ Cartridge3E::Cartridge3E(const uInt8* image, uInt32 size) } // Initialize RAM with random values - class Random random; + class Random& random = Random::getInstance(); for(uInt32 i = 0; i < 32768; ++i) { myRam[i] = random.next(); diff --git a/atari_py/ale_interface/src/emucore/CartAR.cxx b/atari_py/ale_interface/src/emucore/CartAR.cxx index f446ffe..6a93cf7 100644 --- a/atari_py/ale_interface/src/emucore/CartAR.cxx +++ b/atari_py/ale_interface/src/emucore/CartAR.cxx @@ -40,7 +40,8 @@ CartridgeAR::CartridgeAR(const uInt8* image, uInt32 size, bool fastbios) memcpy(myLoadImages, image, size); // Initialize RAM with random values - class Random random; + class Random& random = Random::getInstance(); + for(i = 0; i < 6 * 1024; ++i) { myImage[i] = random.next(); diff --git a/atari_py/ale_interface/src/emucore/CartCV.cxx b/atari_py/ale_interface/src/emucore/CartCV.cxx index 84d6dae..51c2120 100644 --- a/atari_py/ale_interface/src/emucore/CartCV.cxx +++ b/atari_py/ale_interface/src/emucore/CartCV.cxx @@ -38,7 +38,8 @@ CartridgeCV::CartridgeCV(const uInt8* image, uInt32 size) } // Initialize RAM with random values - class Random random; + class Random& random = Random::getInstance(); + for(uInt32 i = 0; i < 1024; ++i) { myRAM[i] = random.next(); diff --git a/atari_py/ale_interface/src/emucore/CartE7.cxx b/atari_py/ale_interface/src/emucore/CartE7.cxx index 6d279bb..4f6cdbf 100644 --- a/atari_py/ale_interface/src/emucore/CartE7.cxx +++ b/atari_py/ale_interface/src/emucore/CartE7.cxx @@ -35,7 +35,8 @@ CartridgeE7::CartridgeE7(const uInt8* image) } // Initialize RAM with random values - class Random random; + class Random& random = Random::getInstance(); + for(uInt32 i = 0; i < 2048; ++i) { myRAM[i] = random.next(); diff --git a/atari_py/ale_interface/src/emucore/CartF4SC.cxx b/atari_py/ale_interface/src/emucore/CartF4SC.cxx index ceb4f94..8d26248 100644 --- a/atari_py/ale_interface/src/emucore/CartF4SC.cxx +++ b/atari_py/ale_interface/src/emucore/CartF4SC.cxx @@ -35,7 +35,8 @@ CartridgeF4SC::CartridgeF4SC(const uInt8* image) } // Initialize RAM with random values - class Random random; + class Random& random = Random::getInstance(); + for(uInt32 i = 0; i < 128; ++i) { myRAM[i] = random.next(); diff --git a/atari_py/ale_interface/src/emucore/CartF6SC.cxx b/atari_py/ale_interface/src/emucore/CartF6SC.cxx index 9b156b4..cbfff3b 100644 --- a/atari_py/ale_interface/src/emucore/CartF6SC.cxx +++ b/atari_py/ale_interface/src/emucore/CartF6SC.cxx @@ -35,7 +35,8 @@ CartridgeF6SC::CartridgeF6SC(const uInt8* image) } // Initialize RAM with random values - class Random random; + class Random& random = Random::getInstance(); + for(uInt32 i = 0; i < 128; ++i) { myRAM[i] = random.next(); diff --git a/atari_py/ale_interface/src/emucore/CartF8SC.cxx b/atari_py/ale_interface/src/emucore/CartF8SC.cxx index 57830e0..27d913e 100644 --- a/atari_py/ale_interface/src/emucore/CartF8SC.cxx +++ b/atari_py/ale_interface/src/emucore/CartF8SC.cxx @@ -35,7 +35,8 @@ CartridgeF8SC::CartridgeF8SC(const uInt8* image) } // Initialize RAM with random values - class Random random; + class Random& random = Random::getInstance(); + for(uInt32 i = 0; i < 128; ++i) { myRAM[i] = random.next(); diff --git a/atari_py/ale_interface/src/emucore/CartFASC.cxx b/atari_py/ale_interface/src/emucore/CartFASC.cxx index c8c596c..b873a47 100644 --- a/atari_py/ale_interface/src/emucore/CartFASC.cxx +++ b/atari_py/ale_interface/src/emucore/CartFASC.cxx @@ -35,7 +35,8 @@ CartridgeFASC::CartridgeFASC(const uInt8* image) } // Initialize RAM with random values - class Random random; + class Random& random = Random::getInstance(); + for(uInt32 i = 0; i < 256; ++i) { myRAM[i] = random.next(); diff --git a/atari_py/ale_interface/src/emucore/CartMC.cxx b/atari_py/ale_interface/src/emucore/CartMC.cxx index a21fd8b..63f71c7 100644 --- a/atari_py/ale_interface/src/emucore/CartMC.cxx +++ b/atari_py/ale_interface/src/emucore/CartMC.cxx @@ -38,7 +38,8 @@ CartridgeMC::CartridgeMC(const uInt8* image, uInt32 size) myRAM = new uInt8[32 * 1024]; // Initialize RAM with random values - class Random random; + class Random& random = Random::getInstance(); + for(i = 0; i < 32 * 1024; ++i) { myRAM[i] = random.next(); diff --git a/atari_py/ale_interface/src/emucore/Console.cxx b/atari_py/ale_interface/src/emucore/Console.cxx index 27233a8..c619dad 100644 --- a/atari_py/ale_interface/src/emucore/Console.cxx +++ b/atari_py/ale_interface/src/emucore/Console.cxx @@ -72,12 +72,6 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props) mySystem = 0; myEvent = 0; - std::string seedStr = myOSystem->settings().getString("random_seed").c_str(); - if (seedStr == "time") - Random::seed((uInt32)time(NULL)); - else - Random::seed((uInt32)atoi(seedStr.c_str())); - // Attach the event subsystem to the current console //ALE myEvent = myOSystem->eventHandler().event(); myEvent = myOSystem->event(); @@ -397,8 +391,8 @@ void Console::initializeAudio() */ void Console::fry() const { - for (int ZPmem=0; ZPmem<0x100; ZPmem += randNumGen.next() % 4) - mySystem->poke(ZPmem, mySystem->peek(ZPmem) & (uInt8)randNumGen.next() % 256); + for (int ZPmem=0; ZPmem<0x100; ZPmem += myOSystem->rng().next() % 4) + mySystem->poke(ZPmem, mySystem->peek(ZPmem) & (uInt8)myOSystem->rng().next() % 256); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/atari_py/ale_interface/src/emucore/Console.hxx b/atari_py/ale_interface/src/emucore/Console.hxx index 23cd046..ef2f61b 100644 --- a/atari_py/ale_interface/src/emucore/Console.hxx +++ b/atari_py/ale_interface/src/emucore/Console.hxx @@ -104,6 +104,13 @@ class Console */ System& system() const { return *mySystem; } + /** + Returns the OSystem for this emulator. + + @return The OSystem. + */ + OSystem& osystem() const { return *myOSystem; } + /** Get the cartridge used by the console which contains the ROM code @@ -247,9 +254,6 @@ class Console // A RIOT of my own! (...with apologies to The Clash...) M6532 *myRiot; - //Random number generator - mutable Random randNumGen; - #ifdef ATARIVOX_SUPPORT AtariVox *vox; #endif diff --git a/atari_py/ale_interface/src/emucore/M6532.cxx b/atari_py/ale_interface/src/emucore/M6532.cxx index 4be0dcc..6a0c60a 100644 --- a/atari_py/ale_interface/src/emucore/M6532.cxx +++ b/atari_py/ale_interface/src/emucore/M6532.cxx @@ -23,6 +23,7 @@ #include "System.hxx" #include "Serializer.hxx" #include "Deserializer.hxx" +#include "OSystem.hxx" #include using namespace std; #include "../common/Log.hpp" @@ -31,13 +32,11 @@ using namespace std; M6532::M6532(const Console& console) : myConsole(console) { - class Random random; - // Randomize the 128 bytes of memory for(uInt32 t = 0; t < 128; ++t) { - myRAM[t] = random.next(); + myRAM[t] = myConsole.osystem().rng().next(); } // Initialize other data members @@ -58,9 +57,7 @@ const char* M6532::name() const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void M6532::reset() { - class Random random; - - myTimer = 25 + (random.next() % 75); + myTimer = 25 + (myConsole.osystem().rng().next() % 75); myIntervalShift = 6; myCyclesWhenTimerSet = 0; myCyclesWhenInterruptReset = 0; diff --git a/atari_py/ale_interface/src/emucore/OSystem.cxx b/atari_py/ale_interface/src/emucore/OSystem.cxx index dc41027..6ef3740 100644 --- a/atari_py/ale_interface/src/emucore/OSystem.cxx +++ b/atari_py/ale_interface/src/emucore/OSystem.cxx @@ -24,8 +24,6 @@ #include using namespace std; -//ALE #include "MediaFactory.hxx" - #ifdef DEBUGGER_SUPPORT #include "Debugger.hxx" #endif @@ -35,21 +33,13 @@ using namespace std; #endif #include "FSNode.hxx" -#include "unzip.h" #include "MD5.hxx" #include "Settings.hxx" #include "PropsSet.hxx" -//ALE #include "EventHandler.hxx" -#include "Event.hxx" //ALE -//ALE #include "Menu.hxx" -//ALE #include "CommandMenu.hxx" -//ALE #include "Launcher.hxx" -//ALE #include "Font.hxx" -//ALE #include "StellaFont.hxx" -//ALE #include "ConsoleFont.hxx" +#include "Event.hxx" #include "OSystem.hxx" #include "SoundSDL.hxx" -//ALE #include "Widget.hxx" + #define MAX_ROM_SIZE 512 * 1024 #include @@ -60,7 +50,7 @@ using namespace std; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OSystem::OSystem() : - myEvent(NULL), //ALE + myEvent(NULL), mySound(NULL), mySettings(NULL), myPropSet(NULL), @@ -86,24 +76,16 @@ OSystem::OSystem() #ifdef CHEATCODE_SUPPORT myFeatures += "Cheats"; #endif - } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OSystem::~OSystem() { - //ALE delete myMenu; - //ALE delete myCommandMenu; - //ALE delete myLauncher; - //ALE delete myFont; - //ALE delete myConsoleFont; - // Remove any game console that is currently attached deleteConsole(); // OSystem takes responsibility for framebuffer and sound, // since it created them - //ALE delete myFrameBuffer; if (mySound != NULL) delete mySound; @@ -121,14 +103,11 @@ OSystem::~OSystem() if (myPropSet != NULL) delete myPropSet; - //ALE delete myEventHandler; if (myEvent != NULL) delete myEvent; if (p_display_screen != NULL) { delete p_display_screen; } - - //ALE delete aiBase; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -174,11 +153,36 @@ bool OSystem::create() // that only have a single sound device (no hardware mixing) createSound(); - //ALE aiBase = new AIBase(this); + // Seed RNG. This will likely get re-called, e.g. by the ALEInterface, but is needed + // by other interfaces. + resetRNGSeed(); return true; } +void OSystem::resetRNGSeed() { + + // We seed the random number generator. The 'time' seed is somewhat redundant, since the + // rng defaults to time. But we'll do it anyway. + if (mySettings->getInt("random_seed") == 0) { + myRandGen.seed((uInt32)time(NULL)); + } else { + int seed = mySettings->getInt("random_seed"); + assert(seed >= 0); + myRandGen.seed((uInt32)seed); + } +} + +bool OSystem::saveState(Serializer& out) { + + // Here we serialize the RNG state. + return myRandGen.saveState(out); +} + +bool OSystem::loadState(Deserializer& in) { + return myRandGen.loadState(in); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void OSystem::setConfigPaths() { @@ -481,72 +485,14 @@ ALE */ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool OSystem::openROM(const string& rom, string& md5, uInt8** image, int* size) { - // Try to open the file as a zipped archive - // If that fails, we assume it's just a gzipped or normal data file - unzFile tz; - if((tz = unzOpen(rom.c_str())) != NULL) - { - if(unzGoToFirstFile(tz) == UNZ_OK) - { - unz_file_info ufo; - - for(;;) // Loop through all files for valid 2600 images - { - // Longer filenames might be possible, but I don't - // think people would name files that long in zip files... - char filename[1024]; - - unzGetCurrentFileInfo(tz, &ufo, filename, 1024, 0, 0, 0, 0); - filename[1023] = '\0'; - - if(strlen(filename) >= 4) - { - // Grab 3-character extension - char* ext = filename + strlen(filename) - 4; - - if(!BSPF_strcasecmp(ext, ".bin") || !BSPF_strcasecmp(ext, ".a26")) - break; - } - - // Scan the next file in the zip - if(unzGoToNextFile(tz) != UNZ_OK) - break; - } - - // Now see if we got a valid image - if(ufo.uncompressed_size <= 0) - { - unzClose(tz); - return false; - } - *size = ufo.uncompressed_size; - *image = new uInt8[*size]; - - // We don't have to check for any return errors from these functions, - // since if there are, 'image' will not contain a valid ROM and the - // calling method can take of it - unzOpenCurrentFile(tz); - unzReadCurrentFile(tz, *image, *size); - unzCloseCurrentFile(tz); - unzClose(tz); - } - else - { - unzClose(tz); - return false; - } - } - else - { - // Assume the file is either gzip'ed or not compressed at all - gzFile f = gzopen(rom.c_str(), "rb"); - if(!f) - return false; + // Assume the file is either gzip'ed or not compressed at all + gzFile f = gzopen(rom.c_str(), "rb"); + if(!f) + return false; - *image = new uInt8[MAX_ROM_SIZE]; - *size = gzread(f, *image, MAX_ROM_SIZE); - gzclose(f); - } + *image = new uInt8[MAX_ROM_SIZE]; + *size = gzread(f, *image, MAX_ROM_SIZE); + gzclose(f); // If we get to this point, we know we have a valid file to open // Now we make sure that the file has a valid properties entry diff --git a/atari_py/ale_interface/src/emucore/OSystem.hxx b/atari_py/ale_interface/src/emucore/OSystem.hxx index 1cec3d1..4eca7d6 100644 --- a/atari_py/ale_interface/src/emucore/OSystem.hxx +++ b/atari_py/ale_interface/src/emucore/OSystem.hxx @@ -343,6 +343,26 @@ class OSystem void skipEmulation() { mySkipEmulation = true; } + /** + Returns the random number generator for this emulator. + */ + Random& rng() { return myRandGen; } + + /** + Resets the seed for our random number generator. + */ + void resetRNGSeed(); + + /** + Serializes the OSystem state. + */ + bool saveState(Serializer& out); + + /** + Deserializes the OSystem state. + */ + bool loadState(Deserializer& in); + public: ////////////////////////////////////////////////////////////////////// // The following methods are system-specific and must be implemented @@ -436,7 +456,8 @@ class OSystem // Pointer to the (currently defined) Console object Console* myConsole; - + // Random number generator shared across the emulator's components + Random myRandGen; // Pointer to the Menu object //ALE Menu* myMenu; diff --git a/atari_py/ale_interface/src/emucore/Random.cxx b/atari_py/ale_interface/src/emucore/Random.cxx index 2d4e74a..6f3075e 100644 --- a/atari_py/ale_interface/src/emucore/Random.cxx +++ b/atari_py/ale_interface/src/emucore/Random.cxx @@ -18,59 +18,129 @@ #include #include "Random.hxx" +#include "Serializer.hxx" +#include "Deserializer.hxx" // TODO(mgb): bring this include in once we switch to C++11. // #include #include "TinyMT/tinymt32.h" -// The random number generator is defined here to avoid having to expose tinymt32.h. -namespace RandomStatic { +// A static Random object for compatibility purposes. Don't use this. +Random Random::s_random; +// Implementation of Random's random number generator wrapper. +class Random::Impl { + typedef tinymt32_t randgen_t; - // Random number generator - randgen_t rndGenerator; -} + public: + + Impl(); -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Random::seed(uInt32 value) -{ - ourSeed = value; - ourSeeded = true; - // TODO(mgb): this is the C++11 variant. - // rndGenerator.seed(ourSeed); + // Implementations of the methods defined in Random.hpp. + void seed(uInt32 value); + uInt32 next(); + double nextDouble(); - tinymt32_init(&RandomStatic::rndGenerator, ourSeed); + private: + + friend class Random; + + // Seed to use for creating new random number generators + uInt32 m_seed; + + // Random number generator + randgen_t m_randgen; +}; + +Random::Impl::Impl() +{ + // Initialize seed to time + //seed((uInt32) time(NULL)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Random::Random() +void Random::Impl::seed(uInt32 value) { - // If we haven't been seeded then seed ourself - if(!ourSeeded) - seed((uInt32) time(NULL)); + m_seed = value; + // TODO(mgb): this is the C++11 variant. + // rndGenerator.seed(ourSeed); + tinymt32_init(&m_randgen, m_seed); } - + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 Random::next() +uInt32 Random::Impl::next() { // TODO(mgb): C++11 // return rndGenerator(); - return static_cast(tinymt32_generate_uint32(&RandomStatic::rndGenerator)); + return static_cast(tinymt32_generate_uint32(&m_randgen)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -double Random::nextDouble() +double Random::Impl::nextDouble() { // TODO(mgb): C++11 // return rndGenerator() / double(rndGenerator.max() + 1.0); - return tinymt32_generate_32double(&RandomStatic::rndGenerator); + return tinymt32_generate_32double(&m_randgen); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 Random::ourSeed = 0; +Random::Random() : + m_pimpl(new Random::Impl()) +{ +} // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Random::ourSeeded = false; +Random::~Random() { + if (m_pimpl != NULL) { + delete m_pimpl; + m_pimpl = NULL; + } +} +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Random::seed(uInt32 value) +{ + m_pimpl->seed(value); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt32 Random::next() +{ + return m_pimpl->next(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +double Random::nextDouble() +{ + return m_pimpl->nextDouble(); +} + +Random& Random::getInstance() { + return s_random; +} + +bool Random::saveState(Serializer& ser) { + + // Serialize the TinyMT state + for (int i = 0; i < 4; i++) + ser.putInt(m_pimpl->m_randgen.status[i]); + // These aren't really needed, but we serialize them anyway + ser.putInt(m_pimpl->m_randgen.mat1); + ser.putInt(m_pimpl->m_randgen.mat2); + ser.putInt(m_pimpl->m_randgen.tmat); + return true; +} + +bool Random::loadState(Deserializer& deser) { + + // Deserialize the TinyMT state + for (int i = 0; i < 4; i++) + m_pimpl->m_randgen.status[i] = deser.getInt(); + m_pimpl->m_randgen.mat1 = deser.getInt(); + m_pimpl->m_randgen.mat2 = deser.getInt(); + m_pimpl->m_randgen.tmat = deser.getInt(); + + return true; +} diff --git a/atari_py/ale_interface/src/emucore/Random.hxx b/atari_py/ale_interface/src/emucore/Random.hxx index 1ed0518..6410983 100644 --- a/atari_py/ale_interface/src/emucore/Random.hxx +++ b/atari_py/ale_interface/src/emucore/Random.hxx @@ -21,13 +21,12 @@ #include "m6502/src/bspf/src/bspf.hxx" -/** - This is a quick-and-dirty random number generator. It is based on - information in Chapter 7 of "Numerical Recipes in C". It's a simple - linear congruential generator. +class Serializer; +class Deserializer; - @author Bradford W. Mott - @version $Id: Random.hxx,v 1.4 2007/01/01 18:04:49 stephena Exp $ +/** + This Random class uses a Mersenne Twister to provide pseudorandom numbers. + The class itself is derived from the original 'Random' class by Bradford W. Mott. */ class Random { @@ -39,13 +38,15 @@ class Random @param value The value to seed the random number generator with */ - static void seed(uInt32 value); + void seed(uInt32 value); /** Create a new random number generator */ Random(); - + + ~Random(); + /** Answer the next random number from the random number generator @@ -60,13 +61,29 @@ class Random */ double nextDouble(); - private: + // Returns a static Random object. DO NOT USE THIS. This is mostly meant for use by the + // code for the various cartridges. + static Random& getInstance(); + + /** + Serializes the RNG state. + */ + bool saveState(Serializer& out); + + /** + Deserializes the RNG state. + */ + bool loadState(Deserializer& in); + + private: - // Seed to use for creating new random number generators - static uInt32 ourSeed; + // Actual rng (implementation hidden away from the header to avoid depending on + // tinymt). + class Impl; + Impl *m_pimpl; - // Indicates if seed has been set or not - static bool ourSeeded; + // A static Random object. Don't use this. + static Random s_random; }; #endif diff --git a/atari_py/ale_interface/src/emucore/Settings.cxx b/atari_py/ale_interface/src/emucore/Settings.cxx index c8ccb73..fe1224c 100644 --- a/atari_py/ale_interface/src/emucore/Settings.cxx +++ b/atari_py/ale_interface/src/emucore/Settings.cxx @@ -93,6 +93,8 @@ Settings::Settings(OSystem* osystem) : myOSystem(osystem) { setInternal("uipalette", "0"); setInternal("mwheel", "4"); setInternal("autoslot", "false"); + + setDefaultSettings(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -108,8 +110,8 @@ void Settings::loadConfig(const char* config_file){ ifstream in(config_file); if(!in || !in.is_open()) { - // ale::Logger::Warning << "Warning: couldn't load settings file: " << config_file << "\n"; - return; + ale::Logger::Warning << "Warning: couldn't load settings file: " << config_file << std::endl; + return; } while(getline(in, line)) { @@ -379,46 +381,58 @@ void Settings::saveConfig() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Settings::setInt(const string& key, const int value) { - ostringstream stream; + std::ostringstream stream; stream << value; - if(int idx = getInternalPos(key) != -1) + if(int idx = getInternalPos(key) != -1){ setInternal(key, stream.str(), idx); - else + } + else{ + verifyVariableExistence(intSettings, key); setExternal(key, stream.str()); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Settings::setFloat(const string& key, const float value) { - ostringstream stream; + std::ostringstream stream; stream << value; - if(int idx = getInternalPos(key) != -1) + if(int idx = getInternalPos(key) != -1){ setInternal(key, stream.str(), idx); - else + } + else{ + verifyVariableExistence(floatSettings, key); setExternal(key, stream.str()); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Settings::setBool(const string& key, const bool value) { - ostringstream stream; + std::ostringstream stream; stream << value; - if(int idx = getInternalPos(key) != -1) + if(int idx = getInternalPos(key) != -1){ setInternal(key, stream.str(), idx); - else + } + else{ + verifyVariableExistence(boolSettings, key); setExternal(key, stream.str()); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Settings::setString(const string& key, const string& value) { - if(int idx = getInternalPos(key) != -1) + if(int idx = getInternalPos(key) != -1){ setInternal(key, value, idx); - else + } + else{ + verifyVariableExistence(stringSettings, key); setExternal(key, value); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -528,7 +542,7 @@ const string& Settings::getString(const string& key, bool strict) const { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Settings::setSize(const string& key, const int value1, const int value2) { - ostringstream buf; + std::ostringstream buf; buf << value1 << "x" << value2; setString(key, buf.str()); } @@ -673,3 +687,58 @@ Settings& Settings::operator = (const Settings&) return *this; } + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void Settings::setDefaultSettings() { + + // Stella settings + stringSettings.insert(pair("cpu", "low")); // Reduce CPU emulation fidelity for speed + + // Controller settings + intSettings.insert(pair("max_num_frames", 0)); + intSettings.insert(pair("max_num_frames_per_episode", 0)); + + // FIFO controller settings + boolSettings.insert(pair("run_length_encoding", true)); + + // Environment customization settings + boolSettings.insert(pair("restricted_action_set", false)); + intSettings.insert(pair("random_seed", 0)); + boolSettings.insert(pair("color_averaging", false)); + boolSettings.insert(pair("send_rgb", false)); + intSettings.insert(pair("frame_skip", 1)); + floatSettings.insert(pair("repeat_action_probability", 0.25)); + stringSettings.insert(pair("rom_file", "")); + + // Record settings + intSettings.insert(pair("fragsize", 64)); // fragsize to 64 ensures proper sound sync + stringSettings.insert(pair("record_screen_dir", "")); + stringSettings.insert(pair("record_sound_filename", "")); + + // Display Settings + boolSettings.insert(pair("display_screen", false)); + + for(map::iterator it = stringSettings.begin(); it != stringSettings.end(); it++) { + this->setString(it->first, it->second); + } + + for(map::iterator it = floatSettings.begin(); it != floatSettings.end(); it++) { + this->setFloat(it->first, it->second); + } + + for(map::iterator it = boolSettings.begin(); it != boolSettings.end(); it++) { + this->setBool(it->first, it->second); + } + + for(map::iterator it = intSettings.begin(); it != intSettings.end(); it++) { + this->setInt(it->first, it->second); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +template +void Settings::verifyVariableExistence(map dict, string key){ + if(dict.find(key) == dict.end()){ + throw std::runtime_error("The key " + key + " you are trying to set does not exist.\n"); + } +} diff --git a/atari_py/ale_interface/src/emucore/Settings.hxx b/atari_py/ale_interface/src/emucore/Settings.hxx index 175491e..98c2634 100644 --- a/atari_py/ale_interface/src/emucore/Settings.hxx +++ b/atari_py/ale_interface/src/emucore/Settings.hxx @@ -21,6 +21,9 @@ class OSystem; +#include +#include + #include "../common/Array.hxx" #include "m6502/src/bspf/src/bspf.hxx" @@ -162,6 +165,7 @@ class Settings */ void setSize(const std::string& key, const int value1, const int value2); + private: // Copy constructor isn't supported by this class so make it private Settings(const Settings&); @@ -177,6 +181,9 @@ class Settings str.substr(first, str.find_last_not_of(' ')-first+1); } + // Sets all of the ALE-specific default settings + void setDefaultSettings(); + protected: // The parent OSystem object OSystem* myOSystem; @@ -206,6 +213,15 @@ class Settings int pos = -1, bool useAsInitial = false); private: + //Maps containing all external settings an user can + //define and their respectives default values. + std::map intSettings; + std::map boolSettings; + std::map floatSettings; + std::map stringSettings; + template + void verifyVariableExistence(std::map dict, std::string key); + // Holds key,value pairs that are necessary for Stella to // function and must be saved on each program exit. SettingsArray myInternalSettings; diff --git a/atari_py/ale_interface/src/environment/ale_screen.hpp b/atari_py/ale_interface/src/environment/ale_screen.hpp index 021b293..9fe2c60 100644 --- a/atari_py/ale_interface/src/environment/ale_screen.hpp +++ b/atari_py/ale_interface/src/environment/ale_screen.hpp @@ -11,7 +11,7 @@ * ale_screen.hpp * * A class that encapsulates an Atari 2600 screen. Code is provided inline for - * efficiency reasonss. + * efficiency reasons. * **************************************************************************** */ diff --git a/atari_py/ale_interface/src/environment/ale_state.cpp b/atari_py/ale_interface/src/environment/ale_state.cpp index 566b8e3..b8fbc70 100644 --- a/atari_py/ale_interface/src/environment/ale_state.cpp +++ b/atari_py/ale_interface/src/environment/ale_state.cpp @@ -15,20 +15,14 @@ #include "../common/Constants.h" using namespace std; +#include + /** Default constructor - loads settings from system */ ALEState::ALEState(): m_left_paddle(PADDLE_DEFAULT_VALUE), m_right_paddle(PADDLE_DEFAULT_VALUE), m_frame_number(0), - m_episode_frame_number(0){ -} - -ALEState::ALEState(const ALEState &rhs): - m_left_paddle(rhs.m_left_paddle), - m_right_paddle(rhs.m_right_paddle), - m_frame_number(rhs.m_frame_number), - m_episode_frame_number(rhs.m_episode_frame_number), - m_serialized_state(rhs.m_serialized_state) { + m_episode_frame_number(0) { } ALEState::ALEState(const ALEState &rhs, std::string serialized): @@ -39,14 +33,33 @@ ALEState::ALEState(const ALEState &rhs, std::string serialized): m_serialized_state(serialized) { } +ALEState::ALEState(const std::string &serialized) { + Deserializer des(serialized); + this->m_left_paddle = des.getInt(); + this->m_right_paddle = des.getInt(); + this->m_frame_number = des.getInt(); + this->m_episode_frame_number = des.getInt(); + this->m_serialized_state = des.getString(); +} + + /** Restores ALE to the given previously saved state. */ -void ALEState::load(OSystem* osystem, RomSettings* settings, std::string md5, const ALEState &rhs) { +void ALEState::load(OSystem* osystem, RomSettings* settings, std::string md5, const ALEState &rhs, + bool load_system) { assert(rhs.m_serialized_state.length() > 0); // Deserialize the stored string into the emulator state Deserializer deser(rhs.m_serialized_state); - + + // A primitive check to produce a meaningful error if this state does not contain osystem info. + if (deser.getBool() != load_system) + throw new std::runtime_error("Attempting to load an ALEState which does not contain " + "system information."); + osystem->console().system().loadState(md5, deser); + // If we have osystem data, load it as well + if (load_system) + osystem->loadState(deser); settings->loadState(deser); // Copy over other member variables @@ -56,11 +69,17 @@ void ALEState::load(OSystem* osystem, RomSettings* settings, std::string md5, co m_frame_number = rhs.m_frame_number; } -ALEState ALEState::save(OSystem* osystem, RomSettings* settings, std::string md5) { +ALEState ALEState::save(OSystem* osystem, RomSettings* settings, std::string md5, + bool save_system) { // Use the emulator's built-in serialization to save the state - Serializer ser; + Serializer ser; + // We use 'save_system' as a check at load time. + ser.putBool(save_system); + osystem->console().system().saveState(md5, ser); + if (save_system) + osystem->saveState(ser); settings->saveState(ser); // Now make a copy of this state, also storing the emulator serialization @@ -68,13 +87,25 @@ ALEState ALEState::save(OSystem* osystem, RomSettings* settings, std::string md5 } void ALEState::incrementFrame(int steps /* = 1 */) { - m_frame_number+=steps; - m_episode_frame_number+=steps; + m_frame_number += steps; + m_episode_frame_number += steps; } -void ALEState::resetEpisodeFrameNumber(){ - m_episode_frame_number = 0; - } +void ALEState::resetEpisodeFrameNumber() { + m_episode_frame_number = 0; +} + +std::string ALEState::serialize() { + Serializer ser; + + ser.putInt(this->m_left_paddle); + ser.putInt(this->m_right_paddle); + ser.putInt(this->m_frame_number); + ser.putInt(this->m_episode_frame_number); + ser.putString(this->m_serialized_state); + + return ser.get_str(); +} @@ -451,6 +482,6 @@ bool ALEState::equals(ALEState &rhs) { return (rhs.m_serialized_state == this->m_serialized_state && rhs.m_left_paddle == this->m_left_paddle && rhs.m_right_paddle == this->m_right_paddle && - rhs.m_frame_number == this->m_frame_number) && - rhs.m_episode_frame_number == this->m_episode_frame_number; + rhs.m_frame_number == this->m_frame_number && + rhs.m_episode_frame_number == this->m_episode_frame_number); } diff --git a/atari_py/ale_interface/src/environment/ale_state.hpp b/atari_py/ale_interface/src/environment/ale_state.hpp index a7e226c..9dee5bc 100644 --- a/atari_py/ale_interface/src/environment/ale_state.hpp +++ b/atari_py/ale_interface/src/environment/ale_state.hpp @@ -35,11 +35,12 @@ class ALEState { public: ALEState(); - // Copy constructor - ALEState(const ALEState &rhs); // Makes a copy of this state, also storing emulator information provided as a string ALEState(const ALEState &rhs, std::string serialized); + // Restores a serialized ALEState + ALEState(const std::string &serialized); + /** Resets the system to its start state. numResetSteps 'RESET' actions are taken after the * start. */ void reset(int numResetSteps = 1); @@ -65,18 +66,22 @@ class ALEState { //Get the number of frames executed this episode. const int getEpisodeFrameNumber() const { return m_episode_frame_number; } + std::string serialize(); + protected: // Let StellaEnvironment access these methods: they are needed for emulation purposes friend class StellaEnvironment; // The two methods below are meant to be used by StellaEnvironment. - /** Restores the environment to a previously saved state. */ - void load(OSystem* osystem, RomSettings* settings, std::string md5, const ALEState &rhs); + /** Restores the environment to a previously saved state. If load_system == true, we also + restore system-specific information (such as the RNG state). */ + void load(OSystem* osystem, RomSettings* settings, std::string md5, const ALEState &rhs, + bool load_system); /** Returns a "copy" of the current state, including the information necessary to restore - * the emulator. */ - ALEState save(OSystem* osystem, RomSettings* settings, std::string md5); + * the emulator. If save_system == true, this includes the RNG state. */ + ALEState save(OSystem* osystem, RomSettings* settings, std::string md5, bool save_system); /** Reset key presses */ void resetKeys(Event* event_obj); diff --git a/atari_py/ale_interface/src/environment/phosphor_blend.cpp b/atari_py/ale_interface/src/environment/phosphor_blend.cpp index ea7b98e..c085bce 100644 --- a/atari_py/ale_interface/src/environment/phosphor_blend.cpp +++ b/atari_py/ale_interface/src/environment/phosphor_blend.cpp @@ -23,7 +23,7 @@ PhosphorBlend::PhosphorBlend(OSystem * osystem): // Taken from default Stella settings m_phosphor_blend_ratio = 77; - // makeAveragePalette(); + makeAveragePalette(); } void PhosphorBlend::process(ALEScreen& screen) { @@ -49,9 +49,9 @@ void PhosphorBlend::makeAveragePalette() { ColourPalette &palette = m_osystem->colourPalette(); - // Precompute the average RGB values for phosphor-averaged colors c1 and c2 - for (int c1 = 0; c1 < 256; c1++) { - for (int c2 = 0; c2 < 256; c2++) { + // Precompute the average RGB values for phosphor-averaged colors c1 and c2. + for (int c1 = 0; c1 < 256; c1 += 2) { + for (int c2 = 0; c2 < 256; c2 += 2) { int r1, g1, b1; int r2, g2, b2; palette.getRGB(c1, r1, g1, b1); @@ -64,7 +64,8 @@ void PhosphorBlend::makeAveragePalette() { } } - // Also make a RGB to NTSC color map + // Also make a RGB to NTSC color map. We drop the lowest two bits to speed + // the initialization a little. TODO(mgbellemare): Find a better solution. for (int r = 0; r < 256; r += 4) { for (int g = 0; g < 256; g += 4) { for (int b = 0; b < 256; b += 4) { @@ -72,7 +73,9 @@ void PhosphorBlend::makeAveragePalette() { int minDist = 256 * 3 + 1; int minIndex = -1; - for (int c1 = 0; c1 < 256; c1++) { + // Look for the closest NTSC value matching (r,g,b). Odd palette + // entries correspond to grayscale values and are ignored. + for (int c1 = 0; c1 < 256; c1 += 2) { // Get the RGB corresponding to c1 int r1, g1, b1; palette.getRGB(c1, r1, g1, b1); diff --git a/atari_py/ale_interface/src/environment/stella_environment.cpp b/atari_py/ale_interface/src/environment/stella_environment.cpp index 17dc689..83a065a 100644 --- a/atari_py/ale_interface/src/environment/stella_environment.cpp +++ b/atari_py/ale_interface/src/environment/stella_environment.cpp @@ -22,7 +22,7 @@ StellaEnvironment::StellaEnvironment(OSystem* osystem, RomSettings* settings): m_osystem(osystem), m_settings(settings), - // m_phosphor_blend(osystem), + m_phosphor_blend(osystem), m_screen(m_osystem->console().mediaSource().height(), m_osystem->console().mediaSource().width()), m_player_a_action(PLAYER_A_NOOP), @@ -103,17 +103,20 @@ void StellaEnvironment::load() { m_saved_states.pop(); } -/** Returns a copy of the current emulator state. */ ALEState StellaEnvironment::cloneState() { - return m_state.save(m_osystem, m_settings, m_cartridge_md5); + return m_state.save(m_osystem, m_settings, m_cartridge_md5, false); } -/** Restores a previously saved copy of the state. */ void StellaEnvironment::restoreState(const ALEState& target_state) { - m_state.load(m_osystem, m_settings, m_cartridge_md5, target_state); - m_osystem->console().mediaSource().update(); - processScreen(); - processRAM(); + m_state.load(m_osystem, m_settings, m_cartridge_md5, target_state, false); +} + +ALEState StellaEnvironment::cloneSystemState() { + return m_state.save(m_osystem, m_settings, m_cartridge_md5, true); +} + +void StellaEnvironment::restoreSystemState(const ALEState& target_state) { + m_state.load(m_osystem, m_settings, m_cartridge_md5, target_state, true); } void StellaEnvironment::noopIllegalActions(Action & player_a_action, Action & player_b_action) { @@ -134,32 +137,35 @@ void StellaEnvironment::noopIllegalActions(Action & player_a_action, Action & pl } reward_t StellaEnvironment::act(Action player_a_action, Action player_b_action) { - + // Total reward received as we repeat the action reward_t sum_rewards = 0; + Random& rng = m_osystem->rng(); + // Apply the same action for a given number of times... note that act() will refuse to emulate // past the terminal state for (size_t i = 0; i < m_frame_skip; i++) { // Stochastically drop actions, according to m_repeat_action_probability - if (m_rand_gen.nextDouble() >= m_repeat_action_probability) + if (rng.nextDouble() >= m_repeat_action_probability) m_player_a_action = player_a_action; // @todo Possibly optimize by avoiding call to rand() when player B is "off" ? - if (m_rand_gen.nextDouble() >= m_repeat_action_probability) + if (rng.nextDouble() >= m_repeat_action_probability) m_player_b_action = player_b_action; // If so desired, request one frame's worth of sound (this does nothing if recording // is not enabled) m_osystem->sound().recordNextFrame(); + // Similarly record screen as needed + if (m_screen_exporter.get() != NULL) + m_screen_exporter->saveNext(m_screen); + // Use the stored actions, which may or may not have changed this frame sum_rewards += oneStepAct(m_player_a_action, m_player_b_action); } - if (m_screen_exporter.get() != NULL) - m_screen_exporter->saveNext(m_screen); - return sum_rewards; } @@ -183,7 +189,7 @@ reward_t StellaEnvironment::oneStepAct(Action player_a_action, Action player_b_a return m_settings->getReward(); } -bool StellaEnvironment::isTerminal() { +bool StellaEnvironment::isTerminal() const { return (m_settings->isTerminal() || (m_max_num_frames_per_episode > 0 && m_state.getEpisodeFrameNumber() >= m_max_num_frames_per_episode)); @@ -230,8 +236,7 @@ const ALEState& StellaEnvironment::getState() const { void StellaEnvironment::processScreen() { if (m_colour_averaging) { // Perform phosphor averaging; the blender stores its result in the given screen - // m_phosphor_blend.process(m_screen); - abort(); + m_phosphor_blend.process(m_screen); } else { // Copy screen over and we're done! diff --git a/atari_py/ale_interface/src/environment/stella_environment.hpp b/atari_py/ale_interface/src/environment/stella_environment.hpp index 03e49a5..9125d80 100644 --- a/atari_py/ale_interface/src/environment/stella_environment.hpp +++ b/atari_py/ale_interface/src/environment/stella_environment.hpp @@ -44,11 +44,18 @@ class StellaEnvironment { void save(); void load(); - /** Returns a copy of the current emulator state. */ + /** Returns a copy of the current emulator state. Note that this doesn't include + pseudorandomness, so that clone/restoreState are suitable for planning. */ ALEState cloneState(); /** Restores a previously saved copy of the state. */ void restoreState(const ALEState&); + /** Returns a copy of the current emulator state. This includes RNG state information, and + more generally should lead to exactly reproducibility. */ + ALEState cloneSystemState(); + /** Restores a previously saved copy of the state, including RNG state information. */ + void restoreSystemState(const ALEState&); + /** Applies the given actions (e.g. updating paddle positions when the paddle is used) * and performs one simulation step in Stella. Returns the resultant reward. When * frame skip is set to > 1, up the corresponding number of simulation steps are performed. @@ -58,7 +65,7 @@ class StellaEnvironment { reward_t act(Action player_a_action, Action player_b_action); /** Returns true once we reach a terminal state */ - bool isTerminal(); + bool isTerminal() const; /** Accessor methods for the environment state. */ void setState(const ALEState & state); @@ -90,7 +97,7 @@ class StellaEnvironment { private: OSystem *m_osystem; RomSettings *m_settings; - // PhosphorBlend m_phosphor_blend; // For performing phosphor colour averaging, if so desired + PhosphorBlend m_phosphor_blend; // For performing phosphor colour averaging, if so desired std::string m_cartridge_md5; // Necessary for saving and loading emulator state std::stack m_saved_states; // States are saved on a stack @@ -108,7 +115,6 @@ class StellaEnvironment { size_t m_frame_skip; // How many frames to emulate per act() float m_repeat_action_probability; // Stochasticity of the environment std::auto_ptr m_screen_exporter; // Automatic screen recorder - Random m_rand_gen; // The last actions taken by our players Action m_player_a_action, m_player_b_action; diff --git a/atari_py/ale_interface/src/external/TinyMT/tinymt32.c b/atari_py/ale_interface/src/external/TinyMT/tinymt32.c index ccc19f2..4f69fd3 100644 --- a/atari_py/ale_interface/src/external/TinyMT/tinymt32.c +++ b/atari_py/ale_interface/src/external/TinyMT/tinymt32.c @@ -60,6 +60,12 @@ static void period_certification(tinymt32_t * random) { * @param seed a 32-bit unsigned integer used as a seed. */ void tinymt32_init(tinymt32_t * random, uint32_t seed) { + // MGB: These values were apparently drawn from the aether. This isn't good for reproducibility. + // I will set them to some bunk values. + random->mat1 = 4753849; + random->mat2 = 3231259923; + random->tmat = 614784120; + int i; random->status[0] = seed; random->status[1] = random->mat1; diff --git a/atari_py/ale_interface/src/main.cpp b/atari_py/ale_interface/src/main.cpp index 6e9767b..f634b55 100644 --- a/atari_py/ale_interface/src/main.cpp +++ b/atari_py/ale_interface/src/main.cpp @@ -22,8 +22,6 @@ #include "emucore/FSNode.hxx" #include "emucore/OSystem.hxx" -#include "common/Defaults.hpp" - #if (defined(WIN32) || defined(__MINGW32__)) # include "os_dependent/SettingsWin32.hxx" # include "os_dependent/OSystemWin32.hxx" diff --git a/atari_py/ale_interface/src/os_dependent/OSystemUNIX.cxx b/atari_py/ale_interface/src/os_dependent/OSystemUNIX.cxx index 60cfcbf..9b31aca 100644 --- a/atari_py/ale_interface/src/os_dependent/OSystemUNIX.cxx +++ b/atari_py/ale_interface/src/os_dependent/OSystemUNIX.cxx @@ -51,7 +51,7 @@ OSystemUNIX::OSystemUNIX() //ALE const string& basedir = string(getenv("HOME")) + "/.stella"; string basedir = string("."); //ALE setBaseDir(basedir); - setConfigFile(basedir + "/stellarc"); + setConfigFile(basedir + "/ale.cfg"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/atari_py/ale_interface/src/os_dependent/OSystemWin32.cxx b/atari_py/ale_interface/src/os_dependent/OSystemWin32.cxx index f7164a9..11a4dd8 100644 --- a/atari_py/ale_interface/src/os_dependent/OSystemWin32.cxx +++ b/atari_py/ale_interface/src/os_dependent/OSystemWin32.cxx @@ -47,7 +47,7 @@ OSystemWin32::OSystemWin32() // For now, we just put it in the same directory as the executable. const string& basedir = "."; setBaseDir(basedir); - setConfigFile(basedir + "\\stellarc"); + setConfigFile(basedir + "\\ale.cfg"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/doc/manual/manual.pdf b/doc/manual/manual.pdf index ef1ab38fad09af431d9bf8f3770b1e3d02203630..12e67c68b1961b0ae3864127c506bbadedb7a3c0 100644 GIT binary patch delta 212334 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%0A_*f3hb?(x`g#dHdHy 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%0AQF04==IHkp2%>yq9{>uhIZfaw;KN2dBf-M>pv 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 Lh-D3vE_u1+$C$V-rRj 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 Gnad|f(#)4C1(poeK3NA{%kcZ$w;}3-rQ*=fP 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 Uf#bn5ak4Tq!IF`QDTu@V4 rl_glue+} - \item{\verb+ale_0_5> doc/examples/RLGlueAgent+} - \item{\verb+ale_0_5> doc/examples/RLGlueExperiment+} - \item{\verb+ale_0_5> ./ale -game_controller rlglue+} -\end{itemize} +\begin{verbatim} +ale_0_5> rl_glue +ale_0_5> doc/examples/RLGlueAgent +ale_0_5> doc/examples/RLGlueExperiment +ale_0_5> ./ale -game_controller rlglue +\end{verbatim} Additional options (such as those described below) can also be passed as command-line arguments. Please refer to the RL-Glue documentation for more details. @@ -386,7 +385,7 @@ \subsection{Available Actions}\label{sec:available_actions} \end{center} Note that the \verb+reset+ (40) action toggles the Atari 2600 switch, rather than reset the -environment, and as such is ignored by most interfaces. The Shared library, CTypes, and fifo +environment, and as such is ignored by most interfaces. The shared library, CTypes, and fifo interfaces provide methods for properly resetting the environment. Player B's actions are defined to be 18 + the equivalent action value for Player A. For example, Player B's up action is \verb+up+ (20). @@ -443,7 +442,7 @@ \subsection{Action Repeat Stochasticity} The motivation for introducing action repeat stochasticity was to help separate \emph{trajectory optimization} research from \emph{robust controller optimization}, the latter often being the desired outcome in reinforcement learning (RL). We strongly encourage RL researchers to use -the default stochasticity level their agents, and clearly report on the setting used. More +the default stochasticity level in their agents, and clearly report the setting used. More details on the effects of action repeat stochasticity will be made available in future publications. @@ -456,7 +455,7 @@ \subsection{Minimal Action Set} accomplished by querying the \verb+RomSettings+ class using the method \verb+getMinimalActionSet+. This then returns a set of actions judged ``minimal'' to play a given game. Due to the potentially high impact of this setting on performance, we encourage researchers -to clearly report on the method used in their experiments. +to clearly report the method used in their experiments. \section{Miscellaneous} @@ -617,6 +616,9 @@ \section{Troubleshooting / FAQ} \label{sec:troubleshooting} Make sure your code contains \verb+#include + and that \verb+__USE_SDL+ is defined. Also, compiling under Mac OS X requires the inclusion of the flag \verb+-framework Cocoa+. See the shared library example for a working example. +\item The Python interface isn't working! It can't find \verb+libale_c.so+. + +Make sure to compile ALE using CMake. This will build the library required by the Python interface. \end{itemize} @@ -652,7 +654,7 @@ \section{ALE Interface Specifications}\label{sec:functions} a float value; \emph{e.g.}: \verb+getBool(``repeat_action_probability'')+. \verb+void setString(const string& key, const string& value)+: Sets the value of any flag - that has a string type; \emph{e.g.}: \verb+setString("random_seed", "time")+. + that has a string type; \emph{e.g.}: \verb+setString("record_screen_dir", "record")+. \verb+loadRom()+ must be called before the setting will take effect. \verb+void setInt(const std::string& key, const int value)+: Sets the value of any flag @@ -695,6 +697,15 @@ \section{ALE Interface Specifications}\label{sec:functions} \verb+const ALEScreen &getScreen()+: Returns a matrix containing the current game screen. + \verb+void getScreenGrayscale(pixel_t *grayscale_output_buffer)+: This method should receive an + array of length width $\times$ height (generally $160 \times 210 = 33,600$) and then it will fill this array + with the grayscale colours + + \verb+void getScreenRGB(pixel_t *output_rgb_buffer)+: This method should receive an array of length + $3 \times$ width $\times$ height (generally $3 \times 160 \times 210 = 100,800$) and then it will fill this + array with the RGB colours. The first positions contain the red colours, followed by the green colours + and then the blue colours + \verb+const ALERAM &getRAM()+: Returns a vector containing current RAM content (byte-level). \verb+void saveState()+: Saves the current state of the system if one wants to be able to recover @@ -702,6 +713,18 @@ \section{ALE Interface Specifications}\label{sec:functions} \verb+void loadState()+: Loads a previous saved state of the system once we have a state saved. + \verb+ALEState cloneState()+: Makes a copy of the environment state. This copy does \textbf{not} + include pseudo-randomness, making it suitable for planning purposes. + + \verb+ALEState cloneSystemState()+: This makes a copy of the system and environment state, + suitable for serialization. This includes pseudo-randomness and so is \textbf{not} suitable for planning + purposes. + + \verb+void restoreState(const ALEState& state)+: Reverse operation of \verb+cloneState()+. This does not + restore pseudo-randomness, so that repeated calls to \verb+restoreState()+ in the stochastic controls setting + will not lead to the same outcomes. By contrast, see \verb+restoreSystemState+. + + \verb+void restoreSystemState(const ALEState& state)+: Reverse operation of \verb+cloneSystemState+. \subsection{Recording trajectories} \indent \indent \verb+void saveScreenPNG(const string& filename)+: Saves the current screen as @@ -730,14 +753,15 @@ \subsection{Main Arguments} -game_controller -- selects an ALE interface default: unset - -random_seed <###|time> -- picks the ALE random seed, or sets it to current time - default: time + -random_seed <###> -- picks the ALE random seed; if set to 0, sets to current + time instead + default: 0 -display_screen -- if true and SDL is enabled, displays ALE screen default: false -sound -- if true and SDL is enabled, the game will have game - sounds enabled + sounds enabled default: false From e6ac8cdccfe1fdca54228696e4571701522ff9fd Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Tue, 2 May 2017 10:08:25 -0700 Subject: [PATCH 031/310] update ALE python/C interface for logging and loading/saving env state `State` is the environment state without system state like pseudorandomness while `SystemState` is the full state. To restore an identical environment where the same actions yield the same successors, make use of `SystemState`s. --- atari_py/__init__.py | 3 + atari_py/ale_c_wrapper.cpp | 24 +++++- atari_py/ale_c_wrapper.h | 45 ++++-------- atari_py/ale_python_interface.py | 122 +++++++++++++++++++------------ 4 files changed, 118 insertions(+), 76 deletions(-) diff --git a/atari_py/__init__.py b/atari_py/__init__.py index f12d58d..e09a7bd 100644 --- a/atari_py/__init__.py +++ b/atari_py/__init__.py @@ -10,3 +10,6 @@ def get_game_path(game_name): def list_games(): files = os.listdir(_game_dir()) return [os.path.basename(f).split(".")[0] for f in files] + +# default to only logging errors +ALEInterface.setLoggerMode(ALEInterface.Logger.Error) diff --git a/atari_py/ale_c_wrapper.cpp b/atari_py/ale_c_wrapper.cpp index 2ddd746..30f6073 100644 --- a/atari_py/ale_c_wrapper.cpp +++ b/atari_py/ale_c_wrapper.cpp @@ -1,3 +1,25 @@ -//all code is currently in the .h file #include "ale_c_wrapper.h" +#include +#include +#include + +void encodeState(ALEState *state, char *buf, int buf_len) { + std::string str = state->serialize(); + + if (buf_len < int(str.length())) { + throw new std::runtime_error("Buffer is not big enough to hold serialized ALEState. Please use encodeStateLen to determine the correct buffer size"); + } + + memcpy(buf, str.data(), str.length()); +} + +int encodeStateLen(ALEState *state) { + return state->serialize().length(); +} + +ALEState *decodeState(const char *serialized, int len) { + std::string str(serialized, len); + + return new ALEState(str); +} \ No newline at end of file diff --git a/atari_py/ale_c_wrapper.h b/atari_py/ale_c_wrapper.h index 197ab8f..cf01cc1 100644 --- a/atari_py/ale_c_wrapper.h +++ b/atari_py/ale_c_wrapper.h @@ -52,16 +52,13 @@ extern "C" { int getScreenWidth(ALEInterface *ale){return ale->getScreen().width();} int getScreenHeight(ALEInterface *ale){return ale->getScreen().height();} - void getScreenRGB(ALEInterface *ale, int *output_buffer){ + void getScreenRGB(ALEInterface *ale, unsigned char *output_buffer){ size_t w = ale->getScreen().width(); size_t h = ale->getScreen().height(); size_t screen_size = w*h; pixel_t *ale_screen_data = ale->getScreen().getArray(); - for(int i = 0;i < screen_size;i++){ - output_buffer[i] = rgb_palette[ale_screen_data[i]]; - } - + ale->theOSystem->colourPalette().applyPaletteRGB(output_buffer, ale_screen_data, screen_size); } void getScreenRGB2(ALEInterface *ale, unsigned char *output_buffer){ @@ -77,10 +74,8 @@ extern "C" { output_buffer[j++] = (zrgb>>8)&0xff; output_buffer[j++] = (zrgb>>0)&0xff; } - } - void getScreenGrayscale(ALEInterface *ale, unsigned char *output_buffer){ size_t w = ale->getScreen().width(); size_t h = ale->getScreen().height(); @@ -92,32 +87,22 @@ extern "C" { void saveState(ALEInterface *ale){ale->saveState();} void loadState(ALEInterface *ale){ale->loadState();} + ALEState* cloneState(ALEInterface *ale){return new ALEState(ale->cloneState());} + void restoreState(ALEInterface *ale, ALEState* state){ale->restoreState(*state);} + ALEState* cloneSystemState(ALEInterface *ale){return new ALEState(ale->cloneSystemState());} + void restoreSystemState(ALEInterface *ale, ALEState* state){ale->restoreSystemState(*state);} + void deleteState(ALEState* state){delete state;} void saveScreenPNG(ALEInterface *ale,const char *filename){ale->saveScreenPNG(filename);} - ALEState* cloneState(ALEInterface *ale) { - return new ALEState(ale->cloneState()); - } - - void ALEState_del(ALEState* state) { - delete state; - } - - void restoreState(ALEInterface *ale, ALEState* state) { - ale->restoreState(*state); - } - - int ALEState_getFrameNumber(ALEState* state) { - return state->getFrameNumber(); - } - - int ALEState_getEpisodeFrameNumber(ALEState* state) { - return state->getEpisodeFrameNumber(); - } - - bool ALEState_equals(ALEState* a, ALEState *b) { - return a->equals(*b); - } + // Encodes the state as a raw bytestream. This may have multiple '\0' characters + // and thus should not be treated as a C string. Use encodeStateLen to find the length + // of the buffer to pass in, or it will be overrun as this simply memcpys bytes into the buffer. + void encodeState(ALEState *state, char *buf, int buf_len); + int encodeStateLen(ALEState *state); + ALEState *decodeState(const char *serialized, int len); + // 0: Info, 1: Warning, 2: Error + void setLoggerMode(int mode) { ale::Logger::setMode(ale::Logger::mode(mode)); } } #endif diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index f93d7ba..72425e0 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -2,6 +2,7 @@ # Author: Ben Goodrich # This directly implements a python version of the arcade learning # environment interface. +__all__ = ['ALEInterface'] from ctypes import * import numpy as np @@ -74,45 +75,26 @@ ale_lib.saveState.restype = None ale_lib.loadState.argtypes = [c_void_p] ale_lib.loadState.restype = None -ale_lib.saveScreenPNG.argtypes = [c_void_p, c_char_p] -ale_lib.saveScreenPNG.restype = None ale_lib.cloneState.argtypes = [c_void_p] ale_lib.cloneState.restype = c_void_p ale_lib.restoreState.argtypes = [c_void_p, c_void_p] ale_lib.restoreState.restype = None - -ale_lib.ALEState_del.argtypes = [c_void_p] -ale_lib.ALEState_del.restype = None -ale_lib.ALEState_getFrameNumber.argtypes = [c_void_p] -ale_lib.ALEState_getFrameNumber.restype = c_int -ale_lib.ALEState_getEpisodeFrameNumber.argtypes = [c_void_p] -ale_lib.ALEState_getEpisodeFrameNumber.restype = c_int -ale_lib.ALEState_equals.argtypes = [c_void_p, c_void_p] -ale_lib.ALEState_equals.restype = c_bool - - -class ALEState(object): - def __init__(self, obj, ale): - self.obj = obj - self.ale = ale - - def __del__(self): - ale_lib.ALEState_del(self.obj) - - def __eq__(self, other): - return isinstance(other, self.__class__) \ - and ale_lib.ALEState_equals(self.obj, other.obj) - - def __ne__(self, other): - return not self.__eq__(other) - - @property - def frame_number(self): - return ale_lib.ALEState_getFrameNumber(self.obj) - - @property - def episode_frame_number(self): - return ale_lib.ALEState_getEpisodeFrameNumber(self.obj) +ale_lib.cloneSystemState.argtypes = [c_void_p] +ale_lib.cloneSystemState.restype = c_void_p +ale_lib.restoreSystemState.argtypes = [c_void_p, c_void_p] +ale_lib.restoreSystemState.restype = None +ale_lib.deleteState.argtypes = [c_void_p] +ale_lib.deleteState.restype = None +ale_lib.saveScreenPNG.argtypes = [c_void_p, c_char_p] +ale_lib.saveScreenPNG.restype = None +ale_lib.encodeState.argtypes = [c_void_p, c_void_p, c_int] +ale_lib.encodeState.restype = None +ale_lib.encodeStateLen.argtypes = [c_void_p] +ale_lib.encodeStateLen.restype = c_int +ale_lib.decodeState.argtypes = [c_void_p, c_int] +ale_lib.decodeState.restype = c_void_p +ale_lib.setLoggerMode.argtypes = [c_int] +ale_lib.setLoggerMode.restype = None def _as_bytes(s): if hasattr(s, 'encode'): @@ -120,6 +102,12 @@ def _as_bytes(s): return s class ALEInterface(object): + # Logger enum + class Logger: + Info = 0 + Warning = 1 + Error = 2 + def __init__(self): self.obj = ale_lib.ALE_new() @@ -181,7 +169,6 @@ def getScreenDims(self): height = ale_lib.getScreenHeight(self.obj) return (width, height) - def getScreen(self, screen_data=None): """This function fills screen_data with the RAW Pixel data screen_data MUST be a numpy array of uint8/int8. This could be initialized like so: @@ -198,12 +185,12 @@ def getScreen(self, screen_data=None): return screen_data def getScreenRGB(self, screen_data=None): - """This function fills screen_data with the data in BGRZ (not actually RGB -- see getScreenRGB2 for that) format. + """This function fills screen_data with the data in RGB format screen_data MUST be a numpy array of uint8. This can be initialized like so: - screen_data = np.empty((height,width,4), dtype=np.uint8) + screen_data = np.empty((height,width,3), dtype=np.uint8) If it is None, then this function will initialize it. - On little-endian machines like x86, the channels are BGRZ order: - screen_data[x, y, 0:4] is [blue, green, red, 0] + On little-endian machines like x86, the channels are BGR order: + screen_data[x, y, 0:3] is [blue, green, red] On big-endian machines (rare in 2017) the channels would be the opposite order. There's not much error checking here: if you supply an array that's too small this function will produce undefined behavior. @@ -211,7 +198,7 @@ def getScreenRGB(self, screen_data=None): if(screen_data is None): width = ale_lib.getScreenWidth(self.obj) height = ale_lib.getScreenHeight(self.obj) - screen_data = np.empty((height, width,4), dtype=np.uint8) + screen_data = np.empty((height, width,3), dtype=np.uint8) ale_lib.getScreenRGB(self.obj, as_ctypes(screen_data[:])) return screen_data @@ -264,21 +251,66 @@ def getRAM(self, ram=None): return ram def saveScreenPNG(self, filename): + """Save the current screen as a png file""" return ale_lib.saveScreenPNG(self.obj, _as_bytes(filename)) def saveState(self): + """Saves the state of the system""" return ale_lib.saveState(self.obj) def loadState(self): + """Loads the state of the system""" return ale_lib.loadState(self.obj) def cloneState(self): - return ALEState(ale_lib.cloneState(self.obj), self) + """This makes a copy of the environment state. This copy does *not* + include pseudorandomness, making it suitable for planning + purposes. By contrast, see cloneSystemState. + """ + return ale_lib.cloneState(self.obj) def restoreState(self, state): - if state.ale is not self: - raise ValueError('Can only restore state on the ale instance it yielded from') - return ale_lib.restoreState(self.obj, state.obj) + """Reverse operation of cloneState(). This does not restore + pseudorandomness, so that repeated calls to restoreState() in + the stochastic controls setting will not lead to the same + outcomes. By contrast, see restoreSystemState. + """ + ale_lib.restoreState(self.obj, state) + + def cloneSystemState(self): + """This makes a copy of the system & environment state, suitable for + serialization. This includes pseudorandomness and so is *not* + suitable for planning purposes. + """ + return ale_lib.cloneSystemState(self.obj) + + def restoreSystemState(self, state): + """Reverse operation of cloneSystemState.""" + ale_lib.restoreSystemState(self.obj, state) + + def deleteState(self, state): + """ Deallocates the ALEState """ + ale_lib.deleteState(state) + + def encodeStateLen(self, state): + return ale_lib.encodeStateLen(state) + + def encodeState(self, state, buf=None): + if buf == None: + length = ale_lib.encodeStateLen(state) + buf = np.zeros(length, dtype=np.uint8) + ale_lib.encodeState(state, as_ctypes(buf), c_int(len(buf))) + return buf + + def decodeState(self, serialized): + return ale_lib.decodeState(as_ctypes(serialized), len(serialized)) def __del__(self): ale_lib.ALE_del(self.obj) + + @staticmethod + def setLoggerMode(mode): + dic = {'info': 0, 'warning': 1, 'error': 2} + mode = dic.get(mode, mode) + assert mode in [0, 1, 2], "Invalid Mode! Mode must be one of 0: info, 1: warning, 2: error" + ale_lib.setLoggerMode(mode) From 6060c410769f9bac217768d33af65bdfe6f93fb8 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Tue, 2 May 2017 10:55:51 -0700 Subject: [PATCH 032/310] drop obsolete defaults now handled by emucore settings --- .../ale_interface/src/common/Defaults.cpp | 39 ------------------- .../ale_interface/src/common/Defaults.hpp | 25 ------------ atari_py/ale_interface/stellarc | 2 - 3 files changed, 66 deletions(-) delete mode 100644 atari_py/ale_interface/src/common/Defaults.cpp delete mode 100644 atari_py/ale_interface/src/common/Defaults.hpp delete mode 100644 atari_py/ale_interface/stellarc diff --git a/atari_py/ale_interface/src/common/Defaults.cpp b/atari_py/ale_interface/src/common/Defaults.cpp deleted file mode 100644 index ff506fc..0000000 --- a/atari_py/ale_interface/src/common/Defaults.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* ***************************************************************************** - * A.L.E (Arcade Learning Environment) - * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and - * the Reinforcement Learning and Artificial Intelligence Laboratory - * Released under the GNU General Public License; see License.txt for details. - * - * Based on: Stella -- "An Atari 2600 VCS Emulator" - * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team - * - * ***************************************************************************** - * Defaults.cpp - * - * Defines methods for setting default parameters. - * - **************************************************************************** */ -#include "Defaults.hpp" - -void setDefaultSettings(Settings &settings) { - // Controller settings - settings.setInt("max_num_frames", 0); - settings.setInt("max_num_frames_per_episode", 0); - - // FIFO controller settings - settings.setBool("run_length_encoding", true); - - // Environment customization settings - settings.setBool("restricted_action_set", false); - settings.setString("random_seed", "time"); - settings.setBool("color_averaging", false); - settings.setBool("send_rgb", false); - settings.setInt("frame_skip", 1); - settings.setFloat("repeat_action_probability", 0.25); - - // Display Settings - settings.setBool("display_screen", false); - - // Record settings - settings.setString("record_sound_filename", ""); -} diff --git a/atari_py/ale_interface/src/common/Defaults.hpp b/atari_py/ale_interface/src/common/Defaults.hpp deleted file mode 100644 index c9bca20..0000000 --- a/atari_py/ale_interface/src/common/Defaults.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/* ***************************************************************************** - * A.L.E (Arcade Learning Environment) - * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and - * the Reinforcement Learning and Artificial Intelligence Laboratory - * Released under the GNU General Public License; see License.txt for details. - * - * Based on: Stella -- "An Atari 2600 VCS Emulator" - * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team - * - * ***************************************************************************** - * Defaults.hpp - * - * Defines methods for setting default parameters. - * - **************************************************************************** */ - -#ifndef __DEFAULTS_HPP__ -#define __DEFAULTS_HPP__ - -#include "../emucore/Settings.hxx" - -/** Sets all of the ALE-specific default settings */ -void setDefaultSettings(Settings &settings); - -#endif // __DEFAULTS_HPP__ diff --git a/atari_py/ale_interface/stellarc b/atari_py/ale_interface/stellarc deleted file mode 100644 index 79f94d2..0000000 --- a/atari_py/ale_interface/stellarc +++ /dev/null @@ -1,2 +0,0 @@ -cpu=low - From acea4088eff3b264d6bad9a2eb6348ebd54d315a Mon Sep 17 00:00:00 2001 From: Tom Brown Date: Thu, 4 May 2017 06:42:41 -0700 Subject: [PATCH 033/310] Bump setup.py version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index cd22780..1b95039 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.0.21', + version='0.0.22-dev', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From ed8f675b5dcdc530a8183032e9ca661127fdc994 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Fri, 12 May 2017 17:08:15 -0700 Subject: [PATCH 034/310] Bump version to drop "dev" tag now that this has been in use --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 1b95039..6527e53 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.0.22-dev', + version='0.0.22', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From 2710154bc2c6fa4eb671d72d8e6262656078c783 Mon Sep 17 00:00:00 2001 From: Greg Brockman Date: Sat, 13 May 2017 15:58:19 -0700 Subject: [PATCH 035/310] Bump minor version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 6527e53..ab2339a 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.0.22', + version='0.1.0', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From f3e437de615899b7bbdfee3f628788eacc21d8e7 Mon Sep 17 00:00:00 2001 From: Greg Brockman Date: Sat, 13 May 2017 19:53:46 -0700 Subject: [PATCH 036/310] Regenerate package_data --- atari_py/package_data.txt | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/atari_py/package_data.txt b/atari_py/package_data.txt index 2743d65..6d35fff 100644 --- a/atari_py/package_data.txt +++ b/atari_py/package_data.txt @@ -4,10 +4,6 @@ ale_c_wrapper.cpp ale_c_wrapper.h ale_interface/CMakeLists.txt ale_interface/Makefile -ale_interface/common.rules -ale_interface/makefile.mac -ale_interface/makefile.unix -ale_interface/setup.sh ale_interface/src/ale_interface.cpp ale_interface/src/ale_interface.hpp ale_interface/src/common/Array.hxx @@ -15,8 +11,6 @@ ale_interface/src/common/ColourPalette.cpp ale_interface/src/common/ColourPalette.hpp ale_interface/src/common/Constants.cpp ale_interface/src/common/Constants.h -ale_interface/src/common/Defaults.cpp -ale_interface/src/common/Defaults.hpp ale_interface/src/common/Log.cpp ale_interface/src/common/Log.hpp ale_interface/src/common/Palettes.hpp @@ -33,14 +27,12 @@ ale_interface/src/common/VideoModeList.hxx ale_interface/src/common/display_screen.cpp ale_interface/src/common/display_screen.h ale_interface/src/common/misc_tools.h -ale_interface/src/common/module.mk ale_interface/src/common/stella.png ale_interface/src/common/stella.xpm ale_interface/src/controllers/ale_controller.cpp ale_interface/src/controllers/ale_controller.hpp ale_interface/src/controllers/fifo_controller.cpp ale_interface/src/controllers/fifo_controller.hpp -ale_interface/src/controllers/module.mk ale_interface/src/controllers/rlglue_controller.cpp ale_interface/src/controllers/rlglue_controller.hpp ale_interface/src/emucore/AtariVox.cxx @@ -141,7 +133,6 @@ ale_interface/src/emucore/TIASnd.cxx ale_interface/src/emucore/TIASnd.hxx ale_interface/src/emucore/m6502/Copyright.txt ale_interface/src/emucore/m6502/License.txt -ale_interface/src/emucore/m6502/module.mk ale_interface/src/emucore/m6502/src/Device.cxx ale_interface/src/emucore/m6502/src/Device.hxx ale_interface/src/emucore/m6502/src/M6502.cxx @@ -162,7 +153,6 @@ ale_interface/src/emucore/m6502/src/System.hxx ale_interface/src/emucore/m6502/src/bspf/Copyright.txt ale_interface/src/emucore/m6502/src/bspf/License.txt ale_interface/src/emucore/m6502/src/bspf/src/bspf.hxx -ale_interface/src/emucore/module.mk ale_interface/src/emucore/rsynth/COPYING ale_interface/src/emucore/rsynth/Elements.def ale_interface/src/emucore/rsynth/PORTING @@ -172,7 +162,6 @@ ale_interface/src/emucore/rsynth/darray.h ale_interface/src/emucore/rsynth/elements.c ale_interface/src/emucore/rsynth/holmes.c ale_interface/src/emucore/rsynth/kmap -ale_interface/src/emucore/rsynth/module.mk ale_interface/src/emucore/rsynth/opsynth.c ale_interface/src/emucore/rsynth/phfeat.h ale_interface/src/emucore/rsynth/phones.c @@ -192,7 +181,6 @@ ale_interface/src/environment/ale_ram.hpp ale_interface/src/environment/ale_screen.hpp ale_interface/src/environment/ale_state.cpp ale_interface/src/environment/ale_state.hpp -ale_interface/src/environment/module.mk ale_interface/src/environment/phosphor_blend.cpp ale_interface/src/environment/phosphor_blend.hpp ale_interface/src/environment/stella_environment.cpp @@ -200,14 +188,12 @@ ale_interface/src/environment/stella_environment.hpp ale_interface/src/external/TinyMT/LICENSE.txt ale_interface/src/external/TinyMT/tinymt32.c ale_interface/src/external/TinyMT/tinymt32.h -ale_interface/src/external/module.mk ale_interface/src/games/RomSettings.cpp ale_interface/src/games/RomSettings.hpp ale_interface/src/games/RomUtils.cpp ale_interface/src/games/RomUtils.hpp ale_interface/src/games/Roms.cpp ale_interface/src/games/Roms.hpp -ale_interface/src/games/module.mk ale_interface/src/games/supported/Adventure.cpp ale_interface/src/games/supported/Adventure.hpp ale_interface/src/games/supported/AirRaid.cpp @@ -335,7 +321,6 @@ ale_interface/src/games/supported/YarsRevenge.hpp ale_interface/src/games/supported/Zaxxon.cpp ale_interface/src/games/supported/Zaxxon.hpp ale_interface/src/main.cpp -ale_interface/src/module.mk ale_interface/src/os_dependent/FSNodePOSIX.cxx ale_interface/src/os_dependent/FSNodeWin32.cxx ale_interface/src/os_dependent/OSystemUNIX.cxx @@ -346,8 +331,6 @@ ale_interface/src/os_dependent/SettingsUNIX.cxx ale_interface/src/os_dependent/SettingsUNIX.hxx ale_interface/src/os_dependent/SettingsWin32.cxx ale_interface/src/os_dependent/SettingsWin32.hxx -ale_interface/src/os_dependent/module.mk -ale_interface/stellarc atari_ntsc_rgb_palette.h atari_roms/adventure.bin atari_roms/air_raid.bin @@ -378,6 +361,7 @@ atari_roms/freeway.bin atari_roms/frostbite.bin atari_roms/gopher.bin atari_roms/gravitar.bin +atari_roms/hero.bin atari_roms/ice_hockey.bin atari_roms/jamesbond.bin atari_roms/journey_escape.bin From f5a1d321bf997ed8a0cda2270f73384b1c792186 Mon Sep 17 00:00:00 2001 From: Greg Brockman Date: Sat, 13 May 2017 19:53:57 -0700 Subject: [PATCH 037/310] Bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ab2339a..cb962e7 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.1.0', + version='0.1.1', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From 21b6d5f226b8cfa8a5ba6f43af48ed4d06c6173c Mon Sep 17 00:00:00 2001 From: Yangqing Jia Date: Fri, 8 Sep 2017 18:00:48 -0700 Subject: [PATCH 038/310] Adding std:: to the transform function --- atari_py/ale_interface/src/emucore/FSNode.hxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/atari_py/ale_interface/src/emucore/FSNode.hxx b/atari_py/ale_interface/src/emucore/FSNode.hxx index 4085651..b05f8f7 100644 --- a/atari_py/ale_interface/src/emucore/FSNode.hxx +++ b/atari_py/ale_interface/src/emucore/FSNode.hxx @@ -120,8 +120,10 @@ class AbstractFilesystemNode { std::string first = displayName(); std::string second = node.displayName(); - transform(first.begin(), first.end(), first.begin(), (int(*)(int)) tolower); - transform(second.begin(), second.end(), second.begin(), (int(*)(int)) tolower); + std::transform( + first.begin(), first.end(), first.begin(), (int(*)(int)) tolower); + std::transform( + second.begin(), second.end(), second.begin(), (int(*)(int)) tolower); return first < second; } From 19a2390c2f5de06253dcec717fae6b119c5d0b22 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 26 Sep 2018 19:39:15 -0700 Subject: [PATCH 039/310] make travis build wheels --- .travis.yml | 34 ++++++++++++---------------------- dockerfile.3.6 | 10 ++++++++++ 2 files changed, 22 insertions(+), 22 deletions(-) create mode 100644 dockerfile.3.6 diff --git a/.travis.yml b/.travis.yml index 8c96188..84dbf97 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,25 +1,15 @@ -dist: trusty sudo: required -cache: - apt: true language: python -addons: - apt: - packages: - - python-dev -python: - - "2.7" - - "3.5" -install: pip install tox-travis -script: tox +services: + - docker +env: + - PYTHON_VER=3.6 + +install: + - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . +script: + - docker run pytest . + - docker run pip wheel --wheel-dir=/tmp/wheeldir . + +# upload the wheels on success / tag / etc -notifications: - slack: - secure: h/Mxm8K+avH/2W0818zCHmLloRPMFN4NJL01+VShvAkH80/acfjeq/+mMdWXXPL/oOB6kSHDk+GDhwR6+s03ZcPMn5INTFvFYqUc6UWmT+NXtOPxGTN0xda6MdYUkWQUKaMyjFrweZQOMOASFBIzPOq4XeVbM5aB8s4EJhnfAcYZhp/idwKbToVihN4KZgxlvZIFc8iEp1o9uSl5qrsaeYYYXRkb6mauacAwOo4/Chu+cOnoLUOnvhBFE3rV3doDNrbnoalO8XiExtgx5CIAYWrlMni7r2Q+LlzgwdyTH19ZtybPxJTZIIWSBQ2UtcoYdIEDcc36GcUwz1VUGg32mLJJnY2xw80CWR4ixFPpLwwP5Y99WTn8v094B4nmFTWOwNWXp3EkqtTN9XcJoRBqXB5ArucIPqrx57dOCljSKx22gL6WaF2p3stSAxIGFektGyGnisaELrFZG1C63aHoUPicj3gUlijmAoUmYaDRf6P1wnpXqBpKDAWWhAMSatvx1ekmEJgR7OQklQnnfjx9kENDUygNUWS4IQwN2qYieuzHFL3of7/30mTM43+Vt/vWN8GI7j01BXu6FNGGloHxjH1pt3bLP/+uj5BJsT2HWF+Z8XR4VE6cyVuKsQAFgCXwOkoDHALbcwsspONDIt/9ixkesgh1oFt4CzU3UuU5wYs= - on_success: change - webhooks: - urls: - - https://hooks.zapier.com/hooks/catch/1711022/6ztmzh/ - - https://hooks.zapier.com/hooks/catch/1711022/6zhc8p/ - on_success: always - on_failure: always diff --git a/dockerfile.3.6 b/dockerfile.3.6 new file mode 100644 index 0000000..aef8fdd --- /dev/null +++ b/dockerfile.3.6 @@ -0,0 +1,10 @@ +FROM python:3.6 + +RUN apt-get -y update && \ + apt-get -y install cmake && \ + pip install pytest + +COPY . /root/code +WORKDIR /root/code + +RUN pip install . From 00151648419809e1e0459aec6fb0de699de5c7fd Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 26 Sep 2018 22:48:39 -0700 Subject: [PATCH 040/310] fix syntax in travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 84dbf97..32030d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,8 +8,8 @@ env: install: - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . script: - - docker run pytest . - - docker run pip wheel --wheel-dir=/tmp/wheeldir . + - docker run atari-py-test pytest . + - docker run atari-py-test pip wheel --wheel-dir=/tmp/wheeldir . # upload the wheels on success / tag / etc From dfedbe364c4dc05a5358fe571dfee51728f44e15 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 12:27:03 -0700 Subject: [PATCH 041/310] bare travis builds --- .travis.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 32030d0..db4c499 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,15 @@ -sudo: required language: python -services: - - docker -env: - - PYTHON_VER=3.6 -install: - - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . -script: - - docker run atari-py-test pytest . - - docker run atari-py-test pip wheel --wheel-dir=/tmp/wheeldir . +os: + - linux + - osx -# upload the wheels on success / tag / etc +python: + - 3.5 + - 3.6 + - 3.7 +script: + - python -c "print('Hello World')" + + From cc7366a2a090feb5b50bdf3d6a7b1e265bc20b62 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 12:29:41 -0700 Subject: [PATCH 042/310] use xenial as a base image for linux --- .travis.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index db4c499..a1540c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,17 @@ language: python -os: - - linux - - osx - python: - 3.5 - 3.6 - 3.7 +matrix: + include: + - os: linux + dist: xenial + + - os: osx + script: - python -c "print('Hello World')" From 2a465fda4450860d91ea9b0484b3f8f176e11ad3 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 12:33:12 -0700 Subject: [PATCH 043/310] use xenial as a base image for linux --- .travis.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index a1540c9..6a8bde9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,12 +5,12 @@ python: - 3.6 - 3.7 -matrix: - include: - - os: linux - dist: xenial - - - os: osx +os: + - dist: xenial + sudo: requires + services: docker + + - osx script: - python -c "print('Hello World')" From c13b90c02f44653607d81cf7089cae0d2c5d959e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 12:37:51 -0700 Subject: [PATCH 044/310] print python version --- .travis.yml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6a8bde9..d7fb0f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,18 +1,9 @@ language: python -python: - - 3.5 - - 3.6 - - 3.7 - os: - - dist: xenial - sudo: requires - services: docker - - osx script: - - python -c "print('Hello World')" + - python -V From fc4574858691e8e2e77403a0a9971073b3d4bcfe Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 12:40:25 -0700 Subject: [PATCH 045/310] test python version --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d7fb0f8..e0a4737 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,3 @@ -language: python - os: - osx From 445c3f184f4ee1723240d0c832ade5ec389afb45 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 13:10:02 -0700 Subject: [PATCH 046/310] try python3 on osx --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e0a4737..7d830dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,6 @@ os: - osx script: - - python -V + - python3 -V From 5515bd976d3efc51e4bbed951b0952e958a2d71d Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 13:13:34 -0700 Subject: [PATCH 047/310] try build on osx and linux --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 7d830dc..34baa68 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,9 @@ os: - osx + - os: linux + serivces: docker + + script: - python3 -V From d650d2ce3106eab998a92f2956e2c396685abf12 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 13:23:23 -0700 Subject: [PATCH 048/310] try installing cmake on osx --- .travis.yml | 11 ++++++----- osx_install.sh | 5 +++++ 2 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 osx_install.sh diff --git a/.travis.yml b/.travis.yml index 34baa68..d6f42e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,12 @@ -os: - - osx +matrix: + include: + - os: osx: + script: ./os_install.sh + - os: linux serivces: docker + script: python3 -V -script: - - python3 -V - diff --git a/osx_install.sh b/osx_install.sh new file mode 100644 index 0000000..4b9907c --- /dev/null +++ b/osx_install.sh @@ -0,0 +1,5 @@ +set -ex +brew install cmake +pip3 install pytest +pytest . + From 64df0b9772cde2233bc1106d59d3d40970f6cf2c Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 13:25:57 -0700 Subject: [PATCH 049/310] syntax in travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d6f42e5..4ffecaa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ matrix: include: - - os: osx: + - os: osx script: ./os_install.sh - os: linux From b8243c709fe001dc306ae8d3d450f5a91dafff71 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 13:28:37 -0700 Subject: [PATCH 050/310] syntax in travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4ffecaa..2d3fb0b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ matrix: include: - os: osx - script: ./os_install.sh + script: ./osx_install.sh - os: linux serivces: docker From d23a1687efa85b66f75a8bd802edcb542ae0259c Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 13:30:44 -0700 Subject: [PATCH 051/310] make osx_install.sh executable --- osx_install.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 osx_install.sh diff --git a/osx_install.sh b/osx_install.sh old mode 100644 new mode 100755 From 0b910720507f7c386a8f8d93a1457f304b3a5b79 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 13:37:50 -0700 Subject: [PATCH 052/310] try building a wheel on osx --- osx_install.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osx_install.sh b/osx_install.sh index 4b9907c..9159e09 100755 --- a/osx_install.sh +++ b/osx_install.sh @@ -1,5 +1,10 @@ set -ex -brew install cmake +# already present in Travis +# brew install cmake + pip3 install pytest pytest . +pip wheel . --wheel-dir=/tmp/wheelhouse +ls -lht /tmp/wheelhouse + From 49f2715bc388e9f1d8d3d7178cd310090826e99b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 13:43:00 -0700 Subject: [PATCH 053/310] wheeling --- osx_install.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osx_install.sh b/osx_install.sh index 9159e09..e19749e 100755 --- a/osx_install.sh +++ b/osx_install.sh @@ -3,8 +3,9 @@ set -ex # brew install cmake pip3 install pytest +pip3 install . pytest . -pip wheel . --wheel-dir=/tmp/wheelhouse +pip3 wheel . --wheel-dir=/tmp/wheelhouse ls -lht /tmp/wheelhouse From de986e5b919a8a0f3d0c86764f1b05ff78ce47ee Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 15:37:26 -0700 Subject: [PATCH 054/310] osx specify platform --- osx_install.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osx_install.sh b/osx_install.sh index e19749e..21ec6c4 100755 --- a/osx_install.sh +++ b/osx_install.sh @@ -6,6 +6,7 @@ pip3 install pytest pip3 install . pytest . -pip3 wheel . --wheel-dir=/tmp/wheelhouse +PYPLATFORM=`python3 -c "import distutils.util; print(distutils.util.get_platform())"` +pip3 wheel . --wheel-dir=/tmp/wheelhouse --build-option --plat-name=$PYPLATFORM ls -lht /tmp/wheelhouse From 3fc27afb1e5305203acb5db0bcda59429c04feee Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 15:49:13 -0700 Subject: [PATCH 055/310] builds on linux using docker --- .travis.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2d3fb0b..7af32f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,14 @@ matrix: script: ./osx_install.sh - os: linux + env: + - PYTHONVER=3.6 serivces: docker - script: python3 -V + install: + - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . + script: + - docker run atari-py-test pytest . + - docker run -v /tmp/wheelhouse:/tmp/wheelhouse atari-py-test pip wheel --wheel-dir=/tmp/wheelhouse From aeb874af478e12d3e0343c20cd70bc9905393d01 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 27 Sep 2018 15:53:41 -0700 Subject: [PATCH 056/310] fixed variable name --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7af32f2..be110ef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ matrix: - os: linux env: - - PYTHONVER=3.6 + - PYTHON_VER=3.6 serivces: docker install: - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . From 90aaa257fa072e92a151f7e7e0af6e10b0ae2194 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 28 Sep 2018 13:12:40 -0700 Subject: [PATCH 057/310] pull platform name from docker --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index be110ef..e447c4e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ matrix: include: - os: osx - script: ./osx_install.sh + script: ./osx_build.sh - os: linux env: @@ -11,7 +11,7 @@ matrix: - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . script: - docker run atari-py-test pytest . - - docker run -v /tmp/wheelhouse:/tmp/wheelhouse atari-py-test pip wheel --wheel-dir=/tmp/wheelhouse + - PLATNAME=$(docker run atari-py-test python -c "import distutils.util; print(distutils.util.platorm_name)") docker run -v /tmp/wheelhouse:/tmp/wheelhouse atari-py-test pip wheel --wheel-dir=/tmp/wheelhouse . From 48fce3c56b1fe9ccca0a7c18acc4b03e1aed21b9 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 28 Sep 2018 13:14:58 -0700 Subject: [PATCH 058/310] build wheels on linux and osx --- .travis.yml | 2 +- linux_build.sh | 6 ++++++ osx_install.sh => osx_build.sh | 0 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100755 linux_build.sh rename osx_install.sh => osx_build.sh (100%) diff --git a/.travis.yml b/.travis.yml index e447c4e..3eb7eee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ matrix: - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . script: - docker run atari-py-test pytest . - - PLATNAME=$(docker run atari-py-test python -c "import distutils.util; print(distutils.util.platorm_name)") docker run -v /tmp/wheelhouse:/tmp/wheelhouse atari-py-test pip wheel --wheel-dir=/tmp/wheelhouse . + - docker run -v /tmp/wheelhouse:/tmp/wheelhouse atari-py-test ./linux_build.sh diff --git a/linux_build.sh b/linux_build.sh new file mode 100755 index 0000000..b44897f --- /dev/null +++ b/linux_build.sh @@ -0,0 +1,6 @@ +set -ex +# already present in Travis +# brew install cmake + +PYPLATFORM=`python -c "import distutils.util; print(distutils.util.get_platform())"` +pip wheel . --wheel-dir=/tmp/wheelhouse --build-option --plat-name=$PYPLATFORM diff --git a/osx_install.sh b/osx_build.sh similarity index 100% rename from osx_install.sh rename to osx_build.sh From b84b3402b183f5148548411b9c5aa234a9f5c11a Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 28 Sep 2018 13:18:18 -0700 Subject: [PATCH 059/310] ls /tmp/wheelhouse --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 3eb7eee..2c8d226 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ matrix: script: - docker run atari-py-test pytest . - docker run -v /tmp/wheelhouse:/tmp/wheelhouse atari-py-test ./linux_build.sh + - ls -lht /tmp/wheelhouse From 52699579a8aad3181cb6205971ec13e38f72a0e5 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 28 Sep 2018 13:24:32 -0700 Subject: [PATCH 060/310] fix docker call syntax --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2c8d226..31f2445 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ matrix: - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . script: - docker run atari-py-test pytest . - - docker run -v /tmp/wheelhouse:/tmp/wheelhouse atari-py-test ./linux_build.sh + - docker run -v /tmp/wheelhouse:/tmp/wheelhouse atari-py-test bash ./linux_build.sh - ls -lht /tmp/wheelhouse From 7631d9855b1f9cdfaed3bc431138e4748d92a205 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 28 Sep 2018 13:39:02 -0700 Subject: [PATCH 061/310] try dockerless build --- .travis.yml | 31 +++++++++++++++++++++---------- osx_build.sh | 2 -- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index 31f2445..0e5ae1c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,17 +3,28 @@ matrix: - os: osx script: ./osx_build.sh + - os: linux - env: - - PYTHON_VER=3.6 - serivces: docker - install: - - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . - script: - - docker run atari-py-test pytest . - - docker run -v /tmp/wheelhouse:/tmp/wheelhouse atari-py-test bash ./linux_build.sh - - ls -lht /tmp/wheelhouse - + python: 3.6 + sudo: reqiured + install: + - apt-get install -y cmake + +script: + - ./osx_build.sh + + +# - os: linux +# env: +# - PYTHON_VER=3.6 +# serivces: docker +# install: +# - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . +# script: +# - docker run atari-py-test pytest . +# - docker run -v /tmp/wheelhouse:/tmp/wheelhouse atari-py-test bash ./linux_build.sh +# - ls -lht /tmp/wheelhouse +# diff --git a/osx_build.sh b/osx_build.sh index 21ec6c4..3dbe0e2 100755 --- a/osx_build.sh +++ b/osx_build.sh @@ -1,6 +1,4 @@ set -ex -# already present in Travis -# brew install cmake pip3 install pytest pip3 install . From 08fc4af110c4ca9f5262ff61875f06b7e64efd17 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 28 Sep 2018 13:41:10 -0700 Subject: [PATCH 062/310] apt-get needs sudo --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0e5ae1c..09b573f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ matrix: python: 3.6 sudo: reqiured install: - - apt-get install -y cmake + - sudo apt-get install -y cmake script: - ./osx_build.sh From 9352747efd0dd246d6a4701ddf6b00a71061c570 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 28 Sep 2018 13:53:04 -0700 Subject: [PATCH 063/310] deploying via script --- .travis.yml | 37 ++++++++++++++++--------------------- osx_build.sh => build.sh | 0 deploy.sh | 1 + linux_build.sh | 6 ------ 4 files changed, 17 insertions(+), 27 deletions(-) rename osx_build.sh => build.sh (100%) create mode 100644 deploy.sh delete mode 100755 linux_build.sh diff --git a/.travis.yml b/.travis.yml index 09b573f..bfa4d1f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,30 +1,25 @@ matrix: include: - os: osx - script: ./osx_build.sh - + script: ./build.sh - os: linux - python: 3.6 - sudo: reqiured - install: - - sudo apt-get install -y cmake - -script: - - ./osx_build.sh + env: + - PYTHON_VER=3.6 + serivces: docker + install: + - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . + script: + - docker run -v /tmp/wheelhouse:/tmp/wheelhouse atari-py-test bash ./build.sh + - ls -lht /tmp/wheelhouse -# - os: linux -# env: -# - PYTHON_VER=3.6 -# serivces: docker -# install: -# - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . -# script: -# - docker run atari-py-test pytest . -# - docker run -v /tmp/wheelhouse:/tmp/wheelhouse atari-py-test bash ./linux_build.sh -# - ls -lht /tmp/wheelhouse -# - +deploy: + provider: script + script: ./deploy.sh test + on: + all_branches: true + + diff --git a/osx_build.sh b/build.sh similarity index 100% rename from osx_build.sh rename to build.sh diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000..9fb9840 --- /dev/null +++ b/deploy.sh @@ -0,0 +1 @@ +echo $1 diff --git a/linux_build.sh b/linux_build.sh deleted file mode 100755 index b44897f..0000000 --- a/linux_build.sh +++ /dev/null @@ -1,6 +0,0 @@ -set -ex -# already present in Travis -# brew install cmake - -PYPLATFORM=`python -c "import distutils.util; print(distutils.util.get_platform())"` -pip wheel . --wheel-dir=/tmp/wheelhouse --build-option --plat-name=$PYPLATFORM From d501a5d51e54d2e320dbcc43a313bd249f0baa98 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 11:51:47 -0700 Subject: [PATCH 064/310] trying to deploy all builds --- .travis.yml | 2 +- deploy.sh | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index bfa4d1f..4533e67 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ matrix: deploy: provider: script - script: ./deploy.sh test + script: ./deploy.sh on: all_branches: true diff --git a/deploy.sh b/deploy.sh index 9fb9840..607b716 100644 --- a/deploy.sh +++ b/deploy.sh @@ -1 +1,4 @@ -echo $1 +set -ex +pip install twine +twine upload /tmp/wheelhouse/atari-py-* + From cb620d3dacde2b07073b09859223408c5497e636 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 12:02:33 -0700 Subject: [PATCH 065/310] update deploy.sh --- deploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 deploy.sh diff --git a/deploy.sh b/deploy.sh old mode 100644 new mode 100755 index 607b716..4e1416c --- a/deploy.sh +++ b/deploy.sh @@ -1,4 +1,4 @@ set -ex pip install twine -twine upload /tmp/wheelhouse/atari-py-* +twine upload /tmp/wheelhouse/atari_py-* From e588937687799fff2408e2d62a646f9cc749f0a7 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 12:11:46 -0700 Subject: [PATCH 066/310] install twine with --user --- deploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy.sh b/deploy.sh index 4e1416c..5bd6ece 100755 --- a/deploy.sh +++ b/deploy.sh @@ -1,4 +1,4 @@ set -ex -pip install twine +pip install --user twine twine upload /tmp/wheelhouse/atari_py-* From fa08c64e22efe2bf5e8d2b17b28079d716292645 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 12:26:57 -0700 Subject: [PATCH 067/310] polishing deploy script --- deploy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy.sh b/deploy.sh index 5bd6ece..63f5645 100755 --- a/deploy.sh +++ b/deploy.sh @@ -1,4 +1,4 @@ set -ex -pip install --user twine -twine upload /tmp/wheelhouse/atari_py-* +pip3 install --user twine +python3 -m twine upload /tmp/wheelhouse/atari_py-* From ca6f7ab466ea6c6a394470b4ed797dbab9dd7069 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 12:37:41 -0700 Subject: [PATCH 068/310] trying again --- deploy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy.sh b/deploy.sh index 63f5645..7c1c967 100755 --- a/deploy.sh +++ b/deploy.sh @@ -1,4 +1,4 @@ set -ex -pip3 install --user twine -python3 -m twine upload /tmp/wheelhouse/atari_py-* +pip install --user twine +python -m twine upload /tmp/wheelhouse/atari_py-* From 3a3f54f14099c8187da42d7316c77ae8edb16532 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 13:28:12 -0700 Subject: [PATCH 069/310] merge build and deploy scripts --- .travis.yml | 13 ++----------- build.sh => build_and_deploy.sh | 6 ++++++ deploy.sh | 4 ---- 3 files changed, 8 insertions(+), 15 deletions(-) rename build.sh => build_and_deploy.sh (71%) delete mode 100755 deploy.sh diff --git a/.travis.yml b/.travis.yml index 4533e67..5022f33 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ matrix: include: - os: osx - script: ./build.sh + script: ./build_and_deploy.sh - os: linux env: @@ -10,16 +10,7 @@ matrix: install: - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . script: - - docker run -v /tmp/wheelhouse:/tmp/wheelhouse atari-py-test bash ./build.sh - - ls -lht /tmp/wheelhouse - - -deploy: - provider: script - script: ./deploy.sh - on: - all_branches: true - + - docker run -e TWINE_USERNAME=$TWINE_USERNAME -e TWINE_PASSWORD=$TWINE_PASSWORD atari-py-test bash ./build_and_deploy.sh diff --git a/build.sh b/build_and_deploy.sh similarity index 71% rename from build.sh rename to build_and_deploy.sh index 3dbe0e2..3a07974 100755 --- a/build.sh +++ b/build_and_deploy.sh @@ -8,3 +8,9 @@ PYPLATFORM=`python3 -c "import distutils.util; print(distutils.util.get_platform pip3 wheel . --wheel-dir=/tmp/wheelhouse --build-option --plat-name=$PYPLATFORM ls -lht /tmp/wheelhouse +if [[ -e $TRAVIS_TAG ]] +do + pip3 install twine + twine upload /tmp/wheelhouse/atari_py-* +done + diff --git a/deploy.sh b/deploy.sh deleted file mode 100755 index 7c1c967..0000000 --- a/deploy.sh +++ /dev/null @@ -1,4 +0,0 @@ -set -ex -pip install --user twine -python -m twine upload /tmp/wheelhouse/atari_py-* - From 0b3ae6fd9469521d0abc77ce98391bc294d1af84 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 13:38:53 -0700 Subject: [PATCH 070/310] pass travis tag to docker container --- .travis.yml | 2 +- build_and_deploy.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5022f33..8e9de80 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ matrix: install: - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . script: - - docker run -e TWINE_USERNAME=$TWINE_USERNAME -e TWINE_PASSWORD=$TWINE_PASSWORD atari-py-test bash ./build_and_deploy.sh + - docker run -e TRAVIS_TAG=$TRAVIS_TAG -e TWINE_USERNAME=$TWINE_USERNAME -e TWINE_PASSWORD=$TWINE_PASSWORD atari-py-test bash ./build_and_deploy.sh diff --git a/build_and_deploy.sh b/build_and_deploy.sh index 3a07974..24685f8 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -8,7 +8,7 @@ PYPLATFORM=`python3 -c "import distutils.util; print(distutils.util.get_platform pip3 wheel . --wheel-dir=/tmp/wheelhouse --build-option --plat-name=$PYPLATFORM ls -lht /tmp/wheelhouse -if [[ -e $TRAVIS_TAG ]] +if [[ ! -z "$TRAVIS_TAG" ]] do pip3 install twine twine upload /tmp/wheelhouse/atari_py-* From 94256f7a51174e9935e4919935cbbf6c869d0732 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 13:56:22 -0700 Subject: [PATCH 071/310] bash syntax --- build_and_deploy.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build_and_deploy.sh b/build_and_deploy.sh index 24685f8..47eabbc 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -8,8 +8,7 @@ PYPLATFORM=`python3 -c "import distutils.util; print(distutils.util.get_platform pip3 wheel . --wheel-dir=/tmp/wheelhouse --build-option --plat-name=$PYPLATFORM ls -lht /tmp/wheelhouse -if [[ ! -z "$TRAVIS_TAG" ]] -do +if [[ ! -z "$TRAVIS_TAG" ]]; do pip3 install twine twine upload /tmp/wheelhouse/atari_py-* done From e9814838c0f53599b6789da8b461dd5f54b669b4 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 14:01:42 -0700 Subject: [PATCH 072/310] try with set TRAVIS_TAG --- build_and_deploy.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build_and_deploy.sh b/build_and_deploy.sh index 47eabbc..346e8d7 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -8,6 +8,7 @@ PYPLATFORM=`python3 -c "import distutils.util; print(distutils.util.get_platform pip3 wheel . --wheel-dir=/tmp/wheelhouse --build-option --plat-name=$PYPLATFORM ls -lht /tmp/wheelhouse +export TRAVIS_TAG="0.1.2" if [[ ! -z "$TRAVIS_TAG" ]]; do pip3 install twine twine upload /tmp/wheelhouse/atari_py-* From 7c9b10c4d0dd0ae92f11710fa0b6b268e3bfe6c9 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 14:04:49 -0700 Subject: [PATCH 073/310] bash syntax --- build_and_deploy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build_and_deploy.sh b/build_and_deploy.sh index 346e8d7..99f57ad 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -9,8 +9,8 @@ pip3 wheel . --wheel-dir=/tmp/wheelhouse --build-option --plat-name=$PYPLATFORM ls -lht /tmp/wheelhouse export TRAVIS_TAG="0.1.2" -if [[ ! -z "$TRAVIS_TAG" ]]; do +if [[ ! -z "$TRAVIS_TAG" ]]; then pip3 install twine twine upload /tmp/wheelhouse/atari_py-* -done +fi From d3ee18c81ab4d09a2b73d9c19dce80c1ef664614 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 14:12:00 -0700 Subject: [PATCH 074/310] use --user option when installing twine --- build_and_deploy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build_and_deploy.sh b/build_and_deploy.sh index 99f57ad..8b1d7a4 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -10,7 +10,7 @@ ls -lht /tmp/wheelhouse export TRAVIS_TAG="0.1.2" if [[ ! -z "$TRAVIS_TAG" ]]; then - pip3 install twine - twine upload /tmp/wheelhouse/atari_py-* + pip3 install --user twine + python3 -m twine upload /tmp/wheelhouse/atari_py-* fi From 386208d52ea40692b877f2dd6b011f6efc7e6edc Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 14:14:42 -0700 Subject: [PATCH 075/310] remove explict tag in build and deploy --- build_and_deploy.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/build_and_deploy.sh b/build_and_deploy.sh index 8b1d7a4..5afba2d 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -8,7 +8,6 @@ PYPLATFORM=`python3 -c "import distutils.util; print(distutils.util.get_platform pip3 wheel . --wheel-dir=/tmp/wheelhouse --build-option --plat-name=$PYPLATFORM ls -lht /tmp/wheelhouse -export TRAVIS_TAG="0.1.2" if [[ ! -z "$TRAVIS_TAG" ]]; then pip3 install --user twine python3 -m twine upload /tmp/wheelhouse/atari_py-* From 13ecf92e6f055ff2b08510cc8f083d28f84ecced Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 14:23:16 -0700 Subject: [PATCH 076/310] test only without tag --- .travis.yml | 2 ++ build_and_deploy.sh | 14 ++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8e9de80..aa24b78 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,8 @@ matrix: include: - os: osx script: ./build_and_deploy.sh + env: + - DEPLOY_SDIST=true - os: linux env: diff --git a/build_and_deploy.sh b/build_and_deploy.sh index 5afba2d..439c040 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -4,12 +4,18 @@ pip3 install pytest pip3 install . pytest . -PYPLATFORM=`python3 -c "import distutils.util; print(distutils.util.get_platform())"` -pip3 wheel . --wheel-dir=/tmp/wheelhouse --build-option --plat-name=$PYPLATFORM -ls -lht /tmp/wheelhouse - if [[ ! -z "$TRAVIS_TAG" ]]; then + + PYPLATFORM=`python3 -c "import distutils.util; print(distutils.util.get_platform())"` + pip3 wheel . --wheel-dir=/tmp/wheelhouse --build-option --plat-name=$PYPLATFORM + ls -lht /tmp/wheelhouse + pip3 install --user twine python3 -m twine upload /tmp/wheelhouse/atari_py-* + + if [[ ! -z "$DEPLOY_SDIST" ]]; then + python3 setup.py sdist + python3 -m twine upload dist/* + fi fi From 687cb8853c37e4cc8c786c8d1ca440a76f573334 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 14:27:34 -0700 Subject: [PATCH 077/310] cleaning up travis.yml --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index aa24b78..7932188 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,11 +8,10 @@ matrix: - os: linux env: - PYTHON_VER=3.6 - serivces: docker install: - - docker build -t atari-py-test -f dockerfile.${PYTHON_VER} . + - docker build -t atari-py-img -f dockerfile.${PYTHON_VER} . script: - - docker run -e TRAVIS_TAG=$TRAVIS_TAG -e TWINE_USERNAME=$TWINE_USERNAME -e TWINE_PASSWORD=$TWINE_PASSWORD atari-py-test bash ./build_and_deploy.sh + - docker run -e TRAVIS_TAG=$TRAVIS_TAG -e TWINE_USERNAME=$TWINE_USERNAME -e TWINE_PASSWORD=$TWINE_PASSWORD atari-py-img bash ./build_and_deploy.sh From 106086ce1021efd954f2f788a9132297154c4033 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 14:30:05 -0700 Subject: [PATCH 078/310] bump version to 0.1.2 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index cb962e7..62b1257 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.1.1', + version='0.1.2', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From b397547caf666e85245776013ab378d9caca4abb Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 15:12:46 -0700 Subject: [PATCH 079/310] linux -> manylinux1 in platform name --- build_and_deploy.sh | 2 +- get_platform.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 get_platform.py diff --git a/build_and_deploy.sh b/build_and_deploy.sh index 439c040..d43a15e 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -6,7 +6,7 @@ pytest . if [[ ! -z "$TRAVIS_TAG" ]]; then - PYPLATFORM=`python3 -c "import distutils.util; print(distutils.util.get_platform())"` + PYPLATFORM=$(python3 get_platform.py) pip3 wheel . --wheel-dir=/tmp/wheelhouse --build-option --plat-name=$PYPLATFORM ls -lht /tmp/wheelhouse diff --git a/get_platform.py b/get_platform.py new file mode 100644 index 0000000..1ad77f9 --- /dev/null +++ b/get_platform.py @@ -0,0 +1,4 @@ +import distutils.util +platform = distutils.util.get_platform() +platform = platform.replace('linux', 'manylinux1') +print(platform) From 5a8ddf2b633a19113630c8ccd61838ff6a7f8a79 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 15:14:27 -0700 Subject: [PATCH 080/310] bump version to 0.1.4 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 62b1257..1c409e2 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.1.2', + version='0.1.4', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From e4b16f0783c8e24c6947f7b335c5fbe4c344fb6e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 16:20:38 -0700 Subject: [PATCH 081/310] update README.md --- README.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 97f2fb3..6adab8f 100644 --- a/README.md +++ b/README.md @@ -9,17 +9,12 @@ A packaged and slightly-modified version of [https://github.com/bbitmaster/ale_p To install via pip, run: ```pip install atari-py``` +That *should* install a correct binary verison for your OS. If that does not work (or if you would like get the latest-latest +version, or you just want to tinker with the code yourself) see install from source. -Alternatively, you can install using setuptools using: +## Installation from source -```python setup.py install``` + - make sure you have git, cmake and zlib1g system packages installed + - clone the repo + - run `pip install -e .` -You can also trigger a build of the C++ code via `make`, and then add -this repo to your `PYTHONPATH`: - -```export PYTHONPATH=/path/to/atari-py:$PYTHONPATH``` - -### Common issues - -- Make sure you have `cmake` installed. On OSX, you probably want - `brew install cmake`. From 2ebaef036438743536e809c08df8063a956fca17 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 16:22:11 -0700 Subject: [PATCH 082/310] added a comment about linux -> multilinux1 change --- get_platform.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/get_platform.py b/get_platform.py index 1ad77f9..a8b37c3 100644 --- a/get_platform.py +++ b/get_platform.py @@ -1,4 +1,9 @@ import distutils.util platform = distutils.util.get_platform() + +# technically, our platform is not actually multilinux... so this may fail in some distros +# however, tested in python:3.6 docker image (by construction) +# and in ubuntu:16.04 platform = platform.replace('linux', 'manylinux1') + print(platform) From cdd4365e8f398c7bc242c0e779d609d073e9a764 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 1 Oct 2018 16:24:01 -0700 Subject: [PATCH 083/310] more changes to README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6adab8f..79987c3 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ To install via pip, run: ```pip install atari-py``` That *should* install a correct binary verison for your OS. If that does not work (or if you would like get the latest-latest -version, or you just want to tinker with the code yourself) see install from source. +version, or you just want to tinker with the code yourself) see next paragraph. ## Installation from source - - make sure you have git, cmake and zlib1g system packages installed + - make sure you have `git`, `cmake` and `zlib1g` system packages installed - clone the repo - run `pip install -e .` From ea997a785eb6e2042e35838e176b9c4936853748 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 11:43:32 -0700 Subject: [PATCH 084/310] try on osx10.11 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 7932188..ce4d62e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ matrix: include: - os: osx + osx_image: xcode8 script: ./build_and_deploy.sh env: - DEPLOY_SDIST=true From 2a23c3ef90d958bd30dd983ec850e242eba57b20 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 11:49:38 -0700 Subject: [PATCH 085/310] try brew install python3 on old osx --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index ce4d62e..f5d1133 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,8 @@ matrix: include: - os: osx osx_image: xcode8 + install: + - brew install python3 script: ./build_and_deploy.sh env: - DEPLOY_SDIST=true From 15c1f5547f9cba5ec4c537b3dab0b4f96b26fcda Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 12:23:23 -0700 Subject: [PATCH 086/310] try with miniconda on osx --- .travis.yml | 2 +- install_ox.sh | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100755 install_ox.sh diff --git a/.travis.yml b/.travis.yml index f5d1133..e545662 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ matrix: - os: osx osx_image: xcode8 install: - - brew install python3 + - ./install_osx.sh script: ./build_and_deploy.sh env: - DEPLOY_SDIST=true diff --git a/install_ox.sh b/install_ox.sh new file mode 100755 index 0000000..1f79035 --- /dev/null +++ b/install_ox.sh @@ -0,0 +1,5 @@ +PYTHON_VER=3.7.0 +brew install wget +wget https://repo.continuum.io/miniconda/Miniconda3-${PYTHON_VER}-MacOSX-x86_64.sh -O ~/miniconda.sh +bash ~/miniconda.sh -b -p $HOME/miniconda +export PATH="$HOME/miniconda/bin:$PATH" From 1146d3d8bd4042a938b672eb4ee14f0499f1609f Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 12:27:42 -0700 Subject: [PATCH 087/310] naming typo --- install_ox.sh => install_osx.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename install_ox.sh => install_osx.sh (100%) diff --git a/install_ox.sh b/install_osx.sh similarity index 100% rename from install_ox.sh rename to install_osx.sh From f9e1307b734521f12631cd78bcf869a7abc85c0b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 12:30:05 -0700 Subject: [PATCH 088/310] add verbosity to install_osx script --- install_osx.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/install_osx.sh b/install_osx.sh index 1f79035..25871fa 100755 --- a/install_osx.sh +++ b/install_osx.sh @@ -1,3 +1,4 @@ +set -ex PYTHON_VER=3.7.0 brew install wget wget https://repo.continuum.io/miniconda/Miniconda3-${PYTHON_VER}-MacOSX-x86_64.sh -O ~/miniconda.sh From 16e916ab8244ce9da1d77c203f1ad21c868e9e12 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 12:38:57 -0700 Subject: [PATCH 089/310] pip and pip3 --- build_and_deploy.sh | 4 ++-- install_osx.sh | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build_and_deploy.sh b/build_and_deploy.sh index d43a15e..55178e9 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -1,7 +1,7 @@ set -ex -pip3 install pytest -pip3 install . +pip install pytest +pip install . pytest . if [[ ! -z "$TRAVIS_TAG" ]]; then diff --git a/install_osx.sh b/install_osx.sh index 25871fa..fd4ea5c 100755 --- a/install_osx.sh +++ b/install_osx.sh @@ -4,3 +4,5 @@ brew install wget wget https://repo.continuum.io/miniconda/Miniconda3-${PYTHON_VER}-MacOSX-x86_64.sh -O ~/miniconda.sh bash ~/miniconda.sh -b -p $HOME/miniconda export PATH="$HOME/miniconda/bin:$PATH" +ln -s $HOME/miniconda/bin/pip $HOME/miniconda/bin/pip3 +ln -s $HOME/miniconda/bin/python $HOME/miniconda/bin/python3 From a3c69f769c03c2eef6a17b9962f5816f6f113f6a Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 12:44:30 -0700 Subject: [PATCH 090/310] use curl instead of wget --- install_osx.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/install_osx.sh b/install_osx.sh index fd4ea5c..69d73ed 100755 --- a/install_osx.sh +++ b/install_osx.sh @@ -1,7 +1,6 @@ set -ex PYTHON_VER=3.7.0 -brew install wget -wget https://repo.continuum.io/miniconda/Miniconda3-${PYTHON_VER}-MacOSX-x86_64.sh -O ~/miniconda.sh +curl https://repo.continuum.io/miniconda/Miniconda3-${PYTHON_VER}-MacOSX-x86_64.sh -o ~/miniconda.sh bash ~/miniconda.sh -b -p $HOME/miniconda export PATH="$HOME/miniconda/bin:$PATH" ln -s $HOME/miniconda/bin/pip $HOME/miniconda/bin/pip3 From 5436ff7d70a9422b58ae5f39a8703d069f712270 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 12:46:42 -0700 Subject: [PATCH 091/310] wip --- install_osx.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/install_osx.sh b/install_osx.sh index 69d73ed..6694a52 100755 --- a/install_osx.sh +++ b/install_osx.sh @@ -4,4 +4,3 @@ curl https://repo.continuum.io/miniconda/Miniconda3-${PYTHON_VER}-MacOSX-x86_64. bash ~/miniconda.sh -b -p $HOME/miniconda export PATH="$HOME/miniconda/bin:$PATH" ln -s $HOME/miniconda/bin/pip $HOME/miniconda/bin/pip3 -ln -s $HOME/miniconda/bin/python $HOME/miniconda/bin/python3 From 3059dcda8908c8009eebd1106ebd36a85d3312ad Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 13:18:56 -0700 Subject: [PATCH 092/310] tests with python3 --- build_and_deploy.sh | 4 ++-- install_osx.sh | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build_and_deploy.sh b/build_and_deploy.sh index 55178e9..d43a15e 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -1,7 +1,7 @@ set -ex -pip install pytest -pip install . +pip3 install pytest +pip3 install . pytest . if [[ ! -z "$TRAVIS_TAG" ]]; then diff --git a/install_osx.sh b/install_osx.sh index 6694a52..9c75359 100755 --- a/install_osx.sh +++ b/install_osx.sh @@ -4,3 +4,4 @@ curl https://repo.continuum.io/miniconda/Miniconda3-${PYTHON_VER}-MacOSX-x86_64. bash ~/miniconda.sh -b -p $HOME/miniconda export PATH="$HOME/miniconda/bin:$PATH" ln -s $HOME/miniconda/bin/pip $HOME/miniconda/bin/pip3 +python --version From 1f24f01dba6d4d137d1a256d03155d09c7dce9ae Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 13:22:06 -0700 Subject: [PATCH 093/310] tests with python3 --- install_osx.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/install_osx.sh b/install_osx.sh index 9c75359..3c2e397 100755 --- a/install_osx.sh +++ b/install_osx.sh @@ -1,7 +1,7 @@ set -ex -PYTHON_VER=3.7.0 -curl https://repo.continuum.io/miniconda/Miniconda3-${PYTHON_VER}-MacOSX-x86_64.sh -o ~/miniconda.sh +CONDA_VER=3.7.0 +curl https://repo.continuum.io/miniconda/Miniconda3-${CONDA_VER}-MacOSX-x86_64.sh -o ~/miniconda.sh bash ~/miniconda.sh -b -p $HOME/miniconda -export PATH="$HOME/miniconda/bin:$PATH" ln -s $HOME/miniconda/bin/pip $HOME/miniconda/bin/pip3 +export PATH="$HOME/miniconda/bin:$PATH" python --version From be567ae428d7b2672c0e2c92df7ef36451ac3c0c Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 13:26:57 -0700 Subject: [PATCH 094/310] polishing install scripts --- build_and_deploy.sh | 13 ++++++------- install_osx.sh | 1 - 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/build_and_deploy.sh b/build_and_deploy.sh index d43a15e..2b1eb21 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -1,18 +1,17 @@ set -ex -pip3 install pytest -pip3 install . -pytest . +python3 -m pip install pytest +python3 -m pip install . +python3 -m pytest . if [[ ! -z "$TRAVIS_TAG" ]]; then PYPLATFORM=$(python3 get_platform.py) - pip3 wheel . --wheel-dir=/tmp/wheelhouse --build-option --plat-name=$PYPLATFORM - ls -lht /tmp/wheelhouse - - pip3 install --user twine + python3 -m pip install --user twine python3 -m twine upload /tmp/wheelhouse/atari_py-* + python3 setup.py bdist_wheel --plat-name=$PYPLATFORM + if [[ ! -z "$DEPLOY_SDIST" ]]; then python3 setup.py sdist python3 -m twine upload dist/* diff --git a/install_osx.sh b/install_osx.sh index 3c2e397..0c944a3 100755 --- a/install_osx.sh +++ b/install_osx.sh @@ -2,6 +2,5 @@ set -ex CONDA_VER=3.7.0 curl https://repo.continuum.io/miniconda/Miniconda3-${CONDA_VER}-MacOSX-x86_64.sh -o ~/miniconda.sh bash ~/miniconda.sh -b -p $HOME/miniconda -ln -s $HOME/miniconda/bin/pip $HOME/miniconda/bin/pip3 export PATH="$HOME/miniconda/bin:$PATH" python --version From dbaa5a35704afc4bbc67e2fb4461e749d93d8b96 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 13:37:57 -0700 Subject: [PATCH 095/310] polishing installation scripts --- .travis.yml | 2 +- install_osx.sh | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e545662..6354022 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ matrix: - os: osx osx_image: xcode8 install: - - ./install_osx.sh + - . install_osx.sh script: ./build_and_deploy.sh env: - DEPLOY_SDIST=true diff --git a/install_osx.sh b/install_osx.sh index 0c944a3..e06f73f 100755 --- a/install_osx.sh +++ b/install_osx.sh @@ -4,3 +4,4 @@ curl https://repo.continuum.io/miniconda/Miniconda3-${CONDA_VER}-MacOSX-x86_64.s bash ~/miniconda.sh -b -p $HOME/miniconda export PATH="$HOME/miniconda/bin:$PATH" python --version +python3 --version From e023cf7842a2ab87497ec18d8e87bbb6a95474f3 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 13:42:11 -0700 Subject: [PATCH 096/310] polishing installation scripts --- build_and_deploy.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/build_and_deploy.sh b/build_and_deploy.sh index 2b1eb21..546388f 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -1,20 +1,20 @@ set -ex -python3 -m pip install pytest -python3 -m pip install . -python3 -m pytest . +pip install pytest +pip install . +pytest . if [[ ! -z "$TRAVIS_TAG" ]]; then PYPLATFORM=$(python3 get_platform.py) - python3 -m pip install --user twine - python3 -m twine upload /tmp/wheelhouse/atari_py-* + pip install --user twine + python -m twine upload /tmp/wheelhouse/atari_py-* - python3 setup.py bdist_wheel --plat-name=$PYPLATFORM + python setup.py bdist_wheel --plat-name=$PYPLATFORM if [[ ! -z "$DEPLOY_SDIST" ]]; then - python3 setup.py sdist - python3 -m twine upload dist/* + python setup.py sdist + python -m twine upload dist/* fi fi From ed5dc360ba5b3d56c8a8a183f1e2d65125719394 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 13:54:43 -0700 Subject: [PATCH 097/310] use python3 --- .travis.yml | 10 ++++++---- build_and_deploy.sh | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6354022..2c9e025 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,12 +2,14 @@ matrix: include: - os: osx osx_image: xcode8 - install: - - . install_osx.sh - script: ./build_and_deploy.sh env: - DEPLOY_SDIST=true - + - PATH=$HOME/miniconda/bin:$PATH + install: + - . install_osx.sh + script: + - ./build_and_deploy.sh + - os: linux env: - PYTHON_VER=3.6 diff --git a/build_and_deploy.sh b/build_and_deploy.sh index 546388f..e309d62 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -1,5 +1,6 @@ set -ex +python --version pip install pytest pip install . pytest . From 13276100c48674214ead28d97550257a6fe62cb0 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 14:02:21 -0700 Subject: [PATCH 098/310] use python3 --- build_and_deploy.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build_and_deploy.sh b/build_and_deploy.sh index e309d62..db7abd2 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -1,14 +1,14 @@ set -ex python --version -pip install pytest -pip install . +python -m pip install pytest +python -m pip install . pytest . if [[ ! -z "$TRAVIS_TAG" ]]; then PYPLATFORM=$(python3 get_platform.py) - pip install --user twine + python -m pip install --user twine python -m twine upload /tmp/wheelhouse/atari_py-* python setup.py bdist_wheel --plat-name=$PYPLATFORM From e24b42d04fd5d9e1d916d6fac65680c734e879ff Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 14:37:11 -0700 Subject: [PATCH 099/310] polishing installation script --- install_osx.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/install_osx.sh b/install_osx.sh index e06f73f..666ea5e 100755 --- a/install_osx.sh +++ b/install_osx.sh @@ -3,5 +3,7 @@ CONDA_VER=3.7.0 curl https://repo.continuum.io/miniconda/Miniconda3-${CONDA_VER}-MacOSX-x86_64.sh -o ~/miniconda.sh bash ~/miniconda.sh -b -p $HOME/miniconda export PATH="$HOME/miniconda/bin:$PATH" +conda install pip python --version python3 --version +pip --version From e4fe0e84b055ba6639e99586f1d4ef949c45bbdb Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 14:41:41 -0700 Subject: [PATCH 100/310] polishing installation script --- build_and_deploy.sh | 11 +++++------ install_osx.sh | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/build_and_deploy.sh b/build_and_deploy.sh index db7abd2..5cfc872 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -1,21 +1,20 @@ set -ex -python --version -python -m pip install pytest -python -m pip install . +pip install pytest +pip install . pytest . if [[ ! -z "$TRAVIS_TAG" ]]; then PYPLATFORM=$(python3 get_platform.py) - python -m pip install --user twine - python -m twine upload /tmp/wheelhouse/atari_py-* + pip install twine + twine upload /tmp/wheelhouse/atari_py-* python setup.py bdist_wheel --plat-name=$PYPLATFORM if [[ ! -z "$DEPLOY_SDIST" ]]; then python setup.py sdist - python -m twine upload dist/* + twine upload dist/* fi fi diff --git a/install_osx.sh b/install_osx.sh index 666ea5e..579e349 100755 --- a/install_osx.sh +++ b/install_osx.sh @@ -3,7 +3,7 @@ CONDA_VER=3.7.0 curl https://repo.continuum.io/miniconda/Miniconda3-${CONDA_VER}-MacOSX-x86_64.sh -o ~/miniconda.sh bash ~/miniconda.sh -b -p $HOME/miniconda export PATH="$HOME/miniconda/bin:$PATH" + conda install pip python --version -python3 --version pip --version From 1419cfb9de7f402b79140e82ef2cbdd98d22dc96 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 14:42:07 -0700 Subject: [PATCH 101/310] bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 1c409e2..b94fab9 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.1.4', + version='0.1.5', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From dcb14cd2756dd3e472f219116c9357deef972404 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 14:44:36 -0700 Subject: [PATCH 102/310] fix upload section of the script --- build_and_deploy.sh | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build_and_deploy.sh b/build_and_deploy.sh index 5cfc872..075c762 100755 --- a/build_and_deploy.sh +++ b/build_and_deploy.sh @@ -8,13 +8,11 @@ if [[ ! -z "$TRAVIS_TAG" ]]; then PYPLATFORM=$(python3 get_platform.py) pip install twine - twine upload /tmp/wheelhouse/atari_py-* - python setup.py bdist_wheel --plat-name=$PYPLATFORM if [[ ! -z "$DEPLOY_SDIST" ]]; then python setup.py sdist - twine upload dist/* fi + twine upload dist/* fi From 8ead2eba3742a6365e64bb52e4b01411314665ed Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 2 Oct 2018 14:44:57 -0700 Subject: [PATCH 103/310] bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b94fab9..a347625 100644 --- a/setup.py +++ b/setup.py @@ -23,7 +23,7 @@ def run(self): DistutilsBuild.run(self) setup(name='atari-py', - version='0.1.5', + version='0.1.6', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From bdfb3811e8d1b73f0ad272e4e799645462d66d21 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 16 Nov 2018 17:17:50 -0800 Subject: [PATCH 104/310] try multibuild --- .travis.yml | 67 +++++++++++++++++++++++++++++++++------------ build_and_deploy.sh | 18 ------------ config.sh | 13 +++++++++ deploy.sh | 11 ++++++++ 4 files changed, 73 insertions(+), 36 deletions(-) delete mode 100755 build_and_deploy.sh create mode 100644 config.sh create mode 100755 deploy.sh diff --git a/.travis.yml b/.travis.yml index 2c9e025..1b74c99 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,22 +1,53 @@ +env: + global: + - REPO_DIR=. + - BUILD_COMMIT=$TRAVIS_COMMIT + - PLAT=x86_64 + +install: + - git clone https://github.com/matthew-brett/multibuild + - . multibuild/common_utils.sh + - . multibuild/travis_steps.sh + - before_install + # - clean_code $REPO_DIR $BUILD_COMMIT + - build_wheel $REPO_DIR $PLAT +script: + - install_run $PLAT + +after_success: + - ./deploy.sh + + matrix: - include: - - os: osx - osx_image: xcode8 - env: - - DEPLOY_SDIST=true - - PATH=$HOME/miniconda/bin:$PATH - install: - - . install_osx.sh - script: - - ./build_and_deploy.sh - + include: + - os: linux - env: - - PYTHON_VER=3.6 - install: - - docker build -t atari-py-img -f dockerfile.${PYTHON_VER} . - script: - - docker run -e TRAVIS_TAG=$TRAVIS_TAG -e TWINE_USERNAME=$TWINE_USERNAME -e TWINE_PASSWORD=$TWINE_PASSWORD atari-py-img bash ./build_and_deploy.sh + env: + - MB_PYTHON_VERSION=3.5 + - os: linux + env: + - MB_PYTHON_VERSION=3.6 + + - os: linux + env: + - MB_PYTHON_VERSION=3.7 + - + - os: osx + osx_image: xcode8.3 + env: + - MB_PYTHON_VERSION=3.5 + - DEPLOY_SDIST=true + + - os: osx + osx_image: xcode8.3 + env: + - MB_PYTHON_VERSION=3.6 + + - os: osx + osx_image: xcode8.3 + env: + - MB_PYTHON_VERSION=3.7 + + diff --git a/build_and_deploy.sh b/build_and_deploy.sh deleted file mode 100755 index 075c762..0000000 --- a/build_and_deploy.sh +++ /dev/null @@ -1,18 +0,0 @@ -set -ex - -pip install pytest -pip install . -pytest . - -if [[ ! -z "$TRAVIS_TAG" ]]; then - - PYPLATFORM=$(python3 get_platform.py) - pip install twine - python setup.py bdist_wheel --plat-name=$PYPLATFORM - - if [[ ! -z "$DEPLOY_SDIST" ]]; then - python setup.py sdist - fi - twine upload dist/* -fi - diff --git a/config.sh b/config.sh new file mode 100644 index 0000000..96e86f6 --- /dev/null +++ b/config.sh @@ -0,0 +1,13 @@ +#!/bin/bash +function pre_build { + set -ex + build_cmake + pip install . + pip install pytest + pytest . +} + +function run_tests { + echo "Hello world with box2d-py" +} + diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..443b0d5 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,11 @@ +set -ex +if [[ ! -z "$TRAVIS_TAG" ]]; then + pip install twine + twine upload wheelhouse/* + + if [[ ! -z "$DEPLOY_SDIST" ]]; then + python setup.py sdist + twine upload dist/* + fi +fi + From d303115e81a104ec987fea1286fe4281c1d78d8a Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 16 Nov 2018 17:48:01 -0800 Subject: [PATCH 105/310] adding cmake and zlib --- config.sh | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.sh b/config.sh index 96e86f6..99c892c 100644 --- a/config.sh +++ b/config.sh @@ -1,7 +1,7 @@ #!/bin/bash function pre_build { set -ex - build_cmake + build_zlib pip install . pip install pytest pytest . diff --git a/setup.py b/setup.py index a347625..4519cde 100644 --- a/setup.py +++ b/setup.py @@ -32,6 +32,6 @@ def run(self): packages=['atari_py'], package_data={'atari_py': package_data}, cmdclass={'build': Build}, - install_requires=['numpy', 'six'], + install_requires=['numpy', 'six', 'cmake'], tests_require=['nose2'] ) From 2ce90ce83ac991511e0f2b97eebee445152e0d9b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 16 Nov 2018 17:51:25 -0800 Subject: [PATCH 106/310] install cmake --- config.sh | 1 + setup.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config.sh b/config.sh index 99c892c..0de6bc8 100644 --- a/config.sh +++ b/config.sh @@ -1,6 +1,7 @@ #!/bin/bash function pre_build { set -ex + get_cmake build_zlib pip install . pip install pytest diff --git a/setup.py b/setup.py index 4519cde..a347625 100644 --- a/setup.py +++ b/setup.py @@ -32,6 +32,6 @@ def run(self): packages=['atari_py'], package_data={'atari_py': package_data}, cmdclass={'build': Build}, - install_requires=['numpy', 'six', 'cmake'], + install_requires=['numpy', 'six'], tests_require=['nose2'] ) From 1837e9252058efe16ec277cde869bf087e9d4bea Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 16 Nov 2018 17:53:02 -0800 Subject: [PATCH 107/310] add test of import in config.sh --- config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.sh b/config.sh index 0de6bc8..42e45d4 100644 --- a/config.sh +++ b/config.sh @@ -9,6 +9,6 @@ function pre_build { } function run_tests { - echo "Hello world with box2d-py" + python -c "import gym; gym.make('Pong-v4')" } From 73d3c2698efdac3f3e0715851256ad5c3341edc3 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 16 Nov 2018 17:54:24 -0800 Subject: [PATCH 108/310] pip install cmake instead of get_cmake --- config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.sh b/config.sh index 42e45d4..acde4dd 100644 --- a/config.sh +++ b/config.sh @@ -1,8 +1,8 @@ #!/bin/bash function pre_build { set -ex - get_cmake build_zlib + pip install cmake pip install . pip install pytest pytest . From 8570790b41993c9285d56c64a569b4f2584c0b28 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 16 Nov 2018 18:04:06 -0800 Subject: [PATCH 109/310] force platform-specific binaries --- config.sh | 1 + setup.py | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/config.sh b/config.sh index acde4dd..97a9ecd 100644 --- a/config.sh +++ b/config.sh @@ -9,6 +9,7 @@ function pre_build { } function run_tests { + pip install gym[atari] python -c "import gym; gym.make('Pong-v4')" } diff --git a/setup.py b/setup.py index a347625..054b635 100644 --- a/setup.py +++ b/setup.py @@ -22,6 +22,16 @@ def run(self): raise DistutilsBuild.run(self) +try: + from wheel.bdist_wheel import bdist_wheel as _bdist_wheel + class bdist_wheel(_bdist_wheel): + def finalize_options(self): + _bdist_wheel.finalize_options(self) + self.root_is_pure = False +except ImportError: + bdist_wheel = None + + setup(name='atari-py', version='0.1.6', description='Python bindings to Atari games', @@ -31,7 +41,7 @@ def run(self): license='', packages=['atari_py'], package_data={'atari_py': package_data}, - cmdclass={'build': Build}, + cmdclass={'build': Build, 'bdist_wheel': bdist_wheel}, install_requires=['numpy', 'six'], tests_require=['nose2'] ) From cb1f6ca458b9e00817688ab9577d9b1688ab5319 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Sat, 17 Nov 2018 15:06:47 -0800 Subject: [PATCH 110/310] the other way to tell setup that our distribution contains binaries --- setup.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/setup.py b/setup.py index 054b635..cc8373d 100644 --- a/setup.py +++ b/setup.py @@ -22,15 +22,12 @@ def run(self): raise DistutilsBuild.run(self) -try: - from wheel.bdist_wheel import bdist_wheel as _bdist_wheel - class bdist_wheel(_bdist_wheel): - def finalize_options(self): - _bdist_wheel.finalize_options(self) - self.root_is_pure = False -except ImportError: - bdist_wheel = None +class BinaryDistribution(dist.Distribution): + def is_pure(self): + return False + def has_ext_modules(self): + return True setup(name='atari-py', version='0.1.6', @@ -41,7 +38,8 @@ def finalize_options(self): license='', packages=['atari_py'], package_data={'atari_py': package_data}, - cmdclass={'build': Build, 'bdist_wheel': bdist_wheel}, + distclass=BinaryDistribution, + cmdclass={'build': Build}, install_requires=['numpy', 'six'], tests_require=['nose2'] ) From c6466b91cb0d9766002f4a7e56064136bf20f604 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Sat, 17 Nov 2018 15:09:00 -0800 Subject: [PATCH 111/310] syntax --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index cc8373d..641508d 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ import multiprocessing import os -from setuptools import setup +from setuptools import setup, dist import subprocess import sys from distutils.command.build import build as DistutilsBuild From abedcd2e87f0129e6b07887dac9ebae884f5e514 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Sat, 17 Nov 2018 21:33:43 -0800 Subject: [PATCH 112/310] setup.py magic --- setup.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/setup.py b/setup.py index 641508d..78daed0 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ import multiprocessing import os -from setuptools import setup, dist +from setuptools import setup, Extension import subprocess import sys from distutils.command.build import build as DistutilsBuild @@ -21,13 +21,11 @@ def run(self): sys.stderr.write("Unable to execute '{}'. HINT: are you sure `make` is installed?\n".format(' '.join(cmd))) raise DistutilsBuild.run(self) - - -class BinaryDistribution(dist.Distribution): - def is_pure(self): - return False - def has_ext_modules(self): - return True + +class CMakeExtension(Extension): + def __init__(self, name, sourcedir=''): + Extension.__init__(self, name, sources=[]) + self.sourcedir = os.path.abspath(sourcedir) setup(name='atari-py', version='0.1.6', @@ -39,6 +37,7 @@ def has_ext_modules(self): packages=['atari_py'], package_data={'atari_py': package_data}, distclass=BinaryDistribution, + ext_modules=[CMakeExtension('atari_py')], cmdclass={'build': Build}, install_requires=['numpy', 'six'], tests_require=['nose2'] From 06b36d9b7d4cd55b30a51cd3be59d7a2f07dbcbe Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Sat, 17 Nov 2018 21:37:42 -0800 Subject: [PATCH 113/310] setup.py syntax --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index 78daed0..f2015aa 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,6 @@ def __init__(self, name, sourcedir=''): license='', packages=['atari_py'], package_data={'atari_py': package_data}, - distclass=BinaryDistribution, ext_modules=[CMakeExtension('atari_py')], cmdclass={'build': Build}, install_requires=['numpy', 'six'], From 85be084787adb12d1886675957e62e34bdaa97c8 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Sat, 17 Nov 2018 21:44:59 -0800 Subject: [PATCH 114/310] setup.py magic --- setup.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index f2015aa..71553b7 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ import multiprocessing import os -from setuptools import setup, Extension +from setuptools import setup, dist, Extension import subprocess import sys from distutils.command.build import build as DistutilsBuild @@ -21,7 +21,13 @@ def run(self): sys.stderr.write("Unable to execute '{}'. HINT: are you sure `make` is installed?\n".format(' '.join(cmd))) raise DistutilsBuild.run(self) - + +class BinaryDistribution(dist.Distribution): + def is_pure(self): + return False + def has_ext_modules(self): + return True + class CMakeExtension(Extension): def __init__(self, name, sourcedir=''): Extension.__init__(self, name, sources=[]) @@ -38,6 +44,7 @@ def __init__(self, name, sourcedir=''): package_data={'atari_py': package_data}, ext_modules=[CMakeExtension('atari_py')], cmdclass={'build': Build}, + distclass=BinaryDistribution, install_requires=['numpy', 'six'], tests_require=['nose2'] ) From 91daf27c1a93b6dc54a9c7201d16dcfe9f5ef9ac Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Sat, 17 Nov 2018 22:06:39 -0800 Subject: [PATCH 115/310] polishing setup.py --- setup.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 71553b7..5b0dafb 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,7 @@ import multiprocessing import os from setuptools import setup, dist, Extension +from setuptools.command.build_ext import build_ext import subprocess import sys from distutils.command.build import build as DistutilsBuild @@ -8,7 +9,7 @@ with open(os.path.join(os.path.dirname(__file__), 'atari_py/package_data.txt')) as f: package_data = [line.rstrip() for line in f.readlines()] -class Build(DistutilsBuild): +class Build(build_ext): def run(self): cores_to_use = max(1, multiprocessing.cpu_count() - 1) cmd = ['make', 'build', '-C', 'atari_py/ale_interface', '-j', str(cores_to_use)] @@ -20,7 +21,7 @@ def run(self): except OSError as e: sys.stderr.write("Unable to execute '{}'. HINT: are you sure `make` is installed?\n".format(' '.join(cmd))) raise - DistutilsBuild.run(self) + # build_ext.run(self) class BinaryDistribution(dist.Distribution): def is_pure(self): @@ -43,8 +44,8 @@ def __init__(self, name, sourcedir=''): packages=['atari_py'], package_data={'atari_py': package_data}, ext_modules=[CMakeExtension('atari_py')], - cmdclass={'build': Build}, - distclass=BinaryDistribution, + cmdclass={'build_ext': Build}, + # distclass=BinaryDistribution, install_requires=['numpy', 'six'], tests_require=['nose2'] ) From 1df6ae18b12b57937af327d89031c60cc28ff854 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Sun, 18 Nov 2018 13:42:35 -0800 Subject: [PATCH 116/310] fix build directory for cmake --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5b0dafb..13fc3f9 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ def run(self): cores_to_use = max(1, multiprocessing.cpu_count() - 1) cmd = ['make', 'build', '-C', 'atari_py/ale_interface', '-j', str(cores_to_use)] try: - subprocess.check_call(cmd) + subprocess.check_call(cmd, cwd=self.build_lib) except subprocess.CalledProcessError as e: sys.stderr.write("Could not build atari-py: %s. (HINT: are you sure cmake is installed? You might also be missing a library. Atari-py requires: zlib [installable as 'apt-get install zlib1g-dev' on Ubuntu].)\n" % e) raise From 148ef41dd7753787ca970dc3214c903f98b2cd63 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Sun, 18 Nov 2018 14:05:08 -0800 Subject: [PATCH 117/310] cleaning up setup.py --- setup.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/setup.py b/setup.py index 13fc3f9..5d35b38 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ import multiprocessing import os -from setuptools import setup, dist, Extension +from setuptools import setup, Extension from setuptools.command.build_ext import build_ext import subprocess import sys @@ -21,14 +21,7 @@ def run(self): except OSError as e: sys.stderr.write("Unable to execute '{}'. HINT: are you sure `make` is installed?\n".format(' '.join(cmd))) raise - # build_ext.run(self) - -class BinaryDistribution(dist.Distribution): - def is_pure(self): - return False - def has_ext_modules(self): - return True - + class CMakeExtension(Extension): def __init__(self, name, sourcedir=''): Extension.__init__(self, name, sources=[]) @@ -45,7 +38,6 @@ def __init__(self, name, sourcedir=''): package_data={'atari_py': package_data}, ext_modules=[CMakeExtension('atari_py')], cmdclass={'build_ext': Build}, - # distclass=BinaryDistribution, install_requires=['numpy', 'six'], tests_require=['nose2'] ) From 87545d6485ad8d45e630b0279a5d81deda0b452e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Sun, 18 Nov 2018 14:05:35 -0800 Subject: [PATCH 118/310] bump version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5d35b38..d7b54b6 100644 --- a/setup.py +++ b/setup.py @@ -28,7 +28,7 @@ def __init__(self, name, sourcedir=''): self.sourcedir = os.path.abspath(sourcedir) setup(name='atari-py', - version='0.1.6', + version='0.1.7', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From ffb05b092411dc107270c462f493f9c5560dfb9b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 19 Nov 2018 14:58:50 -0800 Subject: [PATCH 119/310] cleaning up .travis.yml --- .travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1b74c99..38b32a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,11 +5,9 @@ env: - PLAT=x86_64 install: - - git clone https://github.com/matthew-brett/multibuild - - . multibuild/common_utils.sh + - git clone https://github.com/matthew-brett/multibuild && cd multibuild && checkout 254ad28 && cd .. - . multibuild/travis_steps.sh - before_install - # - clean_code $REPO_DIR $BUILD_COMMIT - build_wheel $REPO_DIR $PLAT script: - install_run $PLAT From 8ac8952d192233fd525897cb861f6d12cde92091 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 19 Nov 2018 15:05:29 -0800 Subject: [PATCH 120/310] cleaning up .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 38b32a5..31ad27a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ env: - PLAT=x86_64 install: - - git clone https://github.com/matthew-brett/multibuild && cd multibuild && checkout 254ad28 && cd .. + - git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout 254ad28 && cd .. - . multibuild/travis_steps.sh - before_install - build_wheel $REPO_DIR $PLAT From 079e56c30ccebc63d1dceb174d8fecb5b29ba3ea Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 19 Nov 2018 15:09:40 -0800 Subject: [PATCH 121/310] cleaning up setup.py --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index d7b54b6..ddb653c 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,6 @@ from setuptools.command.build_ext import build_ext import subprocess import sys -from distutils.command.build import build as DistutilsBuild with open(os.path.join(os.path.dirname(__file__), 'atari_py/package_data.txt')) as f: package_data = [line.rstrip() for line in f.readlines()] From 0fe182aa3a29a98696f966c3cf1d4132ab1b6d88 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 19 Nov 2018 15:11:54 -0800 Subject: [PATCH 122/310] restore sourcing multibuild/common_utils.sh in .travis.sh - otherwise, build_wheel command fails --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 31ad27a..9a6885c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ env: install: - git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout 254ad28 && cd .. + - . multibuild/common_utils.sh - . multibuild/travis_steps.sh - before_install - build_wheel $REPO_DIR $PLAT From 3d950b3e3e59e311115e2f609083ec6da4bf4658 Mon Sep 17 00:00:00 2001 From: Christopher Hesse Date: Wed, 21 Nov 2018 15:59:24 -0800 Subject: [PATCH 123/310] update README with repo status --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 79987c3..2ccf90a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +**Status:** Maintenance (expect bug fixes and minor updates) + # atari_py [![Build Status](https://travis-ci.org/openai/atari-py.svg?branch=master)](https://travis-ci.org/openai/atari-py) From ecb5710697d67641c5373714367adce9556fb35d Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 3 May 2019 15:03:59 -0700 Subject: [PATCH 124/310] try and see --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 9a6885c..99c3cb8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,4 +49,7 @@ matrix: env: - MB_PYTHON_VERSION=3.7 + - os: windows + env: + - MB_PYTHON_VERSION=3.6 From 90fae4f443501b7a548c6250537d9bb86fb789c0 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 3 May 2019 15:23:31 -0700 Subject: [PATCH 125/310] set language:shell in .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 99c3cb8..d127804 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +language: sh env: global: - REPO_DIR=. From a9db0c53a2965468df30d40e88e57705650d3820 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 3 May 2019 15:33:18 -0700 Subject: [PATCH 126/310] missing virtualenv on windows? --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index d127804..3240870 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ env: install: - git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout 254ad28 && cd .. + - pip install virtualenv - . multibuild/common_utils.sh - . multibuild/travis_steps.sh - before_install From a31de3364e1198c11128f7cc40c6f8441bcbb51c Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 3 May 2019 15:46:47 -0700 Subject: [PATCH 127/310] install python on windows --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3240870..a426c7a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,6 @@ env: install: - git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout 254ad28 && cd .. - - pip install virtualenv - . multibuild/common_utils.sh - . multibuild/travis_steps.sh - before_install @@ -55,3 +54,6 @@ matrix: env: - MB_PYTHON_VERSION=3.6 + install: + - choco install python --version 3.6.5 + - pip install virtualenv From 641f1fc4e14f8fc525fffbe5412fab30443777bd Mon Sep 17 00:00:00 2001 From: Christopher Hesse Date: Fri, 3 May 2019 15:49:23 -0700 Subject: [PATCH 128/310] fix gentoo build --- atari_py/ale_interface/src/emucore/unzip.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/atari_py/ale_interface/src/emucore/unzip.h b/atari_py/ale_interface/src/emucore/unzip.h index 2c8ae7f..755600b 100644 --- a/atari_py/ale_interface/src/emucore/unzip.h +++ b/atari_py/ale_interface/src/emucore/unzip.h @@ -41,6 +41,13 @@ #ifndef _unz_H #define _unz_H +/* Gentoo removed OF from their copy of zconf.h + * (https://bugs.gentoo.org/show_bug.cgi?id=383179) */ +/* but our copy of minizip needs it. */ +#ifndef OF +#define OF(args) args +#endif + #ifdef __cplusplus extern "C" { #endif From 83650c9644063a0e4125e19058837bf77bc69185 Mon Sep 17 00:00:00 2001 From: Christopher Hesse Date: Fri, 3 May 2019 15:57:27 -0700 Subject: [PATCH 129/310] fix local install --- setup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ddb653c..4fce5c8 100644 --- a/setup.py +++ b/setup.py @@ -8,10 +8,13 @@ with open(os.path.join(os.path.dirname(__file__), 'atari_py/package_data.txt')) as f: package_data = [line.rstrip() for line in f.readlines()] +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) + class Build(build_ext): def run(self): cores_to_use = max(1, multiprocessing.cpu_count() - 1) - cmd = ['make', 'build', '-C', 'atari_py/ale_interface', '-j', str(cores_to_use)] + cmd = ['make', 'build', '-C', os.path.join(SCRIPT_DIR, 'atari_py/ale_interface'), '-j', str(cores_to_use)] + os.makedirs(self.build_lib, exist_ok=True) try: subprocess.check_call(cmd, cwd=self.build_lib) except subprocess.CalledProcessError as e: From 5bcdfd42a90356848c2f3f4c8b0751be78138d36 Mon Sep 17 00:00:00 2001 From: Christopher Hesse Date: Fri, 3 May 2019 15:59:24 -0700 Subject: [PATCH 130/310] fix example script --- doc/examples/python_example.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/examples/python_example.py b/doc/examples/python_example.py index 7b9a359..946328f 100755 --- a/doc/examples/python_example.py +++ b/doc/examples/python_example.py @@ -4,12 +4,14 @@ # # This is a direct port to python of the shared library example from # ALE provided in doc/examples/sharedLibraryInterfaceExample.cpp +from __future__ import print_function + import sys from random import randrange -from ale_python_interface import ALEInterface +from atari_py import ALEInterface if len(sys.argv) < 2: - print 'Usage:', sys.argv[0], 'rom_file' + print('Usage:', sys.argv[0], 'rom_file') sys.exit() ale = ALEInterface() @@ -37,12 +39,12 @@ legal_actions = ale.getLegalActionSet() # Play 10 episodes -for episode in xrange(10): +for episode in range(10): total_reward = 0 while not ale.game_over(): a = legal_actions[randrange(len(legal_actions))] # Apply an action and get the resulting reward reward = ale.act(a); total_reward += reward - print 'Episode', episode, 'ended with score:', total_reward + print('Episode', episode, 'ended with score:', total_reward) ale.reset_game() From 7e69db291cfcb8dd66ccb1286896026948038eb2 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 3 May 2019 16:40:45 -0700 Subject: [PATCH 131/310] debugging choco install problem --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a426c7a..3b5be46 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,5 +55,5 @@ matrix: - MB_PYTHON_VERSION=3.6 install: - - choco install python --version 3.6.5 + - choco install python --verbose - pip install virtualenv From 8f7c884187cfbd62b6a3b01efbb30e1c8c1df89e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 3 May 2019 17:01:05 -0700 Subject: [PATCH 132/310] debugging choco install problem --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3b5be46..639daf8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,5 +55,5 @@ matrix: - MB_PYTHON_VERSION=3.6 install: - - choco install python --verbose + - choco install python3 - pip install virtualenv From c170ddb5a96556fddd4834651442283a2d2a0798 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 14:08:45 -0700 Subject: [PATCH 133/310] -y --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 639daf8..9cbcbbc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,5 +55,5 @@ matrix: - MB_PYTHON_VERSION=3.6 install: - - choco install python3 + - choco install --yes python3 - pip install virtualenv From 65f64881a9f6c2262bafe752a78a80dc3892a010 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 14:47:50 -0700 Subject: [PATCH 134/310] add --force to python install in windows? --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9cbcbbc..d83509f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,5 +55,5 @@ matrix: - MB_PYTHON_VERSION=3.6 install: - - choco install --yes python3 + - choco install --yes python3 --force - pip install virtualenv From 67a7bf8702d96344de8750de4a2e8705f4e453fe Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 15:03:39 -0700 Subject: [PATCH 135/310] move choco install python to before_install --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d83509f..2effd1c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,6 +54,6 @@ matrix: env: - MB_PYTHON_VERSION=3.6 - install: - - choco install --yes python3 --force + before_install: + - choco install --yes python3 - pip install virtualenv From 10864fc6c482a81336acc58fca4249417d352121 Mon Sep 17 00:00:00 2001 From: Christopher Hesse Date: Fri, 10 May 2019 15:09:10 -0700 Subject: [PATCH 136/310] fix build again --- setup.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 4fce5c8..266de8f 100644 --- a/setup.py +++ b/setup.py @@ -8,15 +8,13 @@ with open(os.path.join(os.path.dirname(__file__), 'atari_py/package_data.txt')) as f: package_data = [line.rstrip() for line in f.readlines()] -SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) class Build(build_ext): def run(self): cores_to_use = max(1, multiprocessing.cpu_count() - 1) - cmd = ['make', 'build', '-C', os.path.join(SCRIPT_DIR, 'atari_py/ale_interface'), '-j', str(cores_to_use)] - os.makedirs(self.build_lib, exist_ok=True) + cmd = ['make', 'build', '-C', 'atari_py/ale_interface', '-j', str(cores_to_use)] try: - subprocess.check_call(cmd, cwd=self.build_lib) + subprocess.check_call(cmd) except subprocess.CalledProcessError as e: sys.stderr.write("Could not build atari-py: %s. (HINT: are you sure cmake is installed? You might also be missing a library. Atari-py requires: zlib [installable as 'apt-get install zlib1g-dev' on Ubuntu].)\n" % e) raise From edcda3161ebf31b894bb77d88a5202dccbaa2d98 Mon Sep 17 00:00:00 2001 From: Christopher Hesse Date: Fri, 10 May 2019 15:21:15 -0700 Subject: [PATCH 137/310] try fix again --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 266de8f..82cf6eb 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ def run(self): cores_to_use = max(1, multiprocessing.cpu_count() - 1) cmd = ['make', 'build', '-C', 'atari_py/ale_interface', '-j', str(cores_to_use)] try: - subprocess.check_call(cmd) + subprocess.check_call(cmd, cwd=None if self.inplace else self.build_lib) except subprocess.CalledProcessError as e: sys.stderr.write("Could not build atari-py: %s. (HINT: are you sure cmake is installed? You might also be missing a library. Atari-py requires: zlib [installable as 'apt-get install zlib1g-dev' on Ubuntu].)\n" % e) raise From 76e385bd53a457100de3555a92f98718aa630e93 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 15:48:16 -0700 Subject: [PATCH 138/310] pip -> pip3 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2effd1c..afadee7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,4 +56,4 @@ matrix: before_install: - choco install --yes python3 - - pip install virtualenv + - pip3 install virtualenv From 69d5dc3f723e424d726f9a1daf31fe928edfe11d Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 15:49:57 -0700 Subject: [PATCH 139/310] block the rest of the builds for faster iterations --- .travis.yml | 56 ++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/.travis.yml b/.travis.yml index afadee7..ac4ade7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,34 +21,34 @@ after_success: matrix: include: - - os: linux - env: - - MB_PYTHON_VERSION=3.5 - - - os: linux - env: - - MB_PYTHON_VERSION=3.6 - - - os: linux - env: - - MB_PYTHON_VERSION=3.7 - - - - os: osx - osx_image: xcode8.3 - env: - - MB_PYTHON_VERSION=3.5 - - DEPLOY_SDIST=true - - - os: osx - osx_image: xcode8.3 - env: - - MB_PYTHON_VERSION=3.6 - - - os: osx - osx_image: xcode8.3 - env: - - MB_PYTHON_VERSION=3.7 +# - os: linux +# env: +# - MB_PYTHON_VERSION=3.5 +# +# - os: linux +# env: +# - MB_PYTHON_VERSION=3.6 +# +# - os: linux +# env: +# - MB_PYTHON_VERSION=3.7 +# +# +# - os: osx +# osx_image: xcode8.3 +# env: +# - MB_PYTHON_VERSION=3.5 +# - DEPLOY_SDIST=true +# +# - os: osx +# osx_image: xcode8.3 +# env: +# - MB_PYTHON_VERSION=3.6 +# +# - os: osx +# osx_image: xcode8.3 +# env: +# - MB_PYTHON_VERSION=3.7 - os: windows env: From 782bdc243ec5a3f2dcc1f488029e079061a776fa Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 15:54:59 -0700 Subject: [PATCH 140/310] refreshenv after python installation --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ac4ade7..524903a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,4 +56,5 @@ matrix: before_install: - choco install --yes python3 + - refreshenv - pip3 install virtualenv From a61174b7a0e4009710628fea8cd168650e6cf95b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 16:06:44 -0700 Subject: [PATCH 141/310] setx path --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 524903a..d71badc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,5 +56,5 @@ matrix: before_install: - choco install --yes python3 - - refreshenv + - setx PATH=%PATH%;C:\Python37 - pip3 install virtualenv From 2ca8a3f4a8171f13d2d7e8ef505ff292462aafff Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 16:20:31 -0700 Subject: [PATCH 142/310] exports --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d71badc..8bafed7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,5 +56,5 @@ matrix: before_install: - choco install --yes python3 - - setx PATH=%PATH%;C:\Python37 + - export PATH=$PATH:C:\Python37 - pip3 install virtualenv From c5d2532fa757590d5a6b06a172e600c99473c6be Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 17:35:52 -0700 Subject: [PATCH 143/310] massaging windows env variables --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8bafed7..d90d355 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,5 +56,8 @@ matrix: before_install: - choco install --yes python3 - - export PATH=$PATH:C:\Python37 + - export PATH=$PATH:"C:\Python37" + - echo $PATH + - which python + - which pip3 - pip3 install virtualenv From 6fb9dd253ded154610044424787e226ebbd3c25d Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 17:39:03 -0700 Subject: [PATCH 144/310] massaging windows env variables --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d90d355..5d9d8a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,7 +56,7 @@ matrix: before_install: - choco install --yes python3 - - export PATH=$PATH:"C:\Python37" + - export PATH=$PATH:/c/Python37 - echo $PATH - which python - which pip3 From c5c630803bcd1bf7eee212cbc6741b74338d415b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 17:50:06 -0700 Subject: [PATCH 145/310] massaging windows env variables --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5d9d8a7..8392238 100644 --- a/.travis.yml +++ b/.travis.yml @@ -59,5 +59,4 @@ matrix: - export PATH=$PATH:/c/Python37 - echo $PATH - which python - - which pip3 - - pip3 install virtualenv + - python -m pip install virtualenv From 5f91d7939c643db53e730d43886ffa0b11abcd99 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 17:52:45 -0700 Subject: [PATCH 146/310] massaging windows env variables --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8392238..99eb45c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -58,5 +58,5 @@ matrix: - choco install --yes python3 - export PATH=$PATH:/c/Python37 - echo $PATH - - which python - - python -m pip install virtualenv + - which python3 + - python3 -m pip install virtualenv From 116e66f6dd9426995667fb2148049f43e847d64b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 17:55:48 -0700 Subject: [PATCH 147/310] rearrange PATH env variable --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 99eb45c..8532bbf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,7 +56,7 @@ matrix: before_install: - choco install --yes python3 - - export PATH=$PATH:/c/Python37 + - export PATH=/c/Python37:$PATH - echo $PATH - which python3 - python3 -m pip install virtualenv From 430b0f75ec4a290f06541149567c5283dbff89ca Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 17:59:59 -0700 Subject: [PATCH 148/310] rearrange PATH env variable --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 8532bbf..c3e6c78 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,6 +57,7 @@ matrix: before_install: - choco install --yes python3 - export PATH=/c/Python37:$PATH + - ls /c/Python37 - echo $PATH - which python3 - python3 -m pip install virtualenv From 3bc5dc147a23201deb5d27849d7b8040d3b6cc37 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 10 May 2019 18:04:15 -0700 Subject: [PATCH 149/310] rearrange PATH env variable --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c3e6c78..8ea965f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -59,5 +59,5 @@ matrix: - export PATH=/c/Python37:$PATH - ls /c/Python37 - echo $PATH - - which python3 - - python3 -m pip install virtualenv + - which python + - python -m pip install virtualenv From 5a6c94b748d0a49b9d5de2d772fa80bb22a0e552 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 13 May 2019 15:58:52 -0700 Subject: [PATCH 150/310] add scripts subfolder to path --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8ea965f..8285ee6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,8 +56,8 @@ matrix: before_install: - choco install --yes python3 - - export PATH=/c/Python37:$PATH - - ls /c/Python37 + - export PATH=/c/Python37:/c/Python37/Scripts:$PATH - echo $PATH - which python - - python -m pip install virtualenv + - which pip + - pip install virtualenv From 1f271b31fae46a04cc1af4bf9a2c8bda8a79d985 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 13 May 2019 16:10:43 -0700 Subject: [PATCH 151/310] try building a wheel? --- .travis.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8285ee6..02dad25 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,10 +54,18 @@ matrix: env: - MB_PYTHON_VERSION=3.6 - before_install: + install: - choco install --yes python3 - export PATH=/c/Python37:/c/Python37/Scripts:$PATH - echo $PATH - which python - which pip - pip install virtualenv + + script: + - pip install cmake + - pip install . + - pip install pytest + - pytest . + - python setup.py bdist_wheel + From 799132e0910c58ede04e08e7649590c0099cddc8 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 13 May 2019 16:21:04 -0700 Subject: [PATCH 152/310] install make --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 02dad25..7b96f3e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,6 +56,7 @@ matrix: install: - choco install --yes python3 + - choch install --yes make - export PATH=/c/Python37:/c/Python37/Scripts:$PATH - echo $PATH - which python From ad7312df2108926c80a6ce8039000f08ae108343 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 13 May 2019 16:27:30 -0700 Subject: [PATCH 153/310] install make --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7b96f3e..e365476 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,7 +56,7 @@ matrix: install: - choco install --yes python3 - - choch install --yes make + - choco install --yes make - export PATH=/c/Python37:/c/Python37/Scripts:$PATH - echo $PATH - which python @@ -68,5 +68,5 @@ matrix: - pip install . - pip install pytest - pytest . - - python setup.py bdist_wheel + - pip wheel . From f51b692eb9fc09d5d9fd5345e60212260032ec7e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 13 May 2019 17:30:31 -0700 Subject: [PATCH 154/310] install make --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e365476..8f31999 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,7 +65,7 @@ matrix: script: - pip install cmake - - pip install . + - pip install -e . - pip install pytest - pytest . - pip wheel . From f4813da4592554df856090bfdc27f6741b58f8f4 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 13 May 2019 17:46:49 -0700 Subject: [PATCH 155/310] windows-compatible dir names in setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ddb653c..91273c8 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ class Build(build_ext): def run(self): cores_to_use = max(1, multiprocessing.cpu_count() - 1) - cmd = ['make', 'build', '-C', 'atari_py/ale_interface', '-j', str(cores_to_use)] + cmd = ['make', 'build', '-C', os.path.join('atari_py','ale_interface', '-j', str(cores_to_use)] try: subprocess.check_call(cmd, cwd=self.build_lib) except subprocess.CalledProcessError as e: From f991455e194f54ee61eb5494e5642ba256c7464e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 14 May 2019 17:15:07 -0700 Subject: [PATCH 156/310] fix syntax --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 91273c8..3e9f795 100644 --- a/setup.py +++ b/setup.py @@ -5,13 +5,13 @@ import subprocess import sys -with open(os.path.join(os.path.dirname(__file__), 'atari_py/package_data.txt')) as f: +with open(os.path.join(os.path.dirname(__file__), 'atari_py', 'package_data.txt')) as f: package_data = [line.rstrip() for line in f.readlines()] class Build(build_ext): def run(self): cores_to_use = max(1, multiprocessing.cpu_count() - 1) - cmd = ['make', 'build', '-C', os.path.join('atari_py','ale_interface', '-j', str(cores_to_use)] + cmd = ['make', 'build', '-C', os.path.join('atari_py','ale_interface'), '-j', str(cores_to_use)] try: subprocess.check_call(cmd, cwd=self.build_lib) except subprocess.CalledProcessError as e: From e0a2be02d34abbb9f0332e58e5fee452ba4aa809 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 15:15:30 -0700 Subject: [PATCH 157/310] fix directory name in setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3e9f795..8903745 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ class Build(build_ext): def run(self): cores_to_use = max(1, multiprocessing.cpu_count() - 1) - cmd = ['make', 'build', '-C', os.path.join('atari_py','ale_interface'), '-j', str(cores_to_use)] + cmd = ['make', 'build', '-C', 'atari_py\\ale_interface', '-j', str(cores_to_use)] try: subprocess.check_call(cmd, cwd=self.build_lib) except subprocess.CalledProcessError as e: From f6245165cf1ab18c41bf552bca4f6bd6cc40312c Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 15:27:06 -0700 Subject: [PATCH 158/310] install without -e --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8f31999..e365476 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,7 +65,7 @@ matrix: script: - pip install cmake - - pip install -e . + - pip install . - pip install pytest - pytest . - pip wheel . From cc4b6e0ff7471b486040265e456d2034f4c5eb1d Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 15:34:11 -0700 Subject: [PATCH 159/310] debugging build --- .travis.yml | 2 +- setup.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index e365476..8f31999 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,7 +65,7 @@ matrix: script: - pip install cmake - - pip install . + - pip install -e . - pip install pytest - pytest . - pip wheel . diff --git a/setup.py b/setup.py index 8903745..12f2f83 100644 --- a/setup.py +++ b/setup.py @@ -11,9 +11,9 @@ class Build(build_ext): def run(self): cores_to_use = max(1, multiprocessing.cpu_count() - 1) - cmd = ['make', 'build', '-C', 'atari_py\\ale_interface', '-j', str(cores_to_use)] + cmd = ['make', 'build', '-j', str(cores_to_use)] try: - subprocess.check_call(cmd, cwd=self.build_lib) + subprocess.check_call(cmd, cwd=os.path.join(self.build_lib, 'atari_py', 'ale_interface') except subprocess.CalledProcessError as e: sys.stderr.write("Could not build atari-py: %s. (HINT: are you sure cmake is installed? You might also be missing a library. Atari-py requires: zlib [installable as 'apt-get install zlib1g-dev' on Ubuntu].)\n" % e) raise From 0090cf3c0bc104a6741b6dfd4bd579daf09236b6 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 15:43:44 -0700 Subject: [PATCH 160/310] fixing build --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 12f2f83..18dffb2 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ def run(self): cores_to_use = max(1, multiprocessing.cpu_count() - 1) cmd = ['make', 'build', '-j', str(cores_to_use)] try: - subprocess.check_call(cmd, cwd=os.path.join(self.build_lib, 'atari_py', 'ale_interface') + subprocess.check_call(cmd, cwd=os.path.join(self.build_lib, 'atari_py', 'ale_interface')) except subprocess.CalledProcessError as e: sys.stderr.write("Could not build atari-py: %s. (HINT: are you sure cmake is installed? You might also be missing a library. Atari-py requires: zlib [installable as 'apt-get install zlib1g-dev' on Ubuntu].)\n" % e) raise From 00a35b61045f57f3e5dc4bd354553ba2e5af7462 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 15:59:05 -0700 Subject: [PATCH 161/310] fixing build --- setup.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 18dffb2..124ac52 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,9 @@ def run(self): cores_to_use = max(1, multiprocessing.cpu_count() - 1) cmd = ['make', 'build', '-j', str(cores_to_use)] try: - subprocess.check_call(cmd, cwd=os.path.join(self.build_lib, 'atari_py', 'ale_interface')) + cwd = os.path.join(self.build_lib, 'atari_py', 'ale_interface') + print('Calling make in ', cwd) + subprocess.check_call(cmd, cwd=cwd) except subprocess.CalledProcessError as e: sys.stderr.write("Could not build atari-py: %s. (HINT: are you sure cmake is installed? You might also be missing a library. Atari-py requires: zlib [installable as 'apt-get install zlib1g-dev' on Ubuntu].)\n" % e) raise From 2a5bc3566d97e7dfc78bc1022b8a273d0d20558d Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 16:37:48 -0700 Subject: [PATCH 162/310] figure out what's wrong with directories --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 124ac52..cec56b2 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,8 @@ def run(self): cores_to_use = max(1, multiprocessing.cpu_count() - 1) cmd = ['make', 'build', '-j', str(cores_to_use)] try: - cwd = os.path.join(self.build_lib, 'atari_py', 'ale_interface') + # cwd = os.path.join(self.build_lib, 'atari_py', 'ale_interface') + cwd = os.path.join('atari_py', 'ale_interface') print('Calling make in ', cwd) subprocess.check_call(cmd, cwd=cwd) except subprocess.CalledProcessError as e: From 53ccb8a27c1e4e1cf2b3acc7101a3fee1f808f74 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 16:54:43 -0700 Subject: [PATCH 163/310] why does build directory not have a makefile --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 8f31999..58b224e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,6 +66,7 @@ matrix: script: - pip install cmake - pip install -e . + - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - pip install pytest - pytest . - pip wheel . From 9749166086b41ed8df4b263a2e7739b78a5cf874 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 17:27:16 -0700 Subject: [PATCH 164/310] use cmake for the final stage of the build (instead of make) --- atari_py/ale_interface/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atari_py/ale_interface/Makefile b/atari_py/ale_interface/Makefile index e77c530..d39c18d 100644 --- a/atari_py/ale_interface/Makefile +++ b/atari_py/ale_interface/Makefile @@ -1,7 +1,7 @@ .PHONY: build clean build: - mkdir -p build && cd build && cmake .. && make -j4 + mkdir -p build && cd build && cmake .. && cmake --build . clean: rm -rf build From a5b2588324e5557a00b67e3ac2835a264d1729c2 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 17:34:31 -0700 Subject: [PATCH 165/310] remove Wunused warning option --- atari_py/ale_interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index d8f1906..765d8f6 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -10,7 +10,7 @@ option(BUILD_CPP_LIB "Build C++ Shared Library" OFF) option(BUILD_CLI "Build ALE Command Line Interface" OFF) option(BUILD_C_LIB "Build ALE C Library (needed for Python interface)" ON) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunused -fPIC -O3 -fomit-frame-pointer -D__STDC_CONSTANT_MACROS") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fPIC -O3 -fomit-frame-pointer -D__STDC_CONSTANT_MACROS") add_definitions(-DHAVE_INTTYPES) set(LINK_LIBS z) From 113a6122c36f454aa6d4c045dc3c5f0cccc2b7ac Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 17:54:42 -0700 Subject: [PATCH 166/310] build before pip install to provide verbose output --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 58b224e..3dd056e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,6 +65,7 @@ matrix: script: - pip install cmake + - make build -C atari_py/ale_interface - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - pip install pytest From 0cca033a6ae49be4ee3af57a70cb646ea3473d7e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 18:03:32 -0700 Subject: [PATCH 167/310] reduce warning verbosity --- atari_py/ale_interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index 765d8f6..c82def2 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -10,7 +10,7 @@ option(BUILD_CPP_LIB "Build C++ Shared Library" OFF) option(BUILD_CLI "Build ALE Command Line Interface" OFF) option(BUILD_C_LIB "Build ALE C Library (needed for Python interface)" ON) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fPIC -O3 -fomit-frame-pointer -D__STDC_CONSTANT_MACROS") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O3 -fomit-frame-pointer -D__STDC_CONSTANT_MACROS") add_definitions(-DHAVE_INTTYPES) set(LINK_LIBS z) From b82a5413af151fe9f67dd23d3d3ef380df026321 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 19:32:00 -0700 Subject: [PATCH 168/310] remove unix and posix settings files for windows build --- atari_py/ale_interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index c82def2..f748595 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -58,7 +58,7 @@ endif() if(WINDOWS OR MINGW) list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsWin32.cxx ${SOURCE_DIR}/os_dependent/OSystemWin32.cxx ${SOURCE_DIR}/os_dependent/FSNodeWin32.cxx) else() - list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsUNIX.cxx ${SOURCE_DIR}/os_dependent/OSystemUNIX.cxx ${SOURCE_DIR}/os_dependent/FSNodePOSIX.cxx) + # list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsUNIX.cxx ${SOURCE_DIR}/os_dependent/OSystemUNIX.cxx ${SOURCE_DIR}/os_dependent/FSNodePOSIX.cxx) SET(BIN_INSTALL_DIR "bin") SET(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE STRING "Library directory name") From a015d725d9fa2d427405bb6e148ad70b3b1c59c8 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 19:53:34 -0700 Subject: [PATCH 169/310] download zlib --- .travis.yml | 1 + installzlib.bat | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 installzlib.bat diff --git a/.travis.yml b/.travis.yml index 3dd056e..9561d8a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,6 +65,7 @@ matrix: script: - pip install cmake + - installzlib.bat - make build -C atari_py/ale_interface - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build diff --git a/installzlib.bat b/installzlib.bat new file mode 100644 index 0000000..e59a25b --- /dev/null +++ b/installzlib.bat @@ -0,0 +1,93 @@ +@echo off + +:: Configuration +set VERSION=1.2.11 +set FILE=zlib-%VERSION%.zip +set DIR=zlib-%VERSION% +set URL=https://zlib.net/zlib%VERSION:.=%.zip + +echo [0/6] Library(zlib==%VERSION%) + +:: Ancient Windows don't support TLS 1.1 and 1.2, so we fall back to insecure download. +set Version= +for /f "skip=1" %%v in ('wmic os get version') do if not defined Version set Version=%%v +for /f "delims=. tokens=1-3" %%a in ("%Version%") do ( + set Version.Major=%%a + set Version.Minor=%%b + set Version.Build=%%c +) + +SET ORIGIN=%cd% +call :joinpath "%ORIGIN%" "install.log" +SET LOG_FILE=%Result% + +:: Cleaning up previous mess +del /Q %FILE% ! >nul 2>&1 +rd /S /Q %DIR% >nul 2>&1 +del /Q %LOG_FILE% ! >nul 2>&1 +copy /y nul %LOG_FILE% >nul 2>&1 + +echo|set /p="[1/6] Downloading... " +echo Fetching %URL% >>%LOG_FILE% 2>&1 +powershell -Command "(New-Object Net.WebClient).DownloadFile('%URL%', '%FILE%')" >>%LOG_FILE% 2>&1 +if %ERRORLEVEL% NEQ 0 (echo FAILED. && echo Log can be found at %LOG_FILE%. && exit /B 1) else (echo done.) + +echo|set /p="[2/6] Extracting... " +powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('%FILE%', '.'); }" +if %ERRORLEVEL% NEQ 0 (echo FAILED. && echo Log can be found at %LOG_FILE%. && exit /B 1) else (echo done.) + +cd %DIR% + +echo|set /p="[3/6] Fixing CMakeLists.txt... " +set OLDSTR=RUNTIME DESTINATION ""\${INSTALL_BIN_DIR}\"" +set NEWSTR=RUNTIME DESTINATION ""bin\"" +call :search_replace "%OLDSTR%" "%NEWSTR%" + +set OLDSTR=ARCHIVE DESTINATION ""\${INSTALL_LIB_DIR}\"" +set NEWSTR=ARCHIVE DESTINATION ""lib\"" +call :search_replace "%OLDSTR%" "%NEWSTR%" + +set OLDSTR=LIBRARY DESTINATION ""\${INSTALL_LIB_DIR}\"" +set NEWSTR=LIBRARY DESTINATION ""lib\"" +call :search_replace "%OLDSTR%" "%NEWSTR%" + +set OLDSTR=DESTINATION ""\${INSTALL_INC_DIR}\"" +set NEWSTR=DESTINATION ""include\"" +call :search_replace "%OLDSTR%" "%NEWSTR%" +if %ERRORLEVEL% NEQ 0 (echo FAILED. && echo Log can be found at %LOG_FILE%. && exit /B 1) else (echo done.) + +mkdir build && cd build + +echo|set /p="[4/6] Configuring... " +cmake .. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="%programfiles%\zlib" >>%LOG_FILE% 2>&1 +if %ERRORLEVEL% NEQ 0 (echo FAILED. && echo Log can be found at %LOG_FILE%. && exit /B 1) else (echo done.) + +echo|set /p="[5/6] Compiling... " +nmake >>%LOG_FILE% 2>&1 +if %ERRORLEVEL% NEQ 0 (echo FAILED. && echo Log can be found at %LOG_FILE%. && exit /B 1) else (echo done.) + +echo|set /p="[6/6] Installing... " +nmake install >>%LOG_FILE% 2>&1 +set PATH=%PATH%;%programfiles%\zlib\bin +if %ERRORLEVEL% NEQ 0 (echo FAILED. && echo Log can be found at %LOG_FILE%. && exit /B 1) else (echo done.) + +cd %ORIGIN% >nul 2>&1 +del /Q %FILE% >nul 2>&1 +rd /S /Q %DIR% >nul 2>&1 + +echo Details can be found at %LOG_FILE%. + +@echo on +@goto :eof + +:joinpath +set Path1=%~1 +set Path2=%~2 +if {%Path1:~-1,1%}=={\} (set Result=%Path1%%Path2%) else (set Result=%Path1%\%Path2%) +goto :eof + +:search_replace +set OLDSTR=%~1 +set NEWSTR=%~2 +set CMD="(gc CMakeLists.txt) -replace '%OLDSTR%', '%NEWSTR%' | Out-File -encoding ASCII CMakeLists.txt" +powershell -Command %CMD% >>%LOG_FILE% 2>&1 From 4debda2071dafd11f5d98bc32b1f0542258a000e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 20:00:10 -0700 Subject: [PATCH 170/310] try to execute installzlib --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9561d8a..e52eded 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,7 +65,7 @@ matrix: script: - pip install cmake - - installzlib.bat + - ./installzlib.bat - make build -C atari_py/ale_interface - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build From 914e7bf07863e6df1ab96e94a7184da9e1da589e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 20:06:36 -0700 Subject: [PATCH 171/310] display error log of zlibinstaller --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index e52eded..ea4a692 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,6 +66,7 @@ matrix: script: - pip install cmake - ./installzlib.bat + - cat /c/Users/travis/build/openai/atari-py/install.log - make build -C atari_py/ale_interface - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build From 5ea39f43d246eb9428b071ff81d2edf68c4c0aa1 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 20:21:46 -0700 Subject: [PATCH 172/310] compile zlib manually --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index ea4a692..5734113 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,6 +57,7 @@ matrix: install: - choco install --yes python3 - choco install --yes make + - choco install --yes curl - export PATH=/c/Python37:/c/Python37/Scripts:$PATH - echo $PATH - which python @@ -65,6 +66,7 @@ matrix: script: - pip install cmake + - curl -O https://zlib.net/zlib1211.zip && unzip zlib1211.zip && cd zlib-1.2.11 && cmake . - ./installzlib.bat - cat /c/Users/travis/build/openai/atari-py/install.log - make build -C atari_py/ale_interface From 8f68cba64f18d71e06478b8b176203b088f0ceec Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 20:57:17 -0700 Subject: [PATCH 173/310] fix zlib installation --- .travis.yml | 3 +-- installzlib1.bat | 7 +++++++ 2 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 installzlib1.bat diff --git a/.travis.yml b/.travis.yml index 5734113..1748766 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,8 +66,7 @@ matrix: script: - pip install cmake - - curl -O https://zlib.net/zlib1211.zip && unzip zlib1211.zip && cd zlib-1.2.11 && cmake . - - ./installzlib.bat + - ./installzlib1.bat - cat /c/Users/travis/build/openai/atari-py/install.log - make build -C atari_py/ale_interface - pip install -e . diff --git a/installzlib1.bat b/installzlib1.bat new file mode 100644 index 0000000..ebc8a19 --- /dev/null +++ b/installzlib1.bat @@ -0,0 +1,7 @@ +curl -O https://zlib.net/zlib1211.zip +unzip zlib1211.zip +cd zlib-1.2.11 +cmake . +cmake --build . + + From d0136e5f455c6213e35bec2d1f9befa6d170a8a9 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 21:35:04 -0700 Subject: [PATCH 174/310] include zlib compilation into the entirety of windows build --- .travis.yml | 5 ++--- atari_py/ale_interface/CMakeLists.txt | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1748766..04bd01f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,9 +66,8 @@ matrix: script: - pip install cmake - - ./installzlib1.bat - - cat /c/Users/travis/build/openai/atari-py/install.log - - make build -C atari_py/ale_interface + - cd atari_py/ale_interface && curl -O https://zlib.net/zlib1211.zip && unzip zlib1211.zip && make build + # - make build -C atari_py/ale_interface - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - pip install pytest diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index f748595..6b88fc9 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -56,6 +56,7 @@ if(APPLE) endif() if(WINDOWS OR MINGW) + ADD_SUBDIRECTORY(zlib-1.2.11) list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsWin32.cxx ${SOURCE_DIR}/os_dependent/OSystemWin32.cxx ${SOURCE_DIR}/os_dependent/FSNodeWin32.cxx) else() # list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsUNIX.cxx ${SOURCE_DIR}/os_dependent/OSystemUNIX.cxx ${SOURCE_DIR}/os_dependent/FSNodePOSIX.cxx) From 214230b480fbb3afb7d3ba96b9e42dc7a4682778 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 15 May 2019 23:16:39 -0700 Subject: [PATCH 175/310] include_directories --- atari_py/ale_interface/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index 6b88fc9..25127be 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -56,7 +56,8 @@ if(APPLE) endif() if(WINDOWS OR MINGW) - ADD_SUBDIRECTORY(zlib-1.2.11) + add_subdirectory(zlib-1.2.11) + include_directories(zlib-1.2.11) list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsWin32.cxx ${SOURCE_DIR}/os_dependent/OSystemWin32.cxx ${SOURCE_DIR}/os_dependent/FSNodeWin32.cxx) else() # list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsUNIX.cxx ${SOURCE_DIR}/os_dependent/OSystemUNIX.cxx ${SOURCE_DIR}/os_dependent/FSNodePOSIX.cxx) From 65781d5f9e6076cdddaaac837adeba2ae3f3b779 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 07:43:56 -0700 Subject: [PATCH 176/310] zlib in src dir --- .travis.yml | 2 +- atari_py/ale_interface/CMakeLists.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 04bd01f..a6b1b3d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,7 +66,7 @@ matrix: script: - pip install cmake - - cd atari_py/ale_interface && curl -O https://zlib.net/zlib1211.zip && unzip zlib1211.zip && make build + - cd atari_py/ale_interface && curl -O https://zlib.net/zlib1211.zip && unzip zlib1211.zip -d src/zlib && make build # - make build -C atari_py/ale_interface - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index 25127be..d6e6f51 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -56,8 +56,8 @@ if(APPLE) endif() if(WINDOWS OR MINGW) - add_subdirectory(zlib-1.2.11) - include_directories(zlib-1.2.11) + # add_subdirectory(zlib-1.2.11) + include_directories(${SOURCE_DIR}/zlib) list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsWin32.cxx ${SOURCE_DIR}/os_dependent/OSystemWin32.cxx ${SOURCE_DIR}/os_dependent/FSNodeWin32.cxx) else() # list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsUNIX.cxx ${SOURCE_DIR}/os_dependent/OSystemUNIX.cxx ${SOURCE_DIR}/os_dependent/FSNodePOSIX.cxx) From 59e842dde8f8c343764fc6dd4c19d3ddc9a8cf5d Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 08:12:55 -0700 Subject: [PATCH 177/310] shuffle stuff around --- atari_py/ale_interface/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index d6e6f51..db26979 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -114,6 +114,7 @@ endif(UNIX) include_directories( ${SOURCE_DIR} + ${SOURCE_DIR}/src/zlib ${SOURCE_DIR}/common ${SOURCE_DIR}/controllers ${SOURCE_DIR}/emucore From f885b8be8fc31fa7fafe3e9c5ad8d58ccfbe81a0 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 08:18:17 -0700 Subject: [PATCH 178/310] shuffle stuff --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a6b1b3d..f80bc5d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,8 +66,9 @@ matrix: script: - pip install cmake - - cd atari_py/ale_interface && curl -O https://zlib.net/zlib1211.zip && unzip zlib1211.zip -d src/zlib && make build - # - make build -C atari_py/ale_interface + - curl -O https://zlib.net/zlib1211.zip + - unzip zlib1211.zip && cp -r zlib-1.2.11 atari_py/ale_interface/src/zlib + - make build -C atari_py/ale_interface - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - pip install pytest From 1df81f85978fdf7f6a53ea83c7bbe66e9f58f79b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 08:39:18 -0700 Subject: [PATCH 179/310] debugging build failure --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index f80bc5d..2473945 100644 --- a/.travis.yml +++ b/.travis.yml @@ -68,6 +68,7 @@ matrix: - pip install cmake - curl -O https://zlib.net/zlib1211.zip - unzip zlib1211.zip && cp -r zlib-1.2.11 atari_py/ale_interface/src/zlib + - ls atari_py/ale_interface/src/zlib - make build -C atari_py/ale_interface - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build From 8db24c7c46f8b86365f89ee11e3efed3751ef8f0 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 08:47:36 -0700 Subject: [PATCH 180/310] fix include directory path --- atari_py/ale_interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index db26979..6705490 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -114,7 +114,7 @@ endif(UNIX) include_directories( ${SOURCE_DIR} - ${SOURCE_DIR}/src/zlib + ${SOURCE_DIR}/zlib ${SOURCE_DIR}/common ${SOURCE_DIR}/controllers ${SOURCE_DIR}/emucore From 1b34b5176ed9971f726d5cbf84ac05aa201f1a8c Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 09:03:30 -0700 Subject: [PATCH 181/310] include --- atari_py/ale_interface/src/games/Roms.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/atari_py/ale_interface/src/games/Roms.hpp b/atari_py/ale_interface/src/games/Roms.hpp index 056906d..9b47b37 100644 --- a/atari_py/ale_interface/src/games/Roms.hpp +++ b/atari_py/ale_interface/src/games/Roms.hpp @@ -13,6 +13,7 @@ #define __ROMS_HPP__ #include +#include struct RomSettings; From d4863ca6e20f87ebd4ce303bdcb26dbfdaffd904 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 09:19:00 -0700 Subject: [PATCH 182/310] more include --- atari_py/ale_interface/src/games/RomSettings.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/atari_py/ale_interface/src/games/RomSettings.hpp b/atari_py/ale_interface/src/games/RomSettings.hpp index c7fc4c4..a7b096c 100644 --- a/atari_py/ale_interface/src/games/RomSettings.hpp +++ b/atari_py/ale_interface/src/games/RomSettings.hpp @@ -33,6 +33,7 @@ #ifndef __ROMSETTINGS_HPP__ #define __ROMSETTINGS_HPP__ +#include #include "../common/Constants.h" #include "../emucore/Serializer.hxx" #include "../emucore/Deserializer.hxx" From 5003fe19ad1de5bb35035d091027de539663b751 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 09:27:57 -0700 Subject: [PATCH 183/310] stuff --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 2473945..857b09f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -68,6 +68,7 @@ matrix: - pip install cmake - curl -O https://zlib.net/zlib1211.zip - unzip zlib1211.zip && cp -r zlib-1.2.11 atari_py/ale_interface/src/zlib + - cd atari_py/ale_interface/src/zlib && cmake --build . && cd ../../../../ - ls atari_py/ale_interface/src/zlib - make build -C atari_py/ale_interface - pip install -e . From 31ee39eb61a4e7fd4e1605d283da792835aee5e1 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 09:46:05 -0700 Subject: [PATCH 184/310] stuff --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 857b09f..44bf8b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -68,7 +68,8 @@ matrix: - pip install cmake - curl -O https://zlib.net/zlib1211.zip - unzip zlib1211.zip && cp -r zlib-1.2.11 atari_py/ale_interface/src/zlib - - cd atari_py/ale_interface/src/zlib && cmake --build . && cd ../../../../ + # - cd atari_py/ale_interface/src/zlib && cmake --build . && cd ../../../../ + - make -C atari_py/ale_interface/src/zlib - ls atari_py/ale_interface/src/zlib - make build -C atari_py/ale_interface - pip install -e . From d0f5ae8944fbed8ef1e2ccaba325dea2e80ce729 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 10:24:19 -0700 Subject: [PATCH 185/310] fixing zlib build instructions --- .travis.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 44bf8b9..1cfa1aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,12 +66,8 @@ matrix: script: - pip install cmake - - curl -O https://zlib.net/zlib1211.zip - - unzip zlib1211.zip && cp -r zlib-1.2.11 atari_py/ale_interface/src/zlib - # - cd atari_py/ale_interface/src/zlib && cmake --build . && cd ../../../../ - - make -C atari_py/ale_interface/src/zlib + - ./installzlib1.bat - ls atari_py/ale_interface/src/zlib - - make build -C atari_py/ale_interface - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - pip install pytest From 62fa2f39d5698ef4e78215641c4c49563a8bb1cc Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 10:40:17 -0700 Subject: [PATCH 186/310] fix --- installzlib1.bat | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/installzlib1.bat b/installzlib1.bat index ebc8a19..f097570 100644 --- a/installzlib1.bat +++ b/installzlib1.bat @@ -1,6 +1,7 @@ curl -O https://zlib.net/zlib1211.zip unzip zlib1211.zip -cd zlib-1.2.11 +cp -r zlib-1.2.11 atari_py/ale_interface/src/zlib +cd atari_py/ale_interface/src/zlib cmake . cmake --build . From 06c65df56eda71545de8545fd9e0eb45a953ee62 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 10:49:55 -0700 Subject: [PATCH 187/310] pre-build for higher log verbosity --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 1cfa1aa..9265565 100644 --- a/.travis.yml +++ b/.travis.yml @@ -68,6 +68,7 @@ matrix: - pip install cmake - ./installzlib1.bat - ls atari_py/ale_interface/src/zlib + - make build -C atari_py/ale_interface - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - pip install pytest From 587da046934b6d5d7497e6feda804ca9effc251d Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 11:41:15 -0700 Subject: [PATCH 188/310] fixes --- atari_py/ale_interface/CMakeLists.txt | 2 +- installzlib1.bat | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index 6705490..572ae28 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -57,7 +57,7 @@ endif() if(WINDOWS OR MINGW) # add_subdirectory(zlib-1.2.11) - include_directories(${SOURCE_DIR}/zlib) + # include_directories(${SOURCE_DIR}/zlib) list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsWin32.cxx ${SOURCE_DIR}/os_dependent/OSystemWin32.cxx ${SOURCE_DIR}/os_dependent/FSNodeWin32.cxx) else() # list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsUNIX.cxx ${SOURCE_DIR}/os_dependent/OSystemUNIX.cxx ${SOURCE_DIR}/os_dependent/FSNodePOSIX.cxx) diff --git a/installzlib1.bat b/installzlib1.bat index f097570..d25e5dd 100644 --- a/installzlib1.bat +++ b/installzlib1.bat @@ -5,4 +5,8 @@ cd atari_py/ale_interface/src/zlib cmake . cmake --build . +cd ../.. +mkdir -p build +cp src/zlib/Debug/zlibstaticd.lib build/z.lib + From 25112ee16140cdf82e24b64d961fd0013e4756ec Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 12:40:20 -0700 Subject: [PATCH 189/310] add shlwapi to link libraries --- atari_py/ale_interface/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index 572ae28..7498620 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -58,6 +58,7 @@ endif() if(WINDOWS OR MINGW) # add_subdirectory(zlib-1.2.11) # include_directories(${SOURCE_DIR}/zlib) + list(APPEND LINK_LIBS shlwapi) list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsWin32.cxx ${SOURCE_DIR}/os_dependent/OSystemWin32.cxx ${SOURCE_DIR}/os_dependent/FSNodeWin32.cxx) else() # list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsUNIX.cxx ${SOURCE_DIR}/os_dependent/OSystemUNIX.cxx ${SOURCE_DIR}/os_dependent/FSNodePOSIX.cxx) From ef59baecc224565dff9ff2ce4f373c136cbfdc72 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 13:02:17 -0700 Subject: [PATCH 190/310] add shlwapi to link libraries --- atari_py/ale_interface/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index 7498620..31ddefa 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -13,6 +13,7 @@ option(BUILD_C_LIB "Build ALE C Library (needed for Python interface)" ON) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O3 -fomit-frame-pointer -D__STDC_CONSTANT_MACROS") add_definitions(-DHAVE_INTTYPES) set(LINK_LIBS z) +list(APPEND LINK_LIBS shlwapi) if(USE_RLGLUE) add_definitions(-D__USE_RLGLUE) @@ -58,7 +59,6 @@ endif() if(WINDOWS OR MINGW) # add_subdirectory(zlib-1.2.11) # include_directories(${SOURCE_DIR}/zlib) - list(APPEND LINK_LIBS shlwapi) list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsWin32.cxx ${SOURCE_DIR}/os_dependent/OSystemWin32.cxx ${SOURCE_DIR}/os_dependent/FSNodeWin32.cxx) else() # list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsUNIX.cxx ${SOURCE_DIR}/os_dependent/OSystemUNIX.cxx ${SOURCE_DIR}/os_dependent/FSNodePOSIX.cxx) From bd8ff14157824b3e810caaf4f37c3196ed93ade7 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 13:30:24 -0700 Subject: [PATCH 191/310] fixing CMakeLists.txt --- atari_py/ale_interface/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index 31ddefa..eda88ca 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -56,12 +56,12 @@ if(APPLE) set(CMAKE_SHARED_LIBRARY_SUFFIX ".so") endif() -if(WINDOWS OR MINGW) +if(WIN32 OR MINGW) # add_subdirectory(zlib-1.2.11) # include_directories(${SOURCE_DIR}/zlib) list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsWin32.cxx ${SOURCE_DIR}/os_dependent/OSystemWin32.cxx ${SOURCE_DIR}/os_dependent/FSNodeWin32.cxx) else() - # list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsUNIX.cxx ${SOURCE_DIR}/os_dependent/OSystemUNIX.cxx ${SOURCE_DIR}/os_dependent/FSNodePOSIX.cxx) + list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsUNIX.cxx ${SOURCE_DIR}/os_dependent/OSystemUNIX.cxx ${SOURCE_DIR}/os_dependent/FSNodePOSIX.cxx) SET(BIN_INSTALL_DIR "bin") SET(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE STRING "Library directory name") From ea2f80fb1c477d1a401e7f17727b30c93de37866 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 13:48:34 -0700 Subject: [PATCH 192/310] stuff --- .travis.yml | 1 - atari_py/ale_interface/CMakeLists.txt | 1 - atari_py/ale_python_interface.py | 8 ++++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9265565..8e61a09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,7 +57,6 @@ matrix: install: - choco install --yes python3 - choco install --yes make - - choco install --yes curl - export PATH=/c/Python37:/c/Python37/Scripts:$PATH - echo $PATH - which python diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index eda88ca..b307147 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -13,7 +13,6 @@ option(BUILD_C_LIB "Build ALE C Library (needed for Python interface)" ON) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O3 -fomit-frame-pointer -D__STDC_CONSTANT_MACROS") add_definitions(-DHAVE_INTTYPES) set(LINK_LIBS z) -list(APPEND LINK_LIBS shlwapi) if(USE_RLGLUE) add_definitions(-D__USE_RLGLUE) diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index 72425e0..cf4cdec 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -10,8 +10,12 @@ import os import six -ale_lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), - 'ale_interface/build/libale_c.so')) +if os.name == 'posix': + ale_lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), + 'ale_interface/build/libale_c.so')) +else: + ale_lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), + 'ale_interface/build/libale_c.dll')) ale_lib.ALE_new.argtypes = None ale_lib.ALE_new.restype = c_void_p From d86d94ceb14ea3fd8abc2ca9b60d35fd96d8e33a Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 14:00:46 -0700 Subject: [PATCH 193/310] .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 8e61a09..2624233 100644 --- a/.travis.yml +++ b/.travis.yml @@ -71,6 +71,7 @@ matrix: - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - pip install pytest + - ls -lht atari_py/ale_interface/build - pytest . - pip wheel . From 1f176d6c3c96d56cc94a537c0527ef964d1b5b4f Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 14:21:06 -0700 Subject: [PATCH 194/310] move the resulting dll --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 2624233..0141617 100644 --- a/.travis.yml +++ b/.travis.yml @@ -68,6 +68,7 @@ matrix: - ./installzlib1.bat - ls atari_py/ale_interface/src/zlib - make build -C atari_py/ale_interface + - cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/build/ale_c.dll - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - pip install pytest From 308716e6f9b512ec84a3aa74f4029f75af8e0c0b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 14:30:21 -0700 Subject: [PATCH 195/310] stuff --- atari_py/ale_python_interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index cf4cdec..01fe094 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -15,7 +15,7 @@ 'ale_interface/build/libale_c.so')) else: ale_lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), - 'ale_interface/build/libale_c.dll')) + 'ale_interface/build/ale_c.dll')) ale_lib.ALE_new.argtypes = None ale_lib.ALE_new.restype = c_void_p From b21b63ec86f83ebb7206a95e3469d284bfd71aaa Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 14:42:39 -0700 Subject: [PATCH 196/310] fix build failure --- atari_py/ale_python_interface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index 01fe094..e4e970f 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -15,7 +15,7 @@ 'ale_interface/build/libale_c.so')) else: ale_lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), - 'ale_interface/build/ale_c.dll')) + 'ale_interface/build/Debug/ale_c.dll')) ale_lib.ALE_new.argtypes = None ale_lib.ALE_new.restype = c_void_p From ab849005f72942d70a96809cff7db6a963951668 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 14:48:18 -0700 Subject: [PATCH 197/310] fixing build failure --- .travis.yml | 5 +++-- atari_py/tests/test_smoke.py | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0141617..e034c2a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -71,8 +71,9 @@ matrix: - cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/build/ale_c.dll - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - - pip install pytest - ls -lht atari_py/ale_interface/build - - pytest . + - python atari_py/tests/test_smoke + # - pip install pytest + #- pytest . - pip wheel . diff --git a/atari_py/tests/test_smoke.py b/atari_py/tests/test_smoke.py index 3fe28bc..d2f54ec 100644 --- a/atari_py/tests/test_smoke.py +++ b/atari_py/tests/test_smoke.py @@ -14,3 +14,8 @@ def test_smoke(): (screen_width,screen_height) = ale.getScreenDims() arr = np.zeros((screen_height, screen_width, 4), dtype=np.uint8) ale.getScreenRGB(arr) + +if __name__ == '__main__': + print('smoke test') + test_smoke() + print('done!') From 2622909f764df8678c0a7d12c283c3dfb7595296 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 16 May 2019 16:02:56 -0700 Subject: [PATCH 198/310] fixing build failurev --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e034c2a..7fa63e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,7 +72,7 @@ matrix: - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - ls -lht atari_py/ale_interface/build - - python atari_py/tests/test_smoke + - python atari_py/tests/test_smoke.py # - pip install pytest #- pytest . - pip wheel . From 9411b94b9e32c5c3867782a601b883327a3f1163 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 14:42:15 -0700 Subject: [PATCH 199/310] try to use 64 bit platform? --- atari_py/ale_interface/Makefile | 2 +- installzlib1.bat | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atari_py/ale_interface/Makefile b/atari_py/ale_interface/Makefile index d39c18d..5ff7a32 100644 --- a/atari_py/ale_interface/Makefile +++ b/atari_py/ale_interface/Makefile @@ -1,7 +1,7 @@ .PHONY: build clean build: - mkdir -p build && cd build && cmake .. && cmake --build . + mkdir -p build && cd build && cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. && cmake --build . clean: rm -rf build diff --git a/installzlib1.bat b/installzlib1.bat index d25e5dd..ebf8a01 100644 --- a/installzlib1.bat +++ b/installzlib1.bat @@ -2,7 +2,7 @@ curl -O https://zlib.net/zlib1211.zip unzip zlib1211.zip cp -r zlib-1.2.11 atari_py/ale_interface/src/zlib cd atari_py/ale_interface/src/zlib -cmake . +cmake -DCMAKE_GENERATOR_PLATFORM=x64 . cmake --build . cd ../.. From ae773fee0d985649d151d7d007baaf53e27c2653 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 14:58:37 -0700 Subject: [PATCH 200/310] visibility of symbols exported into a dll --- atari_py/ale_interface/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index b307147..5486297 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -58,6 +58,7 @@ endif() if(WIN32 OR MINGW) # add_subdirectory(zlib-1.2.11) # include_directories(${SOURCE_DIR}/zlib) + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsWin32.cxx ${SOURCE_DIR}/os_dependent/OSystemWin32.cxx ${SOURCE_DIR}/os_dependent/FSNodeWin32.cxx) else() list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsUNIX.cxx ${SOURCE_DIR}/os_dependent/OSystemUNIX.cxx ${SOURCE_DIR}/os_dependent/FSNodePOSIX.cxx) From e6e919bb2cd34e14f439b57ec27e30d88d9ba229 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 15:10:36 -0700 Subject: [PATCH 201/310] install wheel package --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7fa63e3..9ab0e6a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,8 +72,7 @@ matrix: - pip install -e . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - ls -lht atari_py/ale_interface/build - - python atari_py/tests/test_smoke.py - # - pip install pytest - #- pytest . - - pip wheel . + - pip install pytest + - pytest . + - pip install wheel && pip wheel . From d53f5a6a216a22ec5f327aea529b5ddb41007363 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 15:26:54 -0700 Subject: [PATCH 202/310] non -e build --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9ab0e6a..4ed9cd0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -67,9 +67,9 @@ matrix: - pip install cmake - ./installzlib1.bat - ls atari_py/ale_interface/src/zlib - - make build -C atari_py/ale_interface + # - make build -C atari_py/ale_interface - cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/build/ale_c.dll - - pip install -e . + - pip install . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - ls -lht atari_py/ale_interface/build - pip install pytest From 9f5b5aae10300788e1278df36a8fe818006db0d6 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 15:36:32 -0700 Subject: [PATCH 203/310] move files around --- atari_py/ale_interface/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atari_py/ale_interface/Makefile b/atari_py/ale_interface/Makefile index 5ff7a32..0f76293 100644 --- a/atari_py/ale_interface/Makefile +++ b/atari_py/ale_interface/Makefile @@ -1,7 +1,7 @@ .PHONY: build clean build: - mkdir -p build && cd build && cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. && cmake --build . + mkdir -p build && cd build && cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. && cmake --build . && cp Debug/ale_c.dll .l clean: rm -rf build From 466dc352b8e7d6a434c9bc7496fbda76365d0ee1 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 15:55:25 -0700 Subject: [PATCH 204/310] feeling lucky --- .travis.yml | 8 ++++---- atari_py/ale_python_interface.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4ed9cd0..4d5e518 100644 --- a/.travis.yml +++ b/.travis.yml @@ -68,11 +68,11 @@ matrix: - ./installzlib1.bat - ls atari_py/ale_interface/src/zlib # - make build -C atari_py/ale_interface - - cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/build/ale_c.dll + # - cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/build/ale_c.dll - pip install . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - ls -lht atari_py/ale_interface/build - - pip install pytest - - pytest . - - pip install wheel && pip wheel . + # - pip install pytest + # - pytest . + - pip install wheel && pip wheel . -w wheelhouse diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index e4e970f..01fe094 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -15,7 +15,7 @@ 'ale_interface/build/libale_c.so')) else: ale_lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), - 'ale_interface/build/Debug/ale_c.dll')) + 'ale_interface/build/ale_c.dll')) ale_lib.ALE_new.argtypes = None ale_lib.ALE_new.restype = c_void_p From 6c374a2eb7d59577fe37364da4f0715b26e3e34b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 16:21:17 -0700 Subject: [PATCH 205/310] test the wheel --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4d5e518..155c79b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,7 +72,7 @@ matrix: - pip install . - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - ls -lht atari_py/ale_interface/build - # - pip install pytest - # - pytest . - pip install wheel && pip wheel . -w wheelhouse + - pip install pytest + - rm -rf atari_py pytest --pyargs atari_py From 7eb3fee2bc62ff5ddee2dc590a82c6bb2f74a217 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 16:21:55 -0700 Subject: [PATCH 206/310] test the wheel --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 155c79b..50f5ef7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -73,6 +73,7 @@ matrix: - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - ls -lht atari_py/ale_interface/build - pip install wheel && pip wheel . -w wheelhouse + - ls -lht wheelhouse - pip install pytest - rm -rf atari_py pytest --pyargs atari_py From 2801aa6fa0a420f8d2d91cc3c9d576dfe79614c7 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 16:34:35 -0700 Subject: [PATCH 207/310] fix travis.yml --- .travis.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 50f5ef7..f5b96c5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,14 +66,12 @@ matrix: script: - pip install cmake - ./installzlib1.bat - - ls atari_py/ale_interface/src/zlib # - make build -C atari_py/ale_interface # - cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/build/ale_c.dll - pip install . - - ls -lht /c/Users/travis/build/openai/atari-py/atari_py/ale_interface/build - - ls -lht atari_py/ale_interface/build - pip install wheel && pip wheel . -w wheelhouse - ls -lht wheelhouse + - rm -rf atari_py - pip install pytest - - rm -rf atari_py pytest --pyargs atari_py + - pytest --pyargs atari_py From 740d8cc7e4dc9184d832a42a7d6a958ab675c78c Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 16:38:23 -0700 Subject: [PATCH 208/310] try installing a wheel before testing instead of pip installing the directory --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f5b96c5..a6b5e2d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -68,9 +68,10 @@ matrix: - ./installzlib1.bat # - make build -C atari_py/ale_interface # - cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/build/ale_c.dll - - pip install . + # - pip install . - pip install wheel && pip wheel . -w wheelhouse - - ls -lht wheelhouse + - ls wheelhouse/atari_py* + - pip install wheelhouse/$(ls wheelhouse/atari_py*) - rm -rf atari_py - pip install pytest - pytest --pyargs atari_py From 611fc2061d91eaeb20ec4ef677bc4a770dca63e9 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 16:48:35 -0700 Subject: [PATCH 209/310] add __init__.py to tests submodule --- atari_py/tests/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 atari_py/tests/__init__.py diff --git a/atari_py/tests/__init__.py b/atari_py/tests/__init__.py new file mode 100644 index 0000000..e69de29 From 494ba50fba27c6b62aa5aa205b700743dca6c112 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 16:50:38 -0700 Subject: [PATCH 210/310] fix travis.py --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a6b5e2d..acd9e09 100644 --- a/.travis.yml +++ b/.travis.yml @@ -71,7 +71,7 @@ matrix: # - pip install . - pip install wheel && pip wheel . -w wheelhouse - ls wheelhouse/atari_py* - - pip install wheelhouse/$(ls wheelhouse/atari_py*) + - pip install $(ls wheelhouse/atari_py*) - rm -rf atari_py - pip install pytest - pytest --pyargs atari_py From 5ce9a1d61b426747a908077bce5d3c16a0bbb4a1 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 17:16:13 -0700 Subject: [PATCH 211/310] trying to run tests --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index acd9e09..2cd3476 100644 --- a/.travis.yml +++ b/.travis.yml @@ -74,5 +74,5 @@ matrix: - pip install $(ls wheelhouse/atari_py*) - rm -rf atari_py - pip install pytest - - pytest --pyargs atari_py + - pytest --pyargs atari_py.tests From ad2d4e351a759b840e7501b39a99a3d4c749025e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 18:05:06 -0700 Subject: [PATCH 212/310] include dll into package manifest --- atari_py/package_data.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/atari_py/package_data.txt b/atari_py/package_data.txt index 6d35fff..cefe327 100644 --- a/atari_py/package_data.txt +++ b/atari_py/package_data.txt @@ -1,4 +1,5 @@ ale_interface/build/*.so +ale_interface/build/*.dll ale_interface/build/ale ale_c_wrapper.cpp ale_c_wrapper.h From e131e7649a45991f955ae38d3c2ca310e9333b7e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 18:15:24 -0700 Subject: [PATCH 213/310] skip tests to deploy to pypi (to inspect the wheel) --- .travis.yml | 8 ++-- installzlib.bat | 99 +++++------------------------------------------- installzlib1.bat | 12 ------ setup.py | 1 - 4 files changed, 13 insertions(+), 107 deletions(-) delete mode 100644 installzlib1.bat diff --git a/.travis.yml b/.travis.yml index 2cd3476..7393ca5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -71,8 +71,8 @@ matrix: # - pip install . - pip install wheel && pip wheel . -w wheelhouse - ls wheelhouse/atari_py* - - pip install $(ls wheelhouse/atari_py*) - - rm -rf atari_py - - pip install pytest - - pytest --pyargs atari_py.tests + # - pip install $(ls wheelhouse/atari_py*) + # - rm -rf atari_py + # - pip install pytest + # - pytest --pyargs atari_py.tests diff --git a/installzlib.bat b/installzlib.bat index e59a25b..ebf8a01 100644 --- a/installzlib.bat +++ b/installzlib.bat @@ -1,93 +1,12 @@ -@echo off +curl -O https://zlib.net/zlib1211.zip +unzip zlib1211.zip +cp -r zlib-1.2.11 atari_py/ale_interface/src/zlib +cd atari_py/ale_interface/src/zlib +cmake -DCMAKE_GENERATOR_PLATFORM=x64 . +cmake --build . -:: Configuration -set VERSION=1.2.11 -set FILE=zlib-%VERSION%.zip -set DIR=zlib-%VERSION% -set URL=https://zlib.net/zlib%VERSION:.=%.zip +cd ../.. +mkdir -p build +cp src/zlib/Debug/zlibstaticd.lib build/z.lib -echo [0/6] Library(zlib==%VERSION%) -:: Ancient Windows don't support TLS 1.1 and 1.2, so we fall back to insecure download. -set Version= -for /f "skip=1" %%v in ('wmic os get version') do if not defined Version set Version=%%v -for /f "delims=. tokens=1-3" %%a in ("%Version%") do ( - set Version.Major=%%a - set Version.Minor=%%b - set Version.Build=%%c -) - -SET ORIGIN=%cd% -call :joinpath "%ORIGIN%" "install.log" -SET LOG_FILE=%Result% - -:: Cleaning up previous mess -del /Q %FILE% ! >nul 2>&1 -rd /S /Q %DIR% >nul 2>&1 -del /Q %LOG_FILE% ! >nul 2>&1 -copy /y nul %LOG_FILE% >nul 2>&1 - -echo|set /p="[1/6] Downloading... " -echo Fetching %URL% >>%LOG_FILE% 2>&1 -powershell -Command "(New-Object Net.WebClient).DownloadFile('%URL%', '%FILE%')" >>%LOG_FILE% 2>&1 -if %ERRORLEVEL% NEQ 0 (echo FAILED. && echo Log can be found at %LOG_FILE%. && exit /B 1) else (echo done.) - -echo|set /p="[2/6] Extracting... " -powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('%FILE%', '.'); }" -if %ERRORLEVEL% NEQ 0 (echo FAILED. && echo Log can be found at %LOG_FILE%. && exit /B 1) else (echo done.) - -cd %DIR% - -echo|set /p="[3/6] Fixing CMakeLists.txt... " -set OLDSTR=RUNTIME DESTINATION ""\${INSTALL_BIN_DIR}\"" -set NEWSTR=RUNTIME DESTINATION ""bin\"" -call :search_replace "%OLDSTR%" "%NEWSTR%" - -set OLDSTR=ARCHIVE DESTINATION ""\${INSTALL_LIB_DIR}\"" -set NEWSTR=ARCHIVE DESTINATION ""lib\"" -call :search_replace "%OLDSTR%" "%NEWSTR%" - -set OLDSTR=LIBRARY DESTINATION ""\${INSTALL_LIB_DIR}\"" -set NEWSTR=LIBRARY DESTINATION ""lib\"" -call :search_replace "%OLDSTR%" "%NEWSTR%" - -set OLDSTR=DESTINATION ""\${INSTALL_INC_DIR}\"" -set NEWSTR=DESTINATION ""include\"" -call :search_replace "%OLDSTR%" "%NEWSTR%" -if %ERRORLEVEL% NEQ 0 (echo FAILED. && echo Log can be found at %LOG_FILE%. && exit /B 1) else (echo done.) - -mkdir build && cd build - -echo|set /p="[4/6] Configuring... " -cmake .. -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="%programfiles%\zlib" >>%LOG_FILE% 2>&1 -if %ERRORLEVEL% NEQ 0 (echo FAILED. && echo Log can be found at %LOG_FILE%. && exit /B 1) else (echo done.) - -echo|set /p="[5/6] Compiling... " -nmake >>%LOG_FILE% 2>&1 -if %ERRORLEVEL% NEQ 0 (echo FAILED. && echo Log can be found at %LOG_FILE%. && exit /B 1) else (echo done.) - -echo|set /p="[6/6] Installing... " -nmake install >>%LOG_FILE% 2>&1 -set PATH=%PATH%;%programfiles%\zlib\bin -if %ERRORLEVEL% NEQ 0 (echo FAILED. && echo Log can be found at %LOG_FILE%. && exit /B 1) else (echo done.) - -cd %ORIGIN% >nul 2>&1 -del /Q %FILE% >nul 2>&1 -rd /S /Q %DIR% >nul 2>&1 - -echo Details can be found at %LOG_FILE%. - -@echo on -@goto :eof - -:joinpath -set Path1=%~1 -set Path2=%~2 -if {%Path1:~-1,1%}=={\} (set Result=%Path1%%Path2%) else (set Result=%Path1%\%Path2%) -goto :eof - -:search_replace -set OLDSTR=%~1 -set NEWSTR=%~2 -set CMD="(gc CMakeLists.txt) -replace '%OLDSTR%', '%NEWSTR%' | Out-File -encoding ASCII CMakeLists.txt" -powershell -Command %CMD% >>%LOG_FILE% 2>&1 diff --git a/installzlib1.bat b/installzlib1.bat deleted file mode 100644 index ebf8a01..0000000 --- a/installzlib1.bat +++ /dev/null @@ -1,12 +0,0 @@ -curl -O https://zlib.net/zlib1211.zip -unzip zlib1211.zip -cp -r zlib-1.2.11 atari_py/ale_interface/src/zlib -cd atari_py/ale_interface/src/zlib -cmake -DCMAKE_GENERATOR_PLATFORM=x64 . -cmake --build . - -cd ../.. -mkdir -p build -cp src/zlib/Debug/zlibstaticd.lib build/z.lib - - diff --git a/setup.py b/setup.py index cec56b2..9712be1 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,6 @@ def run(self): try: # cwd = os.path.join(self.build_lib, 'atari_py', 'ale_interface') cwd = os.path.join('atari_py', 'ale_interface') - print('Calling make in ', cwd) subprocess.check_call(cmd, cwd=cwd) except subprocess.CalledProcessError as e: sys.stderr.write("Could not build atari-py: %s. (HINT: are you sure cmake is installed? You might also be missing a library. Atari-py requires: zlib [installable as 'apt-get install zlib1g-dev' on Ubuntu].)\n" % e) From 105c0f90a5f62779dd98d746fecf14feedd28158 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 18:18:20 -0700 Subject: [PATCH 214/310] fix silly typo in the makefile --- .travis.yml | 12 ++++-------- atari_py/ale_interface/Makefile | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7393ca5..82d138d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,13 +66,9 @@ matrix: script: - pip install cmake - ./installzlib1.bat - # - make build -C atari_py/ale_interface - # - cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/build/ale_c.dll - # - pip install . - pip install wheel && pip wheel . -w wheelhouse - - ls wheelhouse/atari_py* - # - pip install $(ls wheelhouse/atari_py*) - # - rm -rf atari_py - # - pip install pytest - # - pytest --pyargs atari_py.tests + - pip install $(ls wheelhouse/atari_py*) + - rm -rf atari_py + - pip install pytest + - pytest --pyargs atari_py.tests diff --git a/atari_py/ale_interface/Makefile b/atari_py/ale_interface/Makefile index 0f76293..df4d363 100644 --- a/atari_py/ale_interface/Makefile +++ b/atari_py/ale_interface/Makefile @@ -1,7 +1,7 @@ .PHONY: build clean build: - mkdir -p build && cd build && cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. && cmake --build . && cp Debug/ale_c.dll .l + mkdir -p build && cd build && cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. && cmake --build . && cp Debug/ale_c.dll . clean: rm -rf build From 9eb4729b790478fbfad3f807f767f7d8f570c60e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 18:30:17 -0700 Subject: [PATCH 215/310] rename installzlib1.bat into installzlib.bat --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 82d138d..293940a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,7 +65,7 @@ matrix: script: - pip install cmake - - ./installzlib1.bat + - ./installzlib.bat - pip install wheel && pip wheel . -w wheelhouse - pip install $(ls wheelhouse/atari_py*) - rm -rf atari_py From 237d2ad00e8315b64df1826f3cc076501e77b612 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 19:40:07 -0700 Subject: [PATCH 216/310] forego test steps --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 293940a..cf85c8c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -67,8 +67,8 @@ matrix: - pip install cmake - ./installzlib.bat - pip install wheel && pip wheel . -w wheelhouse - - pip install $(ls wheelhouse/atari_py*) - - rm -rf atari_py - - pip install pytest - - pytest --pyargs atari_py.tests + # - pip install $(ls wheelhouse/atari_py*) + # - rm -rf atari_py + # - pip install pytest + # - pytest --pyargs atari_py.tests From 8f1ef0c2358ba011614d8d905f1d3e9a42601957 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 19:54:02 -0700 Subject: [PATCH 217/310] only upload atari_py files --- deploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy.sh b/deploy.sh index 443b0d5..9f78e5f 100755 --- a/deploy.sh +++ b/deploy.sh @@ -1,7 +1,7 @@ set -ex if [[ ! -z "$TRAVIS_TAG" ]]; then pip install twine - twine upload wheelhouse/* + twine upload wheelhouse/atari_py* if [[ ! -z "$DEPLOY_SDIST" ]]; then python setup.py sdist From 8c8d69cbd719953d6bd83f9d3d96420f86773349 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Fri, 17 May 2019 23:01:18 -0700 Subject: [PATCH 218/310] try encrypted password --- .travis.yml | 103 +++++++++++++++++----------------------------------- 1 file changed, 34 insertions(+), 69 deletions(-) diff --git a/.travis.yml b/.travis.yml index cf85c8c..dfb9cd4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,74 +1,39 @@ language: sh env: global: - - REPO_DIR=. - - BUILD_COMMIT=$TRAVIS_COMMIT - - PLAT=x86_64 - -install: - - git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout 254ad28 && cd .. - - . multibuild/common_utils.sh - - . multibuild/travis_steps.sh - - before_install - - build_wheel $REPO_DIR $PLAT -script: - - install_run $PLAT - -after_success: - - ./deploy.sh - - + - REPO_DIR=. + - BUILD_COMMIT=$TRAVIS_COMMIT + - PLAT=x86_64 +install: +- git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout + 254ad28 && cd .. +- ". multibuild/common_utils.sh" +- ". multibuild/travis_steps.sh" +- before_install +- build_wheel $REPO_DIR $PLAT +script: +- install_run $PLAT matrix: include: - -# - os: linux -# env: -# - MB_PYTHON_VERSION=3.5 -# -# - os: linux -# env: -# - MB_PYTHON_VERSION=3.6 -# -# - os: linux -# env: -# - MB_PYTHON_VERSION=3.7 -# -# -# - os: osx -# osx_image: xcode8.3 -# env: -# - MB_PYTHON_VERSION=3.5 -# - DEPLOY_SDIST=true -# -# - os: osx -# osx_image: xcode8.3 -# env: -# - MB_PYTHON_VERSION=3.6 -# -# - os: osx -# osx_image: xcode8.3 -# env: -# - MB_PYTHON_VERSION=3.7 - - - os: windows - env: - - MB_PYTHON_VERSION=3.6 - - install: - - choco install --yes python3 - - choco install --yes make - - export PATH=/c/Python37:/c/Python37/Scripts:$PATH - - echo $PATH - - which python - - which pip - - pip install virtualenv - - script: - - pip install cmake - - ./installzlib.bat - - pip install wheel && pip wheel . -w wheelhouse - # - pip install $(ls wheelhouse/atari_py*) - # - rm -rf atari_py - # - pip install pytest - # - pytest --pyargs atari_py.tests - + - os: windows + env: + - MB_PYTHON_VERSION=3.6 + install: + - choco install --yes python3 + - choco install --yes make + - export PATH=/c/Python37:/c/Python37/Scripts:$PATH + - echo $PATH + - which python + - which pip + - pip install virtualenv + script: + - pip install cmake + - "./installzlib.bat" +deploy: + provider: pypi + user: peterz-openai + distributions: bdist_wheel + on: + branch: bc-ssl + password: + secure: ceMj3TRPd2oChl3nh+CW7+hSwN2LzfuV9Lxw4dnTFJlbdx7HUH1m/meEslS0tUqhdW7WdqE+uwRqmMZaAIDB0R4qzoTORhPeHahg3RK7OK/XJnafAObG9bsfNiz4MZ4MWXq5/t5vg9LvQEZcWLXgUxYcNAJlmRAZXDK21JMUdX/P4pESJC/BJW2xWvS5w82PMNHlA7nUJ5aRqL2PMaaEnLN9uovBxo89yhGDahoKP1NkekEWzJP0Z4zQQ9gVO3ncNXa3+1roLruJ64DZ8bIuyutFaIlr57XzK8Lr1R54q/U2iJVxrYOU2Q/TNuXuB2dKqly5tAAxY1ASbLf/k3/pJ+23DozAvlWuY1Ux6vhxx55R9Ma2u4wBFvEMCV+Ys2kVm9O6waoSJEUptQ0FQOrep/umTanSK85iAJgCyGYybsRczWpm+i3M7fLrEWWxWudOQwhQEMbYKv4en/uBad5ovyMgqnr+RO/ZQAdIa6iJ9vupLmRtkoIcTcW1F29yTmFmQ2K9kdKFsuQnr4+0mt3rXqn3HDdIz30S6AfhslY22fymXjbB3FiCQu6f6SWq3v3oaEkJcnEe9UNTRQ2ybClAobwHolhUEzDrh1NdNQ2KKRgxrdRLZwsVw7Fpz/r5l2NnlfCvQIdUPYqEXjSb1vVLsRI9EK50qXjBtORUIBwRkw8= From 98c2257e1f1b43db2d9f48b28e462bad805fc002 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Sun, 19 May 2019 11:55:08 -0700 Subject: [PATCH 219/310] fix the branch name --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index dfb9cd4..2fc398d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,6 @@ deploy: user: peterz-openai distributions: bdist_wheel on: - branch: bc-ssl + branch: windows_build password: secure: ceMj3TRPd2oChl3nh+CW7+hSwN2LzfuV9Lxw4dnTFJlbdx7HUH1m/meEslS0tUqhdW7WdqE+uwRqmMZaAIDB0R4qzoTORhPeHahg3RK7OK/XJnafAObG9bsfNiz4MZ4MWXq5/t5vg9LvQEZcWLXgUxYcNAJlmRAZXDK21JMUdX/P4pESJC/BJW2xWvS5w82PMNHlA7nUJ5aRqL2PMaaEnLN9uovBxo89yhGDahoKP1NkekEWzJP0Z4zQQ9gVO3ncNXa3+1roLruJ64DZ8bIuyutFaIlr57XzK8Lr1R54q/U2iJVxrYOU2Q/TNuXuB2dKqly5tAAxY1ASbLf/k3/pJ+23DozAvlWuY1Ux6vhxx55R9Ma2u4wBFvEMCV+Ys2kVm9O6waoSJEUptQ0FQOrep/umTanSK85iAJgCyGYybsRczWpm+i3M7fLrEWWxWudOQwhQEMbYKv4en/uBad5ovyMgqnr+RO/ZQAdIa6iJ9vupLmRtkoIcTcW1F29yTmFmQ2K9kdKFsuQnr4+0mt3rXqn3HDdIz30S6AfhslY22fymXjbB3FiCQu6f6SWq3v3oaEkJcnEe9UNTRQ2ybClAobwHolhUEzDrh1NdNQ2KKRgxrdRLZwsVw7Fpz/r5l2NnlfCvQIdUPYqEXjSb1vVLsRI9EK50qXjBtORUIBwRkw8= From e0bb9a169ffee8357b31a651b3092e289ea83070 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 20 May 2019 09:55:11 -0700 Subject: [PATCH 220/310] try encrypted env vars? --- .travis.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2fc398d..2ad7b83 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ env: - REPO_DIR=. - BUILD_COMMIT=$TRAVIS_COMMIT - PLAT=x86_64 + - secure: LGDR4d3yLKwhvfN/9SOe8sMJ6Z3mms9a2G8LPvIMhXAFoY/1ULuEn+m8a4K0hcz8/nXdbMIj6qHb3LgmJ77UVVIwU4CoYe9XyjavdrCIWr4oOKZGcckhzjNjRzsdfMNha6dZShyACECdAa5CPsWBd7mxwt5fdICvrpDFcUGgUMT7GdY4voyQinf5ta7yDAAnKDM4dCH8y4Hrhz7VB0eNPkJCPpihaIy6tygcwduojJiqji4AYsDp8QPnijJpCxuKCqkPxfEE4nsXjZHnxjNJv7oWS2kq15XfVPlRbEzK5VoNZVn6dIkrHQ6U4wL8k7pg6FDySHkIwkM93wEAqH1YrHbo0YA1Cw0P3jjdTbhpFMbznGXJ8YnoykpzX3N1vIt47dlpI19y1om3aR+JC7pg3s8LvMYDMc978cFBXsfwxGdPpVV8xCriXqHDZXYYp03R/EF3T8mKPL5sP8ytDvvSEMi+/LSL29ijK28iZ4yYJnVtC97FoVjRR+ygLgt9f3PfW0BwsgaCHf7igAvRVFZBeUss4Z+pm4B704A3gMh5F1uYH1pn20jBUMF7M5xESxszdKtdzA/gXz23SIJO7RWUo7ZEF/pQ0++C7mu4yh+eYP1T2Pp1OeJADGRmPAQArzpQdS0BV1tQn+bQOkLZqbHcWObB3EmjU4Ohxnif5bWpDZY= install: - git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout 254ad28 && cd .. @@ -13,6 +14,8 @@ install: - build_wheel $REPO_DIR $PLAT script: - install_run $PLAT +after_success: +- ./deploy.sh matrix: include: - os: windows @@ -29,11 +32,11 @@ matrix: script: - pip install cmake - "./installzlib.bat" -deploy: - provider: pypi - user: peterz-openai - distributions: bdist_wheel - on: - branch: windows_build - password: - secure: ceMj3TRPd2oChl3nh+CW7+hSwN2LzfuV9Lxw4dnTFJlbdx7HUH1m/meEslS0tUqhdW7WdqE+uwRqmMZaAIDB0R4qzoTORhPeHahg3RK7OK/XJnafAObG9bsfNiz4MZ4MWXq5/t5vg9LvQEZcWLXgUxYcNAJlmRAZXDK21JMUdX/P4pESJC/BJW2xWvS5w82PMNHlA7nUJ5aRqL2PMaaEnLN9uovBxo89yhGDahoKP1NkekEWzJP0Z4zQQ9gVO3ncNXa3+1roLruJ64DZ8bIuyutFaIlr57XzK8Lr1R54q/U2iJVxrYOU2Q/TNuXuB2dKqly5tAAxY1ASbLf/k3/pJ+23DozAvlWuY1Ux6vhxx55R9Ma2u4wBFvEMCV+Ys2kVm9O6waoSJEUptQ0FQOrep/umTanSK85iAJgCyGYybsRczWpm+i3M7fLrEWWxWudOQwhQEMbYKv4en/uBad5ovyMgqnr+RO/ZQAdIa6iJ9vupLmRtkoIcTcW1F29yTmFmQ2K9kdKFsuQnr4+0mt3rXqn3HDdIz30S6AfhslY22fymXjbB3FiCQu6f6SWq3v3oaEkJcnEe9UNTRQ2ybClAobwHolhUEzDrh1NdNQ2KKRgxrdRLZwsVw7Fpz/r5l2NnlfCvQIdUPYqEXjSb1vVLsRI9EK50qXjBtORUIBwRkw8= + deploy: +# provider: pypi +# user: peterz-openai +# distributions: bdist_wheel +# on: +# branch: windows_build +# password: +# secure: ceMj3TRPd2oChl3nh+CW7+hSwN2LzfuV9Lxw4dnTFJlbdx7HUH1m/meEslS0tUqhdW7WdqE+uwRqmMZaAIDB0R4qzoTORhPeHahg3RK7OK/XJnafAObG9bsfNiz4MZ4MWXq5/t5vg9LvQEZcWLXgUxYcNAJlmRAZXDK21JMUdX/P4pESJC/BJW2xWvS5w82PMNHlA7nUJ5aRqL2PMaaEnLN9uovBxo89yhGDahoKP1NkekEWzJP0Z4zQQ9gVO3ncNXa3+1roLruJ64DZ8bIuyutFaIlr57XzK8Lr1R54q/U2iJVxrYOU2Q/TNuXuB2dKqly5tAAxY1ASbLf/k3/pJ+23DozAvlWuY1Ux6vhxx55R9Ma2u4wBFvEMCV+Ys2kVm9O6waoSJEUptQ0FQOrep/umTanSK85iAJgCyGYybsRczWpm+i3M7fLrEWWxWudOQwhQEMbYKv4en/uBad5ovyMgqnr+RO/ZQAdIa6iJ9vupLmRtkoIcTcW1F29yTmFmQ2K9kdKFsuQnr4+0mt3rXqn3HDdIz30S6AfhslY22fymXjbB3FiCQu6f6SWq3v3oaEkJcnEe9UNTRQ2ybClAobwHolhUEzDrh1NdNQ2KKRgxrdRLZwsVw7Fpz/r5l2NnlfCvQIdUPYqEXjSb1vVLsRI9EK50qXjBtORUIBwRkw8= From 48449c721861b30081bc8625801f7a12ce9edd4b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 20 May 2019 11:44:54 -0700 Subject: [PATCH 221/310] dummy commit to trigger build --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 2ad7b83..d030625 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,3 +40,4 @@ matrix: # branch: windows_build # password: # secure: ceMj3TRPd2oChl3nh+CW7+hSwN2LzfuV9Lxw4dnTFJlbdx7HUH1m/meEslS0tUqhdW7WdqE+uwRqmMZaAIDB0R4qzoTORhPeHahg3RK7OK/XJnafAObG9bsfNiz4MZ4MWXq5/t5vg9LvQEZcWLXgUxYcNAJlmRAZXDK21JMUdX/P4pESJC/BJW2xWvS5w82PMNHlA7nUJ5aRqL2PMaaEnLN9uovBxo89yhGDahoKP1NkekEWzJP0Z4zQQ9gVO3ncNXa3+1roLruJ64DZ8bIuyutFaIlr57XzK8Lr1R54q/U2iJVxrYOU2Q/TNuXuB2dKqly5tAAxY1ASbLf/k3/pJ+23DozAvlWuY1Ux6vhxx55R9Ma2u4wBFvEMCV+Ys2kVm9O6waoSJEUptQ0FQOrep/umTanSK85iAJgCyGYybsRczWpm+i3M7fLrEWWxWudOQwhQEMbYKv4en/uBad5ovyMgqnr+RO/ZQAdIa6iJ9vupLmRtkoIcTcW1F29yTmFmQ2K9kdKFsuQnr4+0mt3rXqn3HDdIz30S6AfhslY22fymXjbB3FiCQu6f6SWq3v3oaEkJcnEe9UNTRQ2ybClAobwHolhUEzDrh1NdNQ2KKRgxrdRLZwsVw7Fpz/r5l2NnlfCvQIdUPYqEXjSb1vVLsRI9EK50qXjBtORUIBwRkw8= + From 5d77cb4aa6c0b42ca8bf359db1a6b7cb11fa33b0 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Mon, 20 May 2019 11:45:36 -0700 Subject: [PATCH 222/310] comment out secure var --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d030625..0bf19dc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ env: - REPO_DIR=. - BUILD_COMMIT=$TRAVIS_COMMIT - PLAT=x86_64 - - secure: LGDR4d3yLKwhvfN/9SOe8sMJ6Z3mms9a2G8LPvIMhXAFoY/1ULuEn+m8a4K0hcz8/nXdbMIj6qHb3LgmJ77UVVIwU4CoYe9XyjavdrCIWr4oOKZGcckhzjNjRzsdfMNha6dZShyACECdAa5CPsWBd7mxwt5fdICvrpDFcUGgUMT7GdY4voyQinf5ta7yDAAnKDM4dCH8y4Hrhz7VB0eNPkJCPpihaIy6tygcwduojJiqji4AYsDp8QPnijJpCxuKCqkPxfEE4nsXjZHnxjNJv7oWS2kq15XfVPlRbEzK5VoNZVn6dIkrHQ6U4wL8k7pg6FDySHkIwkM93wEAqH1YrHbo0YA1Cw0P3jjdTbhpFMbznGXJ8YnoykpzX3N1vIt47dlpI19y1om3aR+JC7pg3s8LvMYDMc978cFBXsfwxGdPpVV8xCriXqHDZXYYp03R/EF3T8mKPL5sP8ytDvvSEMi+/LSL29ijK28iZ4yYJnVtC97FoVjRR+ygLgt9f3PfW0BwsgaCHf7igAvRVFZBeUss4Z+pm4B704A3gMh5F1uYH1pn20jBUMF7M5xESxszdKtdzA/gXz23SIJO7RWUo7ZEF/pQ0++C7mu4yh+eYP1T2Pp1OeJADGRmPAQArzpQdS0BV1tQn+bQOkLZqbHcWObB3EmjU4Ohxnif5bWpDZY= + # - secure: LGDR4d3yLKwhvfN/9SOe8sMJ6Z3mms9a2G8LPvIMhXAFoY/1ULuEn+m8a4K0hcz8/nXdbMIj6qHb3LgmJ77UVVIwU4CoYe9XyjavdrCIWr4oOKZGcckhzjNjRzsdfMNha6dZShyACECdAa5CPsWBd7mxwt5fdICvrpDFcUGgUMT7GdY4voyQinf5ta7yDAAnKDM4dCH8y4Hrhz7VB0eNPkJCPpihaIy6tygcwduojJiqji4AYsDp8QPnijJpCxuKCqkPxfEE4nsXjZHnxjNJv7oWS2kq15XfVPlRbEzK5VoNZVn6dIkrHQ6U4wL8k7pg6FDySHkIwkM93wEAqH1YrHbo0YA1Cw0P3jjdTbhpFMbznGXJ8YnoykpzX3N1vIt47dlpI19y1om3aR+JC7pg3s8LvMYDMc978cFBXsfwxGdPpVV8xCriXqHDZXYYp03R/EF3T8mKPL5sP8ytDvvSEMi+/LSL29ijK28iZ4yYJnVtC97FoVjRR+ygLgt9f3PfW0BwsgaCHf7igAvRVFZBeUss4Z+pm4B704A3gMh5F1uYH1pn20jBUMF7M5xESxszdKtdzA/gXz23SIJO7RWUo7ZEF/pQ0++C7mu4yh+eYP1T2Pp1OeJADGRmPAQArzpQdS0BV1tQn+bQOkLZqbHcWObB3EmjU4Ohxnif5bWpDZY= install: - git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout 254ad28 && cd .. From 2df0ff8f6f7dd09730697940576d98c60ae28d6f Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 21 May 2019 13:07:26 -0700 Subject: [PATCH 223/310] dummy commit to trigger build --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0bf19dc..4edfcba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,4 +40,3 @@ matrix: # branch: windows_build # password: # secure: ceMj3TRPd2oChl3nh+CW7+hSwN2LzfuV9Lxw4dnTFJlbdx7HUH1m/meEslS0tUqhdW7WdqE+uwRqmMZaAIDB0R4qzoTORhPeHahg3RK7OK/XJnafAObG9bsfNiz4MZ4MWXq5/t5vg9LvQEZcWLXgUxYcNAJlmRAZXDK21JMUdX/P4pESJC/BJW2xWvS5w82PMNHlA7nUJ5aRqL2PMaaEnLN9uovBxo89yhGDahoKP1NkekEWzJP0Z4zQQ9gVO3ncNXa3+1roLruJ64DZ8bIuyutFaIlr57XzK8Lr1R54q/U2iJVxrYOU2Q/TNuXuB2dKqly5tAAxY1ASbLf/k3/pJ+23DozAvlWuY1Ux6vhxx55R9Ma2u4wBFvEMCV+Ys2kVm9O6waoSJEUptQ0FQOrep/umTanSK85iAJgCyGYybsRczWpm+i3M7fLrEWWxWudOQwhQEMbYKv4en/uBad5ovyMgqnr+RO/ZQAdIa6iJ9vupLmRtkoIcTcW1F29yTmFmQ2K9kdKFsuQnr4+0mt3rXqn3HDdIz30S6AfhslY22fymXjbB3FiCQu6f6SWq3v3oaEkJcnEe9UNTRQ2ybClAobwHolhUEzDrh1NdNQ2KKRgxrdRLZwsVw7Fpz/r5l2NnlfCvQIdUPYqEXjSb1vVLsRI9EK50qXjBtORUIBwRkw8= - From 4b93a2791c6e2fe82832e14b37a94aba0ea31a80 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 21 May 2019 13:11:02 -0700 Subject: [PATCH 224/310] fix .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4edfcba..20f4ef2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,7 +32,7 @@ matrix: script: - pip install cmake - "./installzlib.bat" - deploy: +# deploy: # provider: pypi # user: peterz-openai # distributions: bdist_wheel From 371da8da717b3441d7be86433617990d7bc6d5da Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 21 May 2019 14:31:02 -0700 Subject: [PATCH 225/310] verbose upload to debug --- deploy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy.sh b/deploy.sh index 9f78e5f..207012b 100755 --- a/deploy.sh +++ b/deploy.sh @@ -1,11 +1,11 @@ set -ex if [[ ! -z "$TRAVIS_TAG" ]]; then pip install twine - twine upload wheelhouse/atari_py* + twine upload --verbose wheelhouse/atari_py* if [[ ! -z "$DEPLOY_SDIST" ]]; then python setup.py sdist - twine upload dist/* + twine upload dist/* fi fi From 0a196ca53ab61118432150999f3cdcd82ac72b49 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 21 May 2019 15:23:21 -0700 Subject: [PATCH 226/310] uncommend secret env variable --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 20f4ef2..66a1d53 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ env: - REPO_DIR=. - BUILD_COMMIT=$TRAVIS_COMMIT - PLAT=x86_64 - # - secure: LGDR4d3yLKwhvfN/9SOe8sMJ6Z3mms9a2G8LPvIMhXAFoY/1ULuEn+m8a4K0hcz8/nXdbMIj6qHb3LgmJ77UVVIwU4CoYe9XyjavdrCIWr4oOKZGcckhzjNjRzsdfMNha6dZShyACECdAa5CPsWBd7mxwt5fdICvrpDFcUGgUMT7GdY4voyQinf5ta7yDAAnKDM4dCH8y4Hrhz7VB0eNPkJCPpihaIy6tygcwduojJiqji4AYsDp8QPnijJpCxuKCqkPxfEE4nsXjZHnxjNJv7oWS2kq15XfVPlRbEzK5VoNZVn6dIkrHQ6U4wL8k7pg6FDySHkIwkM93wEAqH1YrHbo0YA1Cw0P3jjdTbhpFMbznGXJ8YnoykpzX3N1vIt47dlpI19y1om3aR+JC7pg3s8LvMYDMc978cFBXsfwxGdPpVV8xCriXqHDZXYYp03R/EF3T8mKPL5sP8ytDvvSEMi+/LSL29ijK28iZ4yYJnVtC97FoVjRR+ygLgt9f3PfW0BwsgaCHf7igAvRVFZBeUss4Z+pm4B704A3gMh5F1uYH1pn20jBUMF7M5xESxszdKtdzA/gXz23SIJO7RWUo7ZEF/pQ0++C7mu4yh+eYP1T2Pp1OeJADGRmPAQArzpQdS0BV1tQn+bQOkLZqbHcWObB3EmjU4Ohxnif5bWpDZY= + - secure: LGDR4d3yLKwhvfN/9SOe8sMJ6Z3mms9a2G8LPvIMhXAFoY/1ULuEn+m8a4K0hcz8/nXdbMIj6qHb3LgmJ77UVVIwU4CoYe9XyjavdrCIWr4oOKZGcckhzjNjRzsdfMNha6dZShyACECdAa5CPsWBd7mxwt5fdICvrpDFcUGgUMT7GdY4voyQinf5ta7yDAAnKDM4dCH8y4Hrhz7VB0eNPkJCPpihaIy6tygcwduojJiqji4AYsDp8QPnijJpCxuKCqkPxfEE4nsXjZHnxjNJv7oWS2kq15XfVPlRbEzK5VoNZVn6dIkrHQ6U4wL8k7pg6FDySHkIwkM93wEAqH1YrHbo0YA1Cw0P3jjdTbhpFMbznGXJ8YnoykpzX3N1vIt47dlpI19y1om3aR+JC7pg3s8LvMYDMc978cFBXsfwxGdPpVV8xCriXqHDZXYYp03R/EF3T8mKPL5sP8ytDvvSEMi+/LSL29ijK28iZ4yYJnVtC97FoVjRR+ygLgt9f3PfW0BwsgaCHf7igAvRVFZBeUss4Z+pm4B704A3gMh5F1uYH1pn20jBUMF7M5xESxszdKtdzA/gXz23SIJO7RWUo7ZEF/pQ0++C7mu4yh+eYP1T2Pp1OeJADGRmPAQArzpQdS0BV1tQn+bQOkLZqbHcWObB3EmjU4Ohxnif5bWpDZY= install: - git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout 254ad28 && cd .. From 4ee7d28b37b343a8039164a519bca8650492dc1b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 21 May 2019 15:28:44 -0700 Subject: [PATCH 227/310] try travis deploy again --- .travis.yml | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 66a1d53..3c9e597 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ env: - REPO_DIR=. - BUILD_COMMIT=$TRAVIS_COMMIT - PLAT=x86_64 - - secure: LGDR4d3yLKwhvfN/9SOe8sMJ6Z3mms9a2G8LPvIMhXAFoY/1ULuEn+m8a4K0hcz8/nXdbMIj6qHb3LgmJ77UVVIwU4CoYe9XyjavdrCIWr4oOKZGcckhzjNjRzsdfMNha6dZShyACECdAa5CPsWBd7mxwt5fdICvrpDFcUGgUMT7GdY4voyQinf5ta7yDAAnKDM4dCH8y4Hrhz7VB0eNPkJCPpihaIy6tygcwduojJiqji4AYsDp8QPnijJpCxuKCqkPxfEE4nsXjZHnxjNJv7oWS2kq15XfVPlRbEzK5VoNZVn6dIkrHQ6U4wL8k7pg6FDySHkIwkM93wEAqH1YrHbo0YA1Cw0P3jjdTbhpFMbznGXJ8YnoykpzX3N1vIt47dlpI19y1om3aR+JC7pg3s8LvMYDMc978cFBXsfwxGdPpVV8xCriXqHDZXYYp03R/EF3T8mKPL5sP8ytDvvSEMi+/LSL29ijK28iZ4yYJnVtC97FoVjRR+ygLgt9f3PfW0BwsgaCHf7igAvRVFZBeUss4Z+pm4B704A3gMh5F1uYH1pn20jBUMF7M5xESxszdKtdzA/gXz23SIJO7RWUo7ZEF/pQ0++C7mu4yh+eYP1T2Pp1OeJADGRmPAQArzpQdS0BV1tQn+bQOkLZqbHcWObB3EmjU4Ohxnif5bWpDZY= + # - secure: LGDR4d3yLKwhvfN/9SOe8sMJ6Z3mms9a2G8LPvIMhXAFoY/1ULuEn+m8a4K0hcz8/nXdbMIj6qHb3LgmJ77UVVIwU4CoYe9XyjavdrCIWr4oOKZGcckhzjNjRzsdfMNha6dZShyACECdAa5CPsWBd7mxwt5fdICvrpDFcUGgUMT7GdY4voyQinf5ta7yDAAnKDM4dCH8y4Hrhz7VB0eNPkJCPpihaIy6tygcwduojJiqji4AYsDp8QPnijJpCxuKCqkPxfEE4nsXjZHnxjNJv7oWS2kq15XfVPlRbEzK5VoNZVn6dIkrHQ6U4wL8k7pg6FDySHkIwkM93wEAqH1YrHbo0YA1Cw0P3jjdTbhpFMbznGXJ8YnoykpzX3N1vIt47dlpI19y1om3aR+JC7pg3s8LvMYDMc978cFBXsfwxGdPpVV8xCriXqHDZXYYp03R/EF3T8mKPL5sP8ytDvvSEMi+/LSL29ijK28iZ4yYJnVtC97FoVjRR+ygLgt9f3PfW0BwsgaCHf7igAvRVFZBeUss4Z+pm4B704A3gMh5F1uYH1pn20jBUMF7M5xESxszdKtdzA/gXz23SIJO7RWUo7ZEF/pQ0++C7mu4yh+eYP1T2Pp1OeJADGRmPAQArzpQdS0BV1tQn+bQOkLZqbHcWObB3EmjU4Ohxnif5bWpDZY= install: - git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout 254ad28 && cd .. @@ -32,11 +32,12 @@ matrix: script: - pip install cmake - "./installzlib.bat" -# deploy: -# provider: pypi -# user: peterz-openai -# distributions: bdist_wheel -# on: -# branch: windows_build -# password: -# secure: ceMj3TRPd2oChl3nh+CW7+hSwN2LzfuV9Lxw4dnTFJlbdx7HUH1m/meEslS0tUqhdW7WdqE+uwRqmMZaAIDB0R4qzoTORhPeHahg3RK7OK/XJnafAObG9bsfNiz4MZ4MWXq5/t5vg9LvQEZcWLXgUxYcNAJlmRAZXDK21JMUdX/P4pESJC/BJW2xWvS5w82PMNHlA7nUJ5aRqL2PMaaEnLN9uovBxo89yhGDahoKP1NkekEWzJP0Z4zQQ9gVO3ncNXa3+1roLruJ64DZ8bIuyutFaIlr57XzK8Lr1R54q/U2iJVxrYOU2Q/TNuXuB2dKqly5tAAxY1ASbLf/k3/pJ+23DozAvlWuY1Ux6vhxx55R9Ma2u4wBFvEMCV+Ys2kVm9O6waoSJEUptQ0FQOrep/umTanSK85iAJgCyGYybsRczWpm+i3M7fLrEWWxWudOQwhQEMbYKv4en/uBad5ovyMgqnr+RO/ZQAdIa6iJ9vupLmRtkoIcTcW1F29yTmFmQ2K9kdKFsuQnr4+0mt3rXqn3HDdIz30S6AfhslY22fymXjbB3FiCQu6f6SWq3v3oaEkJcnEe9UNTRQ2ybClAobwHolhUEzDrh1NdNQ2KKRgxrdRLZwsVw7Fpz/r5l2NnlfCvQIdUPYqEXjSb1vVLsRI9EK50qXjBtORUIBwRkw8= + deploy: + provider: pypi + user: peterz-openai + distributions: bdist_wheel + skip_cleanup: true + on: + branch: windows_build + password: + secure: ceMj3TRPd2oChl3nh+CW7+hSwN2LzfuV9Lxw4dnTFJlbdx7HUH1m/meEslS0tUqhdW7WdqE+uwRqmMZaAIDB0R4qzoTORhPeHahg3RK7OK/XJnafAObG9bsfNiz4MZ4MWXq5/t5vg9LvQEZcWLXgUxYcNAJlmRAZXDK21JMUdX/P4pESJC/BJW2xWvS5w82PMNHlA7nUJ5aRqL2PMaaEnLN9uovBxo89yhGDahoKP1NkekEWzJP0Z4zQQ9gVO3ncNXa3+1roLruJ64DZ8bIuyutFaIlr57XzK8Lr1R54q/U2iJVxrYOU2Q/TNuXuB2dKqly5tAAxY1ASbLf/k3/pJ+23DozAvlWuY1Ux6vhxx55R9Ma2u4wBFvEMCV+Ys2kVm9O6waoSJEUptQ0FQOrep/umTanSK85iAJgCyGYybsRczWpm+i3M7fLrEWWxWudOQwhQEMbYKv4en/uBad5ovyMgqnr+RO/ZQAdIa6iJ9vupLmRtkoIcTcW1F29yTmFmQ2K9kdKFsuQnr4+0mt3rXqn3HDdIz30S6AfhslY22fymXjbB3FiCQu6f6SWq3v3oaEkJcnEe9UNTRQ2ybClAobwHolhUEzDrh1NdNQ2KKRgxrdRLZwsVw7Fpz/r5l2NnlfCvQIdUPYqEXjSb1vVLsRI9EK50qXjBtORUIBwRkw8= From 54b79df61f5e261809bbdf5c80939a0cd4820f0d Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Tue, 21 May 2019 15:35:33 -0700 Subject: [PATCH 228/310] fix deploy section in .travis.yml --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3c9e597..644dde2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,8 +14,8 @@ install: - build_wheel $REPO_DIR $PLAT script: - install_run $PLAT -after_success: -- ./deploy.sh +# after_success: +# - ./deploy.sh matrix: include: - os: windows @@ -32,7 +32,8 @@ matrix: script: - pip install cmake - "./installzlib.bat" - deploy: + +deploy: provider: pypi user: peterz-openai distributions: bdist_wheel From 98295be28768e34e94551225a2ec0f799dc07c7a Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 11:06:08 -0700 Subject: [PATCH 229/310] deploy to s3? --- .travis.yml | 25 +++++++++++++------------ deploy.sh | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 644dde2..0852dfb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,6 @@ env: - REPO_DIR=. - BUILD_COMMIT=$TRAVIS_COMMIT - PLAT=x86_64 - # - secure: LGDR4d3yLKwhvfN/9SOe8sMJ6Z3mms9a2G8LPvIMhXAFoY/1ULuEn+m8a4K0hcz8/nXdbMIj6qHb3LgmJ77UVVIwU4CoYe9XyjavdrCIWr4oOKZGcckhzjNjRzsdfMNha6dZShyACECdAa5CPsWBd7mxwt5fdICvrpDFcUGgUMT7GdY4voyQinf5ta7yDAAnKDM4dCH8y4Hrhz7VB0eNPkJCPpihaIy6tygcwduojJiqji4AYsDp8QPnijJpCxuKCqkPxfEE4nsXjZHnxjNJv7oWS2kq15XfVPlRbEzK5VoNZVn6dIkrHQ6U4wL8k7pg6FDySHkIwkM93wEAqH1YrHbo0YA1Cw0P3jjdTbhpFMbznGXJ8YnoykpzX3N1vIt47dlpI19y1om3aR+JC7pg3s8LvMYDMc978cFBXsfwxGdPpVV8xCriXqHDZXYYp03R/EF3T8mKPL5sP8ytDvvSEMi+/LSL29ijK28iZ4yYJnVtC97FoVjRR+ygLgt9f3PfW0BwsgaCHf7igAvRVFZBeUss4Z+pm4B704A3gMh5F1uYH1pn20jBUMF7M5xESxszdKtdzA/gXz23SIJO7RWUo7ZEF/pQ0++C7mu4yh+eYP1T2Pp1OeJADGRmPAQArzpQdS0BV1tQn+bQOkLZqbHcWObB3EmjU4Ohxnif5bWpDZY= install: - git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout 254ad28 && cd .. @@ -14,8 +13,6 @@ install: - build_wheel $REPO_DIR $PLAT script: - install_run $PLAT -# after_success: -# - ./deploy.sh matrix: include: - os: windows @@ -32,13 +29,17 @@ matrix: script: - pip install cmake - "./installzlib.bat" - + - pip wheel --no-deps -w wheelhouse . + deploy: - provider: pypi - user: peterz-openai - distributions: bdist_wheel - skip_cleanup: true - on: - branch: windows_build - password: - secure: ceMj3TRPd2oChl3nh+CW7+hSwN2LzfuV9Lxw4dnTFJlbdx7HUH1m/meEslS0tUqhdW7WdqE+uwRqmMZaAIDB0R4qzoTORhPeHahg3RK7OK/XJnafAObG9bsfNiz4MZ4MWXq5/t5vg9LvQEZcWLXgUxYcNAJlmRAZXDK21JMUdX/P4pESJC/BJW2xWvS5w82PMNHlA7nUJ5aRqL2PMaaEnLN9uovBxo89yhGDahoKP1NkekEWzJP0Z4zQQ9gVO3ncNXa3+1roLruJ64DZ8bIuyutFaIlr57XzK8Lr1R54q/U2iJVxrYOU2Q/TNuXuB2dKqly5tAAxY1ASbLf/k3/pJ+23DozAvlWuY1Ux6vhxx55R9Ma2u4wBFvEMCV+Ys2kVm9O6waoSJEUptQ0FQOrep/umTanSK85iAJgCyGYybsRczWpm+i3M7fLrEWWxWudOQwhQEMbYKv4en/uBad5ovyMgqnr+RO/ZQAdIa6iJ9vupLmRtkoIcTcW1F29yTmFmQ2K9kdKFsuQnr4+0mt3rXqn3HDdIz30S6AfhslY22fymXjbB3FiCQu6f6SWq3v3oaEkJcnEe9UNTRQ2ybClAobwHolhUEzDrh1NdNQ2KKRgxrdRLZwsVw7Fpz/r5l2NnlfCvQIdUPYqEXjSb1vVLsRI9EK50qXjBtORUIBwRkw8= + provider: s3 + access_key_id: AKIAIR7X3BP26ZWUNFPA + secret_access_key: + secure: wUNE0AxIZ3rQVO6pUXQyfOVI4UN/4bgTb+y8566pFYQ68mzZEW3XNl96n8HtkHGYuJGnNGWGbGKcp2a1MCoiyePR+NnmoUxCledUffU+s88Sxg9Qj7DW8JOLImocNXG+8y2OeC+QjmrkB109inM0c2T+ESeLZi9yALaLSxVEKToXB1EBDtOohjelNcA8xoP9yb4H6yoT01XLNkno2o9fmKc+ZXtLi9xZVpMX1aH0Hs2pchm0WmE7d93XVD0K9ZM/2q1yT8ojJngKAbpJeJQSSSJStNpFBIp7hc+2slFP9/QOCPJQZQuIjJkHj2iXEMgIrerbFgl/n5konQiZFHwDZbmubQR8cfVOmr/+By8n9h13rzL7OpqCx84f4QuaRifRY6vMnu0nqbo7M7vkW0fEzcMOEpn1fcL0ulOOFc9Oedyvn08flK2M3DX10rglncK+MkGdWjH23K/1PLNOCIdNO8kWO+yvuCbdx1oJzMcpr5w52Sh+pWt4xXk1TQvXtzPVxLxf+mGumHvU1wSFW2IbBcLIv3C/BeqeNbyRNIrXT2rfaOzDj8LEXOq3IIdfgKmHx2a4Iz3V3S2a5vJiXeBtr9G4LtH/k9eRRyr6CKN+HqSZSRnwL0W8i3u7QvcP6wSF91lJCpAJpsuu5faE3RKfW/hUd/gsmo1f1tcJZEaCkzo= + bucket: games-wheels + local-dir: wheelhouse + upload-dir: atari-py + acl: public_read + on: + repo: openai/atari-py + branch: windows_build diff --git a/deploy.sh b/deploy.sh index 207012b..d03b182 100755 --- a/deploy.sh +++ b/deploy.sh @@ -1,7 +1,7 @@ set -ex if [[ ! -z "$TRAVIS_TAG" ]]; then pip install twine - twine upload --verbose wheelhouse/atari_py* + twine upload --verbose wheelhouse/atari_py* if [[ ! -z "$DEPLOY_SDIST" ]]; then python setup.py sdist From d04ac91e5e8baa7aed0c2f5a760d16b7d57712e6 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 11:16:36 -0700 Subject: [PATCH 230/310] massaging travis.yml --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0852dfb..c8bebb6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,12 @@ matrix: script: - pip install cmake - "./installzlib.bat" - - pip wheel --no-deps -w wheelhouse . + - pip install wheel && pip wheel . -w wheelhouse --no-deps + - ls wheelhouse/atari_py* + - pip install $(ls wheelhouse/atari_py*) + - rm -rf atari_py + # - pip install pytest + # - pytest --pyargs atari_py.tests deploy: provider: s3 From 48f19684bb1d0747c3be4925cc1e6587b83c129b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 12:01:13 -0700 Subject: [PATCH 231/310] skip cleanup? --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index c8bebb6..70373a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,6 +39,7 @@ matrix: deploy: provider: s3 access_key_id: AKIAIR7X3BP26ZWUNFPA + skip_cleanup: true secret_access_key: secure: wUNE0AxIZ3rQVO6pUXQyfOVI4UN/4bgTb+y8566pFYQ68mzZEW3XNl96n8HtkHGYuJGnNGWGbGKcp2a1MCoiyePR+NnmoUxCledUffU+s88Sxg9Qj7DW8JOLImocNXG+8y2OeC+QjmrkB109inM0c2T+ESeLZi9yALaLSxVEKToXB1EBDtOohjelNcA8xoP9yb4H6yoT01XLNkno2o9fmKc+ZXtLi9xZVpMX1aH0Hs2pchm0WmE7d93XVD0K9ZM/2q1yT8ojJngKAbpJeJQSSSJStNpFBIp7hc+2slFP9/QOCPJQZQuIjJkHj2iXEMgIrerbFgl/n5konQiZFHwDZbmubQR8cfVOmr/+By8n9h13rzL7OpqCx84f4QuaRifRY6vMnu0nqbo7M7vkW0fEzcMOEpn1fcL0ulOOFc9Oedyvn08flK2M3DX10rglncK+MkGdWjH23K/1PLNOCIdNO8kWO+yvuCbdx1oJzMcpr5w52Sh+pWt4xXk1TQvXtzPVxLxf+mGumHvU1wSFW2IbBcLIv3C/BeqeNbyRNIrXT2rfaOzDj8LEXOq3IIdfgKmHx2a4Iz3V3S2a5vJiXeBtr9G4LtH/k9eRRyr6CKN+HqSZSRnwL0W8i3u7QvcP6wSF91lJCpAJpsuu5faE3RKfW/hUd/gsmo1f1tcJZEaCkzo= bucket: games-wheels From 808ae48bbe7defe18daa50ca09e726f519406311 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 12:24:58 -0700 Subject: [PATCH 232/310] debugging build --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 70373a2..e33f71b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,7 @@ matrix: script: - pip install cmake - "./installzlib.bat" + - make - pip install wheel && pip wheel . -w wheelhouse --no-deps - ls wheelhouse/atari_py* - pip install $(ls wheelhouse/atari_py*) From fd2b71ebb8406d6766a004b6934abfa200414d27 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 12:28:24 -0700 Subject: [PATCH 233/310] trying the fix --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index e33f71b..23d29fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,10 +32,10 @@ matrix: - make - pip install wheel && pip wheel . -w wheelhouse --no-deps - ls wheelhouse/atari_py* - - pip install $(ls wheelhouse/atari_py*) - rm -rf atari_py - # - pip install pytest - # - pytest --pyargs atari_py.tests + - pip install $(ls wheelhouse/atari_py*) + - pip install pytest + - pytest --pyargs atari_py.tests deploy: provider: s3 From 6a94537bc74483e116bf24cbc8b1f09a494e0fa0 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 12:38:30 -0700 Subject: [PATCH 234/310] stuff --- .travis.yml | 1 + atari_py/ale_interface/Makefile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 23d29fd..f1c0f87 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,6 +30,7 @@ matrix: - pip install cmake - "./installzlib.bat" - make + - make clean - pip install wheel && pip wheel . -w wheelhouse --no-deps - ls wheelhouse/atari_py* - rm -rf atari_py diff --git a/atari_py/ale_interface/Makefile b/atari_py/ale_interface/Makefile index df4d363..b8846c4 100644 --- a/atari_py/ale_interface/Makefile +++ b/atari_py/ale_interface/Makefile @@ -1,7 +1,7 @@ .PHONY: build clean build: - mkdir -p build && cd build && cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. && cmake --build . && cp Debug/ale_c.dll . + mkdir -p build && cd build && cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. && cmake --build .. && cp Debug/ale_c.dll . clean: rm -rf build From 0be2d3d1d507547bbd146871b0db157baeff37ee Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 12:46:04 -0700 Subject: [PATCH 235/310] restore build --- atari_py/ale_interface/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atari_py/ale_interface/Makefile b/atari_py/ale_interface/Makefile index b8846c4..df4d363 100644 --- a/atari_py/ale_interface/Makefile +++ b/atari_py/ale_interface/Makefile @@ -1,7 +1,7 @@ .PHONY: build clean build: - mkdir -p build && cd build && cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. && cmake --build .. && cp Debug/ale_c.dll . + mkdir -p build && cd build && cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. && cmake --build . && cp Debug/ale_c.dll . clean: rm -rf build From 09a531645224c795c126364d34acbdb7eb21677a Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 13:14:16 -0700 Subject: [PATCH 236/310] debugging --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f1c0f87..29b39f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,11 +29,13 @@ matrix: script: - pip install cmake - "./installzlib.bat" - - make - - make clean + # - make + # - make clean - pip install wheel && pip wheel . -w wheelhouse --no-deps - ls wheelhouse/atari_py* - rm -rf atari_py + - unzip $(ls wheelhouse/atari_py*) + - rm -rf atari_py* - pip install $(ls wheelhouse/atari_py*) - pip install pytest - pytest --pyargs atari_py.tests From e5b844ba0bafa1e6b0906f193350d80e85aba71a Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 13:59:10 -0700 Subject: [PATCH 237/310] try no globs in package data --- atari_py/package_data.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atari_py/package_data.txt b/atari_py/package_data.txt index cefe327..421d046 100644 --- a/atari_py/package_data.txt +++ b/atari_py/package_data.txt @@ -1,5 +1,5 @@ ale_interface/build/*.so -ale_interface/build/*.dll +ale_interface/build/ale_c.dll ale_interface/build/ale ale_c_wrapper.cpp ale_c_wrapper.h From 755d24c862673a8c74d416ed5a4ae5bba3cfa443 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 14:21:41 -0700 Subject: [PATCH 238/310] extra verbosity to pip wheel --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 29b39f6..b8c9fdb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,7 +31,7 @@ matrix: - "./installzlib.bat" # - make # - make clean - - pip install wheel && pip wheel . -w wheelhouse --no-deps + - pip install wheel && pip wheel . -w wheelhouse --no-deps -vvv - ls wheelhouse/atari_py* - rm -rf atari_py - unzip $(ls wheelhouse/atari_py*) From 76e6a0fbd36f29ddf25273466e36352895f9002e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 14:41:17 -0700 Subject: [PATCH 239/310] fixing build --- atari_py/ale_interface/Makefile | 2 +- atari_py/package_data.txt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/atari_py/ale_interface/Makefile b/atari_py/ale_interface/Makefile index df4d363..d3f2322 100644 --- a/atari_py/ale_interface/Makefile +++ b/atari_py/ale_interface/Makefile @@ -1,7 +1,7 @@ .PHONY: build clean build: - mkdir -p build && cd build && cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. && cmake --build . && cp Debug/ale_c.dll . + mkdir -p build && cd build && cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. && cmake --build . && cp Debug/ale_c.dll .. && ls -lt .. clean: rm -rf build diff --git a/atari_py/package_data.txt b/atari_py/package_data.txt index 421d046..d52b19d 100644 --- a/atari_py/package_data.txt +++ b/atari_py/package_data.txt @@ -1,5 +1,6 @@ -ale_interface/build/*.so +ale_interface/build/libale_c.so ale_interface/build/ale_c.dll +ale_interface/ale_c.dll ale_interface/build/ale ale_c_wrapper.cpp ale_c_wrapper.h From d62df19fafb6222286e3cbe197915e34ad7bacda Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 14:49:38 -0700 Subject: [PATCH 240/310] set include_package_data=True in setup.py --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 9712be1..b0f386d 100644 --- a/setup.py +++ b/setup.py @@ -37,6 +37,7 @@ def __init__(self, name, sourcedir=''): license='', packages=['atari_py'], package_data={'atari_py': package_data}, + include_package_data: True, ext_modules=[CMakeExtension('atari_py')], cmdclass={'build_ext': Build}, install_requires=['numpy', 'six'], From 9c9c87a977d71b3df515d5d0c197454a337a15b2 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 14:57:07 -0700 Subject: [PATCH 241/310] typo --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b0f386d..070c579 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ def __init__(self, name, sourcedir=''): license='', packages=['atari_py'], package_data={'atari_py': package_data}, - include_package_data: True, + include_package_data=True, ext_modules=[CMakeExtension('atari_py')], cmdclass={'build_ext': Build}, install_requires=['numpy', 'six'], From 0aa813dd0dd69ba7e054a26fa040f2ce423747e0 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 15:12:16 -0700 Subject: [PATCH 242/310] stuff --- atari_py/ale_interface/ale_c.dll | 1 + atari_py/package_data.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 atari_py/ale_interface/ale_c.dll diff --git a/atari_py/ale_interface/ale_c.dll b/atari_py/ale_interface/ale_c.dll new file mode 100644 index 0000000..9ce06a8 --- /dev/null +++ b/atari_py/ale_interface/ale_c.dll @@ -0,0 +1 @@ +# dummy diff --git a/atari_py/package_data.txt b/atari_py/package_data.txt index d52b19d..acdb431 100644 --- a/atari_py/package_data.txt +++ b/atari_py/package_data.txt @@ -1,9 +1,9 @@ ale_interface/build/libale_c.so ale_interface/build/ale_c.dll -ale_interface/ale_c.dll ale_interface/build/ale ale_c_wrapper.cpp ale_c_wrapper.h +ale_interface/ale_c.dll ale_interface/CMakeLists.txt ale_interface/Makefile ale_interface/src/ale_interface.cpp From 7d35857a625e74197844fd3c34cef44446c57fd7 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 15:23:01 -0700 Subject: [PATCH 243/310] getting closer to the problem... --- atari_py/ale_python_interface.py | 2 +- atari_py/package_data.txt | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index 01fe094..8740d46 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -15,7 +15,7 @@ 'ale_interface/build/libale_c.so')) else: ale_lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), - 'ale_interface/build/ale_c.dll')) + 'ale_interface/ale_c.dll')) ale_lib.ALE_new.argtypes = None ale_lib.ALE_new.restype = c_void_p diff --git a/atari_py/package_data.txt b/atari_py/package_data.txt index acdb431..37921cc 100644 --- a/atari_py/package_data.txt +++ b/atari_py/package_data.txt @@ -1,9 +1,8 @@ ale_interface/build/libale_c.so -ale_interface/build/ale_c.dll +ale_interface/ale_c.dll ale_interface/build/ale ale_c_wrapper.cpp ale_c_wrapper.h -ale_interface/ale_c.dll ale_interface/CMakeLists.txt ale_interface/Makefile ale_interface/src/ale_interface.cpp From c4dc336c359c08c9ffc8d0dd8e742107f06ab437 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 15:34:38 -0700 Subject: [PATCH 244/310] deploy to s3 for unzipping / debugging --- .travis.yml | 12 ++++++------ setup.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index b8c9fdb..1bf379d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,12 +33,12 @@ matrix: # - make clean - pip install wheel && pip wheel . -w wheelhouse --no-deps -vvv - ls wheelhouse/atari_py* - - rm -rf atari_py - - unzip $(ls wheelhouse/atari_py*) - - rm -rf atari_py* - - pip install $(ls wheelhouse/atari_py*) - - pip install pytest - - pytest --pyargs atari_py.tests + # - rm -rf atari_py + # - unzip $(ls wheelhouse/atari_py*) + # - rm -rf atari_py* + # - pip install $(ls wheelhouse/atari_py*) + # - pip install pytest + # - pytest --pyargs atari_py.tests deploy: provider: s3 diff --git a/setup.py b/setup.py index 070c579..0d5a989 100644 --- a/setup.py +++ b/setup.py @@ -29,7 +29,7 @@ def __init__(self, name, sourcedir=''): self.sourcedir = os.path.abspath(sourcedir) setup(name='atari-py', - version='0.1.7', + version='0.1.8', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From a548d45d70f2c88e4f9d53ff07119765f071c169 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 15:53:56 -0700 Subject: [PATCH 245/310] do not call make in setup.py --- .travis.yml | 13 +++++-------- setup.py | 3 ++- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1bf379d..3da3e1d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,16 +29,13 @@ matrix: script: - pip install cmake - "./installzlib.bat" - # - make - # - make clean + - make - pip install wheel && pip wheel . -w wheelhouse --no-deps -vvv - ls wheelhouse/atari_py* - # - rm -rf atari_py - # - unzip $(ls wheelhouse/atari_py*) - # - rm -rf atari_py* - # - pip install $(ls wheelhouse/atari_py*) - # - pip install pytest - # - pytest --pyargs atari_py.tests + - rm -rf atari_py* + - pip install $(ls wheelhouse/atari_py*) + - pip install pytest + - pytest --pyargs atari_py.tests deploy: provider: s3 diff --git a/setup.py b/setup.py index 0d5a989..606d06d 100644 --- a/setup.py +++ b/setup.py @@ -10,6 +10,7 @@ class Build(build_ext): def run(self): + return cores_to_use = max(1, multiprocessing.cpu_count() - 1) cmd = ['make', 'build', '-j', str(cores_to_use)] try: @@ -29,7 +30,7 @@ def __init__(self, name, sourcedir=''): self.sourcedir = os.path.abspath(sourcedir) setup(name='atari-py', - version='0.1.8', + version='0.1.9', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From d3acb9846814e8cefe3772a380005d828c8a9455 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 16:13:49 -0700 Subject: [PATCH 246/310] debugging packaging --- .travis.yml | 6 +++--- setup.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3da3e1d..6f79773 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,9 +33,9 @@ matrix: - pip install wheel && pip wheel . -w wheelhouse --no-deps -vvv - ls wheelhouse/atari_py* - rm -rf atari_py* - - pip install $(ls wheelhouse/atari_py*) - - pip install pytest - - pytest --pyargs atari_py.tests + # - pip install $(ls wheelhouse/atari_py*) + # - pip install pytest + # - pytest --pyargs atari_py.tests deploy: provider: s3 diff --git a/setup.py b/setup.py index 606d06d..1417667 100644 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ def __init__(self, name, sourcedir=''): self.sourcedir = os.path.abspath(sourcedir) setup(name='atari-py', - version='0.1.9', + version='0.1.10', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From 4e94d91a3872a5906ea456fa0e2758879e9a8a60 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 17:05:15 -0700 Subject: [PATCH 247/310] include tests into the package_data.txt --- atari_py/package_data.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/atari_py/package_data.txt b/atari_py/package_data.txt index 37921cc..fae2437 100644 --- a/atari_py/package_data.txt +++ b/atari_py/package_data.txt @@ -397,3 +397,4 @@ atari_roms/wizard_of_wor.bin atari_roms/yars_revenge.bin atari_roms/zaxxon.bin package_data.txt +tests/*.py From 23b197ce500a611f3b3f478cf6538c0773554b53 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 17:10:06 -0700 Subject: [PATCH 248/310] re-enable tests --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6f79773..3da3e1d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,9 +33,9 @@ matrix: - pip install wheel && pip wheel . -w wheelhouse --no-deps -vvv - ls wheelhouse/atari_py* - rm -rf atari_py* - # - pip install $(ls wheelhouse/atari_py*) - # - pip install pytest - # - pytest --pyargs atari_py.tests + - pip install $(ls wheelhouse/atari_py*) + - pip install pytest + - pytest --pyargs atari_py.tests deploy: provider: s3 From 9c976c7c32900955b6a2de3bb4d176e1e2358e7c Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 17:35:04 -0700 Subject: [PATCH 249/310] cleaning up --- .travis.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3da3e1d..9717066 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,19 +17,18 @@ matrix: include: - os: windows env: - - MB_PYTHON_VERSION=3.6 + # - MB_PYTHON_VERSION=3.5 + #- MB_PYTHON_VERSION=3.6 + - MB_PYTHON_VERSION=3.7 install: - - choco install --yes python3 + - choco install --yes python3 --version $MB_PYTHON_VERSION - choco install --yes make - export PATH=/c/Python37:/c/Python37/Scripts:$PATH - - echo $PATH - - which python - - which pip - - pip install virtualenv - script: - pip install cmake - "./installzlib.bat" - make + - cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/ale_c.dll + script: - pip install wheel && pip wheel . -w wheelhouse --no-deps -vvv - ls wheelhouse/atari_py* - rm -rf atari_py* From 38f12952feebf7c4e32232b60980959250b21fb7 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 17:37:31 -0700 Subject: [PATCH 250/310] more cleanups --- .travis.yml | 3 ++- atari_py/ale_interface/Makefile | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9717066..00ff8af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,8 @@ matrix: install: - choco install --yes python3 --version $MB_PYTHON_VERSION - choco install --yes make - - export PATH=/c/Python37:/c/Python37/Scripts:$PATH + - export PYROOT=/c/Python${MB_PYTHON_VRESION//./} + - export PATH=$PYROOT:$PYROOT/Scripts:$PATH - pip install cmake - "./installzlib.bat" - make diff --git a/atari_py/ale_interface/Makefile b/atari_py/ale_interface/Makefile index d3f2322..5ff7a32 100644 --- a/atari_py/ale_interface/Makefile +++ b/atari_py/ale_interface/Makefile @@ -1,7 +1,7 @@ .PHONY: build clean build: - mkdir -p build && cd build && cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. && cmake --build . && cp Debug/ale_c.dll .. && ls -lt .. + mkdir -p build && cd build && cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. && cmake --build . clean: rm -rf build From 030ffaf1a5c19b751cc585e168e4fa368d0d4485 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 17:38:04 -0700 Subject: [PATCH 251/310] deploy only on tags --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 00ff8af..fb598d5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,4 +49,4 @@ deploy: acl: public_read on: repo: openai/atari-py - branch: windows_build + tags: true From edcb4589482c56df441e009d784a80556b6a1f48 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 17:41:34 -0700 Subject: [PATCH 252/310] debugging --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index fb598d5..fad6238 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,8 +23,9 @@ matrix: install: - choco install --yes python3 --version $MB_PYTHON_VERSION - choco install --yes make - - export PYROOT=/c/Python${MB_PYTHON_VRESION//./} + - export PYROOT=/c/Python${MB_PYTHON_VERSION//./} - export PATH=$PYROOT:$PYROOT/Scripts:$PATH + - echo $PATH - pip install cmake - "./installzlib.bat" - make From 60acde7ce3816ea5b590e7adf747445a244810ab Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 17:55:07 -0700 Subject: [PATCH 253/310] multiple python version --- .travis.yml | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index fad6238..1f92b87 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,26 +17,25 @@ matrix: include: - os: windows env: - # - MB_PYTHON_VERSION=3.5 - #- MB_PYTHON_VERSION=3.6 - - MB_PYTHON_VERSION=3.7 + - MB_PYTHON_VERSION=3.5 + - MB_PYTHON_VERSION=3.6 + - MB_PYTHON_VERSION=3.7 install: - - choco install --yes python3 --version $MB_PYTHON_VERSION - - choco install --yes make - - export PYROOT=/c/Python${MB_PYTHON_VERSION//./} - - export PATH=$PYROOT:$PYROOT/Scripts:$PATH - - echo $PATH - - pip install cmake - - "./installzlib.bat" - - make - - cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/ale_c.dll + - choco install --yes python3 --version $MB_PYTHON_VERSION + - choco install --yes make + - export PYROOT=/c/Python${MB_PYTHON_VERSION//./} + - export PATH=$PYROOT:$PYROOT/Scripts:$PATH + - pip install cmake + - "./installzlib.bat" + - make + - cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/ale_c.dll script: - - pip install wheel && pip wheel . -w wheelhouse --no-deps -vvv - - ls wheelhouse/atari_py* - - rm -rf atari_py* - - pip install $(ls wheelhouse/atari_py*) - - pip install pytest - - pytest --pyargs atari_py.tests + - pip install wheel && pip wheel . -w wheelhouse --no-deps -vvv + - ls wheelhouse/atari_py* + - rm -rf atari_py* + - pip install $(ls wheelhouse/atari_py*) + - pip install pytest + - pytest --pyargs atari_py.tests deploy: provider: s3 From d2d0a1c35b16361b6506ab1a46ad427628cced76 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 18:02:20 -0700 Subject: [PATCH 254/310] move build steps into a separate script --- .travis.yml | 32 +++++++++++++------------------- win_build.sh | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 19 deletions(-) create mode 100644 win_build.sh diff --git a/.travis.yml b/.travis.yml index 1f92b87..9c53abd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,26 +17,20 @@ matrix: include: - os: windows env: - - MB_PYTHON_VERSION=3.5 - - MB_PYTHON_VERSION=3.6 - MB_PYTHON_VERSION=3.7 - install: - - choco install --yes python3 --version $MB_PYTHON_VERSION - - choco install --yes make - - export PYROOT=/c/Python${MB_PYTHON_VERSION//./} - - export PATH=$PYROOT:$PYROOT/Scripts:$PATH - - pip install cmake - - "./installzlib.bat" - - make - - cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/ale_c.dll - script: - - pip install wheel && pip wheel . -w wheelhouse --no-deps -vvv - - ls wheelhouse/atari_py* - - rm -rf atari_py* - - pip install $(ls wheelhouse/atari_py*) - - pip install pytest - - pytest --pyargs atari_py.tests - + install: "" + script: win_build.sh + # - os: windows + # env: + # - MB_PYTHON_VERSION=3.7 + # install: "" + # script: win_build.sh + # - os: windows + # env: + # - MB_PYTHON_VERSION=3.7 + # install: "" + # script: win_build.sh + deploy: provider: s3 access_key_id: AKIAIR7X3BP26ZWUNFPA diff --git a/win_build.sh b/win_build.sh new file mode 100644 index 0000000..35ff396 --- /dev/null +++ b/win_build.sh @@ -0,0 +1,15 @@ +set -ex +choco install --yes python3 --version $MB_PYTHON_VERSION +choco install --yes make +export PYROOT=/c/Python${MB_PYTHON_VERSION//./} +export PATH=$PYROOT:$PYROOT/Scripts:$PATH +pip install cmake pytest +./installzlib.bat +make +cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/ale_c.dll +pip install wheel && pip wheel . -w wheelhouse --no-deps -vvv +ls wheelhouse/atari_py* +rm -rf atari_py* +pip install $(ls wheelhouse/atari_py*) +pytest --pyargs atari_py.tests + From 3b10c2b3d052968a4946fd385ff3cc0ccffc67c2 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 18:04:29 -0700 Subject: [PATCH 255/310] proper script call --- .travis.yml | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9c53abd..bdacbdb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,21 +15,33 @@ script: - install_run $PLAT matrix: include: +# - os: linux +# env: +# - MB_PYTHON_VERSION=3.5 +# +# - os: linux +# env: +# - MB_PYTHON_VERSION=3.6 +# - os: linux +# env: +# - MB_PYTHON_VERSION=3.7 +# +# - os: windows +# env: +# - MB_PYTHON_VERSION=3.7 +# install: "" +# script: win_build.sh +# - os: windows +# env: +# - MB_PYTHON_VERSION=3.7 +# install: "" +# script: win_build.sh - os: windows env: - MB_PYTHON_VERSION=3.7 install: "" - script: win_build.sh - # - os: windows - # env: - # - MB_PYTHON_VERSION=3.7 - # install: "" - # script: win_build.sh - # - os: windows - # env: - # - MB_PYTHON_VERSION=3.7 - # install: "" - # script: win_build.sh + script: ./win_build.sh + deploy: provider: s3 From 3e896cd7fff40e07facfd8ff9aba4e2b1c6be3e2 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 18:15:54 -0700 Subject: [PATCH 256/310] build matrix --- .travis.yml | 37 +++++++++++++++++-------------------- build.sh | 13 +++++++++++++ multibuild.sh | 14 ++++++++++++++ 3 files changed, 44 insertions(+), 20 deletions(-) create mode 100755 build.sh create mode 100644 multibuild.sh diff --git a/.travis.yml b/.travis.yml index bdacbdb..8681028 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,20 +1,17 @@ language: sh env: - global: - - REPO_DIR=. - - BUILD_COMMIT=$TRAVIS_COMMIT - - PLAT=x86_64 -install: -- git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout - 254ad28 && cd .. -- ". multibuild/common_utils.sh" -- ". multibuild/travis_steps.sh" -- before_install -- build_wheel $REPO_DIR $PLAT -script: -- install_run $PLAT -matrix: - include: +install: "" +script: ./build.sh +os: + - windows + - linux + # - osx +env: + - PY_VER=3.7 + - PY_VER=3.6 +osx_image: xcode8.3 +# matrix: +# include: # - os: linux # env: # - MB_PYTHON_VERSION=3.5 @@ -36,11 +33,11 @@ matrix: # - MB_PYTHON_VERSION=3.7 # install: "" # script: win_build.sh - - os: windows - env: - - MB_PYTHON_VERSION=3.7 - install: "" - script: ./win_build.sh +# - os: windows +# env: +# - MB_PYTHON_VERSION=3.7 +# install: "" +# script: ./win_build.sh deploy: diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..90b8ce8 --- /dev/null +++ b/build.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -ex + +if [ $(uname) == 'Linux' ]; then + ./multibuild.sh + exit 0 +fi + +if [ $(uname) == 'Darwin' ]; then + ./multibuild.sh + exit 0 +fi +./win_build.sh diff --git a/multibuild.sh b/multibuild.sh new file mode 100644 index 0000000..4ece3fc --- /dev/null +++ b/multibuild.sh @@ -0,0 +1,14 @@ +set -ex +export REPO_DIR=. +export BUILD_COMMIT=$TRAVIS_COMMIT +export PLAT=x86_64 +export MB_PYTHON_VERSION=$PY_VER + +git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout + 254ad28 && cd .. +". multibuild/common_utils.sh" +". multibuild/travis_steps.sh" +before_install +build_wheel $REPO_DIR $PLAT +install_run $PLAT + From 9743bc31923fd9daa70cae38821ecbdfe92a0ffb Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 18:17:46 -0700 Subject: [PATCH 257/310] fix env variable in py build --- win_build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/win_build.sh b/win_build.sh index 35ff396..ec3c8ce 100644 --- a/win_build.sh +++ b/win_build.sh @@ -1,7 +1,7 @@ set -ex -choco install --yes python3 --version $MB_PYTHON_VERSION +choco install --yes python3 --version $PY_VER choco install --yes make -export PYROOT=/c/Python${MB_PYTHON_VERSION//./} +export PYROOT=/c/Python${PY_VER//./} export PATH=$PYROOT:$PYROOT/Scripts:$PATH pip install cmake pytest ./installzlib.bat From be9b40e63e6580ae899fb211f50b5b4d1af3e14d Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 18:18:22 -0700 Subject: [PATCH 258/310] make multibuild.sh executable --- multibuild.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 multibuild.sh diff --git a/multibuild.sh b/multibuild.sh old mode 100644 new mode 100755 From bbd3d75e1b7eba70c7446c735432667e5a44fb73 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 18:19:28 -0700 Subject: [PATCH 259/310] enable all branches --- .travis.yml | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8681028..30f5b44 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,40 +5,12 @@ script: ./build.sh os: - windows - linux - # - osx + - osx env: - PY_VER=3.7 - PY_VER=3.6 + - PY_VER=3.5 osx_image: xcode8.3 -# matrix: -# include: -# - os: linux -# env: -# - MB_PYTHON_VERSION=3.5 -# -# - os: linux -# env: -# - MB_PYTHON_VERSION=3.6 -# - os: linux -# env: -# - MB_PYTHON_VERSION=3.7 -# -# - os: windows -# env: -# - MB_PYTHON_VERSION=3.7 -# install: "" -# script: win_build.sh -# - os: windows -# env: -# - MB_PYTHON_VERSION=3.7 -# install: "" -# script: win_build.sh -# - os: windows -# env: -# - MB_PYTHON_VERSION=3.7 -# install: "" -# script: ./win_build.sh - deploy: provider: s3 From ac0da217396bfe4bb489711ea3029f0f8d2b5d50 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 18:20:39 -0700 Subject: [PATCH 260/310] fix multiline --- multibuild.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/multibuild.sh b/multibuild.sh index 4ece3fc..1867b5f 100755 --- a/multibuild.sh +++ b/multibuild.sh @@ -4,8 +4,7 @@ export BUILD_COMMIT=$TRAVIS_COMMIT export PLAT=x86_64 export MB_PYTHON_VERSION=$PY_VER -git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout - 254ad28 && cd .. +git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout 254ad28 && cd .. ". multibuild/common_utils.sh" ". multibuild/travis_steps.sh" before_install From 9f6fa40aec9a8c24b22ac2313ecde68f2393cbeb Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 18:22:43 -0700 Subject: [PATCH 261/310] massage setup.py --- setup.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 1417667..9a2c8c8 100644 --- a/setup.py +++ b/setup.py @@ -10,12 +10,12 @@ class Build(build_ext): def run(self): - return + # return cores_to_use = max(1, multiprocessing.cpu_count() - 1) cmd = ['make', 'build', '-j', str(cores_to_use)] try: - # cwd = os.path.join(self.build_lib, 'atari_py', 'ale_interface') - cwd = os.path.join('atari_py', 'ale_interface') + cwd = os.path.join(self.build_lib, 'atari_py', 'ale_interface') + # cwd = os.path.join('atari_py', 'ale_interface') subprocess.check_call(cmd, cwd=cwd) except subprocess.CalledProcessError as e: sys.stderr.write("Could not build atari-py: %s. (HINT: are you sure cmake is installed? You might also be missing a library. Atari-py requires: zlib [installable as 'apt-get install zlib1g-dev' on Ubuntu].)\n" % e) From 4f55abccc88da4050147aedb8c85ccbe115a7ce6 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 18:39:19 -0700 Subject: [PATCH 262/310] silly patch to setup.py --- setup.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9a2c8c8..37005ce 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,9 @@ class Build(build_ext): def run(self): - # return + if os.name != 'posix': + # silly patch to disable build steps on windows, as we are building externally + return cores_to_use = max(1, multiprocessing.cpu_count() - 1) cmd = ['make', 'build', '-j', str(cores_to_use)] try: From de52688f9897c5fdaf8393f28d0e8dcccab4c895 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 21:21:36 -0700 Subject: [PATCH 263/310] exclude py35 --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 30f5b44..7166f30 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,12 +4,12 @@ install: "" script: ./build.sh os: - windows - - linux - - osx + # - linux + # - osx env: - PY_VER=3.7 - PY_VER=3.6 - - PY_VER=3.5 + # - PY_VER=3.5 osx_image: xcode8.3 deploy: From 8282d66057e1c449e1ffdb7db4a73e230d2ecdc2 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 21:23:14 -0700 Subject: [PATCH 264/310] fix multibuild.sh script --- multibuild.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/multibuild.sh b/multibuild.sh index 1867b5f..c5b50fa 100755 --- a/multibuild.sh +++ b/multibuild.sh @@ -5,8 +5,8 @@ export PLAT=x86_64 export MB_PYTHON_VERSION=$PY_VER git clone https://github.com/matthew-brett/multibuild && cd multibuild && git checkout 254ad28 && cd .. -". multibuild/common_utils.sh" -". multibuild/travis_steps.sh" +source multibuild/common_utils.sh +source multibuild/travis_steps.sh before_install build_wheel $REPO_DIR $PLAT install_run $PLAT From 4df7ea4f7ee081e896afb1cb71ec9fdd3d3a2ba4 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Wed, 22 May 2019 21:23:51 -0700 Subject: [PATCH 265/310] re-enable linux and osx builds --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7166f30..2c849a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,8 @@ install: "" script: ./build.sh os: - windows - # - linux - # - osx + - linux + - osx env: - PY_VER=3.7 - PY_VER=3.6 From d6158e943ebf2557d4208db61708297936ad820c Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 10:50:13 -0700 Subject: [PATCH 266/310] do not use make --- setup.py | 8 ++++---- win_build.sh | 8 +++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index 37005ce..c0327e1 100644 --- a/setup.py +++ b/setup.py @@ -14,11 +14,11 @@ def run(self): # silly patch to disable build steps on windows, as we are building externally return cores_to_use = max(1, multiprocessing.cpu_count() - 1) - cmd = ['make', 'build', '-j', str(cores_to_use)] try: - cwd = os.path.join(self.build_lib, 'atari_py', 'ale_interface') - # cwd = os.path.join('atari_py', 'ale_interface') - subprocess.check_call(cmd, cwd=cwd) + cwd = os.path.join(self.build_lib, 'atari_py', 'ale_interface', 'build') + os.makedirs(cwd, exist_ok=True) + subprocess.check_call(['cmake', '..'], cwd=cwd) + subprocess.check_call(['cmake', '--build', '..'], cwd=cwd) except subprocess.CalledProcessError as e: sys.stderr.write("Could not build atari-py: %s. (HINT: are you sure cmake is installed? You might also be missing a library. Atari-py requires: zlib [installable as 'apt-get install zlib1g-dev' on Ubuntu].)\n" % e) raise diff --git a/win_build.sh b/win_build.sh index ec3c8ce..108e590 100644 --- a/win_build.sh +++ b/win_build.sh @@ -5,7 +5,13 @@ export PYROOT=/c/Python${PY_VER//./} export PATH=$PYROOT:$PYROOT/Scripts:$PATH pip install cmake pytest ./installzlib.bat -make +mkdir -p atari_py/ale_interface/build + +cd atari_py/ale_interface/build +cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. +cmake --build . +cd ../../../ + cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/ale_c.dll pip install wheel && pip wheel . -w wheelhouse --no-deps -vvv ls wheelhouse/atari_py* From 32404a5df866981d24daae607276b3767fd655f7 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 10:50:49 -0700 Subject: [PATCH 267/310] do not use make, do not install make on windows --- win_build.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/win_build.sh b/win_build.sh index 108e590..ec4f1d7 100644 --- a/win_build.sh +++ b/win_build.sh @@ -1,6 +1,5 @@ set -ex choco install --yes python3 --version $PY_VER -choco install --yes make export PYROOT=/c/Python${PY_VER//./} export PATH=$PYROOT:$PYROOT/Scripts:$PATH pip install cmake pytest From 57c0a62380f00d6f43aac1bb4c33de6b652e5995 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 10:53:28 -0700 Subject: [PATCH 268/310] fix cmake --build call in setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index c0327e1..3da4131 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ def run(self): cwd = os.path.join(self.build_lib, 'atari_py', 'ale_interface', 'build') os.makedirs(cwd, exist_ok=True) subprocess.check_call(['cmake', '..'], cwd=cwd) - subprocess.check_call(['cmake', '--build', '..'], cwd=cwd) + subprocess.check_call(['cmake', '--build', '.'], cwd=cwd) except subprocess.CalledProcessError as e: sys.stderr.write("Could not build atari-py: %s. (HINT: are you sure cmake is installed? You might also be missing a library. Atari-py requires: zlib [installable as 'apt-get install zlib1g-dev' on Ubuntu].)\n" % e) raise From b73da54da4545fce3e68a5884c18c3a02d06650a Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 11:01:35 -0700 Subject: [PATCH 269/310] include python 3.5 for linux and osx --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2c849a7..bc03fd9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,12 @@ os: env: - PY_VER=3.7 - PY_VER=3.6 - # - PY_VER=3.5 + - PY_VER=3.5 osx_image: xcode8.3 +matrix: + exclude: + os: windows + env: PY_VER=3.5 deploy: provider: s3 From 1a14a2746c7a5ae814bd026cb5b7bc742adb89d2 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 11:06:27 -0700 Subject: [PATCH 270/310] fixing setup.py for posix builds --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3da4131..0c4ef87 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,8 @@ def run(self): return cores_to_use = max(1, multiprocessing.cpu_count() - 1) try: - cwd = os.path.join(self.build_lib, 'atari_py', 'ale_interface', 'build') + # cwd = os.path.join(self.build_lib, 'atari_py', 'ale_interface', 'build') + cwd = os.path.join('atari_py', 'ale_interface', 'build') os.makedirs(cwd, exist_ok=True) subprocess.check_call(['cmake', '..'], cwd=cwd) subprocess.check_call(['cmake', '--build', '.'], cwd=cwd) From 6e521075ac7f9c106d9c1b052e00053ab74b76a8 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 11:14:47 -0700 Subject: [PATCH 271/310] remove tests before building the wheel? --- config.sh | 8 +++++--- setup.py | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/config.sh b/config.sh index 97a9ecd..8d182d5 100644 --- a/config.sh +++ b/config.sh @@ -3,13 +3,15 @@ function pre_build { set -ex build_zlib pip install cmake - pip install . - pip install pytest - pytest . + # pip install . + # pip install pytest + # pytest . } function run_tests { pip install gym[atari] python -c "import gym; gym.make('Pong-v4')" + pip install pytest + pytest --pyargs atari_py.tests } diff --git a/setup.py b/setup.py index 0c4ef87..281b0d1 100644 --- a/setup.py +++ b/setup.py @@ -15,8 +15,8 @@ def run(self): return cores_to_use = max(1, multiprocessing.cpu_count() - 1) try: - # cwd = os.path.join(self.build_lib, 'atari_py', 'ale_interface', 'build') - cwd = os.path.join('atari_py', 'ale_interface', 'build') + cwd = os.path.join(self.build_lib, 'atari_py', 'ale_interface', 'build') + # cwd = os.path.join('atari_py', 'ale_interface', 'build') os.makedirs(cwd, exist_ok=True) subprocess.check_call(['cmake', '..'], cwd=cwd) subprocess.check_call(['cmake', '--build', '.'], cwd=cwd) From 35d1c1a5c8d96fcf97bb7dc15692f2c694898b09 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 11:39:47 -0700 Subject: [PATCH 272/310] cleanups --- Makefile | 17 ----------------- atari_py/ale_interface/CMakeLists.txt | 1 - atari_py/ale_interface/Makefile | 7 ------- setup.py | 3 +-- 4 files changed, 1 insertion(+), 27 deletions(-) delete mode 100644 Makefile delete mode 100644 atari_py/ale_interface/Makefile diff --git a/Makefile b/Makefile deleted file mode 100644 index 5fd410b..0000000 --- a/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -.PHONY: build clean - -build: - make -C atari_py/ale_interface build - -clean: - rm -rf dist atari_py.egg-info - make -C atari_py/ale_interface clean - -package_data: - ( echo "ale_interface/build/*.so" && echo "ale_interface/build/ale" && cd atari_py && git ls-files |grep -v \\.py$ ) > atari_py/package_data.txt - -upload: - make clean - rm -rf dist - python setup.py sdist - twine upload dist/* diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index 5486297..c50cd44 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -56,7 +56,6 @@ if(APPLE) endif() if(WIN32 OR MINGW) - # add_subdirectory(zlib-1.2.11) # include_directories(${SOURCE_DIR}/zlib) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsWin32.cxx ${SOURCE_DIR}/os_dependent/OSystemWin32.cxx ${SOURCE_DIR}/os_dependent/FSNodeWin32.cxx) diff --git a/atari_py/ale_interface/Makefile b/atari_py/ale_interface/Makefile deleted file mode 100644 index 5ff7a32..0000000 --- a/atari_py/ale_interface/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -.PHONY: build clean - -build: - mkdir -p build && cd build && cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. && cmake --build . - -clean: - rm -rf build diff --git a/setup.py b/setup.py index 082bfcd..3891a94 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,6 @@ def run(self): cores_to_use = max(1, multiprocessing.cpu_count() - 1) try: cwd = os.path.join('' if self.inplace else self.build_lib, 'atari_py', 'ale_interface', 'build') - # cwd = os.path.join('atari_py', 'ale_interface', 'build') os.makedirs(cwd, exist_ok=True) subprocess.check_call(['cmake', '..'], cwd=cwd) subprocess.check_call(['cmake', '--build', '.'], cwd=cwd) @@ -34,7 +33,7 @@ def __init__(self, name, sourcedir=''): self.sourcedir = os.path.abspath(sourcedir) setup(name='atari-py', - version='0.1.10', + version='0.1.11', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From eb6fe8f55f737a88be45495264c6e8f2eaa7dd86 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 11:40:35 -0700 Subject: [PATCH 273/310] cleanups --- atari_py/ale_interface/ale_c.dll | 1 - 1 file changed, 1 deletion(-) delete mode 100644 atari_py/ale_interface/ale_c.dll diff --git a/atari_py/ale_interface/ale_c.dll b/atari_py/ale_interface/ale_c.dll deleted file mode 100644 index 9ce06a8..0000000 --- a/atari_py/ale_interface/ale_c.dll +++ /dev/null @@ -1 +0,0 @@ -# dummy From 6a063babf72bad58d0f77bf7a3952ce1070a3a40 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 11:42:03 -0700 Subject: [PATCH 274/310] more cleanups --- atari_py/ale_python_interface.py | 2 +- atari_py/package_data.txt | 2 +- win_build.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index 8740d46..01fe094 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -15,7 +15,7 @@ 'ale_interface/build/libale_c.so')) else: ale_lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), - 'ale_interface/ale_c.dll')) + 'ale_interface/build/ale_c.dll')) ale_lib.ALE_new.argtypes = None ale_lib.ALE_new.restype = c_void_p diff --git a/atari_py/package_data.txt b/atari_py/package_data.txt index fae2437..7ef7864 100644 --- a/atari_py/package_data.txt +++ b/atari_py/package_data.txt @@ -1,5 +1,5 @@ ale_interface/build/libale_c.so -ale_interface/ale_c.dll +ale_interface/build/ale_c.dll ale_interface/build/ale ale_c_wrapper.cpp ale_c_wrapper.h diff --git a/win_build.sh b/win_build.sh index ec4f1d7..493e7bc 100644 --- a/win_build.sh +++ b/win_build.sh @@ -9,9 +9,9 @@ mkdir -p atari_py/ale_interface/build cd atari_py/ale_interface/build cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. cmake --build . +cp Debug/ale_c.dll . cd ../../../ -cp atari_py/ale_interface/build/Debug/ale_c.dll atari_py/ale_interface/ale_c.dll pip install wheel && pip wheel . -w wheelhouse --no-deps -vvv ls wheelhouse/atari_py* rm -rf atari_py* From 624be6799e79bfa8b566f1b46912923a8aca9cd4 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 11:43:59 -0700 Subject: [PATCH 275/310] nicer or switch in build.sh --- build.sh | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/build.sh b/build.sh index 90b8ce8..a16a252 100755 --- a/build.sh +++ b/build.sh @@ -1,13 +1,8 @@ #!/bin/bash set -ex -if [ $(uname) == 'Linux' ]; then +if [ $(uname) == 'Linux' ] || [ $(uname) == 'Darwin' ]; then ./multibuild.sh - exit 0 +else + ./win_build.sh fi - -if [ $(uname) == 'Darwin' ]; then - ./multibuild.sh - exit 0 -fi -./win_build.sh From c8ef408cc9e11cd800fee047638762b4ed4f75c9 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 13:51:45 -0700 Subject: [PATCH 276/310] try build stages --- .travis.yml | 62 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/.travis.yml b/.travis.yml index bc03fd9..40f716a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,30 +2,38 @@ language: sh env: install: "" script: ./build.sh -os: - - windows - - linux - - osx -env: - - PY_VER=3.7 - - PY_VER=3.6 - - PY_VER=3.5 -osx_image: xcode8.3 -matrix: - exclude: - os: windows - env: PY_VER=3.5 - -deploy: - provider: s3 - access_key_id: AKIAIR7X3BP26ZWUNFPA - skip_cleanup: true - secret_access_key: - secure: wUNE0AxIZ3rQVO6pUXQyfOVI4UN/4bgTb+y8566pFYQ68mzZEW3XNl96n8HtkHGYuJGnNGWGbGKcp2a1MCoiyePR+NnmoUxCledUffU+s88Sxg9Qj7DW8JOLImocNXG+8y2OeC+QjmrkB109inM0c2T+ESeLZi9yALaLSxVEKToXB1EBDtOohjelNcA8xoP9yb4H6yoT01XLNkno2o9fmKc+ZXtLi9xZVpMX1aH0Hs2pchm0WmE7d93XVD0K9ZM/2q1yT8ojJngKAbpJeJQSSSJStNpFBIp7hc+2slFP9/QOCPJQZQuIjJkHj2iXEMgIrerbFgl/n5konQiZFHwDZbmubQR8cfVOmr/+By8n9h13rzL7OpqCx84f4QuaRifRY6vMnu0nqbo7M7vkW0fEzcMOEpn1fcL0ulOOFc9Oedyvn08flK2M3DX10rglncK+MkGdWjH23K/1PLNOCIdNO8kWO+yvuCbdx1oJzMcpr5w52Sh+pWt4xXk1TQvXtzPVxLxf+mGumHvU1wSFW2IbBcLIv3C/BeqeNbyRNIrXT2rfaOzDj8LEXOq3IIdfgKmHx2a4Iz3V3S2a5vJiXeBtr9G4LtH/k9eRRyr6CKN+HqSZSRnwL0W8i3u7QvcP6wSF91lJCpAJpsuu5faE3RKfW/hUd/gsmo1f1tcJZEaCkzo= - bucket: games-wheels - local-dir: wheelhouse - upload-dir: atari-py - acl: public_read - on: - repo: openai/atari-py - tags: true +jobs: + include: + - stage: compile + os: + - windows + - linux + - osx + env: + - PY_VER=3.7 + - PY_VER=3.6 + - PY_VER=3.5 + osx_image: xcode8.3 + matrix: + exclude: + os: windows + env: PY_VER=3.5 + + deploy: + provider: s3 + access_key_id: AKIAIR7X3BP26ZWUNFPA + skip_cleanup: true + secret_access_key: + secure: wUNE0AxIZ3rQVO6pUXQyfOVI4UN/4bgTb+y8566pFYQ68mzZEW3XNl96n8HtkHGYuJGnNGWGbGKcp2a1MCoiyePR+NnmoUxCledUffU+s88Sxg9Qj7DW8JOLImocNXG+8y2OeC+QjmrkB109inM0c2T+ESeLZi9yALaLSxVEKToXB1EBDtOohjelNcA8xoP9yb4H6yoT01XLNkno2o9fmKc+ZXtLi9xZVpMX1aH0Hs2pchm0WmE7d93XVD0K9ZM/2q1yT8ojJngKAbpJeJQSSSJStNpFBIp7hc+2slFP9/QOCPJQZQuIjJkHj2iXEMgIrerbFgl/n5konQiZFHwDZbmubQR8cfVOmr/+By8n9h13rzL7OpqCx84f4QuaRifRY6vMnu0nqbo7M7vkW0fEzcMOEpn1fcL0ulOOFc9Oedyvn08flK2M3DX10rglncK+MkGdWjH23K/1PLNOCIdNO8kWO+yvuCbdx1oJzMcpr5w52Sh+pWt4xXk1TQvXtzPVxLxf+mGumHvU1wSFW2IbBcLIv3C/BeqeNbyRNIrXT2rfaOzDj8LEXOq3IIdfgKmHx2a4Iz3V3S2a5vJiXeBtr9G4LtH/k9eRRyr6CKN+HqSZSRnwL0W8i3u7QvcP6wSF91lJCpAJpsuu5faE3RKfW/hUd/gsmo1f1tcJZEaCkzo= + bucket: games-wheels + local-dir: wheelhouse + upload-dir: atari-py + acl: public_read + on: + repo: openai/atari-py + tags: true + - stage: deploy_to_pypi + os: ubuntu + install: "" + script: + - echo "test" From 988dd0bbdb684cd5eeaec640f6c3a2bd68eb09bc Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 13:56:26 -0700 Subject: [PATCH 277/310] reorg .travis.yml --- .travis.yml | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index 40f716a..94c9ccd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,25 +1,24 @@ language: sh env: install: "" -script: ./build.sh +os: + - windows + - linux + - osx +env: + - PY_VER=3.7 + - PY_VER=3.6 + - PY_VER=3.5 +osx_image: xcode8.3 +matrix: + exclude: + os: windows + env: PY_VER=3.5 jobs: include: - stage: compile - os: - - windows - - linux - - osx - env: - - PY_VER=3.7 - - PY_VER=3.6 - - PY_VER=3.5 - osx_image: xcode8.3 - matrix: - exclude: - os: windows - env: PY_VER=3.5 - - deploy: + script: ./build.sh + deploy: provider: s3 access_key_id: AKIAIR7X3BP26ZWUNFPA skip_cleanup: true @@ -33,7 +32,9 @@ jobs: repo: openai/atari-py tags: true - stage: deploy_to_pypi - os: ubuntu + os: linux + env: + - PY_VER=3.6 install: "" script: - echo "test" From 50a507150946da800ae88942f71924191469b4fc Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 13:59:19 -0700 Subject: [PATCH 278/310] reorg .travis.yml --- .travis.yml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index 94c9ccd..b72b356 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: sh env: install: "" +script: ./build.sh os: - windows - linux @@ -14,24 +15,23 @@ matrix: exclude: os: windows env: PY_VER=3.5 -jobs: +deploy: + provider: s3 + access_key_id: AKIAIR7X3BP26ZWUNFPA + skip_cleanup: true + secret_access_key: + secure: wUNE0AxIZ3rQVO6pUXQyfOVI4UN/4bgTb+y8566pFYQ68mzZEW3XNl96n8HtkHGYuJGnNGWGbGKcp2a1MCoiyePR+NnmoUxCledUffU+s88Sxg9Qj7DW8JOLImocNXG+8y2OeC+QjmrkB109inM0c2T+ESeLZi9yALaLSxVEKToXB1EBDtOohjelNcA8xoP9yb4H6yoT01XLNkno2o9fmKc+ZXtLi9xZVpMX1aH0Hs2pchm0WmE7d93XVD0K9ZM/2q1yT8ojJngKAbpJeJQSSSJStNpFBIp7hc+2slFP9/QOCPJQZQuIjJkHj2iXEMgIrerbFgl/n5konQiZFHwDZbmubQR8cfVOmr/+By8n9h13rzL7OpqCx84f4QuaRifRY6vMnu0nqbo7M7vkW0fEzcMOEpn1fcL0ulOOFc9Oedyvn08flK2M3DX10rglncK+MkGdWjH23K/1PLNOCIdNO8kWO+yvuCbdx1oJzMcpr5w52Sh+pWt4xXk1TQvXtzPVxLxf+mGumHvU1wSFW2IbBcLIv3C/BeqeNbyRNIrXT2rfaOzDj8LEXOq3IIdfgKmHx2a4Iz3V3S2a5vJiXeBtr9G4LtH/k9eRRyr6CKN+HqSZSRnwL0W8i3u7QvcP6wSF91lJCpAJpsuu5faE3RKfW/hUd/gsmo1f1tcJZEaCkzo= + bucket: games-wheels + local-dir: wheelhouse + upload-dir: atari-py + acl: public_read + on: + repo: openai/atari-py + tags: true + + jobs: include: - - stage: compile - script: ./build.sh - deploy: - provider: s3 - access_key_id: AKIAIR7X3BP26ZWUNFPA - skip_cleanup: true - secret_access_key: - secure: wUNE0AxIZ3rQVO6pUXQyfOVI4UN/4bgTb+y8566pFYQ68mzZEW3XNl96n8HtkHGYuJGnNGWGbGKcp2a1MCoiyePR+NnmoUxCledUffU+s88Sxg9Qj7DW8JOLImocNXG+8y2OeC+QjmrkB109inM0c2T+ESeLZi9yALaLSxVEKToXB1EBDtOohjelNcA8xoP9yb4H6yoT01XLNkno2o9fmKc+ZXtLi9xZVpMX1aH0Hs2pchm0WmE7d93XVD0K9ZM/2q1yT8ojJngKAbpJeJQSSSJStNpFBIp7hc+2slFP9/QOCPJQZQuIjJkHj2iXEMgIrerbFgl/n5konQiZFHwDZbmubQR8cfVOmr/+By8n9h13rzL7OpqCx84f4QuaRifRY6vMnu0nqbo7M7vkW0fEzcMOEpn1fcL0ulOOFc9Oedyvn08flK2M3DX10rglncK+MkGdWjH23K/1PLNOCIdNO8kWO+yvuCbdx1oJzMcpr5w52Sh+pWt4xXk1TQvXtzPVxLxf+mGumHvU1wSFW2IbBcLIv3C/BeqeNbyRNIrXT2rfaOzDj8LEXOq3IIdfgKmHx2a4Iz3V3S2a5vJiXeBtr9G4LtH/k9eRRyr6CKN+HqSZSRnwL0W8i3u7QvcP6wSF91lJCpAJpsuu5faE3RKfW/hUd/gsmo1f1tcJZEaCkzo= - bucket: games-wheels - local-dir: wheelhouse - upload-dir: atari-py - acl: public_read - on: - repo: openai/atari-py - tags: true - - stage: deploy_to_pypi + - stage: deploy_to_pypi os: linux env: - PY_VER=3.6 From 691e775ec2d755317a3004ae212047d7194c4471 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 14:01:07 -0700 Subject: [PATCH 279/310] reorg .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b72b356..6c904b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,8 +29,8 @@ deploy: repo: openai/atari-py tags: true - jobs: - include: +jobs: + include: - stage: deploy_to_pypi os: linux env: From 22340f7a49e6124100ad524d35f8f03aac66a84e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 15:00:55 -0700 Subject: [PATCH 280/310] reorg .travis.yml --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6c904b2..5292edb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,9 +32,9 @@ deploy: jobs: include: - stage: deploy_to_pypi - os: linux - env: - - PY_VER=3.6 - install: "" + # os: linux + # env: + # - PY_VER=3.6 + # install: "" script: - echo "test" From c237a1717ba0a281a72a9a6701fe836cfb9f975b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 15:36:06 -0700 Subject: [PATCH 281/310] reorg .travis.yml --- .travis.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5292edb..5e90273 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,19 +15,19 @@ matrix: exclude: os: windows env: PY_VER=3.5 -deploy: - provider: s3 - access_key_id: AKIAIR7X3BP26ZWUNFPA - skip_cleanup: true - secret_access_key: - secure: wUNE0AxIZ3rQVO6pUXQyfOVI4UN/4bgTb+y8566pFYQ68mzZEW3XNl96n8HtkHGYuJGnNGWGbGKcp2a1MCoiyePR+NnmoUxCledUffU+s88Sxg9Qj7DW8JOLImocNXG+8y2OeC+QjmrkB109inM0c2T+ESeLZi9yALaLSxVEKToXB1EBDtOohjelNcA8xoP9yb4H6yoT01XLNkno2o9fmKc+ZXtLi9xZVpMX1aH0Hs2pchm0WmE7d93XVD0K9ZM/2q1yT8ojJngKAbpJeJQSSSJStNpFBIp7hc+2slFP9/QOCPJQZQuIjJkHj2iXEMgIrerbFgl/n5konQiZFHwDZbmubQR8cfVOmr/+By8n9h13rzL7OpqCx84f4QuaRifRY6vMnu0nqbo7M7vkW0fEzcMOEpn1fcL0ulOOFc9Oedyvn08flK2M3DX10rglncK+MkGdWjH23K/1PLNOCIdNO8kWO+yvuCbdx1oJzMcpr5w52Sh+pWt4xXk1TQvXtzPVxLxf+mGumHvU1wSFW2IbBcLIv3C/BeqeNbyRNIrXT2rfaOzDj8LEXOq3IIdfgKmHx2a4Iz3V3S2a5vJiXeBtr9G4LtH/k9eRRyr6CKN+HqSZSRnwL0W8i3u7QvcP6wSF91lJCpAJpsuu5faE3RKfW/hUd/gsmo1f1tcJZEaCkzo= - bucket: games-wheels - local-dir: wheelhouse - upload-dir: atari-py - acl: public_read - on: - repo: openai/atari-py - tags: true +# deploy: +# provider: s3 +# access_key_id: AKIAIR7X3BP26ZWUNFPA +# skip_cleanup: true +# secret_access_key: +# secure: wUNE0AxIZ3rQVO6pUXQyfOVI4UN/4bgTb+y8566pFYQ68mzZEW3XNl96n8HtkHGYuJGnNGWGbGKcp2a1MCoiyePR+NnmoUxCledUffU+s88Sxg9Qj7DW8JOLImocNXG+8y2OeC+QjmrkB109inM0c2T+ESeLZi9yALaLSxVEKToXB1EBDtOohjelNcA8xoP9yb4H6yoT01XLNkno2o9fmKc+ZXtLi9xZVpMX1aH0Hs2pchm0WmE7d93XVD0K9ZM/2q1yT8ojJngKAbpJeJQSSSJStNpFBIp7hc+2slFP9/QOCPJQZQuIjJkHj2iXEMgIrerbFgl/n5konQiZFHwDZbmubQR8cfVOmr/+By8n9h13rzL7OpqCx84f4QuaRifRY6vMnu0nqbo7M7vkW0fEzcMOEpn1fcL0ulOOFc9Oedyvn08flK2M3DX10rglncK+MkGdWjH23K/1PLNOCIdNO8kWO+yvuCbdx1oJzMcpr5w52Sh+pWt4xXk1TQvXtzPVxLxf+mGumHvU1wSFW2IbBcLIv3C/BeqeNbyRNIrXT2rfaOzDj8LEXOq3IIdfgKmHx2a4Iz3V3S2a5vJiXeBtr9G4LtH/k9eRRyr6CKN+HqSZSRnwL0W8i3u7QvcP6wSF91lJCpAJpsuu5faE3RKfW/hUd/gsmo1f1tcJZEaCkzo= +# bucket: games-wheels +# local-dir: wheelhouse +# upload-dir: atari-py +# acl: public_read +# on: +# repo: openai/atari-py +# tags: true jobs: include: From cb166cfcedfe747772676a008ce0f17458b39741 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 15:39:56 -0700 Subject: [PATCH 282/310] reorg .travis.yml --- .travis.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5e90273..8f0d873 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,12 +29,12 @@ matrix: # repo: openai/atari-py # tags: true -jobs: - include: - - stage: deploy_to_pypi - # os: linux - # env: - # - PY_VER=3.6 - # install: "" - script: - - echo "test" +# jobs: +# include: +# - stage: deploy_to_pypi +# # os: linux +# # env: +# # - PY_VER=3.6 +# # install: "" +# script: +# - echo "test" From 1272d3d596784f2d248f7624aa6a4632abe1b424 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 15:41:00 -0700 Subject: [PATCH 283/310] reorg .travis.yml --- .travis.yml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8f0d873..4fbabd7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,15 @@ language: sh env: -install: "" +jobs: + include: + - stage: deploy_to_pypi + # os: linux + # env: + # - PY_VER=3.6 + # install: "" + script: + - echo "test" + script: ./build.sh os: - windows @@ -29,12 +38,4 @@ matrix: # repo: openai/atari-py # tags: true -# jobs: -# include: -# - stage: deploy_to_pypi -# # os: linux -# # env: -# # - PY_VER=3.6 -# # install: "" -# script: -# - echo "test" + From 4c268a58062d07acb85301ebf58f9f83c7ae0c65 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 15:41:47 -0700 Subject: [PATCH 284/310] reorg .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4fbabd7..ea940e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ jobs: script: - echo "test" -script: ./build.sh +# script: ./build.sh os: - windows - linux From 0e65c31cf6987b2f1bc0d274b7e172d6345d6be3 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 15:44:13 -0700 Subject: [PATCH 285/310] reorg .travis.yml --- .travis.yml | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index ea940e3..2ede8f5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,5 @@ language: sh -env: -jobs: - include: - - stage: deploy_to_pypi - # os: linux - # env: - # - PY_VER=3.6 - # install: "" - script: - - echo "test" - -# script: ./build.sh +script: ./build.sh os: - windows - linux @@ -38,4 +27,14 @@ matrix: # repo: openai/atari-py # tags: true +jobs: + include: + - stage: deploy + # os: linux + # env: + # - PY_VER=3.6 + # install: "" + script: + - echo "test" + From 0fe8518b031ad95338efaa4503944728e5d8600b Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 15:45:04 -0700 Subject: [PATCH 286/310] reorg .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2ede8f5..0581946 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ matrix: jobs: include: - - stage: deploy + - stage: "abc" # os: linux # env: # - PY_VER=3.6 From 7595d08a7f3e2bb0cc801efbf30ab23140f18a7f Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 15:47:53 -0700 Subject: [PATCH 287/310] reorg .travis.yml --- .travis.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0581946..2f2d159 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,10 +9,10 @@ env: - PY_VER=3.6 - PY_VER=3.5 osx_image: xcode8.3 -matrix: - exclude: - os: windows - env: PY_VER=3.5 +# matrix: +# exclude: +# os: windows +# env: PY_VER=3.5 # deploy: # provider: s3 # access_key_id: AKIAIR7X3BP26ZWUNFPA @@ -29,12 +29,11 @@ matrix: jobs: include: - - stage: "abc" + - stage: deploy # os: linux # env: # - PY_VER=3.6 # install: "" - script: - - echo "test" + script: echo "test" From cb9f4abdc1ad4408ef5d1cbaee452f70e628d7e7 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 15:48:35 -0700 Subject: [PATCH 288/310] reorg .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2f2d159..29b1a71 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ env: - PY_VER=3.7 - PY_VER=3.6 - PY_VER=3.5 -osx_image: xcode8.3 +# osx_image: xcode8.3 # matrix: # exclude: # os: windows From 235e06fb190c53134590629f630598f73871d71c Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 15:49:39 -0700 Subject: [PATCH 289/310] reorg .travis.yml --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 29b1a71..a4cce2a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,9 @@ language: sh script: ./build.sh -os: - - windows - - linux - - osx +os: linux +# - windows +# - linux +# - osx env: - PY_VER=3.7 - PY_VER=3.6 From fffd5dc983729acc90b54fb5c64c90537fe840f7 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 15:50:33 -0700 Subject: [PATCH 290/310] reorg .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a4cce2a..5ea00b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,6 @@ jobs: # env: # - PY_VER=3.6 # install: "" - script: echo "test" + script: echo "test" From fcce203418510217c46edcb000c33cf02cd2bad5 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 15:51:43 -0700 Subject: [PATCH 291/310] reorg .travis.yml --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5ea00b8..5b39df6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,12 @@ language: sh script: ./build.sh -os: linux -# - windows -# - linux -# - osx +os: + - linux + - windows + - osx env: - - PY_VER=3.7 - PY_VER=3.6 + - PY_VER=3.7 - PY_VER=3.5 # osx_image: xcode8.3 # matrix: From 9d469db24a10bdb9fc9e49872a560fa4e0a7df24 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 15:52:30 -0700 Subject: [PATCH 292/310] reorg .travis.yml --- .travis.yml | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5b39df6..7843eec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,32 +8,28 @@ env: - PY_VER=3.6 - PY_VER=3.7 - PY_VER=3.5 -# osx_image: xcode8.3 -# matrix: -# exclude: -# os: windows -# env: PY_VER=3.5 -# deploy: -# provider: s3 -# access_key_id: AKIAIR7X3BP26ZWUNFPA -# skip_cleanup: true -# secret_access_key: -# secure: wUNE0AxIZ3rQVO6pUXQyfOVI4UN/4bgTb+y8566pFYQ68mzZEW3XNl96n8HtkHGYuJGnNGWGbGKcp2a1MCoiyePR+NnmoUxCledUffU+s88Sxg9Qj7DW8JOLImocNXG+8y2OeC+QjmrkB109inM0c2T+ESeLZi9yALaLSxVEKToXB1EBDtOohjelNcA8xoP9yb4H6yoT01XLNkno2o9fmKc+ZXtLi9xZVpMX1aH0Hs2pchm0WmE7d93XVD0K9ZM/2q1yT8ojJngKAbpJeJQSSSJStNpFBIp7hc+2slFP9/QOCPJQZQuIjJkHj2iXEMgIrerbFgl/n5konQiZFHwDZbmubQR8cfVOmr/+By8n9h13rzL7OpqCx84f4QuaRifRY6vMnu0nqbo7M7vkW0fEzcMOEpn1fcL0ulOOFc9Oedyvn08flK2M3DX10rglncK+MkGdWjH23K/1PLNOCIdNO8kWO+yvuCbdx1oJzMcpr5w52Sh+pWt4xXk1TQvXtzPVxLxf+mGumHvU1wSFW2IbBcLIv3C/BeqeNbyRNIrXT2rfaOzDj8LEXOq3IIdfgKmHx2a4Iz3V3S2a5vJiXeBtr9G4LtH/k9eRRyr6CKN+HqSZSRnwL0W8i3u7QvcP6wSF91lJCpAJpsuu5faE3RKfW/hUd/gsmo1f1tcJZEaCkzo= -# bucket: games-wheels -# local-dir: wheelhouse -# upload-dir: atari-py -# acl: public_read -# on: -# repo: openai/atari-py -# tags: true +osx_image: xcode8.3 +matrix: + exclude: + os: windows + env: PY_VER=3.5 +deploy: + provider: s3 + access_key_id: AKIAIR7X3BP26ZWUNFPA + skip_cleanup: true + secret_access_key: + secure: wUNE0AxIZ3rQVO6pUXQyfOVI4UN/4bgTb+y8566pFYQ68mzZEW3XNl96n8HtkHGYuJGnNGWGbGKcp2a1MCoiyePR+NnmoUxCledUffU+s88Sxg9Qj7DW8JOLImocNXG+8y2OeC+QjmrkB109inM0c2T+ESeLZi9yALaLSxVEKToXB1EBDtOohjelNcA8xoP9yb4H6yoT01XLNkno2o9fmKc+ZXtLi9xZVpMX1aH0Hs2pchm0WmE7d93XVD0K9ZM/2q1yT8ojJngKAbpJeJQSSSJStNpFBIp7hc+2slFP9/QOCPJQZQuIjJkHj2iXEMgIrerbFgl/n5konQiZFHwDZbmubQR8cfVOmr/+By8n9h13rzL7OpqCx84f4QuaRifRY6vMnu0nqbo7M7vkW0fEzcMOEpn1fcL0ulOOFc9Oedyvn08flK2M3DX10rglncK+MkGdWjH23K/1PLNOCIdNO8kWO+yvuCbdx1oJzMcpr5w52Sh+pWt4xXk1TQvXtzPVxLxf+mGumHvU1wSFW2IbBcLIv3C/BeqeNbyRNIrXT2rfaOzDj8LEXOq3IIdfgKmHx2a4Iz3V3S2a5vJiXeBtr9G4LtH/k9eRRyr6CKN+HqSZSRnwL0W8i3u7QvcP6wSF91lJCpAJpsuu5faE3RKfW/hUd/gsmo1f1tcJZEaCkzo= + bucket: games-wheels + local-dir: wheelhouse + upload-dir: atari-py + acl: public_read + on: + repo: openai/atari-py + tags: true jobs: include: - - stage: deploy - # os: linux - # env: - # - PY_VER=3.6 - # install: "" + - stage: deploy_to_pypi script: echo "test" From 23ffc41827e72891fd4d50a7a027480c13780cf1 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 16:01:33 -0700 Subject: [PATCH 293/310] pull data from s3, deploy to pypi darn you travis --- .travis.yml | 11 +++++++---- deploy_to_pypi.sh | 12 ++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100755 deploy_to_pypi.sh diff --git a/.travis.yml b/.travis.yml index 7843eec..6572d32 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,10 @@ deploy: jobs: include: - - stage: deploy_to_pypi - script: echo "test" - - + - stage: "Deploy to PyPI" + script: ./deploy_to_pypi.sh + env: + - TWINE_USERNAME=peterz-openai + - AWS_ACCESS_KEY_ID=AKIAIR7X3BP26ZWUNFPA + - secure: "SyhACCi80Ejps8g7B0+Aos1VSdzocz9N5SNhqCm8+f7fDedOXi8WsbyJKViAV7+NL2e0F66clKZDARqGYxiEDnXavRle8vQ/fF4XZ/gleuh8J9mwLVtOrdURK9zmA6USpviPQarELfpOCqi1sNblK+JL9zFbKji1GwKDcL/OPSkW/3FDTfz0UZBCftLh0wtDF6BOrspYji7Xxjsrj3m/59pS1Dq4IprliPD4GB8luLipxB8d9vezxi+GBLvMnlZJnngkNEueARqrPjGNmXRhduyMezNvMyBt4jVj+zLSyrn118aUk87NByatTDlapzo1Br8BdxAEiNNOIfvwaTI2Y+CZWOkiR5qvaPoPjT7BH2F6Ji9q/sjQQiDMzQQl1F99vbTibQUH8u/fj1h8mvg3oAObRxyltGGjA+VkDdwlUrOVP3JhZ7HNNKA3n4WDFxMcKl3gJguHd2tVozYsHOEsuNmWF5RMSP+ZZDNwhGGC1A83jnctAcMHXuerzKTYg5smCqLRUWGOaGbab13Z1ish5RCTgQXF0gAAsASwiJwRliZrVKuzWuxDJkf8Ly+2WT+TBumd2ezzohPYvy5e7rEjK05kGdY+x0MeQXWIcT6go7WjgmbryXNmVl64wNQyzhOALhs+ZiW81svV1mcr0uc52LqitN8F005VRuPfOMko7g8=" + - secure: "xprU2DixxZLvQSpeCl++QSGnPEprC8RfEk3//CH3sz2Qwt/xHBX3YfK8dVRBOeKa3+ixv2hJMqAYVjAGlzAu14TfesTEOivaWtdlGgBpDWaofYz0v1OgyFnEpfSHTOyHhlpfxZX1jNabu5xt7XQ5+/CWpxLrFIpufVKZO9DNiLhbBmGPVnnrsml9/PQijCnHssiGlLDYxLQOT/1DITjG8EhmNvcj2RY/IYFVRhCV9iANW65OObbpQ08gx0rtrf+u5cy9xmNdXPEVofd3PZM1SRPCLyf//siUdglRMtAsB0fMCV+oojQEL3yjqL0hlc7qc+b5ZiFDppsQ+RMjV/gtOt7N630rdInRBHtDKsnUpLK8OshTxKeVLEbX3jjXV3Dbg8AcUoXjspFdsAX5cCw4m228iZkLTMG4kFa0zYCx26pjTzPtWmh3if2PYyMPniJ1BNRta5S50/z2Jkpo+sE6MuVXN2xyK4+IDBNV9dfsaAw58WrNg7ZDFepgAYf1egriHoNT5zlPXsWnLFB4LI/3JkbQAotH+ybL/qgMT87KYTGRY40um2Pb76eozhmaaxL4xSoSty0CspXf2gfGZoHOqlehtm8uDmvpSFJVn7Gbaz4JUaDgClxMxEQZQPbL5QGIc53pBAKTRBC1HRHSFd8lOqZjVAcX9i2boT+e8qbkKDg=" diff --git a/deploy_to_pypi.sh b/deploy_to_pypi.sh new file mode 100755 index 0000000..e4f187d --- /dev/null +++ b/deploy_to_pypi.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -ex + +if [[ -z "$TRAVIS_TAG" ]]; then + echo "Not a tagged commit, quitting" + exit 0 +fi + +pip install awscli twine +mkdir -p wheelhouse +aws s3 cp s3://games-wheels/atari-py/atari_py-${TRAVIS_TAG}-* +twine upload --verbose wheelhouse/atari_py* From cef54aced51000f983a2421c45f3c780b67f0b1d Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 16:50:24 -0700 Subject: [PATCH 294/310] use virtualenv in deployment script --- deploy_to_pypi.sh | 4 ++++ setup.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/deploy_to_pypi.sh b/deploy_to_pypi.sh index e4f187d..00ec060 100755 --- a/deploy_to_pypi.sh +++ b/deploy_to_pypi.sh @@ -6,6 +6,10 @@ if [[ -z "$TRAVIS_TAG" ]]; then exit 0 fi +pip install virtualenv --user +python -m virtualenv --python=python3 .venv +source .venv/bin/activate + pip install awscli twine mkdir -p wheelhouse aws s3 cp s3://games-wheels/atari-py/atari_py-${TRAVIS_TAG}-* diff --git a/setup.py b/setup.py index 3891a94..2f24e37 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ def __init__(self, name, sourcedir=''): self.sourcedir = os.path.abspath(sourcedir) setup(name='atari-py', - version='0.1.11', + version='0.1.12', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From 50747703fd1688c7ace253f7352d2fbd9bf2ac6e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 16:52:12 -0700 Subject: [PATCH 295/310] fake the tag; also fix the script download part --- deploy_to_pypi.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/deploy_to_pypi.sh b/deploy_to_pypi.sh index 00ec060..a0cde96 100755 --- a/deploy_to_pypi.sh +++ b/deploy_to_pypi.sh @@ -1,6 +1,8 @@ #!/bin/bash set -ex +TRAVIS_TAG=0.1.12 + if [[ -z "$TRAVIS_TAG" ]]; then echo "Not a tagged commit, quitting" exit 0 @@ -12,5 +14,5 @@ source .venv/bin/activate pip install awscli twine mkdir -p wheelhouse -aws s3 cp s3://games-wheels/atari-py/atari_py-${TRAVIS_TAG}-* +aws s3 cp s3://games-wheels/atari-py/atari_py-${TRAVIS_TAG}-* wheelhouse/ twine upload --verbose wheelhouse/atari_py* From ee232472d5d77d7afff26a7418fe131cf9f415c3 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 16:52:45 -0700 Subject: [PATCH 296/310] try linux builds only for faster iteration --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6572d32..3d4c806 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,8 @@ language: sh script: ./build.sh os: - linux - - windows - - osx + # - windows + # - osx env: - PY_VER=3.6 - PY_VER=3.7 From aefa9e8291c3c001972ff379e3fd58f85a46993f Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 16:53:28 -0700 Subject: [PATCH 297/310] restore tag to 0.1.11 --- deploy_to_pypi.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy_to_pypi.sh b/deploy_to_pypi.sh index a0cde96..0641f3c 100755 --- a/deploy_to_pypi.sh +++ b/deploy_to_pypi.sh @@ -1,7 +1,7 @@ #!/bin/bash set -ex -TRAVIS_TAG=0.1.12 +TRAVIS_TAG=0.1.11 if [[ -z "$TRAVIS_TAG" ]]; then echo "Not a tagged commit, quitting" From 1fadb219998583d0c018a4523ad7b630ad917790 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 17:05:29 -0700 Subject: [PATCH 298/310] use folders on s3 for different versions --- .travis.yml | 2 +- deploy_to_pypi.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3d4c806..bfe90af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,7 +21,7 @@ deploy: secure: wUNE0AxIZ3rQVO6pUXQyfOVI4UN/4bgTb+y8566pFYQ68mzZEW3XNl96n8HtkHGYuJGnNGWGbGKcp2a1MCoiyePR+NnmoUxCledUffU+s88Sxg9Qj7DW8JOLImocNXG+8y2OeC+QjmrkB109inM0c2T+ESeLZi9yALaLSxVEKToXB1EBDtOohjelNcA8xoP9yb4H6yoT01XLNkno2o9fmKc+ZXtLi9xZVpMX1aH0Hs2pchm0WmE7d93XVD0K9ZM/2q1yT8ojJngKAbpJeJQSSSJStNpFBIp7hc+2slFP9/QOCPJQZQuIjJkHj2iXEMgIrerbFgl/n5konQiZFHwDZbmubQR8cfVOmr/+By8n9h13rzL7OpqCx84f4QuaRifRY6vMnu0nqbo7M7vkW0fEzcMOEpn1fcL0ulOOFc9Oedyvn08flK2M3DX10rglncK+MkGdWjH23K/1PLNOCIdNO8kWO+yvuCbdx1oJzMcpr5w52Sh+pWt4xXk1TQvXtzPVxLxf+mGumHvU1wSFW2IbBcLIv3C/BeqeNbyRNIrXT2rfaOzDj8LEXOq3IIdfgKmHx2a4Iz3V3S2a5vJiXeBtr9G4LtH/k9eRRyr6CKN+HqSZSRnwL0W8i3u7QvcP6wSF91lJCpAJpsuu5faE3RKfW/hUd/gsmo1f1tcJZEaCkzo= bucket: games-wheels local-dir: wheelhouse - upload-dir: atari-py + upload-dir: atari-py/$TRAVIS_TAG acl: public_read on: repo: openai/atari-py diff --git a/deploy_to_pypi.sh b/deploy_to_pypi.sh index 0641f3c..9a516df 100755 --- a/deploy_to_pypi.sh +++ b/deploy_to_pypi.sh @@ -1,7 +1,7 @@ #!/bin/bash set -ex -TRAVIS_TAG=0.1.11 +# TRAVIS_TAG=0.1.13 if [[ -z "$TRAVIS_TAG" ]]; then echo "Not a tagged commit, quitting" @@ -14,5 +14,5 @@ source .venv/bin/activate pip install awscli twine mkdir -p wheelhouse -aws s3 cp s3://games-wheels/atari-py/atari_py-${TRAVIS_TAG}-* wheelhouse/ +aws s3 cp --recursive s3://games-wheels/atari-py/atari_py-${TRAVIS_TAG} wheelhouse/ twine upload --verbose wheelhouse/atari_py* From e333e208f5ceb15e5c993b9fa479936e12982472 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 17:05:54 -0700 Subject: [PATCH 299/310] bump version to 0.1.13 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 2f24e37..913e8c3 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ def __init__(self, name, sourcedir=''): self.sourcedir = os.path.abspath(sourcedir) setup(name='atari-py', - version='0.1.12', + version='0.1.13', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From d52f563c156f705bb5227e8bea9f458cb3856b93 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 17:07:57 -0700 Subject: [PATCH 300/310] minifixes, bump version to 0.1.14 --- deploy_to_pypi.sh | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy_to_pypi.sh b/deploy_to_pypi.sh index 9a516df..af776ed 100755 --- a/deploy_to_pypi.sh +++ b/deploy_to_pypi.sh @@ -14,5 +14,5 @@ source .venv/bin/activate pip install awscli twine mkdir -p wheelhouse -aws s3 cp --recursive s3://games-wheels/atari-py/atari_py-${TRAVIS_TAG} wheelhouse/ +aws s3 cp --recursive s3://games-wheels/atari-py/${TRAVIS_TAG} wheelhouse/ twine upload --verbose wheelhouse/atari_py* diff --git a/setup.py b/setup.py index 913e8c3..03445ce 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ def __init__(self, name, sourcedir=''): self.sourcedir = os.path.abspath(sourcedir) setup(name='atari-py', - version='0.1.13', + version='0.1.14', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI', From c530d644a28e9d577cfc4bf17a624afa5aa878ee Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 17:15:10 -0700 Subject: [PATCH 301/310] add explanations to the eclectic travis.yml --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index bfe90af..82ab83f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,9 @@ deploy: tags: true jobs: + # this extra stage is due to Travis bug that prevets deploying to pypi from windows or usage of + # secret env variables on windows. Instead of doing either, we are deploying to s3 first, and + # then using a separate stage to download files from s3 and deploy them to pypi. include: - stage: "Deploy to PyPI" script: ./deploy_to_pypi.sh From 96c143a336e710245921a3ac5712d352b751c9b9 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 17:22:14 -0700 Subject: [PATCH 302/310] fudge the tag --- .travis.yml | 10 +++++----- deploy_to_pypi.sh | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 82ab83f..7f83bd4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,13 @@ language: sh -script: ./build.sh +script: echo "hi" # ./build.sh os: - linux # - windows # - osx env: - PY_VER=3.6 - - PY_VER=3.7 - - PY_VER=3.5 + # - PY_VER=3.7 + # - PY_VER=3.5 osx_image: xcode8.3 matrix: exclude: @@ -37,5 +37,5 @@ jobs: env: - TWINE_USERNAME=peterz-openai - AWS_ACCESS_KEY_ID=AKIAIR7X3BP26ZWUNFPA - - secure: "SyhACCi80Ejps8g7B0+Aos1VSdzocz9N5SNhqCm8+f7fDedOXi8WsbyJKViAV7+NL2e0F66clKZDARqGYxiEDnXavRle8vQ/fF4XZ/gleuh8J9mwLVtOrdURK9zmA6USpviPQarELfpOCqi1sNblK+JL9zFbKji1GwKDcL/OPSkW/3FDTfz0UZBCftLh0wtDF6BOrspYji7Xxjsrj3m/59pS1Dq4IprliPD4GB8luLipxB8d9vezxi+GBLvMnlZJnngkNEueARqrPjGNmXRhduyMezNvMyBt4jVj+zLSyrn118aUk87NByatTDlapzo1Br8BdxAEiNNOIfvwaTI2Y+CZWOkiR5qvaPoPjT7BH2F6Ji9q/sjQQiDMzQQl1F99vbTibQUH8u/fj1h8mvg3oAObRxyltGGjA+VkDdwlUrOVP3JhZ7HNNKA3n4WDFxMcKl3gJguHd2tVozYsHOEsuNmWF5RMSP+ZZDNwhGGC1A83jnctAcMHXuerzKTYg5smCqLRUWGOaGbab13Z1ish5RCTgQXF0gAAsASwiJwRliZrVKuzWuxDJkf8Ly+2WT+TBumd2ezzohPYvy5e7rEjK05kGdY+x0MeQXWIcT6go7WjgmbryXNmVl64wNQyzhOALhs+ZiW81svV1mcr0uc52LqitN8F005VRuPfOMko7g8=" - - secure: "xprU2DixxZLvQSpeCl++QSGnPEprC8RfEk3//CH3sz2Qwt/xHBX3YfK8dVRBOeKa3+ixv2hJMqAYVjAGlzAu14TfesTEOivaWtdlGgBpDWaofYz0v1OgyFnEpfSHTOyHhlpfxZX1jNabu5xt7XQ5+/CWpxLrFIpufVKZO9DNiLhbBmGPVnnrsml9/PQijCnHssiGlLDYxLQOT/1DITjG8EhmNvcj2RY/IYFVRhCV9iANW65OObbpQ08gx0rtrf+u5cy9xmNdXPEVofd3PZM1SRPCLyf//siUdglRMtAsB0fMCV+oojQEL3yjqL0hlc7qc+b5ZiFDppsQ+RMjV/gtOt7N630rdInRBHtDKsnUpLK8OshTxKeVLEbX3jjXV3Dbg8AcUoXjspFdsAX5cCw4m228iZkLTMG4kFa0zYCx26pjTzPtWmh3if2PYyMPniJ1BNRta5S50/z2Jkpo+sE6MuVXN2xyK4+IDBNV9dfsaAw58WrNg7ZDFepgAYf1egriHoNT5zlPXsWnLFB4LI/3JkbQAotH+ybL/qgMT87KYTGRY40um2Pb76eozhmaaxL4xSoSty0CspXf2gfGZoHOqlehtm8uDmvpSFJVn7Gbaz4JUaDgClxMxEQZQPbL5QGIc53pBAKTRBC1HRHSFd8lOqZjVAcX9i2boT+e8qbkKDg=" + - secure: "i0qbR3wG2OvJWVBKnAVkgtNIPPxoNQz8KBn+c9RBAWZw0XDsjkUwsDZMTXzll1Do24xLb9FVti2iq7GsNvHcCzltSGOLv6UDm2ywJc4Bz/Fyho27A0kYGe6W/FwtEt+VTkx4z0+7tNOb4KVhs26OmIGdKMJwNibnU86rRtzf05Iq7xS+8Mi/9j09oC9ZXACzOFTmbQe98Gq93ROo+7wfpCVJip9QigJTSZhE7axBEtpXlZ5//T2Eo2bxbJs5f9tNiMrLRy8NMYq1B/he9HevpxlqE15+wJs9exaDClWLtsb7trFKSnmrqtUeXI3aUIQwLgQfaYJlvvmSBUtJxxyk5QHLn3+0u6TCA9ZbHaEElXSLrcexjSEp37+HXH0Z69JzTYn0pVX4IvrmuLhgg4X3z7Ys3SyIe8Tq39QubQ8TWM8bzBN5H0VYObY35BmLl68k2AF61Rq0obJS48ekguzf88DwI9UzxYm8LnlsgpyeX1iLJ6Sy9xdP3S/5onP1+bzaDZ7JNMabNmJ22ZjqPyBp+mUyBjfab9ouDS07CNAPmyQV6VWSL8EaD9QawWB0khgKoen+NNFGeivEIgCRanP9Rg7mpw7Px9elwbl2hXGco7EGdZFPV89uHWEhL2nHUmxVjaRUNlSXjDrwI6f8vlMfbHU5PskxlrG047F/is3gQ00=" + - secure: "NZRMo04bBX2X7phT29rQKDklPFVbnqMoUAhrVFjTLxvAqsQdericyalMjXsE79IA02uZEsHfS45P9YXzgHC4uCZI6694kOZfhmBtQ0FxeJ5M3Zx6IRyMhf92rk7F/DRcRBe78JIBkgTXDJCyQoEX1/RIYIz723BSzRGosOJa1xUub8MQ7Rl3TF54j9JAshBNBTpIw1tORWo3K1A8FucQNgI3N7DucWhg+C3D7cxZok5xwz7FoXHt+Xv7wFvCETaNIsmu/3EI15K9Y43XXQ2rBc46g41SDX7f1rwVNl0D8kStjyDdhdQODDdKPMe3dl6Lckz0qMTaoTUnWL91L+qBAFHsC2imWJVNGL+/4iyTRQAsq/hl7GYNcesfm7kCXNcCjSeyx3ZkOOgZ0okFKWZK51RuKjlCcKgDOMSInCW8vR2rRK699wAfePr38t5TO5E2uQ+hF52NMbzDKw9C6azX4UaWuKPio8oxseOWfLKSYZTCVirBikLM8m4LABCZyKiMlTR1SdzxQmrLAxgnWaD+QYY4SoN4fButDjONOARFKF5e3njzVQo2nHmXb1EATOmnQ4pjKcJezSccIcmYeWpPskXWSmJbWi81zwHz/AyqH6fEnAWmVj0RKjrBfyCZCtEGBikQ9KTJuVHupwNT17CyZKUxtxBpYOpFnk+mLLom3Ak=" diff --git a/deploy_to_pypi.sh b/deploy_to_pypi.sh index af776ed..70481df 100755 --- a/deploy_to_pypi.sh +++ b/deploy_to_pypi.sh @@ -1,7 +1,7 @@ #!/bin/bash set -ex -# TRAVIS_TAG=0.1.13 +TRAVIS_TAG=0.1.14 if [[ -z "$TRAVIS_TAG" ]]; then echo "Not a tagged commit, quitting" From 772c26509aacf534a9bd3b6536348cd0328524aa Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 17:29:43 -0700 Subject: [PATCH 303/310] fixing download from s3 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 7f83bd4..ef432d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,5 +37,6 @@ jobs: env: - TWINE_USERNAME=peterz-openai - AWS_ACCESS_KEY_ID=AKIAIR7X3BP26ZWUNFPA + - AWS_DEFAULT_REGION=us-west-2 - secure: "i0qbR3wG2OvJWVBKnAVkgtNIPPxoNQz8KBn+c9RBAWZw0XDsjkUwsDZMTXzll1Do24xLb9FVti2iq7GsNvHcCzltSGOLv6UDm2ywJc4Bz/Fyho27A0kYGe6W/FwtEt+VTkx4z0+7tNOb4KVhs26OmIGdKMJwNibnU86rRtzf05Iq7xS+8Mi/9j09oC9ZXACzOFTmbQe98Gq93ROo+7wfpCVJip9QigJTSZhE7axBEtpXlZ5//T2Eo2bxbJs5f9tNiMrLRy8NMYq1B/he9HevpxlqE15+wJs9exaDClWLtsb7trFKSnmrqtUeXI3aUIQwLgQfaYJlvvmSBUtJxxyk5QHLn3+0u6TCA9ZbHaEElXSLrcexjSEp37+HXH0Z69JzTYn0pVX4IvrmuLhgg4X3z7Ys3SyIe8Tq39QubQ8TWM8bzBN5H0VYObY35BmLl68k2AF61Rq0obJS48ekguzf88DwI9UzxYm8LnlsgpyeX1iLJ6Sy9xdP3S/5onP1+bzaDZ7JNMabNmJ22ZjqPyBp+mUyBjfab9ouDS07CNAPmyQV6VWSL8EaD9QawWB0khgKoen+NNFGeivEIgCRanP9Rg7mpw7Px9elwbl2hXGco7EGdZFPV89uHWEhL2nHUmxVjaRUNlSXjDrwI6f8vlMfbHU5PskxlrG047F/is3gQ00=" - secure: "NZRMo04bBX2X7phT29rQKDklPFVbnqMoUAhrVFjTLxvAqsQdericyalMjXsE79IA02uZEsHfS45P9YXzgHC4uCZI6694kOZfhmBtQ0FxeJ5M3Zx6IRyMhf92rk7F/DRcRBe78JIBkgTXDJCyQoEX1/RIYIz723BSzRGosOJa1xUub8MQ7Rl3TF54j9JAshBNBTpIw1tORWo3K1A8FucQNgI3N7DucWhg+C3D7cxZok5xwz7FoXHt+Xv7wFvCETaNIsmu/3EI15K9Y43XXQ2rBc46g41SDX7f1rwVNl0D8kStjyDdhdQODDdKPMe3dl6Lckz0qMTaoTUnWL91L+qBAFHsC2imWJVNGL+/4iyTRQAsq/hl7GYNcesfm7kCXNcCjSeyx3ZkOOgZ0okFKWZK51RuKjlCcKgDOMSInCW8vR2rRK699wAfePr38t5TO5E2uQ+hF52NMbzDKw9C6azX4UaWuKPio8oxseOWfLKSYZTCVirBikLM8m4LABCZyKiMlTR1SdzxQmrLAxgnWaD+QYY4SoN4fButDjONOARFKF5e3njzVQo2nHmXb1EATOmnQ4pjKcJezSccIcmYeWpPskXWSmJbWi81zwHz/AyqH6fEnAWmVj0RKjrBfyCZCtEGBikQ9KTJuVHupwNT17CyZKUxtxBpYOpFnk+mLLom3Ak=" From d853084cab43500ee8258329fcadaa81356e39d2 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 17:32:12 -0700 Subject: [PATCH 304/310] debugging s3 download SignatureDoesNotMatch error --- deploy_to_pypi.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy_to_pypi.sh b/deploy_to_pypi.sh index 70481df..2bfc403 100755 --- a/deploy_to_pypi.sh +++ b/deploy_to_pypi.sh @@ -14,5 +14,6 @@ source .venv/bin/activate pip install awscli twine mkdir -p wheelhouse +env aws s3 cp --recursive s3://games-wheels/atari-py/${TRAVIS_TAG} wheelhouse/ twine upload --verbose wheelhouse/atari_py* From 79bcec1e855eb399b2844e6834a5f658cc47a542 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 17:50:14 -0700 Subject: [PATCH 305/310] wheels --- deploy_to_pypi.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/deploy_to_pypi.sh b/deploy_to_pypi.sh index 2bfc403..9e71bdb 100755 --- a/deploy_to_pypi.sh +++ b/deploy_to_pypi.sh @@ -15,5 +15,17 @@ source .venv/bin/activate pip install awscli twine mkdir -p wheelhouse env -aws s3 cp --recursive s3://games-wheels/atari-py/${TRAVIS_TAG} wheelhouse/ -twine upload --verbose wheelhouse/atari_py* +# ugh something in awscli does not work on travis we'll download objects via curl +# aws s3 cp --recursive s3://games-wheels/atari-py/${TRAVIS_TAG} wheelhouse/ +SUFFIXES="-manylinux1_x86_64.whl -win_amd64.whl -macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl" +PLATFORMS="-cp35-cp35m -cp36-cp36m -cp37-cp37m" +URLPREFIX="https://s3-us-west-2.amazonaws.com/games-wheels/atari-py/${TRAVIS_TAG}" + +cd wheelhouse +for s in $SUFFIXES; do + for p in $PLATFORM; do + curl -O ${URLPREFIX}${p}${s} + done; +done + +twine upload --verbose atari_py* From c950fb3b2e5065a6629c871361bcfebac4131ac1 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 18:08:04 -0700 Subject: [PATCH 306/310] typo --- deploy_to_pypi.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy_to_pypi.sh b/deploy_to_pypi.sh index 9e71bdb..bde434f 100755 --- a/deploy_to_pypi.sh +++ b/deploy_to_pypi.sh @@ -23,7 +23,7 @@ URLPREFIX="https://s3-us-west-2.amazonaws.com/games-wheels/atari-py/${TRAVIS_TAG cd wheelhouse for s in $SUFFIXES; do - for p in $PLATFORM; do + for p in $PLATFORMS; do curl -O ${URLPREFIX}${p}${s} done; done From bc005d07dadea6a0f8358a062b8be2e8ef23c8dd Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 18:09:56 -0700 Subject: [PATCH 307/310] clean up CMakeLists.txt --- atari_py/ale_interface/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index c50cd44..dfeb319 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -56,7 +56,6 @@ if(APPLE) endif() if(WIN32 OR MINGW) - # include_directories(${SOURCE_DIR}/zlib) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsWin32.cxx ${SOURCE_DIR}/os_dependent/OSystemWin32.cxx ${SOURCE_DIR}/os_dependent/FSNodeWin32.cxx) else() From 7f6e86adabf8eaa41161d57459df2cadf72420d7 Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 18:12:19 -0700 Subject: [PATCH 308/310] more typos --- deploy_to_pypi.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy_to_pypi.sh b/deploy_to_pypi.sh index bde434f..6e59ee5 100755 --- a/deploy_to_pypi.sh +++ b/deploy_to_pypi.sh @@ -19,7 +19,7 @@ env # aws s3 cp --recursive s3://games-wheels/atari-py/${TRAVIS_TAG} wheelhouse/ SUFFIXES="-manylinux1_x86_64.whl -win_amd64.whl -macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl" PLATFORMS="-cp35-cp35m -cp36-cp36m -cp37-cp37m" -URLPREFIX="https://s3-us-west-2.amazonaws.com/games-wheels/atari-py/${TRAVIS_TAG}" +URLPREFIX="https://s3-us-west-2.amazonaws.com/games-wheels/atari-py/${TRAVIS_TAG}/atari_py-${TRAVIS_TAG}" cd wheelhouse for s in $SUFFIXES; do From e389a83e1ef56a6d45f4e48833e92c319b53c07f Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 18:16:57 -0700 Subject: [PATCH 309/310] deploy only existing files --- deploy_to_pypi.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/deploy_to_pypi.sh b/deploy_to_pypi.sh index 6e59ee5..e467a05 100755 --- a/deploy_to_pypi.sh +++ b/deploy_to_pypi.sh @@ -17,13 +17,14 @@ mkdir -p wheelhouse env # ugh something in awscli does not work on travis we'll download objects via curl # aws s3 cp --recursive s3://games-wheels/atari-py/${TRAVIS_TAG} wheelhouse/ -SUFFIXES="-manylinux1_x86_64.whl -win_amd64.whl -macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl" -PLATFORMS="-cp35-cp35m -cp36-cp36m -cp37-cp37m" +# SUFFIXES="-manylinux1_x86_64.whl -win_amd64.whl -macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl" +SUFFIXES="-manylinux1_x86_64.whl" +PY_VERS="-cp35-cp35m -cp36-cp36m -cp37-cp37m" URLPREFIX="https://s3-us-west-2.amazonaws.com/games-wheels/atari-py/${TRAVIS_TAG}/atari_py-${TRAVIS_TAG}" cd wheelhouse for s in $SUFFIXES; do - for p in $PLATFORMS; do + for p in $PY_VERS; do curl -O ${URLPREFIX}${p}${s} done; done From d8b30632e3c98783243135e61c7200ce1339e88e Mon Sep 17 00:00:00 2001 From: Peter Zhokhov Date: Thu, 23 May 2019 18:19:35 -0700 Subject: [PATCH 310/310] re-enable all stuff --- .travis.yml | 10 +++++----- deploy_to_pypi.sh | 8 ++++---- setup.py | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index ef432d4..cbed0de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,13 @@ language: sh -script: echo "hi" # ./build.sh +script: ./build.sh os: - linux - # - windows - # - osx + - windows + - osx env: - PY_VER=3.6 - # - PY_VER=3.7 - # - PY_VER=3.5 + - PY_VER=3.7 + - PY_VER=3.5 osx_image: xcode8.3 matrix: exclude: diff --git a/deploy_to_pypi.sh b/deploy_to_pypi.sh index e467a05..6545c49 100755 --- a/deploy_to_pypi.sh +++ b/deploy_to_pypi.sh @@ -1,7 +1,7 @@ #!/bin/bash set -ex -TRAVIS_TAG=0.1.14 +# TRAVIS_TAG=0.1.14 if [[ -z "$TRAVIS_TAG" ]]; then echo "Not a tagged commit, quitting" @@ -17,9 +17,9 @@ mkdir -p wheelhouse env # ugh something in awscli does not work on travis we'll download objects via curl # aws s3 cp --recursive s3://games-wheels/atari-py/${TRAVIS_TAG} wheelhouse/ -# SUFFIXES="-manylinux1_x86_64.whl -win_amd64.whl -macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl" -SUFFIXES="-manylinux1_x86_64.whl" -PY_VERS="-cp35-cp35m -cp36-cp36m -cp37-cp37m" +SUFFIXES="-manylinux1_x86_64.whl -win_amd64.whl -macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl" +# SUFFIXES="-manylinux1_x86_64.whl" +PY_VERS="-cp36-cp36m -cp37-cp37m" URLPREFIX="https://s3-us-west-2.amazonaws.com/games-wheels/atari-py/${TRAVIS_TAG}/atari_py-${TRAVIS_TAG}" cd wheelhouse diff --git a/setup.py b/setup.py index 03445ce..6e3f8ea 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ def __init__(self, name, sourcedir=''): self.sourcedir = os.path.abspath(sourcedir) setup(name='atari-py', - version='0.1.14', + version='0.1.15', description='Python bindings to Atari games', url='https://github.com/openai/atari-py', author='OpenAI',