Loading

NeurIPS 2022 - The Neural MMO Challenge

NeurIPS 2022 Neural MMO Challenge Tutorial

Introduction of the action space and the observation space of the Neural MMO Challenge Environment

xixi

Tutorial on NMMO's observation and action space

This is a tutorial to show the observation space and action space of Neural MMO's environment.

Installation

See https://gitlab.aicrowd.com/neural-mmo/neurips2022-nmmo-starter-kit

In [ ]:
# install neurips competition setup and nmmo
!pip install --ignore-requires-python openskill==0.2.0a0
!pip install git+http://gitlab.aicrowd.com/neural-mmo/neurips2022-nmmo.git
Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/
Collecting openskill==0.2.0a0
  Downloading openskill-0.2.0a0-py3-none-any.whl (41 kB)
     |████████████████████████████████| 41 kB 52 kB/s 
Requirement already satisfied: scipy<2.0.0,>=1.7.3 in /usr/local/lib/python3.7/dist-packages (from openskill==0.2.0a0) (1.7.3)
Requirement already satisfied: numpy<1.23.0,>=1.16.5 in /usr/local/lib/python3.7/dist-packages (from scipy<2.0.0,>=1.7.3->openskill==0.2.0a0) (1.21.6)
Installing collected packages: openskill
Successfully installed openskill-0.2.0a0
Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/
Collecting git+http://gitlab.aicrowd.com/Wu_Bo_/nips2022nmmo.git
  Cloning http://gitlab.aicrowd.com/Wu_Bo_/nips2022nmmo.git to /tmp/pip-req-build-rj4skmop
  Running command git clone -q http://gitlab.aicrowd.com/Wu_Bo_/nips2022nmmo.git /tmp/pip-req-build-rj4skmop
Collecting nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz
  Using cached https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz
Requirement already satisfied: numpy in /usr/local/lib/python3.7/dist-packages (from neurips2022nmmo==0.2.5) (1.21.6)
Requirement already satisfied: prettytable>=3.0.0 in /usr/local/lib/python3.7/dist-packages (from neurips2022nmmo==0.2.5) (3.3.0)
Requirement already satisfied: pyzmq>=22.0.0 in /usr/local/lib/python3.7/dist-packages (from neurips2022nmmo==0.2.5) (23.2.0)
Requirement already satisfied: cloudpickle>=1.0.0 in /usr/local/lib/python3.7/dist-packages (from neurips2022nmmo==0.2.5) (1.3.0)
Requirement already satisfied: tqdm>=4.60.0 in /usr/local/lib/python3.7/dist-packages (from neurips2022nmmo==0.2.5) (4.64.0)
Collecting loguru>=0.5.0
  Using cached loguru-0.6.0-py3-none-any.whl (58 kB)
Collecting pytest-benchmark==3.4.1
  Using cached pytest_benchmark-3.4.1-py2.py3-none-any.whl (50 kB)
Requirement already satisfied: openskill==0.2.0-alpha.0 in /usr/local/lib/python3.7/dist-packages (from nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (0.2.0a0)
Collecting fire==0.4.0
  Downloading fire-0.4.0.tar.gz (87 kB)
     |████████████████████████████████| 87 kB 3.3 MB/s 
Collecting setproctitle==1.1.10
  Downloading setproctitle-1.1.10.zip (34 kB)
Collecting service-identity==21.1.0
  Downloading service_identity-21.1.0-py2.py3-none-any.whl (12 kB)
Collecting autobahn==19.3.3
  Downloading autobahn-19.3.3-py2.py3-none-any.whl (389 kB)
     |████████████████████████████████| 389 kB 27.7 MB/s 
Collecting Twisted==19.2.0
  Downloading Twisted-19.2.0.tar.bz2 (3.1 MB)
     |████████████████████████████████| 3.1 MB 59.1 MB/s 
Collecting vec-noise==1.1.4
  Downloading vec_noise-1.1.4.zip (134 kB)
     |████████████████████████████████| 134 kB 58.1 MB/s 
Collecting imageio==2.8.0
  Downloading imageio-2.8.0-py3-none-any.whl (3.3 MB)
     |████████████████████████████████| 3.3 MB 54.8 MB/s 
Collecting tqdm>=4.60.0
  Downloading tqdm-4.61.1-py2.py3-none-any.whl (75 kB)
     |████████████████████████████████| 75 kB 4.2 MB/s 
Collecting lz4==4.0.0
  Downloading lz4-4.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB)
     |████████████████████████████████| 1.2 MB 49.5 MB/s 
Collecting pettingzoo
  Downloading PettingZoo-1.20.1-py3-none-any.whl (804 kB)
     |████████████████████████████████| 804 kB 65.9 MB/s 
Requirement already satisfied: six>=1.11.0 in /usr/local/lib/python3.7/dist-packages (from autobahn==19.3.3->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (1.15.0)
Collecting txaio>=18.8.1
  Downloading txaio-22.2.1-py2.py3-none-any.whl (30 kB)
Requirement already satisfied: termcolor in /usr/local/lib/python3.7/dist-packages (from fire==0.4.0->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (1.1.0)
Requirement already satisfied: pillow in /usr/local/lib/python3.7/dist-packages (from imageio==2.8.0->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (7.1.2)
Requirement already satisfied: scipy<2.0.0,>=1.7.3 in /usr/local/lib/python3.7/dist-packages (from openskill==0.2.0-alpha.0->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (1.7.3)
Collecting py-cpuinfo
  Downloading py-cpuinfo-8.0.0.tar.gz (99 kB)
     |████████████████████████████████| 99 kB 10.0 MB/s 
Collecting pytest>=3.8
  Downloading pytest-7.1.2-py3-none-any.whl (297 kB)
     |████████████████████████████████| 297 kB 50.2 MB/s 
Requirement already satisfied: attrs>=19.1.0 in /usr/local/lib/python3.7/dist-packages (from service-identity==21.1.0->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (22.1.0)
Requirement already satisfied: pyasn1 in /usr/local/lib/python3.7/dist-packages (from service-identity==21.1.0->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (0.4.8)
Collecting cryptography
  Downloading cryptography-37.0.4-cp36-abi3-manylinux_2_24_x86_64.whl (4.1 MB)
     |████████████████████████████████| 4.1 MB 42.1 MB/s 
Requirement already satisfied: pyasn1-modules in /usr/local/lib/python3.7/dist-packages (from service-identity==21.1.0->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (0.2.8)
Collecting zope.interface>=4.4.2
  Downloading zope.interface-5.4.0-cp37-cp37m-manylinux2010_x86_64.whl (251 kB)
     |████████████████████████████████| 251 kB 64.3 MB/s 
Collecting constantly>=15.1
  Downloading constantly-15.1.0-py2.py3-none-any.whl (7.9 kB)
Collecting incremental>=16.10.1
  Using cached incremental-21.3.0-py2.py3-none-any.whl (15 kB)
Collecting Automat>=0.3.0
  Downloading Automat-20.2.0-py2.py3-none-any.whl (31 kB)
Collecting hyperlink>=17.1.1
  Downloading hyperlink-21.0.0-py2.py3-none-any.whl (74 kB)
     |████████████████████████████████| 74 kB 3.4 MB/s 
Collecting PyHamcrest>=1.9.0
  Downloading pyhamcrest-2.0.4-py3-none-any.whl (52 kB)
     |████████████████████████████████| 52 kB 1.8 MB/s 
Requirement already satisfied: idna>=2.5 in /usr/local/lib/python3.7/dist-packages (from hyperlink>=17.1.1->Twisted==19.2.0->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (2.10)
Requirement already satisfied: wcwidth in /usr/local/lib/python3.7/dist-packages (from prettytable>=3.0.0->neurips2022nmmo==0.2.5) (0.2.5)
Requirement already satisfied: importlib-metadata in /usr/local/lib/python3.7/dist-packages (from prettytable>=3.0.0->neurips2022nmmo==0.2.5) (4.12.0)
Requirement already satisfied: tomli>=1.0.0 in /usr/local/lib/python3.7/dist-packages (from pytest>=3.8->pytest-benchmark==3.4.1->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (2.0.1)
Requirement already satisfied: py>=1.8.2 in /usr/local/lib/python3.7/dist-packages (from pytest>=3.8->pytest-benchmark==3.4.1->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (1.11.0)
Collecting iniconfig
  Downloading iniconfig-1.1.1-py2.py3-none-any.whl (5.0 kB)
Collecting pluggy<2.0,>=0.12
  Downloading pluggy-1.0.0-py2.py3-none-any.whl (13 kB)
Requirement already satisfied: packaging in /usr/local/lib/python3.7/dist-packages (from pytest>=3.8->pytest-benchmark==3.4.1->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (21.3)
Requirement already satisfied: typing-extensions>=3.6.4 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata->prettytable>=3.0.0->neurips2022nmmo==0.2.5) (4.1.1)
Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.7/dist-packages (from importlib-metadata->prettytable>=3.0.0->neurips2022nmmo==0.2.5) (3.8.1)
Requirement already satisfied: setuptools in /usr/local/lib/python3.7/dist-packages (from zope.interface>=4.4.2->Twisted==19.2.0->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (57.4.0)
Requirement already satisfied: cffi>=1.12 in /usr/local/lib/python3.7/dist-packages (from cryptography->service-identity==21.1.0->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (1.15.1)
Requirement already satisfied: pycparser in /usr/local/lib/python3.7/dist-packages (from cffi>=1.12->cryptography->service-identity==21.1.0->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (2.21)
Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in /usr/local/lib/python3.7/dist-packages (from packaging->pytest>=3.8->pytest-benchmark==3.4.1->nmmo@ https://github.com/bowuaaa/environment/archive/refs/tags/test0812-2.tar.gz->neurips2022nmmo==0.2.5) (3.0.9)
Collecting gym>=0.24.1
  Downloading gym-0.25.1.tar.gz (732 kB)
     |████████████████████████████████| 732 kB 55.2 MB/s 
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
    Preparing wheel metadata ... done
Collecting gym-notices>=0.0.4
  Downloading gym_notices-0.0.7-py3-none-any.whl (2.7 kB)
Building wheels for collected packages: neurips2022nmmo, nmmo, fire, setproctitle, Twisted, vec-noise, gym, py-cpuinfo
  Building wheel for neurips2022nmmo (setup.py) ... done
  Created wheel for neurips2022nmmo: filename=neurips2022nmmo-0.2.5-py3-none-any.whl size=27657 sha256=b3689edf73331293600051beeebcad6aa7746ad076b7762863a30bf9a95e6808
  Stored in directory: /tmp/pip-ephem-wheel-cache-4z_0773v/wheels/24/b6/7a/87a3f3d3e9c0d7e5d310b28130cff348ca0f79ab4b83242276
  Building wheel for nmmo (setup.py) ... done
  Created wheel for nmmo: filename=nmmo-1.6.0-py3-none-any.whl size=641333 sha256=bf6e5e68016879a5804ccf8d41deae8f0208b36f7d5a91bb2c5589fe3ac28773
  Stored in directory: /root/.cache/pip/wheels/4e/7a/30/a1d74273815d29541aec35a844dd34a1995d72428d8e3b6fb7
  Building wheel for fire (setup.py) ... done
  Created wheel for fire: filename=fire-0.4.0-py2.py3-none-any.whl size=115942 sha256=4811fe8246dc39a97d7d00cb03e781ed66e4a49802f8b5fa6c65ff387bc10d49
  Stored in directory: /root/.cache/pip/wheels/8a/67/fb/2e8a12fa16661b9d5af1f654bd199366799740a85c64981226
  Building wheel for setproctitle (setup.py) ... done
  Created wheel for setproctitle: filename=setproctitle-1.1.10-cp37-cp37m-linux_x86_64.whl size=35209 sha256=b3b9bb02f9c196a1d8585307430d788e460801c90859cbe2489597d64c62ab69
  Stored in directory: /root/.cache/pip/wheels/c2/fc/58/bd368d9483b36eafa3673e2acd8dcd121b0695d10719fe5fce
  Building wheel for Twisted (setup.py) ... done
  Created wheel for Twisted: filename=Twisted-19.2.0-cp37-cp37m-linux_x86_64.whl size=3045128 sha256=f18a7316839514dca486d3be5dae2b336eeb902c16f00ab393e4118cebac2601
  Stored in directory: /root/.cache/pip/wheels/29/80/ed/9dc8ba80624047e0de94ef0405f14db26edb0a5e94bc5d188a
  Building wheel for vec-noise (setup.py) ... done
  Created wheel for vec-noise: filename=vec_noise-1.1.4-cp37-cp37m-linux_x86_64.whl size=80746 sha256=2ae701cd1043039f22578eb19566ea88fb582b1921b7d26be3dace2406a6096f
  Stored in directory: /root/.cache/pip/wheels/fc/0c/19/5932b4834cf3204ed2ae845e788f07c79b3279c302d55d6fa8
  Building wheel for gym (PEP 517) ... done
  Created wheel for gym: filename=gym-0.25.1-py3-none-any.whl size=849048 sha256=5246efaba3820bb8fc4b57b59f5bef1ee4ccb65b3f27043dee1f145d1e313551
  Stored in directory: /root/.cache/pip/wheels/0e/2d/04/f964345f96b1348723057d60011be1e48885a027c9c5b92210
  Building wheel for py-cpuinfo (setup.py) ... done
  Created wheel for py-cpuinfo: filename=py_cpuinfo-8.0.0-py3-none-any.whl size=22257 sha256=72482625a9b40537a748c4bb5ccfaa010c1e05fa236be552afbd4b5b3ee29c4e
  Stored in directory: /root/.cache/pip/wheels/d2/f1/1f/041add21dc9c4220157f1bd2bd6afe1f1a49524c3396b94401
Successfully built neurips2022nmmo nmmo fire setproctitle Twisted vec-noise gym py-cpuinfo
Installing collected packages: pluggy, iniconfig, gym-notices, zope.interface, txaio, pytest, PyHamcrest, py-cpuinfo, incremental, hyperlink, gym, cryptography, constantly, Automat, vec-noise, Twisted, tqdm, setproctitle, service-identity, pytest-benchmark, pettingzoo, lz4, imageio, fire, autobahn, nmmo, loguru, neurips2022nmmo
  Attempting uninstall: pluggy
    Found existing installation: pluggy 0.7.1
    Uninstalling pluggy-0.7.1:
      Successfully uninstalled pluggy-0.7.1
  Attempting uninstall: pytest
    Found existing installation: pytest 3.6.4
    Uninstalling pytest-3.6.4:
      Successfully uninstalled pytest-3.6.4
  Attempting uninstall: gym
    Found existing installation: gym 0.17.3
    Uninstalling gym-0.17.3:
      Successfully uninstalled gym-0.17.3
  Attempting uninstall: tqdm
    Found existing installation: tqdm 4.64.0
    Uninstalling tqdm-4.64.0:
      Successfully uninstalled tqdm-4.64.0
  Attempting uninstall: imageio
    Found existing installation: imageio 2.9.0
    Uninstalling imageio-2.9.0:
      Successfully uninstalled imageio-2.9.0
Successfully installed Automat-20.2.0 PyHamcrest-2.0.4 Twisted-19.2.0 autobahn-19.3.3 constantly-15.1.0 cryptography-37.0.4 fire-0.4.0 gym-0.25.1 gym-notices-0.0.7 hyperlink-21.0.0 imageio-2.8.0 incremental-21.3.0 iniconfig-1.1.1 loguru-0.6.0 lz4-4.0.0 neurips2022nmmo-0.2.5 nmmo-1.6.0 pettingzoo-1.20.1 pluggy-1.0.0 py-cpuinfo-8.0.0 pytest-7.1.2 pytest-benchmark-3.4.1 service-identity-21.1.0 setproctitle-1.1.10 tqdm-4.61.1 txaio-22.2.1 vec-noise-1.1.4 zope.interface-5.4.0

After installation, we can establish a demo environment to show how NMMO works.

In [ ]:
import nmmo
from nmmo import config

class TestConfig(config.Medium, config.AllGameSystems):
    pass

conf = TestConfig()
env = nmmo.Env( conf )
100%|██████████| 1/1 [00:00<00:00,  9.50it/s]
Generating 1 maps

The env setting for this competition:

  • Map of 128 * 128 grids
  • 128 players (16 teams * 8 players/team)
  • All players spawn concurrently when game starts

If you want to see the detailed configuration:

In [ ]:
for attr in dir(config):
    if not attr.startswith( '__' ):
        print( f'{attr}: {getattr( config, attr )} ' )
AllGameSystems: <class 'nmmo.core.config.AllGameSystems'> 
Combat: <class 'nmmo.core.config.Combat'> 
Communication: <class 'nmmo.core.config.Communication'> 
Config: <class 'nmmo.core.config.Config'> 
Default: <class 'nmmo.core.config.Default'> 
Equipment: <class 'nmmo.core.config.Equipment'> 
Exchange: <class 'nmmo.core.config.Exchange'> 
Item: <class 'nmmo.core.config.Item'> 
Large: <class 'nmmo.core.config.Large'> 
Medium: <class 'nmmo.core.config.Medium'> 
NPC: <class 'nmmo.core.config.NPC'> 
Profession: <class 'nmmo.core.config.Profession'> 
Progression: <class 'nmmo.core.config.Progression'> 
Resource: <class 'nmmo.core.config.Resource'> 
Small: <class 'nmmo.core.config.Small'> 
T: <function set_trace at 0x7f37c23a14d0> 
Template: <class 'nmmo.core.config.Template'> 
Terrain: <class 'nmmo.core.config.Terrain'> 
material: <module 'nmmo.lib.material' from '/usr/local/lib/python3.7/dist-packages/nmmo/lib/material.py'> 
nmmo: <module 'nmmo' from '/usr/local/lib/python3.7/dist-packages/nmmo/__init__.py'> 
np: <module 'numpy' from '/usr/local/lib/python3.7/dist-packages/numpy/__init__.py'> 
os: <module 'os' from '/usr/lib/python3.7/os.py'> 
spawn: <module 'nmmo.lib.spawn' from '/usr/local/lib/python3.7/dist-packages/nmmo/lib/spawn.py'> 
utils: <module 'nmmo.lib.utils' from '/usr/local/lib/python3.7/dist-packages/nmmo/lib/utils.py'> 
validate: <function validate at 0x7f379dcaf290> 

Observation Space

You can get the observation space via env.observation_space(agent) but the output is really verbose.

In [ ]:
env.observation_space(agent=1)
Out[ ]:
Dict(Entity: Dict(Continuous: Box(-1048576.0, 1048576.0, (100, 24), float32), Discrete: Box(0, 4096, (100, 5), int32), N: Box(0, 100, (1,), int32)), Item: Dict(Continuous: Box(-1048576.0, 1048576.0, (170, 16), float32), Discrete: Box(0, 4096, (170, 3), int32), N: Box(0, 170, (1,), int32)), Market: Dict(Continuous: Box(-1048576.0, 1048576.0, (170, 16), float32), Discrete: Box(0, 4096, (170, 3), int32), N: Box(0, 170, (1,), int32)), Tile: Dict(Continuous: Box(-1048576.0, 1048576.0, (225, 4), float32), Discrete: Box(0, 4096, (225, 3), int32), N: Box(0, 15, (1,), int32)))

It is hard to understand, so the obs will be explained in detail in the following chapter.

In [ ]:
obs = env.reset()
print(obs.keys())
/usr/local/python3/lib/python3.9/site-packages/nmmo/lib/spawn.py:86: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
  lows   = (left+np.zeros(per_side, dtype=np.int)).tolist()
dict_keys([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128])

The env returns obs in a dict and the dict keys are the agent's id from 1 to 128.

And let's take a look at the obs single agent receives:

In [ ]:
obs[1].keys()
Out[ ]:
dict_keys(['Entity', 'Tile', 'Item', 'Market'])

The agent's obs consists of two parts:

  • Entity: the information of yourself, other players and npcs.
  • Tile: the information of local map with 15x15 size.
  • Item: the information of weapon, tool, comsummer that the Entity equiped
  • Market: the information (in selling goods) of global market

Entity Information

In [ ]:
obs[1]['Entity'].keys()
Out[ ]:
dict_keys(['Continuous', 'Discrete', 'N'])
In [ ]:
obs[1]['Entity']['Continuous'].shape
Out[ ]:
(100, 24)
In [ ]:
obs[1]['Entity']['Discrete'].shape
Out[ ]:
(100, 5)
In [ ]:
obs[1]['Entity']['N']
Out[ ]:
array([3], dtype=int32)

The entity information is a dictionary with the following keys

  • Continuous: the continuous features, a 2d ndarray with shape 100*24.
    • The first dimention 100 is the max number of agents that can be observed, and is controlled by config.N_AGENT_OBS.
    • The second dimention 24 is the number of feature columns and the meaning of each column will be explained in detail.
  • Discrete: the discrete features, a 2d ndarray with shape 100*5.
    • The first dimention 100 is the max number of agents that can be observed, and is controlled by config.N_AGENT_OBS.
    • The second dimention 5 is the number of feature columns.
    • Notice that the discrete information is duplicate of (a part of) the continuous information, which means you can simply drop the discrete information.
  • N: the number of agents observed (including yourself) in current vision.

Tile Information

In [ ]:
obs[1]['Tile'].keys()
Out[ ]:
dict_keys(['Continuous', 'Discrete', 'N'])
In [ ]:
obs[1]['Tile']['Continuous'].shape
Out[ ]:
(225, 4)
In [ ]:
obs[1]['Tile']['Discrete'].shape
Out[ ]:
(225, 3)
In [ ]:
obs[1]['Tile']['N']
Out[ ]:
array([15], dtype=int32)

The tile information is a dictionary with the following keys

  • Continuous: the continuous features, a 2d ndarray with shape 225*4.
    • The first dimention 225 is the number of tiles within agent's vision, which is controlled by config.NSTIM. When config.NSTIM=7 by default, the number of tiles is (2*7+1)^2 = 225.
    • The second dimention 4 is the number of feature columns and the meaning of each column will be explained in detail.
  • Discrete: the discrete features, a 2d ndarray with shape 225*3.
    • The first dimention 225 is the number of tiles within agent's vision, which is controlled by config.NSTIM.
    • The second dimention 3 is the number of feature columns.
    • Notice that the discrete information is also duplicate of (a part of) the continuous information, which means you can simply drop the discrete information.
  • N: the number of distinct tile observations (fixed) ## Item Information
In [ ]:
obs[1]['Item'].keys()
Out[ ]:
dict_keys(['Continuous', 'Discrete', 'N'])
In [ ]:
obs[1]['Item']['Continuous'].shape
Out[ ]:
(170, 16)
In [ ]:
obs[1]['Item']['Discrete'].shape
Out[ ]:
(170, 3)
In [ ]:
obs[1]['Item']['N']
Out[ ]:
array([1], dtype=int32)

The item information is a dictionary with the following keys

  • Continuous: the continuous features, a 2d ndarray with shape 170*16.
    • The first dimention 170 is the number of items, which is controlled by config.NPC_LEVEL_MAX. When config.NPC_LEVEL_MAX=10 by default, the number of items is 17*10 = 170.
    • The second dimention 16 is the number of feature columns and the meaning of each column will be explained in detail.
  • Discrete: the discrete features, a 2d ndarray with shape 170*3.
    • The first dimention 170 is the number of items, which is controlled by config.NPC_LEVEL_MAX. When config.NPC_LEVEL_MAX=10 by default, the number of items is 17*10 = 170.
    • The second dimention 3 is the number of feature columns.
    • Notice that the discrete information is also duplicate of (a part of) the continuous information, which means you can simply drop the discrete information.
  • N: the number of distinct item observations (fixed)

Market Information

In [ ]:
obs[1]['Market'].keys()
Out[ ]:
dict_keys(['Continuous', 'Discrete', 'N'])
In [ ]:
obs[1]['Market']['Continuous'].shape
Out[ ]:
(170, 16)
In [ ]:
obs[1]['Market']['Discrete'].shape
Out[ ]:
(170, 3)
In [ ]:
obs[1]['Market']['N']
Out[ ]:
array([0], dtype=int32)

The market information is a dictionary with the following keys

  • Continuous: the continuous features, a 2d ndarray with shape 170*16.
    • The first dimention 170 is the max number of items in market, which is controlled by config.NPC_LEVEL_MAX. When config.NPC_LEVEL_MAX=10 by default, the number of items is 17*10 = 170.
    • The second dimention 16 is the number of feature columns and the meaning of each column will be explained in detail.
  • Discrete: the discrete features, a 2d ndarray with shape 170*3.
    • The first dimention 170 is the number of items, which is controlled by config.NPC_LEVEL_MAX. When config.NPC_LEVEL_MAX=10 by default, the number of items is 17*10 = 170.
    • The second dimention 3 is the number of feature columns.
    • Notice that the discrete information is also duplicate of (a part of) the continuous information, which means you can simply drop the discrete information.
  • N: the number of distinct item observations (fixed)

Feature Columns

Raw Features index1 index2 Dimension Type attr
Obs (raw obs) Entity (100*24) 0 1 scalar Mask
1 1 scalar "ID"
2 1 scalar AttackerID
3 1 scalar Level
4 1 scalar ItemLevel
5 1 scalar Comm
6 1 scalar Population
7 1 scalar R
8 1 scalar C
9 1 scalar Damage
10 1 scalar TimeAlive
11 1 scalar Freeze (deprecated)
12 1 scalar Gold
13 1 scalar Health
14 1 scalar Food
15 1 scalar Water
16 1 scalar Melee Level
17 1 scalar Range Level
18 1 scalar Mage Level
19 1 scalar Fishing Level
20 1 scalar Herbalism Level
21 1 scalar Prospecting Level
22 1 scalar Carving Level
23 1 scalar Alchemy Level
Tile (225*4) 0 1 scalar NEnts
1 1 scalar Index
2 1 scalar R
3 1 scalar C
Item (170*16) 0 1 scalar "ID"
1 1 scalar Index
2 1 scalar Level
3 1 scalar Capacity
4 1 scalar Quantity
5 1 scalar Tradable
6 1 scalar MeleeAttack
7 1 scalar RangeAttack
8 1 scalar MageAttack
9 1 scalar MeleeDefense
10 1 scalar RangeDefense
11 1 scalar MageDefense
12 1 scalar HealthRestore
13 1 scalar ResourceRestore
14 1 scalar Price
15 1 scalar Equipped
Market (170*16) 0 1 scalar "ID"
1 1 scalar Index
2 1 scalar Level
3 1 scalar Capacity
4 1 scalar Quantity
5 1 scalar Tradable
6 1 scalar MeleeAttack
7 1 scalar RangeAttack
8 1 scalar MageAttack
9 1 scalar MeleeDefense
10 1 scalar RangeDefense
11 1 scalar MageDefense
12 1 scalar HealthRestore
13 1 scalar ResourceRestore
14 1 scalar Price
15 1 scalar Equipped

Action Space

In [ ]:
from nmmo.io import action
act_space = env.action_space(agent=1)
print("Action space:")
print("*"*2,action.Attack,": ",act_space[action.Attack])
print("-"*8,action.Style,": ",act_space[action.Attack][action.Style])
print("-"*8,action.Target,": ",act_space[action.Attack][action.Target])
print("*"*2,action.Move,": ",act_space[action.Move])
print("-"*8,action.Direction,act_space[action.Move][action.Direction])
print("*"*2,action.Buy,": ",act_space[action.Buy])
print("-"*8,action.Item, act_space[action.Buy][action.Item])
print("*"*2,action.Sell,": ",act_space[action.Sell])
print("-"*8,action.Item, act_space[action.Sell][action.Item])
print("-"*8,action.Price, act_space[action.Sell][action.Price])
print("*"*2,action.Use,": ",act_space[action.Use])
print("-"*8,action.Item, act_space[action.Use][action.Item])
print("*"*2,action.Comm,": ",act_space[action.Comm])
print("-"*8,action.Token, act_space[action.Comm][action.Token])
Action space:
** <class 'nmmo.io.action.Attack'> :  Dict(<class 'nmmo.io.action.Style'>: Discrete(3), <class 'nmmo.io.action.Target'>: Discrete(100))
-------- <class 'nmmo.io.action.Style'> :  Discrete(3)
-------- <class 'nmmo.io.action.Target'> :  Discrete(100)
** <class 'nmmo.io.action.Move'> :  Dict(<class 'nmmo.io.action.Direction'>: Discrete(4))
-------- <class 'nmmo.io.action.Direction'> Discrete(4)
** <class 'nmmo.io.action.Buy'> :  Dict(<class 'nmmo.io.action.Item'>: Discrete(170))
-------- <class 'nmmo.io.action.Item'> Discrete(170)
** <class 'nmmo.io.action.Sell'> :  Dict(<class 'nmmo.io.action.Item'>: Discrete(170), <class 'nmmo.io.action.Price'>: Discrete(5))
-------- <class 'nmmo.io.action.Item'> Discrete(170)
-------- <class 'nmmo.io.action.Price'> Discrete(5)
** <class 'nmmo.io.action.Use'> :  Dict(<class 'nmmo.io.action.Item'>: Discrete(170))
-------- <class 'nmmo.io.action.Item'> Discrete(170)
** <class 'nmmo.io.action.Comm'> :  Dict(<class 'nmmo.io.action.Token'>: Discrete(170))
-------- <class 'nmmo.io.action.Token'> Discrete(170)

As shown above, the action space is presented as a nested dictionary. And the keys are the classes from nmmo.io.action.

The agent can perform 6 actions at the same timestep:

  1. Attack: you can attack an entity (include npc and other players) within your vision.The action can be empty.(If you don't send this action, the agent will not attack anyone.)

    • Target: Choose the target the agent attack.
    • Style: Choose the style the agent use to attack.
  2. Move: you can move in the four directions. The action can be empty.(If you don't send this action, the agent will stay.)

    • Direction: Choose the direction the agent moves.
  3. Buy: you can buy some items from the glbal market. (If you don't send this action, the agent will not buy any items)

    • Item: Choose items that the agent need in global market to buy.
  4. Sell: you can put some items on the glbal market with preset price. (If you don't send this action, the agent will not sell any items)

    • Item: Choose the items that the agent not need to sell.
    • Price: Choose a preset price to sell the Item.
  5. Use: you can use the consumer item to restrore healthy, food or water. (If you don't send this action, the agent will not use any items)

    • Item: Choose the consumerable items to restore healthy, food or water.
  6. Comm: you can show other agents that items you need

    • Token: represent the items you need

And you should return actions like this:

In [ ]:
from nmmo.io import action
actions = {
  1: {
    action.Attack:{
      action.Style: 0,
      action.Target: 3
      },
    action.Move: {
      action.Direction: 1
    },
    action.Buy: {
      action.Item: 4
    },
    action.Sell: {
      action.Item: 2,
      action.Price: 5
    },
    action.Use: {
      action.Item: 4
    },
    action.Comm: {
      action.Token: 0
    }
  },
  2: {
    action.Attack:{
      action.Style: 0,
      action.Target: 3
      },
    action.Move: {
      action.Direction: 1
    },
    action.Buy: {
      action.Item: 4
    },
    action.Sell: {
      action.Item: 2,
      action.Price: 5
    },
    action.Use: {
      action.Item: 4
    },
    action.Comm: {
      action.Token: 0
    }
  },
  ...
}

Team-Based Env

With game setting of the competition, it would be better to make the input and output based on team. Therefore, users can focus on training teams, and do not need to care about how to seperate players into teams manully.

The TeamBasedEnv is almost the same as the nmmo.Env except for the reset() and step() methods which handle the team-player mapping automatically.

TeamBasedEnv is used in evaluation, and it may be used in training too.

In [ ]:
from neurips2022nmmo import CompetitionConfig, TeamBasedEnv

env = TeamBasedEnv(CompetitionConfig())

# input
actions_by_team = {
    # actions of team0
    0: {
        0: action_of_player0_in_team0,
        1: action_of_player1_in_team0,
        ...
        7: action_of_player7_in_team0,
    },
    # actions of team1
    1: {
        0: action_of_player0_in_team1,
        ...
    },
    ...
    # actions of team15
    15: {
        ...
        7: action_of_player7_in_team15
    },
}

(   
    observations_by_team, 
    rewards_by_team, 
    dones_by_team, 
    infos_by_team,
) = env.step(actions_by_team)

print(observations_by_team)

...

{
    # observations of team0
    0: {
        0: obs_of_player0_in_team0,
        1: obs_of_player1_in_team0,
        ...
        7: obs_of_player7_in_team0,
        'stat': current statistical data,
    },
    # observations of team1
    1: {
        0: obs_of_player0_in_team1,
        ...
    },
    ...
    # observations of team15
    15: {
        ...
        7: obs_of_player7_in_team15
    },
}

Comments

You must login before you can post a comment.

Execute