diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..cf2bd4e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+.idea
+*__pycache__*
+MAMEToolkit/emulator/mame/roms/sfiii3n.zip
+MAMEToolkit/emulator/mame/mame
\ No newline at end of file
diff --git a/MAMEToolkit/__init__.py b/MAMEToolkit/__init__.py
new file mode 100644
index 0000000..3187fa7
--- /dev/null
+++ b/MAMEToolkit/__init__.py
@@ -0,0 +1,2 @@
+from MAMEToolkit import emulator
+from MAMEToolkit import sf_environment
\ No newline at end of file
diff --git a/src/emulator/Action.py b/MAMEToolkit/emulator/Action.py
similarity index 100%
rename from src/emulator/Action.py
rename to MAMEToolkit/emulator/Action.py
diff --git a/src/emulator/pipes/Address.py b/MAMEToolkit/emulator/Address.py
similarity index 100%
rename from src/emulator/pipes/Address.py
rename to MAMEToolkit/emulator/Address.py
diff --git a/src/emulator/Console.py b/MAMEToolkit/emulator/Console.py
similarity index 91%
rename from src/emulator/Console.py
rename to MAMEToolkit/emulator/Console.py
index a491f91..e0420bb 100755
--- a/src/emulator/Console.py
+++ b/MAMEToolkit/emulator/Console.py
@@ -1,6 +1,7 @@
import os
+from pathlib import Path
from subprocess import Popen, PIPE
-from src.emulator.StreamGobbler import StreamGobbler
+from MAMEToolkit.emulator.StreamGobbler import StreamGobbler
import queue
import logging
@@ -13,10 +14,10 @@ class Console(object):
# render is for displaying the frames to the emulator window, disabling it has little to no effect
# throttle enabled will run any game at the intended gameplay speed, disabling it will run the game as fast as the computer can handle
# debug enabled will print everything that comes out of the Lua engine console
- def __init__(self, game_id, render=True, throttle=False, debug=False):
+ def __init__(self, roms_path, game_id, render=True, throttle=False, debug=False):
self.logger = logging.getLogger("Console")
- command = "exec ./mame -rompath roms -pluginspath plugins -skip_gameinfo -sound none -console "+game_id
+ command = f"exec ./mame -rompath '{str(Path(roms_path).absolute())}' -pluginspath plugins -skip_gameinfo -sound none -console "+game_id
if not render:
command += " -video none"
if throttle:
diff --git a/src/emulator/Emulator.py b/MAMEToolkit/emulator/Emulator.py
similarity index 91%
rename from src/emulator/Emulator.py
rename to MAMEToolkit/emulator/Emulator.py
index 3568232..fca4ee2 100755
--- a/src/emulator/Emulator.py
+++ b/MAMEToolkit/emulator/Emulator.py
@@ -1,8 +1,8 @@
import atexit
import os
-from src.emulator.Console import Console
-from src.emulator.pipes.Pipe import Pipe
-from src.emulator.pipes.DataPipe import DataPipe
+from MAMEToolkit.emulator.Console import Console
+from MAMEToolkit.emulator.pipes.Pipe import Pipe
+from MAMEToolkit.emulator.pipes.DataPipe import DataPipe
# Converts a list of action Enums into the relevant Lua engine representation
@@ -11,8 +11,8 @@ def actions_to_string(actions):
return '+'.join(action_strings)
-def list_actions(game_id):
- console = Console(game_id)
+def list_actions(roms_path, game_id):
+ console = Console(roms_path, game_id)
console.writeln('iop = manager:machine():ioport()')
actions = []
ports = console.writeln("for k,v in pairs(iop.ports) do print(k) end", expect_output=True, timeout=0.5)
@@ -27,17 +27,17 @@ def list_actions(game_id):
# An interface for using the Lua engine console functionality
class Emulator(object):
- # env_id - the unique id of the emulator
+ # env_id - the unique id of the emulator, used for fifo pipes
# game_id - the game id being used
# memory_addresses - The internal memory addresses of the game which this class will return the value of at every time step
# frame_ratio - the ratio of frames that will be returned, 3 means 1 out of every 3 frames will be returned. Note that his also effects how often memory addresses are read and actions are sent
# See console for render, throttle & debug
- def __init__(self, env_id, game_id, memory_addresses, frame_ratio=3, render=True, throttle=False, debug=False):
+ def __init__(self, env_id, roms_path, game_id, memory_addresses, frame_ratio=3, render=True, throttle=False, debug=False):
self.memoryAddresses = memory_addresses
self.frameRatio = frame_ratio
# setup lua engine
- self.console = Console(game_id, render=render, throttle=throttle, debug=debug)
+ self.console = Console(roms_path, game_id, render=render, throttle=throttle, debug=debug)
atexit.register(self.close)
self.wait_for_resource_registration()
self.create_lua_variables()
diff --git a/src/emulator/StreamGobbler.py b/MAMEToolkit/emulator/StreamGobbler.py
similarity index 100%
rename from src/emulator/StreamGobbler.py
rename to MAMEToolkit/emulator/StreamGobbler.py
diff --git a/MAMEToolkit/emulator/__init__.py b/MAMEToolkit/emulator/__init__.py
new file mode 100644
index 0000000..1223f1e
--- /dev/null
+++ b/MAMEToolkit/emulator/__init__.py
@@ -0,0 +1,3 @@
+from MAMEToolkit.emulator.Action import Action
+from MAMEToolkit.emulator.Emulator import Emulator, list_actions
+from MAMEToolkit.emulator.Address import Address
\ No newline at end of file
diff --git a/src/emulator/mame/history/history.db b/MAMEToolkit/emulator/mame/history/history.db
similarity index 100%
rename from src/emulator/mame/history/history.db
rename to MAMEToolkit/emulator/mame/history/history.db
diff --git a/src/emulator/mame/plugins/README.md b/MAMEToolkit/emulator/mame/plugins/README.md
similarity index 100%
rename from src/emulator/mame/plugins/README.md
rename to MAMEToolkit/emulator/mame/plugins/README.md
diff --git a/src/emulator/mame/plugins/boot.lua b/MAMEToolkit/emulator/mame/plugins/boot.lua
similarity index 100%
rename from src/emulator/mame/plugins/boot.lua
rename to MAMEToolkit/emulator/mame/plugins/boot.lua
diff --git a/src/emulator/mame/plugins/cheat/cheat_json.lua b/MAMEToolkit/emulator/mame/plugins/cheat/cheat_json.lua
similarity index 100%
rename from src/emulator/mame/plugins/cheat/cheat_json.lua
rename to MAMEToolkit/emulator/mame/plugins/cheat/cheat_json.lua
diff --git a/src/emulator/mame/plugins/cheat/cheat_simple.lua b/MAMEToolkit/emulator/mame/plugins/cheat/cheat_simple.lua
similarity index 100%
rename from src/emulator/mame/plugins/cheat/cheat_simple.lua
rename to MAMEToolkit/emulator/mame/plugins/cheat/cheat_simple.lua
diff --git a/src/emulator/mame/plugins/cheat/cheat_xml.lua b/MAMEToolkit/emulator/mame/plugins/cheat/cheat_xml.lua
similarity index 100%
rename from src/emulator/mame/plugins/cheat/cheat_xml.lua
rename to MAMEToolkit/emulator/mame/plugins/cheat/cheat_xml.lua
diff --git a/src/emulator/mame/plugins/cheat/init.lua b/MAMEToolkit/emulator/mame/plugins/cheat/init.lua
similarity index 100%
rename from src/emulator/mame/plugins/cheat/init.lua
rename to MAMEToolkit/emulator/mame/plugins/cheat/init.lua
diff --git a/src/emulator/mame/plugins/cheat/plugin.json b/MAMEToolkit/emulator/mame/plugins/cheat/plugin.json
similarity index 100%
rename from src/emulator/mame/plugins/cheat/plugin.json
rename to MAMEToolkit/emulator/mame/plugins/cheat/plugin.json
diff --git a/src/emulator/mame/plugins/cheat/xml_to_json.lua b/MAMEToolkit/emulator/mame/plugins/cheat/xml_to_json.lua
similarity index 100%
rename from src/emulator/mame/plugins/cheat/xml_to_json.lua
rename to MAMEToolkit/emulator/mame/plugins/cheat/xml_to_json.lua
diff --git a/src/emulator/mame/plugins/cheatfind/init.lua b/MAMEToolkit/emulator/mame/plugins/cheatfind/init.lua
similarity index 100%
rename from src/emulator/mame/plugins/cheatfind/init.lua
rename to MAMEToolkit/emulator/mame/plugins/cheatfind/init.lua
diff --git a/src/emulator/mame/plugins/cheatfind/plugin.json b/MAMEToolkit/emulator/mame/plugins/cheatfind/plugin.json
similarity index 100%
rename from src/emulator/mame/plugins/cheatfind/plugin.json
rename to MAMEToolkit/emulator/mame/plugins/cheatfind/plugin.json
diff --git a/src/emulator/mame/plugins/console/init.lua b/MAMEToolkit/emulator/mame/plugins/console/init.lua
similarity index 100%
rename from src/emulator/mame/plugins/console/init.lua
rename to MAMEToolkit/emulator/mame/plugins/console/init.lua
diff --git a/src/emulator/mame/plugins/console/plugin.json b/MAMEToolkit/emulator/mame/plugins/console/plugin.json
similarity index 100%
rename from src/emulator/mame/plugins/console/plugin.json
rename to MAMEToolkit/emulator/mame/plugins/console/plugin.json
diff --git a/src/emulator/mame/plugins/data/button_char.lua b/MAMEToolkit/emulator/mame/plugins/data/button_char.lua
similarity index 100%
rename from src/emulator/mame/plugins/data/button_char.lua
rename to MAMEToolkit/emulator/mame/plugins/data/button_char.lua
diff --git a/src/emulator/mame/plugins/data/data_command.lua b/MAMEToolkit/emulator/mame/plugins/data/data_command.lua
similarity index 100%
rename from src/emulator/mame/plugins/data/data_command.lua
rename to MAMEToolkit/emulator/mame/plugins/data/data_command.lua
diff --git a/src/emulator/mame/plugins/data/data_gameinit.lua b/MAMEToolkit/emulator/mame/plugins/data/data_gameinit.lua
similarity index 100%
rename from src/emulator/mame/plugins/data/data_gameinit.lua
rename to MAMEToolkit/emulator/mame/plugins/data/data_gameinit.lua
diff --git a/src/emulator/mame/plugins/data/data_hiscore.lua b/MAMEToolkit/emulator/mame/plugins/data/data_hiscore.lua
similarity index 100%
rename from src/emulator/mame/plugins/data/data_hiscore.lua
rename to MAMEToolkit/emulator/mame/plugins/data/data_hiscore.lua
diff --git a/src/emulator/mame/plugins/data/data_history.lua b/MAMEToolkit/emulator/mame/plugins/data/data_history.lua
similarity index 100%
rename from src/emulator/mame/plugins/data/data_history.lua
rename to MAMEToolkit/emulator/mame/plugins/data/data_history.lua
diff --git a/src/emulator/mame/plugins/data/data_mameinfo.lua b/MAMEToolkit/emulator/mame/plugins/data/data_mameinfo.lua
similarity index 100%
rename from src/emulator/mame/plugins/data/data_mameinfo.lua
rename to MAMEToolkit/emulator/mame/plugins/data/data_mameinfo.lua
diff --git a/src/emulator/mame/plugins/data/data_marp.lua b/MAMEToolkit/emulator/mame/plugins/data/data_marp.lua
similarity index 100%
rename from src/emulator/mame/plugins/data/data_marp.lua
rename to MAMEToolkit/emulator/mame/plugins/data/data_marp.lua
diff --git a/src/emulator/mame/plugins/data/data_messinfo.lua b/MAMEToolkit/emulator/mame/plugins/data/data_messinfo.lua
similarity index 100%
rename from src/emulator/mame/plugins/data/data_messinfo.lua
rename to MAMEToolkit/emulator/mame/plugins/data/data_messinfo.lua
diff --git a/src/emulator/mame/plugins/data/data_story.lua b/MAMEToolkit/emulator/mame/plugins/data/data_story.lua
similarity index 100%
rename from src/emulator/mame/plugins/data/data_story.lua
rename to MAMEToolkit/emulator/mame/plugins/data/data_story.lua
diff --git a/src/emulator/mame/plugins/data/data_sysinfo.lua b/MAMEToolkit/emulator/mame/plugins/data/data_sysinfo.lua
similarity index 100%
rename from src/emulator/mame/plugins/data/data_sysinfo.lua
rename to MAMEToolkit/emulator/mame/plugins/data/data_sysinfo.lua
diff --git a/src/emulator/mame/plugins/data/database.lua b/MAMEToolkit/emulator/mame/plugins/data/database.lua
similarity index 100%
rename from src/emulator/mame/plugins/data/database.lua
rename to MAMEToolkit/emulator/mame/plugins/data/database.lua
diff --git a/src/emulator/mame/plugins/data/init.lua b/MAMEToolkit/emulator/mame/plugins/data/init.lua
similarity index 100%
rename from src/emulator/mame/plugins/data/init.lua
rename to MAMEToolkit/emulator/mame/plugins/data/init.lua
diff --git a/src/emulator/mame/plugins/data/load_dat.lua b/MAMEToolkit/emulator/mame/plugins/data/load_dat.lua
similarity index 100%
rename from src/emulator/mame/plugins/data/load_dat.lua
rename to MAMEToolkit/emulator/mame/plugins/data/load_dat.lua
diff --git a/src/emulator/mame/plugins/data/plugin.json b/MAMEToolkit/emulator/mame/plugins/data/plugin.json
similarity index 100%
rename from src/emulator/mame/plugins/data/plugin.json
rename to MAMEToolkit/emulator/mame/plugins/data/plugin.json
diff --git a/src/emulator/mame/plugins/dummy/init.lua b/MAMEToolkit/emulator/mame/plugins/dummy/init.lua
similarity index 100%
rename from src/emulator/mame/plugins/dummy/init.lua
rename to MAMEToolkit/emulator/mame/plugins/dummy/init.lua
diff --git a/src/emulator/mame/plugins/dummy/plugin.json b/MAMEToolkit/emulator/mame/plugins/dummy/plugin.json
similarity index 100%
rename from src/emulator/mame/plugins/dummy/plugin.json
rename to MAMEToolkit/emulator/mame/plugins/dummy/plugin.json
diff --git a/src/emulator/mame/plugins/gdbstub/init.lua b/MAMEToolkit/emulator/mame/plugins/gdbstub/init.lua
similarity index 100%
rename from src/emulator/mame/plugins/gdbstub/init.lua
rename to MAMEToolkit/emulator/mame/plugins/gdbstub/init.lua
diff --git a/src/emulator/mame/plugins/gdbstub/plugin.json b/MAMEToolkit/emulator/mame/plugins/gdbstub/plugin.json
similarity index 100%
rename from src/emulator/mame/plugins/gdbstub/plugin.json
rename to MAMEToolkit/emulator/mame/plugins/gdbstub/plugin.json
diff --git a/src/emulator/mame/plugins/hiscore/hiscore.dat b/MAMEToolkit/emulator/mame/plugins/hiscore/hiscore.dat
similarity index 100%
rename from src/emulator/mame/plugins/hiscore/hiscore.dat
rename to MAMEToolkit/emulator/mame/plugins/hiscore/hiscore.dat
diff --git a/src/emulator/mame/plugins/hiscore/init.lua b/MAMEToolkit/emulator/mame/plugins/hiscore/init.lua
similarity index 100%
rename from src/emulator/mame/plugins/hiscore/init.lua
rename to MAMEToolkit/emulator/mame/plugins/hiscore/init.lua
diff --git a/src/emulator/mame/plugins/hiscore/plugin.json b/MAMEToolkit/emulator/mame/plugins/hiscore/plugin.json
similarity index 100%
rename from src/emulator/mame/plugins/hiscore/plugin.json
rename to MAMEToolkit/emulator/mame/plugins/hiscore/plugin.json
diff --git a/src/emulator/mame/plugins/hiscore/sort_hiscore.lua b/MAMEToolkit/emulator/mame/plugins/hiscore/sort_hiscore.lua
similarity index 100%
rename from src/emulator/mame/plugins/hiscore/sort_hiscore.lua
rename to MAMEToolkit/emulator/mame/plugins/hiscore/sort_hiscore.lua
diff --git a/src/emulator/mame/plugins/json/LICENSE b/MAMEToolkit/emulator/mame/plugins/json/LICENSE
similarity index 100%
rename from src/emulator/mame/plugins/json/LICENSE
rename to MAMEToolkit/emulator/mame/plugins/json/LICENSE
diff --git a/src/emulator/mame/plugins/json/README.md b/MAMEToolkit/emulator/mame/plugins/json/README.md
similarity index 100%
rename from src/emulator/mame/plugins/json/README.md
rename to MAMEToolkit/emulator/mame/plugins/json/README.md
diff --git a/src/emulator/mame/plugins/json/init.lua b/MAMEToolkit/emulator/mame/plugins/json/init.lua
similarity index 100%
rename from src/emulator/mame/plugins/json/init.lua
rename to MAMEToolkit/emulator/mame/plugins/json/init.lua
diff --git a/src/emulator/mame/plugins/json/plugin.json b/MAMEToolkit/emulator/mame/plugins/json/plugin.json
similarity index 100%
rename from src/emulator/mame/plugins/json/plugin.json
rename to MAMEToolkit/emulator/mame/plugins/json/plugin.json
diff --git a/src/emulator/mame/plugins/layout/init.lua b/MAMEToolkit/emulator/mame/plugins/layout/init.lua
similarity index 100%
rename from src/emulator/mame/plugins/layout/init.lua
rename to MAMEToolkit/emulator/mame/plugins/layout/init.lua
diff --git a/src/emulator/mame/plugins/layout/plugin.json b/MAMEToolkit/emulator/mame/plugins/layout/plugin.json
similarity index 100%
rename from src/emulator/mame/plugins/layout/plugin.json
rename to MAMEToolkit/emulator/mame/plugins/layout/plugin.json
diff --git a/src/emulator/mame/plugins/portname/init.lua b/MAMEToolkit/emulator/mame/plugins/portname/init.lua
similarity index 100%
rename from src/emulator/mame/plugins/portname/init.lua
rename to MAMEToolkit/emulator/mame/plugins/portname/init.lua
diff --git a/src/emulator/mame/plugins/portname/plugin.json b/MAMEToolkit/emulator/mame/plugins/portname/plugin.json
similarity index 100%
rename from src/emulator/mame/plugins/portname/plugin.json
rename to MAMEToolkit/emulator/mame/plugins/portname/plugin.json
diff --git a/src/emulator/mame/plugins/timer/init.lua b/MAMEToolkit/emulator/mame/plugins/timer/init.lua
similarity index 100%
rename from src/emulator/mame/plugins/timer/init.lua
rename to MAMEToolkit/emulator/mame/plugins/timer/init.lua
diff --git a/src/emulator/mame/plugins/timer/plugin.json b/MAMEToolkit/emulator/mame/plugins/timer/plugin.json
similarity index 100%
rename from src/emulator/mame/plugins/timer/plugin.json
rename to MAMEToolkit/emulator/mame/plugins/timer/plugin.json
diff --git a/src/emulator/pipes/DataPipe.py b/MAMEToolkit/emulator/pipes/DataPipe.py
similarity index 96%
rename from src/emulator/pipes/DataPipe.py
rename to MAMEToolkit/emulator/pipes/DataPipe.py
index 422e890..699f49d 100755
--- a/src/emulator/pipes/DataPipe.py
+++ b/MAMEToolkit/emulator/pipes/DataPipe.py
@@ -1,5 +1,5 @@
import numpy as np
-from src.emulator.pipes.Pipe import Pipe
+from MAMEToolkit.emulator.pipes.Pipe import Pipe
# A special implementation of a Linux FIFO pipe which is used for reading all of the frame data and memory address values from the emulator
diff --git a/src/emulator/pipes/Pipe.py b/MAMEToolkit/emulator/pipes/Pipe.py
similarity index 92%
rename from src/emulator/pipes/Pipe.py
rename to MAMEToolkit/emulator/pipes/Pipe.py
index da63c98..45130cb 100755
--- a/src/emulator/pipes/Pipe.py
+++ b/MAMEToolkit/emulator/pipes/Pipe.py
@@ -1,5 +1,5 @@
import os
-from src.emulator.StreamGobbler import StreamGobbler
+from MAMEToolkit.emulator.StreamGobbler import StreamGobbler
from pathlib import Path
from queue import Queue
from threading import Thread
@@ -25,11 +25,13 @@ class Pipe(object):
def __init__(self, env_id, pipe_id, mode, pipes_path):
self.pipeId = pipe_id + "Pipe"
self.mode = mode
- self.pipes_path = pipes_path
- self.path = Path(pipes_path + "/" + pipe_id + "-" + str(env_id) + ".pipe")
+ self.pipes_path = Path(pipes_path)
+ if not self.pipes_path.exists():
+ self.pipes_path.mkdir()
+ self.path = self.pipes_path.joinpath(Path(pipe_id + "-" + str(env_id) + ".pipe"))
self.logger = logging.getLogger("Pipe: "+str(self.path.absolute()))
if self.path.exists():
- os.remove(str(self.path.absolute()))
+ self.path.unlink()
os.mkfifo(str(self.path.absolute()))
self.logger.info("Created pipe file")
diff --git a/src/sf_environment/Actions.py b/MAMEToolkit/sf_environment/Actions.py
similarity index 96%
rename from src/sf_environment/Actions.py
rename to MAMEToolkit/sf_environment/Actions.py
index 334f253..401f449 100755
--- a/src/sf_environment/Actions.py
+++ b/MAMEToolkit/sf_environment/Actions.py
@@ -1,5 +1,5 @@
from enum import Enum
-from src.emulator.Action import Action
+from MAMEToolkit.emulator.Action import Action
# An enumerable class used to specify which actions can be used to interact with a game
diff --git a/src/sf_environment/Environment.py b/MAMEToolkit/sf_environment/Environment.py
similarity index 92%
rename from src/sf_environment/Environment.py
rename to MAMEToolkit/sf_environment/Environment.py
index b09d3aa..8a021f1 100644
--- a/src/sf_environment/Environment.py
+++ b/MAMEToolkit/sf_environment/Environment.py
@@ -1,7 +1,7 @@
-from src.emulator.Emulator import Emulator
-from src.emulator.pipes.Address import Address
-from src.sf_environment.Steps import *
-from src.sf_environment.Actions import Actions
+from MAMEToolkit.emulator.Emulator import Emulator
+from MAMEToolkit.emulator.Address import Address
+from MAMEToolkit.sf_environment.Steps import *
+from MAMEToolkit.sf_environment.Actions import Actions
# Combines the data of multiple time steps
@@ -58,15 +58,16 @@ def index_to_attack_action(action):
# The Street Fighter specific interface for training an agent against the game
class Environment(object):
+ # env_id - the unique identifier of the emulator environment, used to create fifo pipes
# difficulty - the difficult to be used in story mode gameplay
- # frameRatio, framesPerStep - see emulator class
+ # frame_ratio, frames_per_step - see Emulator class
# render, throttle, debug - see Console class
- def __init__(self, env_id, difficulty=3, frame_ratio=2, frames_per_step=3, render=True, throttle=False, debug=False):
+ def __init__(self, env_id, roms_path, difficulty=3, frame_ratio=3, frames_per_step=3, render=True, throttle=False, debug=False):
self.difficulty = difficulty
self.frame_ratio = frame_ratio
self.frames_per_step = frames_per_step
self.throttle = throttle
- self.emu = Emulator(env_id, "sfiii3n", setup_memory_addresses(), frame_ratio=frame_ratio, render=render, throttle=throttle, debug=debug)
+ self.emu = Emulator(env_id, roms_path, "sfiii3n", setup_memory_addresses(), frame_ratio=frame_ratio, render=render, throttle=throttle, debug=debug)
self.started = False
self.expected_health = {"P1": 0, "P2": 0}
self.expected_wins = {"P1": 0, "P2": 0}
diff --git a/src/sf_environment/Steps.py b/MAMEToolkit/sf_environment/Steps.py
similarity index 98%
rename from src/sf_environment/Steps.py
rename to MAMEToolkit/sf_environment/Steps.py
index 64f462e..df31e68 100644
--- a/src/sf_environment/Steps.py
+++ b/MAMEToolkit/sf_environment/Steps.py
@@ -1,4 +1,4 @@
-from src.sf_environment.Actions import Actions
+from MAMEToolkit.sf_environment.Actions import Actions
# A = Agent
# C = Computer
diff --git a/MAMEToolkit/sf_environment/__init__.py b/MAMEToolkit/sf_environment/__init__.py
new file mode 100644
index 0000000..d16c3e6
--- /dev/null
+++ b/MAMEToolkit/sf_environment/__init__.py
@@ -0,0 +1,3 @@
+from MAMEToolkit.sf_environment.Environment import Environment
+from MAMEToolkit.sf_environment import Steps
+from MAMEToolkit.sf_environment.Actions import Actions
\ No newline at end of file
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..15b93ab
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,3 @@
+include MAMEToolkit/emulator/pipes/*
+include MAMEToolkit/emulator/mame/mame
+recursive-include MAMEToolkit/emulator/mame/plugins/ *
\ No newline at end of file
diff --git a/README.md b/README.md
index b730f72..63d76b9 100644
--- a/README.md
+++ b/README.md
@@ -3,20 +3,31 @@
## About
This Python library has the to potential to train your reinforcement learning algorithm on almost any arcade game. It is currently available on Linux systems and works as a wrapper around [MAME](http://mamedev.org/). The toolkit allows your algorithm to step through gameplay while recieving the frame data and internal memory address values for tracking the games state, along with sending actions to interact with the game.
+## Installation
+You can use `pip` to install the library, just run:
+```bash
+pip install MAMEToolkit
+```
+
+**DISCLAIMER: We are unable to provide you with any game ROMs. It is the users own legal responsibility to acquire a game ROM for emulation. This library should only be used for non-commercial research purposes.**
+
## Street Fighter Random Agent Demo
-The toolkit has currently been applied to Street Fighter III Third Strike: Fight for the Future, but can modified for any game available on MAME. The following demonstrates how a random agent can be written for a street fighter environment.
+The toolkit has currently been applied to Street Fighter III Third Strike: Fight for the Future (Japan 990608, NO CD), but can modified for any game available on MAME. The following demonstrates how a random agent can be written for a street fighter environment.
```python
import random
-from sf_environment.Environment import Environment
+from MAMEToolkit.sf_environment import Environment
-env = Environment(difficulty=3, frame_ratio=3, frames_per_step=3)
+roms_path = "roms/"
+env = Environment("env1", roms_path)
env.start()
while True:
move_action = random.randint(0, 8)
attack_action = random.randint(0, 9)
- frames, reward, round_done, stage_done = env.step(move_action, attack_action)
- if stage_done:
- env.next_game()
+ frames, reward, round_done, stage_done, game_done = env.step(move_action, attack_action)
+ if game_done:
+ env.new_game()
+ elif stage_done:
+ env.next_stage()
elif round_done:
env.next_round()
```
@@ -25,7 +36,7 @@ The toolkit also supports hogwild training:
```Python
from threading import Thread
import random
-from src.sf_environment.Environment import Environment
+from MAMEToolkit.sf_environment import Environment
def run_env(env):
@@ -33,9 +44,11 @@ def run_env(env):
while True:
move_action = random.randint(0, 8)
attack_action = random.randint(0, 9)
- frames, reward, round_done, stage_done = env.step(move_action, attack_action)
- if stage_done:
- env.next_game()
+ frames, reward, round_done, stage_done, game_done = env.step(move_action, attack_action)
+ if game_done:
+ env.new_game()
+ elif stage_done:
+ env.next_stage()
elif round_done:
env.next_round()
@@ -43,7 +56,8 @@ def run_env(env):
def main():
workers = 8
# Environments must be created outside of the threads
- envs = [Environment(difficulty=5, frame_ratio=3, frames_per_step=3) for i in range(workers)]
+ roms_path = "roms/"
+ envs = [Environment(f"env{i}", roms_path) for i in range(workers)]
threads = [Thread(target=run_env, args=(envs[i], )) for i in range(workers)]
[thread.start() for thread in threads]
```
@@ -53,11 +67,23 @@ def main():
## Setting Up Your Own Game Environment
It doesn't take much to interact with the emulator itself using the toolkit, however the challenge comes from finding the memory address values associated with the internal state you care about, and tracking said state with your environment class.
The internal memory states of a game can be tracked using the [MAME Cheat Debugger](http://docs.mamedev.org/debugger/cheats.html), which allows you to track how the memory address values of the game change over time.
-To create an emulation of the game you must first have the ROM for the game you are emulating and know the game ID used by MAME, for example for this version of street fighter it is 'sfiii3n'. Once you have these and have determined the memory addresses you wish to track you can start the emulation:
+To create an emulation of the game you must first have the ROM for the game you are emulating and know the game ID used by MAME, for example for this version of street fighter it is 'sfiii3n'.
+
+**Game ID's**
+The id of your game can be found by running:
```python
-from emulator.Emulator import Emulator
-from emulator.pipes.Address import Address
+from MAMEToolkit.emulator import Emulator
+emulator = Emulator("env1", "", "", memory_addresses)
+```
+This will bring up the MAME emulator. You can search through the list of games to find the one you want. The id of the game is always in brackets at the end of the game title.
+
+**Memory Addresses**
+Once you have these and have determined the memory addresses you wish to track you can start the emulation:
+```python
+from MAMEToolkit.emulator import Emulator
+from MAMEToolkit.emulator import Address
+roms_path = "roms/"
game_id = "sfiii3n"
memory_addresses = {
"fighting": Address('0x0200EE44', 'u8'),
@@ -67,9 +93,12 @@ memory_addresses = {
"healthP2": Address('0x020691A3', 's8')
}
-emulator = Emulator("sfiii3n", memory_addresses)
+emulator = Emulator("env1", roms_path, "sfiii3n", memory_addresses)
```
-This will immediately start the emulation and halt it when it toolkit has linked to the emulator process. Once the toolkit is linked, you can step the emulator along using the step function:
+This will immediately start the emulation and halt it when it toolkit has linked to the emulator process.
+
+**Stepping the emulator**
+Once the toolkit is linked, you can step the emulator along using the step function:
```python
data = emulator.step([])
@@ -82,19 +111,21 @@ player2_health = data["healthP2"]
```
The step function returns the frame data as a NumPy matrix, along with all of the memory address integer values from that timestep.
+**Sending inputs**
To send actions to the emulator you also need to determine which input ports and fields the game supports. For example, with street fighter to insert a coin the following code is required:
```python
-from emulator.Action import Action
+from MAMEToolkit.emulator import Action
insert_coin = Action(':INPUTS', 'Coin 1')
data = emulator.step([insert_coin])
```
To identify which ports are availble use the list actions command:
```python
-from emulator.Emulator import list_actions
+from MAMEToolkit.emulator import list_actions
+roms_path = "roms/"
game_id = "sfiii3n"
-print(list_actions(game_id))
+print(list_actions(roms_path, game_id))
```
which for street fighter returns the list with all the ports and fields available for sending actions to the step function:
```python
@@ -134,14 +165,14 @@ There is also the problem of transitioning games between non-learnable gameplay
The emulator class also has a frame_ratio argument which can be used for adjusting the frame rate seen by your algorithm. By default MAME generates frames at 60 frames per second, however, this may be too many frames for your algorithm. The toolkit by default will use a frame_ratio of 3, which means that 1 in 3 frames are sent through the toolkit, this converts the frame rate to 20 frames per second. Using a higher frame_ratio also increases the performance of the toolkit.
```Python
-from emulator.Emulator import Emulator
+from MAMEToolkit.emulator import Emulator
-emulator = Emulator("sfiii3n", memory_addresses, frame_ratio=3)
+emulator = Emulator(roms_path, game_id, memory_addresses, frame_ratio=3)
```
## Library Performance Benchmarks with PC Specs
The development and testing of this toolkit have been completed on an 8-core AMD FX-8300 3.3GHz CPU along with a 3GB GeForce GTX 1060 GPU.
-With a single random agent, the street fighter environment can be run at 600%+ the normal gameplay speed. And For hogwild training with 8 random agents, the environment can be run at 550%+ the normal gameplay speed.
+With a single random agent, the street fighter environment can be run at 600%+ the normal gameplay speed. And For hogwild training with 8 random agents, the environment can be run at 300%+ the normal gameplay speed.
## Simple ConvNet Agent
To ensure that the toolkit is able to train algorithms, a simple 5 layer ConvNet was setup with minimal tuning. The algorithm was able to successfully learn some simple mechanics of Street Fighter, such as combos and blocking. The Street Fighter gameplay works by having the player fight different opponents across 10 stages of increasing difficulty. Initially, the algorithm would reach stage 2 on average, but eventually could reach stage 5 on average after 2200 episodes of training. The learning rate was tracked using the net damage done vs damage taken of a single playthough for each episode.
diff --git a/__init__.py b/__init__.py
deleted file mode 100644
index 0c6e3bb..0000000
--- a/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from emulator import *
-import sf_environment
diff --git a/setup.py b/setup.py
index 2c9191c..8cc9306 100644
--- a/setup.py
+++ b/setup.py
@@ -1,21 +1,22 @@
-import setuptools
+from setuptools import setup, find_packages
with open("README.md", "r") as fh:
long_description = fh.read()
-setuptools.setup(
+setup(
name="MAMEToolkit",
- version="0.0.1",
+ version="1.0.0",
author="Michael Murray",
author_email="m.j.murray123@gmail.com",
description="A library to train your RL algorithms against MAME arcade games on Linux",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/M-J-Murray/MAMEToolkit",
- packages=setuptools.find_packages(),
+ packages=find_packages(exclude=['MAMEToolkit/emulator/mame/roms']),
+ include_package_data=True,
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
- "Operating System :: POSIX :: Linux",
+ "Operating System :: POSIX :: Linux"
],
)
\ No newline at end of file
diff --git a/src/emulator/mame/cfg/sfiii3n.cfg b/src/emulator/mame/cfg/sfiii3n.cfg
deleted file mode 100644
index b01f5f7..0000000
--- a/src/emulator/mame/cfg/sfiii3n.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/test/emulator/pipes/AddressTest.py b/test/emulator/AddressTest.py
similarity index 94%
rename from test/emulator/pipes/AddressTest.py
rename to test/emulator/AddressTest.py
index b6673fd..adab96c 100755
--- a/test/emulator/pipes/AddressTest.py
+++ b/test/emulator/AddressTest.py
@@ -1,6 +1,6 @@
import unittest
from hamcrest import *
-from src.emulator.pipes.Address import Address
+from MAMEToolkit.emulator.Address import Address
class AddressTest(unittest.TestCase):
diff --git a/test/emulator/ConsoleTest.py b/test/emulator/ConsoleTest.py
index 4399d8c..d6d3bde 100755
--- a/test/emulator/ConsoleTest.py
+++ b/test/emulator/ConsoleTest.py
@@ -2,13 +2,13 @@
from hamcrest import *
from time import sleep
from multiprocessing import set_start_method, Process, Queue
-from src.emulator.Console import Console
+from MAMEToolkit.emulator.Console import Console
def run_console(game_id, output_queue):
console = None
try:
- console = Console(game_id)
+ console = Console("MAMEToolkit/emulator/mame/roms", game_id)
sleep(5)
console.writeln('s = manager:machine().screens[":screen"]')
output = console.writeln('print(s:width())', expect_output=True)
@@ -23,7 +23,7 @@ def test_write_read(self):
game_id = "sfiii3n"
console = None
try:
- console = Console(game_id)
+ console = Console("/home/michael/dev/MAMEToolkit/MAMEToolkit/emulator/mame/roms", game_id)
sleep(5)
console.writeln('s = manager:machine().screens[":screen"]')
output = console.writeln('print(s:width())', expect_output=True)
diff --git a/test/emulator/EmulatorTest.py b/test/emulator/EmulatorTest.py
index edfbbd4..596c727 100755
--- a/test/emulator/EmulatorTest.py
+++ b/test/emulator/EmulatorTest.py
@@ -1,15 +1,15 @@
import unittest
from hamcrest import *
-from src.emulator.Emulator import Emulator
-from src.emulator.pipes.Address import Address
+from MAMEToolkit.emulator.Emulator import Emulator
+from MAMEToolkit.emulator.Address import Address
from multiprocessing import set_start_method, Process, Queue
-def run_emulator(env_id, game_id, memory_addresses, output_queue):
+def run_emulator(env_id, game_id, roms_path, memory_addresses, output_queue):
emulator = None
try:
- emulator = Emulator(env_id, game_id, memory_addresses)
+ emulator = Emulator(env_id, roms_path, game_id, memory_addresses)
output_queue.put(emulator.step([]))
finally:
emulator.close()
@@ -22,7 +22,7 @@ def test_screen_dimensions(self):
game_id = "sfiii3n"
emulator = None
try:
- emulator = Emulator("testEnv1", game_id, memory_addresses)
+ emulator = Emulator("testEnv1", "/home/michael/dev/MAMEToolkit/MAMEToolkit/emulator/mame/roms", game_id, memory_addresses)
assert_that(emulator.screenDims["width"], equal_to(384))
assert_that(emulator.screenDims["height"], equal_to(224))
finally:
@@ -46,7 +46,7 @@ def test_multiprocessing(self):
game_id = "sfiii3n"
memory_addresses = {"test": Address("02000008", "u8")}
output_queue = Queue()
- processes = [Process(target=run_emulator, args=[f"testEnv{i}", game_id, memory_addresses, output_queue]) for i in range(workers)]
+ processes = [Process(target=run_emulator, args=[f"testEnv{i}", "/home/michael/dev/MAMEToolkit/MAMEToolkit/emulator/mame/roms", game_id, memory_addresses, output_queue]) for i in range(workers)]
[process.start() for process in processes]
[process.join() for process in processes]
for i in range(workers):
diff --git a/test/emulator/StreamGobblerTest.py b/test/emulator/StreamGobblerTest.py
index 489631c..47d3dc5 100755
--- a/test/emulator/StreamGobblerTest.py
+++ b/test/emulator/StreamGobblerTest.py
@@ -1,6 +1,6 @@
import unittest
from hamcrest import *
-from src.emulator.StreamGobbler import StreamGobbler
+from MAMEToolkit.emulator.StreamGobbler import StreamGobbler
from multiprocessing import set_start_method, Process, Queue
import queue
diff --git a/test/emulator/pipes/DataPipeTest.py b/test/emulator/pipes/DataPipeTest.py
index 9370962..bf5da5a 100755
--- a/test/emulator/pipes/DataPipeTest.py
+++ b/test/emulator/pipes/DataPipeTest.py
@@ -3,8 +3,8 @@
from threading import Thread
from queue import Queue as DefaultQueue
-from src.emulator.pipes.DataPipe import DataPipe
-from src.emulator.pipes.Address import Address
+from MAMEToolkit.emulator.pipes.DataPipe import DataPipe
+from MAMEToolkit.emulator.Address import Address
from multiprocessing import set_start_method, Process, Queue as MPQueue
diff --git a/test/emulator/pipes/PipeTest.py b/test/emulator/pipes/PipeTest.py
index 0744fbb..ab236f4 100755
--- a/test/emulator/pipes/PipeTest.py
+++ b/test/emulator/pipes/PipeTest.py
@@ -4,7 +4,7 @@
from queue import Queue as DefaultQueue
from multiprocessing import set_start_method, Process, Queue as MPQueue
-from src.emulator.pipes.Pipe import Pipe
+from MAMEToolkit.emulator.pipes.Pipe import Pipe
import os
os.chdir(os.path.abspath(os.path.join(os.path.dirname(__file__), '../')))