Apply pyribs to Game GAN generation from MM-NEAT
This code extracts relevant portions of the MM-NEAT code repository written in Java and makes it easy to package them into a reasonably small jar file that allows the domains to be optimized by the Python code for pyribs. However, the pre-compiled jar file ExternalRealValuedGenotypeTask.jar
could be used with any code in any language that can launch an external process and communicate with it via the console. The core domains that are focused on from MM-NEAT are those that involve generating video game levels using a Generative Adversarial Network (GAN). The specific domains are Mario, Zelda, Lode Runner, and Mega Man. In fact, this repository also shares much in common with the GameGAN repository, which is also derived from MM-NEAT. Here is how to use the code.
- Install Java 1.8. Note that more recent versions of Java will not work.
- Install Python 3.7.3. More recent versions of Python probably do work, but are not extensively tested.
- Run
pip install -r requirements.txt
to install needed Python packages, including PyTorch 1.9.0+ and pyribs. Not 100% sure everything you need is here. Also, you will need to install CUDA support for PyTorch on your own if you want it. ExternalRealValuedGenotypeTask.jar
already exists in the repository, but if you want to modify the Java code and recompile it on your own, you can use Apache Ant with the scriptbuild.xml
. Specifically, use the commandant -f build.xml
. The main class of the runnable jar isedu.southwestern.tasks.export.ExternalRealValuedGenotypeExecutor
- You must create a file named
my_python_path.txt
in the basePyribsForGameGAN
directory that contains a single line of text, which is the full path to the location of your Python executable. For example:C:\ProgramData\Anaconda3\python.exe
or in some cases justpython
. This is needed because even though you are launching a Java process from Python, the Java process itself launches another Python process, and needs to know how to do that. - Run
main.py
. It will show some usage information if you do not provide correct command line parameters. The syntax ispython main.py <batch file> <run number> <map_elites | cma_me_imp>
where<batch file>
is one of the pre-existing batch files in the basePyribsForGameGAN
directory (more on these in a moment),<run number>
is an integer to distinguish repetitions of the same experiment, and the final parameter must be either the stringmap_elites
(for vanilla MAP-Elites) orcma_me_imp
(for CMA-ME using 5 Improvement Emitters). An example ispython main.py ExternalMario-DecorateNSLeniency.bat 0 cma_me_imp
. Note that it is very important that the string for the batch file match exactly one of the pre-existing names.
main.py
is a simple Python script that uses the authentic, official pyribs code for MAP-Elites and (most importantly) CMA-ME. It launches a Java process based on the contents of whichever batch file you select (although batch files are a Windows scripting tool, the code here is written in a way that should work on Mac/Linux). The Java code runs the official versions of GAN-based level generation code used by MM-NEAT in several previous publications. However, the actual GAN code is also written in Python, and is launched by the Java process. This code is contained in the python/GAN
subdirectory (this is why my_python_path.txt
is needed).
Basically, the Java process that is launched waits for input via the command line, which is sent to it via main.py
in the form of a solution vector. The Java code receives these solution vectors and responds with lots of information related to the performance and characterization of the solution. In order to know what information to extract and how to use it, the main.py
script has to be aware of the specific batch file used (there are various cases in main.py
in several places that check which batch file was used). However, most of these files function similarly, in that a Python dictionary containing relevant information is created:
data_out['binScore']
contains the fitness, or quality score, of the individual solution (a generated level)data_out['Bin Coordinates']
contains the coordinates in the multi-dimensional archive of elites where the solution belongs.- Other information that could be used as part of a so-called "behavior characterization" is also included in
data_out
but is mostly ignored.
Essentially, the Java code does the work of discretizing each solution's characterization ("behavior characterization") in advance, so the mapping into the archive is mostly an identity mapping. However, many of the Java archives are 3D, whereas pyribs only seems to smoothly handle the display of 2D archives, so main.py
also does the work of converting 3D coordinates into 2D archives whose display styles are mostly consistent with how results in these domains were presented in previous publications. Here are the specific batch files, their behavior characterizations, and publications they are associated with (if any).
ExternalLodeRunner-PercentGroundNumGoldAndEnemies.bat
: Lode Runner levels with archive based on the percentage of ground tiles, the number of treasure items, and the number of enemies in the level. Used in this GECCO poster paper which was derived from this longer arXiv article. These publications relied on six different GANs trained on different collections of Lode Runner levels, but this batch file only contains the parameters to apply the GAN trained on the first 100 Lode Runner levels. However, the other GANs used in that study are available in this repository for use as well inpython/GAN/LodeRunnerGAN
. Fitness is the maximum of the percentage of reachable tiles (between 0 and 1) and the length of the optimal solution path. The reachable percentage only comes into play if the level is not beatable.ExternalMario-DecorateNSLeniency.bat
: Mario levels based on the sums of measures of decoration, space coverage, and leniency across 10 stitched together segments. First used in this GECCO paper and more recently used in this arXiv article where it is referred to as Sum DSL. Fitness is length of optimal solution path.ExternalMario-DistinctNSDecorate.bat
: Mario levels based on the number of distinct segments and calculations of alternating space coverage and decoration across 10 stitched together segments. Used in this arXiv article where it is referred to as Distinct ASAD. Fitness is length of optimal solution path.ExternalMario-LatentPartition2Slices.bat
: Mario levels of just 2 segments that are characterized based on the sums of the latent variables contributing to both the first and second segments. Not used in any publication, but is similar to the behavior characterization used for the function optimization baselines in the original pyribs paper. Fitness is length of optimal solution path.ExternalMegaMan-DistinctVerticalAndConnectivity.bat
: Mega Man levels consisting of 10 segments characterized by the number of distinct segments, the number of vertical segments, and the percentage of reachable tiles in the level. Not yet used in any publication. Fitness is the maximum of the percentage of reachable tiles (between 0 and 1) and the length of the optimal solution path. The reachable percentage only comes into play if the level is not beatable.ExternalZelda-DistinctBTRooms.bat
: 5 by 5 Zelda dungeons characterized by the number of distinct rooms, the amount of backtracking required in the optimal solution path, and the number of reachable rooms. Used in this arXiv article where it is referred to as Distinct BTR. Fitness is the percentage of rooms in the optimal solution path.ExternalZelda-WallWaterRooms.bat
: 5 by 5 Zelda dungeons characterized by the number of reachable rooms, and the percentages of both water and wall tiles contained in the dungeon. First used in this GECCO paper (with 10 by 10 dungeons) and more recently used in this arXiv article where it is referred to as WWR. Fitness is the percentage of rooms in the optimal solution path.
Some preliminary results in each domain are presented in the results
directory.