mirror of
https://github.com/Farama-Foundation/Gymnasium.git
synced 2025-08-01 06:07:08 +00:00
Add Doom envs (group key doom)
This commit is contained in:
@@ -254,3 +254,51 @@ register(
|
|||||||
'board_size': 9,
|
'board_size': 9,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Doom
|
||||||
|
# ----------------------------------------
|
||||||
|
|
||||||
|
register(
|
||||||
|
id='DoomBasic-v0',
|
||||||
|
entry_point='gym.envs.doom:DoomBasicEnv',
|
||||||
|
)
|
||||||
|
|
||||||
|
register(
|
||||||
|
id='DoomCorridor-v0',
|
||||||
|
entry_point='gym.envs.doom:DoomCorridorEnv',
|
||||||
|
)
|
||||||
|
|
||||||
|
register(
|
||||||
|
id='DoomDefendCenter-v0',
|
||||||
|
entry_point='gym.envs.doom:DoomDefendCenterEnv',
|
||||||
|
)
|
||||||
|
|
||||||
|
register(
|
||||||
|
id='DoomDefendLine-v0',
|
||||||
|
entry_point='gym.envs.doom:DoomDefendLineEnv',
|
||||||
|
)
|
||||||
|
|
||||||
|
register(
|
||||||
|
id='DoomHealthGathering-v0',
|
||||||
|
entry_point='gym.envs.doom:DoomHealthGatheringEnv',
|
||||||
|
)
|
||||||
|
|
||||||
|
register(
|
||||||
|
id='DoomMyWayHome-v0',
|
||||||
|
entry_point='gym.envs.doom:DoomMyWayHomeEnv',
|
||||||
|
)
|
||||||
|
|
||||||
|
register(
|
||||||
|
id='DoomPredictPosition-v0',
|
||||||
|
entry_point='gym.envs.doom:DoomPredictPositionEnv',
|
||||||
|
)
|
||||||
|
|
||||||
|
register(
|
||||||
|
id='DoomTakeCover-v0',
|
||||||
|
entry_point='gym.envs.doom:DoomTakeCoverEnv',
|
||||||
|
)
|
||||||
|
|
||||||
|
register(
|
||||||
|
id='DoomDeathmatch-v0',
|
||||||
|
entry_point='gym.envs.doom:DoomDeathmatchEnv',
|
||||||
|
)
|
||||||
|
10
gym/envs/doom/__init__.py
Normal file
10
gym/envs/doom/__init__.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from gym.envs.doom.doom_env import DoomEnv
|
||||||
|
from gym.envs.doom.doom_basic import DoomBasicEnv
|
||||||
|
from gym.envs.doom.doom_corridor import DoomCorridorEnv
|
||||||
|
from gym.envs.doom.doom_defend_center import DoomDefendCenterEnv
|
||||||
|
from gym.envs.doom.doom_defend_line import DoomDefendLineEnv
|
||||||
|
from gym.envs.doom.doom_health_gathering import DoomHealthGatheringEnv
|
||||||
|
from gym.envs.doom.doom_my_way_home import DoomMyWayHomeEnv
|
||||||
|
from gym.envs.doom.doom_predict_position import DoomPredictPositionEnv
|
||||||
|
from gym.envs.doom.doom_take_cover import DoomTakeCoverEnv
|
||||||
|
from gym.envs.doom.doom_deathmatch import DoomDeathmatchEnv
|
44
gym/envs/doom/assets/basic.cfg
Normal file
44
gym/envs/doom/assets/basic.cfg
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# Lines starting with # are treated as comments (or with whitespaces+#).
|
||||||
|
# It doesn't matter if you use capital letters or not.
|
||||||
|
# It doesn't matter if you use underscore or camel notation for keys, e.g. episode_timeout is the same as episodeTimeout.
|
||||||
|
|
||||||
|
# Rewards (Negative living reward means you lose points for staying alive, and need to finish asap)
|
||||||
|
living_reward = -1
|
||||||
|
|
||||||
|
# Rendering options
|
||||||
|
screen_resolution = RES_640x480
|
||||||
|
screen_format = BGR24
|
||||||
|
render_hud = True
|
||||||
|
render_crosshair = false
|
||||||
|
render_weapon = true
|
||||||
|
render_decals = false
|
||||||
|
render_particles = false
|
||||||
|
|
||||||
|
# make episodes start after 14 tics (after unholstering the gun) (35 tics per seconds)
|
||||||
|
episode_start_time = 14
|
||||||
|
|
||||||
|
# make episodes finish after 35 tics (10 seconds)
|
||||||
|
episode_timeout = 350
|
||||||
|
|
||||||
|
# Available buttons
|
||||||
|
available_buttons =
|
||||||
|
{
|
||||||
|
ATTACK
|
||||||
|
MOVE_RIGHT
|
||||||
|
MOVE_LEFT
|
||||||
|
}
|
||||||
|
|
||||||
|
# Game variables that will be in the state
|
||||||
|
available_game_variables =
|
||||||
|
{
|
||||||
|
KILLCOUNT
|
||||||
|
HEALTH
|
||||||
|
ARMOR
|
||||||
|
SELECTED_WEAPON
|
||||||
|
SELECTED_WEAPON_AMMO
|
||||||
|
AMMO2
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = PLAYER
|
||||||
|
doom_skill = 5
|
||||||
|
sound_enabled = false
|
47
gym/envs/doom/assets/deadly_corridor.cfg
Normal file
47
gym/envs/doom/assets/deadly_corridor.cfg
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# Lines starting with # are treated as comments (or with whitespaces+#).
|
||||||
|
# It doesn't matter if you use capital letters or not.
|
||||||
|
# It doesn't matter if you use underscore or camel notation for keys, e.g. episode_timeout is the same as episodeTimeout.
|
||||||
|
|
||||||
|
# Rewards (Large penalty for being killed)
|
||||||
|
death_penalty = 100
|
||||||
|
|
||||||
|
# Rendering options
|
||||||
|
screen_resolution = RES_640x480
|
||||||
|
screen_format = BGR24
|
||||||
|
render_hud = true
|
||||||
|
render_crosshair = false
|
||||||
|
render_weapon = true
|
||||||
|
render_decals = false
|
||||||
|
render_particles = false
|
||||||
|
|
||||||
|
# Episode Start Time (Immediate)
|
||||||
|
episode_start_time = 0
|
||||||
|
|
||||||
|
# Make episodes finish after 2100 tics (1 minutes)
|
||||||
|
episode_timeout = 2100
|
||||||
|
|
||||||
|
# Available buttons
|
||||||
|
available_buttons =
|
||||||
|
{
|
||||||
|
ATTACK
|
||||||
|
MOVE_RIGHT
|
||||||
|
MOVE_LEFT
|
||||||
|
MOVE_FORWARD
|
||||||
|
TURN_RIGHT
|
||||||
|
TURN_LEFT
|
||||||
|
}
|
||||||
|
|
||||||
|
# Game variables that will be in the state
|
||||||
|
available_game_variables =
|
||||||
|
{
|
||||||
|
KILLCOUNT
|
||||||
|
HEALTH
|
||||||
|
ARMOR
|
||||||
|
SELECTED_WEAPON
|
||||||
|
SELECTED_WEAPON_AMMO
|
||||||
|
AMMO2
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = PLAYER
|
||||||
|
doom_skill = 5
|
||||||
|
sound_enabled = false
|
92
gym/envs/doom/assets/deathmatch.cfg
Normal file
92
gym/envs/doom/assets/deathmatch.cfg
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
# Lines starting with # are treated as comments (or with whitespaces+#).
|
||||||
|
# It doesn't matter if you use capital letters or not.
|
||||||
|
# It doesn't matter if you use underscore or camel notation for keys, e.g. episode_timeout is the same as episodeTimeout.
|
||||||
|
|
||||||
|
# Rendering options
|
||||||
|
screen_resolution = RES_640x480
|
||||||
|
screen_format = BGR24
|
||||||
|
render_hud = true
|
||||||
|
render_crosshair = false
|
||||||
|
render_weapon = true
|
||||||
|
render_decals = false
|
||||||
|
render_particles = false
|
||||||
|
|
||||||
|
# Immediate Start
|
||||||
|
episode_start_time = 0
|
||||||
|
|
||||||
|
# Make episodes finish after 3 minutes (6300 ticks)
|
||||||
|
episode_timeout = 6300
|
||||||
|
|
||||||
|
# Available buttons
|
||||||
|
available_buttons =
|
||||||
|
{
|
||||||
|
ATTACK
|
||||||
|
USE
|
||||||
|
JUMP
|
||||||
|
CROUCH
|
||||||
|
TURN180
|
||||||
|
|
||||||
|
RELOAD
|
||||||
|
ZOOM
|
||||||
|
SPEED
|
||||||
|
STRAFE
|
||||||
|
|
||||||
|
MOVE_RIGHT
|
||||||
|
MOVE_LEFT
|
||||||
|
MOVE_BACKWARD
|
||||||
|
MOVE_FORWARD
|
||||||
|
TURN_RIGHT
|
||||||
|
|
||||||
|
TURN_LEFT
|
||||||
|
LOOK_UP
|
||||||
|
LOOK_DOWN
|
||||||
|
LAND
|
||||||
|
SELECT_WEAPON1
|
||||||
|
|
||||||
|
SELECT_WEAPON2
|
||||||
|
SELECT_WEAPON3
|
||||||
|
SELECT_WEAPON4
|
||||||
|
SELECT_WEAPON5
|
||||||
|
SELECT_WEAPON6
|
||||||
|
|
||||||
|
SELECT_WEAPON7
|
||||||
|
SELECT_WEAPON8
|
||||||
|
SELECT_WEAPON9
|
||||||
|
SELECT_WEAPON0
|
||||||
|
SELECT_NEXT_WEAPON
|
||||||
|
|
||||||
|
SELECT_PREV_WEAPON
|
||||||
|
DROP_SELECTED_WEAPON
|
||||||
|
ACTIVATE_SELECTED_WEAPON
|
||||||
|
SELECT_NEXT_ITEM
|
||||||
|
SELECT_PREV_ITEM
|
||||||
|
|
||||||
|
DROP_SELECTED_ITEM
|
||||||
|
LOOK_UP_DOWN_DELTA
|
||||||
|
TURN_LEFT_RIGHT_DELTA
|
||||||
|
MOVE_FORWARD_BACKWARD_DELTA
|
||||||
|
MOVE_LEFT_RIGHT_DELTA
|
||||||
|
MOVE_UP_DOWN_DELTA
|
||||||
|
}
|
||||||
|
|
||||||
|
# Game variables that will be in the state
|
||||||
|
available_game_variables =
|
||||||
|
{
|
||||||
|
KILLCOUNT
|
||||||
|
HEALTH
|
||||||
|
ARMOR
|
||||||
|
|
||||||
|
SELECTED_WEAPON
|
||||||
|
SELECTED_WEAPON_AMMO
|
||||||
|
|
||||||
|
AMMO1
|
||||||
|
AMMO2
|
||||||
|
AMMO3
|
||||||
|
AMMO4
|
||||||
|
AMMO5
|
||||||
|
AMMO6
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = PLAYER
|
||||||
|
doom_skill = 5
|
||||||
|
sound_enabled = false
|
44
gym/envs/doom/assets/defend_the_center.cfg
Normal file
44
gym/envs/doom/assets/defend_the_center.cfg
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# Lines starting with # are treated as comments (or with whitespaces+#).
|
||||||
|
# It doesn't matter if you use capital letters or not.
|
||||||
|
# It doesn't matter if you use underscore or camel notation for keys, e.g. episode_timeout is the same as episodeTimeout.
|
||||||
|
|
||||||
|
# Rewards
|
||||||
|
death_penalty = 1
|
||||||
|
|
||||||
|
# Rendering options
|
||||||
|
screen_resolution = RES_640x480
|
||||||
|
screen_format = BGR24
|
||||||
|
render_hud = true
|
||||||
|
render_crosshair = false
|
||||||
|
render_weapon = true
|
||||||
|
render_decals = false
|
||||||
|
render_particles = false
|
||||||
|
|
||||||
|
# make episodes start after 14 tics (after unholstering the gun) (35 tics per seconds)
|
||||||
|
episode_start_time = 14
|
||||||
|
|
||||||
|
# Make episodes finish after 2100 tics (1 minutes)
|
||||||
|
episode_timeout = 2100
|
||||||
|
|
||||||
|
# Available buttons
|
||||||
|
available_buttons =
|
||||||
|
{
|
||||||
|
ATTACK
|
||||||
|
TURN_RIGHT
|
||||||
|
TURN_LEFT
|
||||||
|
}
|
||||||
|
|
||||||
|
# Game variables that will be in the state
|
||||||
|
available_game_variables =
|
||||||
|
{
|
||||||
|
KILLCOUNT
|
||||||
|
HEALTH
|
||||||
|
ARMOR
|
||||||
|
SELECTED_WEAPON
|
||||||
|
SELECTED_WEAPON_AMMO
|
||||||
|
AMMO2
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = PLAYER
|
||||||
|
doom_skill = 3
|
||||||
|
sound_enabled = false
|
44
gym/envs/doom/assets/defend_the_line.cfg
Normal file
44
gym/envs/doom/assets/defend_the_line.cfg
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# Lines starting with # are treated as comments (or with whitespaces+#).
|
||||||
|
# It doesn't matter if you use capital letters or not.
|
||||||
|
# It doesn't matter if you use underscore or camel notation for keys, e.g. episode_timeout is the same as episodeTimeout.
|
||||||
|
|
||||||
|
# Rewards
|
||||||
|
death_penalty = 1
|
||||||
|
|
||||||
|
# Rendering options
|
||||||
|
screen_resolution = RES_640x480
|
||||||
|
screen_format = BGR24
|
||||||
|
render_hud = true
|
||||||
|
render_crosshair = false
|
||||||
|
render_weapon = true
|
||||||
|
render_decals = false
|
||||||
|
render_particles = false
|
||||||
|
|
||||||
|
# make episodes start after 14 tics (after unholstering the gun) (35 tics per seconds)
|
||||||
|
episode_start_time = 14
|
||||||
|
|
||||||
|
# Make episodes finish after 2100 tics (1 minutes)
|
||||||
|
episode_timeout = 2100
|
||||||
|
|
||||||
|
# Available buttons
|
||||||
|
available_buttons =
|
||||||
|
{
|
||||||
|
ATTACK
|
||||||
|
TURN_RIGHT
|
||||||
|
TURN_LEFT
|
||||||
|
}
|
||||||
|
|
||||||
|
# Game variables that will be in the state
|
||||||
|
available_game_variables =
|
||||||
|
{
|
||||||
|
KILLCOUNT
|
||||||
|
HEALTH
|
||||||
|
ARMOR
|
||||||
|
SELECTED_WEAPON
|
||||||
|
SELECTED_WEAPON_AMMO
|
||||||
|
AMMO2
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = PLAYER
|
||||||
|
doom_skill = 5
|
||||||
|
sound_enabled = false
|
46
gym/envs/doom/assets/health_gathering.cfg
Normal file
46
gym/envs/doom/assets/health_gathering.cfg
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Lines starting with # are treated as comments (or with whitespaces+#).
|
||||||
|
# It doesn't matter if you use capital letters or not.
|
||||||
|
# It doesn't matter if you use underscore or camel notation for keys, e.g. episode_timeout is the same as episodeTimeout.
|
||||||
|
|
||||||
|
# Rewards (Bonus for staying alive, large penalty for being killed)
|
||||||
|
living_reward = 1
|
||||||
|
death_penalty = 100
|
||||||
|
|
||||||
|
# Rendering options
|
||||||
|
screen_resolution = RES_640x480
|
||||||
|
screen_format = BGR24
|
||||||
|
render_hud = true
|
||||||
|
render_crosshair = false
|
||||||
|
render_weapon = false
|
||||||
|
render_decals = false
|
||||||
|
render_particles = false
|
||||||
|
|
||||||
|
# make episodes start after 14 tics (after unholstering the gun) (35 tics per seconds)
|
||||||
|
episode_start_time = 14
|
||||||
|
|
||||||
|
# Make episodes finish after 2100 tics (1 minutes)
|
||||||
|
episode_timeout = 2100
|
||||||
|
|
||||||
|
# Available buttons
|
||||||
|
available_buttons =
|
||||||
|
{
|
||||||
|
MOVE_FORWARD
|
||||||
|
TURN_RIGHT
|
||||||
|
TURN_LEFT
|
||||||
|
}
|
||||||
|
|
||||||
|
# Game variables that will be in the state
|
||||||
|
available_game_variables =
|
||||||
|
{
|
||||||
|
KILLCOUNT
|
||||||
|
HEALTH
|
||||||
|
ARMOR
|
||||||
|
SELECTED_WEAPON
|
||||||
|
SELECTED_WEAPON_AMMO
|
||||||
|
AMMO2
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = PLAYER
|
||||||
|
doom_skill = 5
|
||||||
|
sound_enabled = false
|
||||||
|
|
45
gym/envs/doom/assets/my_way_home.cfg
Normal file
45
gym/envs/doom/assets/my_way_home.cfg
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# Lines starting with # are treated as comments (or with whitespaces+#).
|
||||||
|
# It doesn't matter if you use capital letters or not.
|
||||||
|
# It doesn't matter if you use underscore or camel notation for keys, e.g. episode_timeout is the same as episodeTimeout.
|
||||||
|
|
||||||
|
# Rewards
|
||||||
|
living_reward = -0.0001
|
||||||
|
|
||||||
|
# Rendering options
|
||||||
|
screen_resolution = RES_640x480
|
||||||
|
screen_format = BGR24
|
||||||
|
render_hud = true
|
||||||
|
render_crosshair = false
|
||||||
|
render_weapon = false
|
||||||
|
render_decals = false
|
||||||
|
render_particles = false
|
||||||
|
|
||||||
|
# make episodes start after 14 tics (after unholstering the gun) (35 tics per seconds)
|
||||||
|
episode_start_time = 14
|
||||||
|
|
||||||
|
# Make episodes finish after 4200 tics (2 minutes)
|
||||||
|
episode_timeout = 4200
|
||||||
|
|
||||||
|
# Available buttons
|
||||||
|
available_buttons =
|
||||||
|
{
|
||||||
|
MOVE_FORWARD
|
||||||
|
TURN_RIGHT
|
||||||
|
TURN_LEFT
|
||||||
|
}
|
||||||
|
|
||||||
|
# Game variables that will be in the state
|
||||||
|
available_game_variables =
|
||||||
|
{
|
||||||
|
KILLCOUNT
|
||||||
|
HEALTH
|
||||||
|
ARMOR
|
||||||
|
SELECTED_WEAPON
|
||||||
|
SELECTED_WEAPON_AMMO
|
||||||
|
AMMO0
|
||||||
|
AMMO2
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = PLAYER
|
||||||
|
doom_skill = 5
|
||||||
|
sound_enabled = false
|
45
gym/envs/doom/assets/predict_position.cfg
Normal file
45
gym/envs/doom/assets/predict_position.cfg
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# Lines starting with # are treated as comments (or with whitespaces+#).
|
||||||
|
# It doesn't matter if you use capital letters or not.
|
||||||
|
# It doesn't matter if you use underscore or camel notation for keys, e.g. episode_timeout is the same as episodeTimeout.
|
||||||
|
|
||||||
|
# Rewards
|
||||||
|
living_reward = -0.0001
|
||||||
|
|
||||||
|
# Rendering options
|
||||||
|
screen_resolution = RES_640x480
|
||||||
|
screen_format = BGR24
|
||||||
|
render_hud = true
|
||||||
|
render_crosshair = false
|
||||||
|
render_weapon = true
|
||||||
|
render_decals = false
|
||||||
|
render_particles = false
|
||||||
|
|
||||||
|
# make episodes start after 16 tics (after unholstering the rocket launcher) (35 tics per seconds)
|
||||||
|
episode_start_time = 16
|
||||||
|
|
||||||
|
# Make episodes finish after 700 tics (20 seconds)
|
||||||
|
episode_timeout = 700
|
||||||
|
|
||||||
|
# Available buttons
|
||||||
|
available_buttons =
|
||||||
|
{
|
||||||
|
ATTACK
|
||||||
|
TURN_RIGHT
|
||||||
|
TURN_LEFT
|
||||||
|
}
|
||||||
|
|
||||||
|
# Game variables that will be in the state
|
||||||
|
available_game_variables =
|
||||||
|
{
|
||||||
|
KILLCOUNT
|
||||||
|
HEALTH
|
||||||
|
ARMOR
|
||||||
|
SELECTED_WEAPON
|
||||||
|
SELECTED_WEAPON_AMMO
|
||||||
|
AMMO2
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = PLAYER
|
||||||
|
doom_skill = 3
|
||||||
|
sound_enabled = false
|
||||||
|
|
43
gym/envs/doom/assets/take_cover.cfg
Normal file
43
gym/envs/doom/assets/take_cover.cfg
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Lines starting with # are treated as comments (or with whitespaces+#).
|
||||||
|
# It doesn't matter if you use capital letters or not.
|
||||||
|
# It doesn't matter if you use underscore or camel notation for keys, e.g. episode_timeout is the same as episodeTimeout.
|
||||||
|
|
||||||
|
# Rewards
|
||||||
|
living_reward = 1
|
||||||
|
|
||||||
|
# Rendering options
|
||||||
|
screen_resolution = RES_640x480
|
||||||
|
screen_format = BGR24
|
||||||
|
render_hud = true
|
||||||
|
render_crosshair = false
|
||||||
|
render_weapon = false
|
||||||
|
render_decals = false
|
||||||
|
render_particles = false
|
||||||
|
|
||||||
|
# make episodes start after 14 tics (after unholstering the gun) (35 tics per seconds)
|
||||||
|
episode_start_time = 14
|
||||||
|
|
||||||
|
# Make episodes finish after 2100 tics (1 minutes)
|
||||||
|
episode_timeout = 2100
|
||||||
|
|
||||||
|
# Available buttons
|
||||||
|
available_buttons =
|
||||||
|
{
|
||||||
|
MOVE_RIGHT
|
||||||
|
MOVE_LEFT
|
||||||
|
}
|
||||||
|
|
||||||
|
# Game variables that will be in the state
|
||||||
|
available_game_variables =
|
||||||
|
{
|
||||||
|
KILLCOUNT
|
||||||
|
HEALTH
|
||||||
|
ARMOR
|
||||||
|
SELECTED_WEAPON
|
||||||
|
SELECTED_WEAPON_AMMO
|
||||||
|
AMMO2
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = PLAYER
|
||||||
|
doom_skill = 5
|
||||||
|
sound_enabled = false
|
63
gym/envs/doom/controls.md
Normal file
63
gym/envs/doom/controls.md
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
###Controls
|
||||||
|
|
||||||
|
Doom is usually played with a full keyboard, and multiple keys can be pressed at once.
|
||||||
|
|
||||||
|
To replicate this, we broke down the possible actions in 40 keys. Each key can be pressed (value of 1), or unpressed (value of 0).
|
||||||
|
|
||||||
|
The deltas (35 to 39) indicate speed of change (values 0 to 10), where higher values will make the player move faster on an axis.
|
||||||
|
|
||||||
|
A list of values is expected to be passed as the action (e.g. [0, 1, 0, 0, 1, 0, .... ]).
|
||||||
|
|
||||||
|
Each map is restricted on what actions can be performed, but the mapping is the same across all maps.
|
||||||
|
|
||||||
|
For example, if we want to [0] - ATTACK, [2] - JUMP, and [12] - MOVE_FORWARD at the same time, we would submit the following action:
|
||||||
|
|
||||||
|
```python
|
||||||
|
action = [0] * 40
|
||||||
|
action[0] = 1
|
||||||
|
action[2] = 1
|
||||||
|
action[12] = 1
|
||||||
|
```
|
||||||
|
|
||||||
|
The full list of possible actions is:
|
||||||
|
|
||||||
|
* [0] - ATTACK - Shoot weapon - Values 0 or 1
|
||||||
|
* [1] - USE - Use item - Values 0 or 1
|
||||||
|
* [2] - JUMP - Jump - Values 0 or 1
|
||||||
|
* [3] - CROUCH - Crouch - Values 0 or 1
|
||||||
|
* [4] - TURN180 - Perform 180 turn - Values 0 or 1
|
||||||
|
* [5] - RELOAD - Reload weapon - Values 0 or 1
|
||||||
|
* [6] - ZOOM - Toggle zoom in/out - Values 0 or 1
|
||||||
|
* [7] - SPEED - Run faster - Values 0 or 1
|
||||||
|
* [8] - STRAFE - Strafe (moving sideways in a circle) - Values 0 or 1
|
||||||
|
* [9] - MOVE_RIGHT - Move to the right - Values 0 or 1
|
||||||
|
* [10] - MOVE_LEFT - Move to the left - Values 0 or 1
|
||||||
|
* [11] - MOVE_BACKWARD - Move backward - Values 0 or 1
|
||||||
|
* [12] - MOVE_FORWARD - Move forward - Values 0 or 1
|
||||||
|
* [13] - TURN_RIGHT - Turn right - Values 0 or 1
|
||||||
|
* [14] - TURN_LEFT - Turn left - Values 0 or 1
|
||||||
|
* [15] - LOOK_UP - Look up - Values 0 or 1
|
||||||
|
* [16] - LOOK_DOWN - Look down - Values 0 or 1
|
||||||
|
* [17] - LAND - Land (e.g. drop from ladder) - Values 0 or 1
|
||||||
|
* [18] - SELECT_WEAPON1 - Select weapon 1 - Values 0 or 1
|
||||||
|
* [19] - SELECT_WEAPON2 - Select weapon 2 - Values 0 or 1
|
||||||
|
* [20] - SELECT_WEAPON3 - Select weapon 3 - Values 0 or 1
|
||||||
|
* [21] - SELECT_WEAPON4 - Select weapon 4 - Values 0 or 1
|
||||||
|
* [22] - SELECT_WEAPON5 - Select weapon 5 - Values 0 or 1
|
||||||
|
* [23] - SELECT_WEAPON6 - Select weapon 6 - Values 0 or 1
|
||||||
|
* [24] - SELECT_WEAPON7 - Select weapon 7 - Values 0 or 1
|
||||||
|
* [25] - SELECT_WEAPON8 - Select weapon 8 - Values 0 or 1
|
||||||
|
* [26] - SELECT_WEAPON9 - Select weapon 9 - Values 0 or 1
|
||||||
|
* [27] - SELECT_WEAPON0 - Select weapon 0 - Values 0 or 1
|
||||||
|
* [28] - SELECT_NEXT_WEAPON - Select next weapon - Values 0 or 1
|
||||||
|
* [29] - SELECT_PREV_WEAPON - Select previous weapon - Values 0 or 1
|
||||||
|
* [30] - DROP_SELECTED_WEAPON - Drop selected weapon - Values 0 or 1
|
||||||
|
* [31] - ACTIVATE_SELECTED_WEAPON - Activate selected weapon - Values 0 or 1
|
||||||
|
* [32] - SELECT_NEXT_ITEM - Select next item - Values 0 or 1
|
||||||
|
* [33] - SELECT_PREV_ITEM - Select previous item - Values 0 or 1
|
||||||
|
* [34] - DROP_SELECTED_ITEM - Drop selected item - Values 0 or 1
|
||||||
|
* [35] - LOOK_UP_DOWN_DELTA - Look Up - Values 0 to 10 (Higher value increases speed)
|
||||||
|
* [36] - TURN_LEFT_RIGHT_DELTA - Turn left/right - Values 0 to 10 (Higher value increases speed)
|
||||||
|
* [37] - MOVE_FORWARD_BACKWARD_DELTA - Move forward/backward - Values 0 to 10 (Higher value increases speed)
|
||||||
|
* [38] - MOVE_LEFT_RIGHT_DELTA - Move left/right - Values 0 to 10 (Higher value increases speed)
|
||||||
|
* [39] - MOVE_UP_DOWN_DELTA - Move up/down - Values 0 to 10 (Higher value increases speed)
|
57
gym/envs/doom/doom_basic.py
Normal file
57
gym/envs/doom/doom_basic.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from doom_py import DoomGame, Mode, Button, GameVariable, ScreenFormat, ScreenResolution, Loader
|
||||||
|
from gym import error, spaces
|
||||||
|
from gym.envs.doom import doom_env
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class DoomBasicEnv(doom_env.DoomEnv):
|
||||||
|
"""
|
||||||
|
------------ Training Mission 1 - Basic ------------
|
||||||
|
This map is rectangular with gray walls, ceiling and floor.
|
||||||
|
You are spawned in the center of the longer wall, and a red
|
||||||
|
circular monster is spawned randomly on the opposite wall.
|
||||||
|
You need to kill the monster (one bullet is enough).
|
||||||
|
|
||||||
|
Allowed actions:
|
||||||
|
[0] - ATTACK - Shoot weapon - Values 0 or 1
|
||||||
|
[9] - MOVE_RIGHT - Move to the right - Values 0 or 1
|
||||||
|
[10] - MOVE_LEFT - Move to the left - Values 0 or 1
|
||||||
|
Note: see controls.md for details
|
||||||
|
|
||||||
|
Rewards:
|
||||||
|
+101 - Killing the monster
|
||||||
|
- 5 - Missing a shot
|
||||||
|
- 1 - Several times per second - Kill the monster faster!
|
||||||
|
|
||||||
|
Goal: 10 points
|
||||||
|
Kill the monster in 3 secs with 1 shot
|
||||||
|
|
||||||
|
Ends when:
|
||||||
|
- Monster is dead
|
||||||
|
- Player is dead
|
||||||
|
- Timeout (10 seconds - 350 frames)
|
||||||
|
-----------------------------------------------------
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
package_directory = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
self.loader = Loader()
|
||||||
|
self.game = DoomGame()
|
||||||
|
self.game.load_config(os.path.join(package_directory, 'assets/basic.cfg'))
|
||||||
|
self.game.set_vizdoom_path(self.loader.get_vizdoom_path())
|
||||||
|
self.game.set_doom_game_path(self.loader.get_freedoom_path())
|
||||||
|
self.game.set_doom_scenario_path(self.loader.get_scenario_path('basic.wad'))
|
||||||
|
self.game.set_doom_map('map01')
|
||||||
|
self.screen_height = 480 # Must match .cfg file
|
||||||
|
self.screen_width = 640 # Must match .cfg file
|
||||||
|
# 3 allowed actions [0, 9, 10] (must match .cfg file)
|
||||||
|
self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3))
|
||||||
|
self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3))
|
||||||
|
self.game.set_window_visible(False)
|
||||||
|
self.viewer = None
|
||||||
|
self.game.init()
|
||||||
|
self.game.new_episode()
|
58
gym/envs/doom/doom_corridor.py
Normal file
58
gym/envs/doom/doom_corridor.py
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from doom_py import DoomGame, Mode, Button, GameVariable, ScreenFormat, ScreenResolution, Loader
|
||||||
|
from gym import error, spaces
|
||||||
|
from gym.envs.doom import doom_env
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class DoomCorridorEnv(doom_env.DoomEnv):
|
||||||
|
"""
|
||||||
|
------------ Training Mission 2 - Corridor ------------
|
||||||
|
This map is designed to improve your navigation. There is a vest
|
||||||
|
at the end of the corridor, with 6 enemies (3 groups of 2). Your goal
|
||||||
|
is to get to the vest as soon as possible, without being killed.
|
||||||
|
|
||||||
|
Allowed actions:
|
||||||
|
[0] - ATTACK - Shoot weapon - Values 0 or 1
|
||||||
|
[9] - MOVE_RIGHT - Move to the right - Values 0 or 1
|
||||||
|
[10] - MOVE_LEFT - Move to the left - Values 0 or 1
|
||||||
|
[12] - MOVE_FORWARD - Move forward - Values 0 or 1
|
||||||
|
[13] - TURN_RIGHT - Turn right - Values 0 or 1
|
||||||
|
[14] - TURN_LEFT - Turn left - Values 0 or 1
|
||||||
|
Note: see controls.md for details
|
||||||
|
|
||||||
|
Rewards:
|
||||||
|
+ dX - For getting closer to the vest
|
||||||
|
- dX - For getting further from the vest
|
||||||
|
-100 - Penalty for being killed
|
||||||
|
|
||||||
|
Goal: 1,270 points
|
||||||
|
Reach the vest (try also killing guards, rather than just running)
|
||||||
|
|
||||||
|
Ends when:
|
||||||
|
- Player touches vest
|
||||||
|
- Player is dead
|
||||||
|
- Timeout (1 minutes - 2,100 frames)
|
||||||
|
-----------------------------------------------------
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
package_directory = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
self.loader = Loader()
|
||||||
|
self.game = DoomGame()
|
||||||
|
self.game.load_config(os.path.join(package_directory, 'assets/deadly_corridor.cfg'))
|
||||||
|
self.game.set_vizdoom_path(self.loader.get_vizdoom_path())
|
||||||
|
self.game.set_doom_game_path(self.loader.get_freedoom_path())
|
||||||
|
self.game.set_doom_scenario_path(self.loader.get_scenario_path('deadly_corridor.wad'))
|
||||||
|
self.screen_height = 480 # Must match .cfg file
|
||||||
|
self.screen_width = 640 # Must match .cfg file
|
||||||
|
# action indexes are [0, 9, 10, 12, 13, 14]
|
||||||
|
self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 6))
|
||||||
|
self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3))
|
||||||
|
self.game.set_window_visible(False)
|
||||||
|
self.viewer = None
|
||||||
|
self.game.init()
|
||||||
|
self.game.new_episode()
|
48
gym/envs/doom/doom_deathmatch.py
Normal file
48
gym/envs/doom/doom_deathmatch.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from doom_py import DoomGame, Mode, Button, GameVariable, ScreenFormat, ScreenResolution, Loader
|
||||||
|
from gym import error, spaces
|
||||||
|
from gym.envs.doom import doom_env
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class DoomDeathmatchEnv(doom_env.DoomEnv):
|
||||||
|
"""
|
||||||
|
------------ Final Mission - Deathmatch ------------
|
||||||
|
Kill as many monsters as possible without being killed.
|
||||||
|
|
||||||
|
Allowed actions:
|
||||||
|
ALL
|
||||||
|
Note: see controls.md for details
|
||||||
|
|
||||||
|
Rewards:
|
||||||
|
+1 - Killing a monster
|
||||||
|
|
||||||
|
Goal: 25 points
|
||||||
|
Kill 25 monsters without being killed
|
||||||
|
|
||||||
|
Ends when:
|
||||||
|
- Player is dead
|
||||||
|
- Timeout (3 minutes - 6,300 frames)
|
||||||
|
-----------------------------------------------------
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
package_directory = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
self.loader = Loader()
|
||||||
|
self.game = DoomGame()
|
||||||
|
self.game.load_config(os.path.join(package_directory, 'assets/deathmatch.cfg'))
|
||||||
|
self.game.set_vizdoom_path(self.loader.get_vizdoom_path())
|
||||||
|
self.game.set_doom_game_path(self.loader.get_freedoom_path())
|
||||||
|
self.game.set_doom_scenario_path(self.loader.get_scenario_path('deathmatch.wad'))
|
||||||
|
self.screen_height = 480 # Must match .cfg file
|
||||||
|
self.screen_width = 640 # Must match .cfg file
|
||||||
|
# 41 allowed actions (must match .cfg file)
|
||||||
|
self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 36 + [[0, 10, 0]] * 5))
|
||||||
|
self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3))
|
||||||
|
self.game.set_window_visible(False)
|
||||||
|
self.viewer = None
|
||||||
|
self.game.init()
|
||||||
|
self.game.new_episode()
|
57
gym/envs/doom/doom_defend_center.py
Normal file
57
gym/envs/doom/doom_defend_center.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from doom_py import DoomGame, Mode, Button, GameVariable, ScreenFormat, ScreenResolution, Loader
|
||||||
|
from gym import error, spaces
|
||||||
|
from gym.envs.doom import doom_env
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class DoomDefendCenterEnv(doom_env.DoomEnv):
|
||||||
|
"""
|
||||||
|
------------ Training Mission 3 - Defend the Center ------------
|
||||||
|
This map is designed to teach you how to kill and how to stay alive.
|
||||||
|
You will also need to keep an eye on your ammunition level. You are only
|
||||||
|
rewarded for kills, so figure out how to stay alive.
|
||||||
|
|
||||||
|
The map is a circle with monsters in the middle. Monsters will
|
||||||
|
respawn with additional health when killed. Kill as many as you can
|
||||||
|
before you run out of ammo.
|
||||||
|
|
||||||
|
Allowed actions:
|
||||||
|
[0] - ATTACK - Shoot weapon - Values 0 or 1
|
||||||
|
[13] - TURN_RIGHT - Turn right - Values 0 or 1
|
||||||
|
[14] - TURN_LEFT - Turn left - Values 0 or 1
|
||||||
|
Note: see controls.md for details
|
||||||
|
|
||||||
|
Rewards:
|
||||||
|
+ 1 - Killing the monster
|
||||||
|
- 1 - Penalty for being killed
|
||||||
|
|
||||||
|
Goal: 10 points
|
||||||
|
Kill 10 monsters (you have 26 ammo)
|
||||||
|
|
||||||
|
Ends when:
|
||||||
|
- Player is dead
|
||||||
|
- Timeout (60 seconds - 2100 frames)
|
||||||
|
-----------------------------------------------------
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
package_directory = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
self.loader = Loader()
|
||||||
|
self.game = DoomGame()
|
||||||
|
self.game.load_config(os.path.join(package_directory, 'assets/defend_the_center.cfg'))
|
||||||
|
self.game.set_vizdoom_path(self.loader.get_vizdoom_path())
|
||||||
|
self.game.set_doom_game_path(self.loader.get_freedoom_path())
|
||||||
|
self.game.set_doom_scenario_path(self.loader.get_scenario_path('defend_the_center.wad'))
|
||||||
|
self.screen_height = 480 # Must match .cfg file
|
||||||
|
self.screen_width = 640 # Must match .cfg file
|
||||||
|
# 3 allowed actions [0, 13, 14] (must match .cfg file)
|
||||||
|
self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3))
|
||||||
|
self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3))
|
||||||
|
self.game.set_window_visible(False)
|
||||||
|
self.viewer = None
|
||||||
|
self.game.init()
|
||||||
|
self.game.new_episode()
|
57
gym/envs/doom/doom_defend_line.py
Normal file
57
gym/envs/doom/doom_defend_line.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from doom_py import DoomGame, Mode, Button, GameVariable, ScreenFormat, ScreenResolution, Loader
|
||||||
|
from gym import error, spaces
|
||||||
|
from gym.envs.doom import doom_env
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class DoomDefendLineEnv(doom_env.DoomEnv):
|
||||||
|
"""
|
||||||
|
------------ Training Mission 4 - Defend the Line ------------
|
||||||
|
This map is designed to teach you how to kill and how to stay alive.
|
||||||
|
Your ammo will automatically replenish. You are only rewarded for kills,
|
||||||
|
so figure out how to stay alive.
|
||||||
|
|
||||||
|
The map is a rectangle with monsters in the middle. Monsters will
|
||||||
|
respawn with additional health when killed. Kill as many as you can
|
||||||
|
before they kill you. This map is harder than the previous.
|
||||||
|
|
||||||
|
Allowed actions:
|
||||||
|
[0] - ATTACK - Shoot weapon - Values 0 or 1
|
||||||
|
[13] - TURN_RIGHT - Turn right - Values 0 or 1
|
||||||
|
[14] - TURN_LEFT - Turn left - Values 0 or 1
|
||||||
|
Note: see controls.md for details
|
||||||
|
|
||||||
|
Rewards:
|
||||||
|
+ 1 - Killing the monster
|
||||||
|
- 1 - Penalty for being killed
|
||||||
|
|
||||||
|
Goal: 25 points
|
||||||
|
Kill 25 monsters
|
||||||
|
|
||||||
|
Ends when:
|
||||||
|
- Player is dead
|
||||||
|
- Timeout (60 seconds - 2100 frames)
|
||||||
|
-----------------------------------------------------
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
package_directory = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
self.loader = Loader()
|
||||||
|
self.game = DoomGame()
|
||||||
|
self.game.load_config(os.path.join(package_directory, 'assets/defend_the_line.cfg'))
|
||||||
|
self.game.set_vizdoom_path(self.loader.get_vizdoom_path())
|
||||||
|
self.game.set_doom_game_path(self.loader.get_freedoom_path())
|
||||||
|
self.game.set_doom_scenario_path(self.loader.get_scenario_path('defend_the_line.wad'))
|
||||||
|
self.screen_height = 480 # Must match .cfg file
|
||||||
|
self.screen_width = 640 # Must match .cfg file
|
||||||
|
# 3 allowed actions [0, 13, 14] (must match .cfg file)
|
||||||
|
self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3))
|
||||||
|
self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3))
|
||||||
|
self.game.set_window_visible(False)
|
||||||
|
self.viewer = None
|
||||||
|
self.game.init()
|
||||||
|
self.game.new_episode()
|
61
gym/envs/doom/doom_env.py
Normal file
61
gym/envs/doom/doom_env.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import logging
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
import numpy
|
||||||
|
|
||||||
|
import gym
|
||||||
|
|
||||||
|
try:
|
||||||
|
import doom_py
|
||||||
|
except ImportError as e:
|
||||||
|
raise gym.error.DependencyNotInstalled("{}. (HINT: you can install Doom dependencies with 'pip install gym[doom].)'".format(e))
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class DoomEnv(gym.Env):
|
||||||
|
metadata = {'render.modes': ['human', 'rgb_array']}
|
||||||
|
|
||||||
|
def _step(self, action):
|
||||||
|
# action is a np array but DoomGame.make_action expects a list of ints
|
||||||
|
list_action = [int(x) for x in action]
|
||||||
|
try:
|
||||||
|
state = self.game.get_state()
|
||||||
|
reward = self.game.make_action(list_action)
|
||||||
|
if self.game.is_episode_finished():
|
||||||
|
is_finished = True
|
||||||
|
else:
|
||||||
|
is_finished = False
|
||||||
|
return state.image_buffer.copy(), reward, is_finished, {}
|
||||||
|
|
||||||
|
except doom_py.vizdoom.doom_is_not_running_exception:
|
||||||
|
return [], 0, True, {}
|
||||||
|
|
||||||
|
def _reset(self):
|
||||||
|
self.game.new_episode()
|
||||||
|
return self.game.get_state().image_buffer.copy()
|
||||||
|
|
||||||
|
def _render(self, mode='human', close=False):
|
||||||
|
if close:
|
||||||
|
if self.viewer is not None:
|
||||||
|
self.viewer.close()
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
state = self.game.get_state()
|
||||||
|
img = state.image_buffer
|
||||||
|
if mode == 'rgb_array':
|
||||||
|
# VizDoom returns None if the episode is finished, let's make it
|
||||||
|
# an empty image so the recorder doesn't stop
|
||||||
|
if img is None:
|
||||||
|
return numpy.zeros((self.screen_height, self.screen_width, 3), dtype=numpy.uint8)
|
||||||
|
return img
|
||||||
|
elif mode is 'human':
|
||||||
|
from gym.envs.classic_control import rendering
|
||||||
|
if self.viewer is None:
|
||||||
|
self.viewer = rendering.SimpleImageViewer()
|
||||||
|
self.viewer.imshow(img)
|
||||||
|
sleep(0.02857) # 35 fps = 0.02857 sleep between frames
|
||||||
|
except doom_py.vizdoom.doom_is_not_running_exception:
|
||||||
|
pass # Doom has been closed
|
||||||
|
|
||||||
|
def _close(self):
|
||||||
|
self.game.close()
|
55
gym/envs/doom/doom_health_gathering.py
Normal file
55
gym/envs/doom/doom_health_gathering.py
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from doom_py import DoomGame, Mode, Button, GameVariable, ScreenFormat, ScreenResolution, Loader
|
||||||
|
from gym import error, spaces
|
||||||
|
from gym.envs.doom import doom_env
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class DoomHealthGatheringEnv(doom_env.DoomEnv):
|
||||||
|
"""
|
||||||
|
------------ Training Mission 5 - Health Gathering ------------
|
||||||
|
This map is a guide on how to survive by collecting health packs.
|
||||||
|
It is a rectangle with green, acidic floor which hurts the player
|
||||||
|
periodically. There are also medkits spread around the map, and
|
||||||
|
additional kits will spawn at interval.
|
||||||
|
|
||||||
|
Allowed actions:
|
||||||
|
[12] - MOVE_FORWARD - Move forward - Values 0 or 1
|
||||||
|
[13] - TURN_RIGHT - Turn right - Values 0 or 1
|
||||||
|
[14] - TURN_LEFT - Turn left - Values 0 or 1
|
||||||
|
Note: see controls.md for details
|
||||||
|
|
||||||
|
Rewards:
|
||||||
|
+ 1 - Several times per second - Survive as long as possible
|
||||||
|
-100 - Death penalty
|
||||||
|
|
||||||
|
Goal: 1000 points
|
||||||
|
Stay alive long enough to reach 1,000 points (~ 30 secs)
|
||||||
|
|
||||||
|
Ends when:
|
||||||
|
- Player is dead
|
||||||
|
- Timeout (60 seconds - 2,100 frames)
|
||||||
|
-----------------------------------------------------
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
package_directory = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
self.loader = Loader()
|
||||||
|
self.game = DoomGame()
|
||||||
|
self.game.load_config(os.path.join(package_directory, 'assets/health_gathering.cfg'))
|
||||||
|
self.game.set_vizdoom_path(self.loader.get_vizdoom_path())
|
||||||
|
self.game.set_doom_game_path(self.loader.get_freedoom_path())
|
||||||
|
self.game.set_doom_scenario_path(self.loader.get_scenario_path('health_gathering.wad'))
|
||||||
|
self.game.set_doom_map('map01')
|
||||||
|
self.screen_height = 480 # Must match .cfg file
|
||||||
|
self.screen_width = 640 # Must match .cfg file
|
||||||
|
# 3 allowed actions [12, 13, 14] (must match .cfg file)
|
||||||
|
self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3))
|
||||||
|
self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3))
|
||||||
|
self.game.set_window_visible(False)
|
||||||
|
self.viewer = None
|
||||||
|
self.game.init()
|
||||||
|
self.game.new_episode()
|
54
gym/envs/doom/doom_my_way_home.py
Normal file
54
gym/envs/doom/doom_my_way_home.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from doom_py import DoomGame, Mode, Button, GameVariable, ScreenFormat, ScreenResolution, Loader
|
||||||
|
from gym import error, spaces
|
||||||
|
from gym.envs.doom import doom_env
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class DoomMyWayHomeEnv(doom_env.DoomEnv):
|
||||||
|
"""
|
||||||
|
------------ Training Mission 6 - My Way Home ------------
|
||||||
|
This map is designed to improve navigational skills. It is a series of
|
||||||
|
interconnected rooms and 1 corridor with a dead end. Each room
|
||||||
|
has a separate color. There is a green vest in one of the room.
|
||||||
|
The vest is always in the same room. Player must find the vest.
|
||||||
|
|
||||||
|
Allowed actions:
|
||||||
|
[12] - MOVE_FORWARD - Move forward - Values 0 or 1
|
||||||
|
[13] - TURN_RIGHT - Turn right - Values 0 or 1
|
||||||
|
[14] - TURN_LEFT - Turn left - Values 0 or 1
|
||||||
|
Note: see controls.md for details
|
||||||
|
|
||||||
|
Rewards:
|
||||||
|
+ 1 - Finding the vest
|
||||||
|
-0.0001 - Several times per second - Find the vest quick!
|
||||||
|
|
||||||
|
Goal: 0.50 point
|
||||||
|
Find the vest
|
||||||
|
|
||||||
|
Ends when:
|
||||||
|
- Vest is found
|
||||||
|
- Timeout (2 minutes - 4,200 frames)
|
||||||
|
-----------------------------------------------------
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
package_directory = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
self.loader = Loader()
|
||||||
|
self.game = DoomGame()
|
||||||
|
self.game.load_config(os.path.join(package_directory, 'assets/my_way_home.cfg'))
|
||||||
|
self.game.set_vizdoom_path(self.loader.get_vizdoom_path())
|
||||||
|
self.game.set_doom_game_path(self.loader.get_freedoom_path())
|
||||||
|
self.game.set_doom_scenario_path(self.loader.get_scenario_path('my_way_home.wad'))
|
||||||
|
self.screen_height = 480 # Must match .cfg file
|
||||||
|
self.screen_width = 640 # Must match .cfg file
|
||||||
|
# 3 allowed actions [12, 13, 14] (must match .cfg file)
|
||||||
|
self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3))
|
||||||
|
self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3))
|
||||||
|
self.game.set_window_visible(False)
|
||||||
|
self.viewer = None
|
||||||
|
self.game.init()
|
||||||
|
self.game.new_episode()
|
60
gym/envs/doom/doom_predict_position.py
Normal file
60
gym/envs/doom/doom_predict_position.py
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from doom_py import DoomGame, Mode, Button, GameVariable, ScreenFormat, ScreenResolution, Loader
|
||||||
|
from gym import error, spaces
|
||||||
|
from gym.envs.doom import doom_env
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class DoomPredictPositionEnv(doom_env.DoomEnv):
|
||||||
|
"""
|
||||||
|
------------ Training Mission 7 - Predict Position ------------
|
||||||
|
This map is designed to train you on using a rocket launcher.
|
||||||
|
It is a rectangular map with a monster on the opposite side. You need
|
||||||
|
to use your rocket launcher to kill it. The rocket adds a delay between
|
||||||
|
the moment it is fired and the moment it reaches the other side of the room.
|
||||||
|
You need to predict the position of the monster to kill it.
|
||||||
|
|
||||||
|
Allowed actions:
|
||||||
|
[0] - ATTACK - Shoot weapon - Values 0 or 1
|
||||||
|
[13] - TURN_RIGHT - Turn right - Values 0 or 1
|
||||||
|
[14] - TURN_LEFT - Turn left - Values 0 or 1
|
||||||
|
Note: see controls.md for details
|
||||||
|
|
||||||
|
Rewards:
|
||||||
|
+ 1 - Killing the monster
|
||||||
|
-0.0001 - Several times per second - Kill the monster faster!
|
||||||
|
|
||||||
|
Goal: 0.5 point
|
||||||
|
Kill the monster
|
||||||
|
|
||||||
|
Hint: Missile launcher takes longer to load. You must wait a good second after the game starts
|
||||||
|
before trying to fire it.
|
||||||
|
|
||||||
|
Ends when:
|
||||||
|
- Monster is dead
|
||||||
|
- Out of missile (you only have one)
|
||||||
|
- Timeout (20 seconds - 700 frames)
|
||||||
|
-----------------------------------------------------
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
package_directory = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
self.loader = Loader()
|
||||||
|
self.game = DoomGame()
|
||||||
|
self.game.load_config(os.path.join(package_directory, 'assets/predict_position.cfg'))
|
||||||
|
self.game.set_vizdoom_path(self.loader.get_vizdoom_path())
|
||||||
|
self.game.set_doom_game_path(self.loader.get_freedoom_path())
|
||||||
|
self.game.set_doom_scenario_path(self.loader.get_scenario_path('predict_position.wad'))
|
||||||
|
self.game.set_doom_map('map01')
|
||||||
|
self.screen_height = 480 # Must match .cfg file
|
||||||
|
self.screen_width = 640 # Must match .cfg file
|
||||||
|
# 3 allowed actions [0, 13, 14] (must match .cfg file)
|
||||||
|
self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3))
|
||||||
|
self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3))
|
||||||
|
self.game.set_window_visible(False)
|
||||||
|
self.viewer = None
|
||||||
|
self.game.init()
|
||||||
|
self.game.new_episode()
|
52
gym/envs/doom/doom_take_cover.py
Normal file
52
gym/envs/doom/doom_take_cover.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
from doom_py import DoomGame, Mode, Button, GameVariable, ScreenFormat, ScreenResolution, Loader
|
||||||
|
from gym import error, spaces
|
||||||
|
from gym.envs.doom import doom_env
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class DoomTakeCoverEnv(doom_env.DoomEnv):
|
||||||
|
"""
|
||||||
|
------------ Training Mission 8 - Take Cover ------------
|
||||||
|
This map is to train you on the damage of incoming missiles.
|
||||||
|
It is a rectangular map with monsters firing missiles and fireballs
|
||||||
|
at you. You need to survive as long as possible.
|
||||||
|
|
||||||
|
Allowed actions:
|
||||||
|
[9] - MOVE_RIGHT - Move to the right - Values 0 or 1
|
||||||
|
[10] - MOVE_LEFT - Move to the left - Values 0 or 1
|
||||||
|
Note: see controls.md for details
|
||||||
|
|
||||||
|
Rewards:
|
||||||
|
+ 1 - Several times per second - Survive as long as possible
|
||||||
|
|
||||||
|
Goal: 750 points
|
||||||
|
Survive for ~ 20 seconds
|
||||||
|
|
||||||
|
Ends when:
|
||||||
|
- Player is dead (one or two fireballs should be enough to kill you)
|
||||||
|
- Timeout (60 seconds - 2,100 frames)
|
||||||
|
-----------------------------------------------------
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
package_directory = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
self.loader = Loader()
|
||||||
|
self.game = DoomGame()
|
||||||
|
self.game.load_config(os.path.join(package_directory, 'assets/take_cover.cfg'))
|
||||||
|
self.game.set_vizdoom_path(self.loader.get_vizdoom_path())
|
||||||
|
self.game.set_doom_game_path(self.loader.get_freedoom_path())
|
||||||
|
self.game.set_doom_scenario_path(self.loader.get_scenario_path('take_cover.wad'))
|
||||||
|
self.game.set_doom_map('map01')
|
||||||
|
self.screen_height = 480 # Must match .cfg file
|
||||||
|
self.screen_width = 640 # Must match .cfg file
|
||||||
|
# 2 allowed actions [9, 10] (must match .cfg file)
|
||||||
|
self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 2))
|
||||||
|
self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3))
|
||||||
|
self.game.set_window_visible(False)
|
||||||
|
self.viewer = None
|
||||||
|
self.game.init()
|
||||||
|
self.game.new_episode()
|
@@ -57,6 +57,12 @@ add_group(
|
|||||||
description='Simple text environments to get you started.'
|
description='Simple text environments to get you started.'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_group(
|
||||||
|
id='doom',
|
||||||
|
name='Doom',
|
||||||
|
description='Doom environments based on VizDoom.'
|
||||||
|
)
|
||||||
|
|
||||||
# classic control
|
# classic control
|
||||||
|
|
||||||
add_task(
|
add_task(
|
||||||
@@ -456,6 +462,61 @@ The game is simulated through the Arcade Learning Environment [ALE]_, which uses
|
|||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# doom
|
||||||
|
add_task(
|
||||||
|
id='DoomBasic-v0',
|
||||||
|
group='doom',
|
||||||
|
experimental=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
add_task(
|
||||||
|
id='DoomCorridor-v0',
|
||||||
|
group='doom',
|
||||||
|
experimental=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
add_task(
|
||||||
|
id='DoomDefendCenter-v0',
|
||||||
|
group='doom',
|
||||||
|
experimental=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
add_task(
|
||||||
|
id='DoomDefendLine-v0',
|
||||||
|
group='doom',
|
||||||
|
experimental=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
add_task(
|
||||||
|
id='DoomHealthGathering-v0',
|
||||||
|
group='doom',
|
||||||
|
experimental=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
add_task(
|
||||||
|
id='DoomMyWayHome-v0',
|
||||||
|
group='doom',
|
||||||
|
experimental=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
add_task(
|
||||||
|
id='DoomPredictPosition-v0',
|
||||||
|
group='doom',
|
||||||
|
experimental=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
add_task(
|
||||||
|
id='DoomTakeCover-v0',
|
||||||
|
group='doom',
|
||||||
|
experimental=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
add_task(
|
||||||
|
id='DoomDeathmatch-v0',
|
||||||
|
group='doom',
|
||||||
|
experimental=True,
|
||||||
|
)
|
||||||
|
|
||||||
# Deprecated
|
# Deprecated
|
||||||
|
|
||||||
# MuJoCo
|
# MuJoCo
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
from .box import Box
|
from .box import Box
|
||||||
from .discrete import Discrete
|
from .discrete import Discrete
|
||||||
|
from .high_low import HighLow
|
||||||
from .tuple_space import Tuple
|
from .tuple_space import Tuple
|
||||||
|
|
||||||
__all__ = ["Box", "Discrete", "Tuple"]
|
__all__ = ["Box", "Discrete", "HighLow", "Tuple"]
|
||||||
|
57
gym/spaces/high_low.py
Normal file
57
gym/spaces/high_low.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
from gym import Space
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
class HighLow(Space):
|
||||||
|
"""
|
||||||
|
A matrix of dimensions n x 3, where
|
||||||
|
|
||||||
|
- n is the number of options in the space (e.g. buttons that can be pressed simultaneously)
|
||||||
|
- u[1] (the first column) is the minimum value (inclusive) that the option can have
|
||||||
|
- u[2] (the second column) is the maximum value (inclusive) that the option can have
|
||||||
|
- u[3] (the third column) is the precision (0 = rounded to integer, 2 = rounded to 2 decimals)
|
||||||
|
|
||||||
|
e.g. if the space is composed of ATTACK (values: 0-100), MOVE_LEFT(0-1), MOVE_RIGHT(0,1)
|
||||||
|
the space would be [ [0.0, 100.0, 2], [0, 1, 0], [0, 1, 0] ]
|
||||||
|
"""
|
||||||
|
def __init__(self, matrix):
|
||||||
|
"""
|
||||||
|
A matrix of shape (n, 3), where the first column is the minimum (inclusive), the second column
|
||||||
|
is the maximum (inclusive), and the third column is the precision (number of decimals to keep)
|
||||||
|
|
||||||
|
e.g. np.matrix([[0, 1, 0], [0, 1, 0], [0.0, 100.0, 2]])
|
||||||
|
"""
|
||||||
|
(num_rows, num_cols) = matrix.shape
|
||||||
|
assert num_rows >= 1
|
||||||
|
assert num_cols == 3
|
||||||
|
self.matrix = matrix
|
||||||
|
self.num_rows = num_rows
|
||||||
|
|
||||||
|
def sample(self):
|
||||||
|
# For each row: round(random .* (max - min) + min, precision)
|
||||||
|
max_minus_min = self.matrix[:, 1] - self.matrix[:, 0]
|
||||||
|
random_matrix = np.multiply(max_minus_min, np.random.rand(self.num_rows, 1)) + self.matrix[:, 0]
|
||||||
|
rounded_matrix = np.zeros(self.num_rows)
|
||||||
|
for i in range(self.num_rows):
|
||||||
|
rounded_matrix[i] = round(random_matrix[i, 0], int(self.matrix[i, 2]))
|
||||||
|
return rounded_matrix
|
||||||
|
|
||||||
|
def contains(self, x):
|
||||||
|
if x.shape[0] != self.num_rows:
|
||||||
|
return False
|
||||||
|
for i in range(self.num_rows):
|
||||||
|
if not (self.matrix[i, 0] <= x[i] <= self.matrix[i, 1]):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def to_jsonable(self, sample_n):
|
||||||
|
return np.array(sample_n).tolist()
|
||||||
|
def from_jsonable(self, sample_n):
|
||||||
|
return [np.asarray(sample) for sample in sample_n]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def shape(self):
|
||||||
|
return self.matrix.shape
|
||||||
|
def __repr__(self):
|
||||||
|
return "High-Low" + str(self.shape)
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.matrix == other.matrix
|
@@ -3,12 +3,13 @@ import json # note: ujson fails this test due to float equality
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
from nose2 import tools
|
from nose2 import tools
|
||||||
|
|
||||||
from gym.spaces import Tuple, Box, Discrete
|
from gym.spaces import Tuple, Box, Discrete, HighLow
|
||||||
|
|
||||||
@tools.params(Discrete(3),
|
@tools.params(Discrete(3),
|
||||||
Tuple([Discrete(5), Discrete(10)]),
|
Tuple([Discrete(5), Discrete(10)]),
|
||||||
Tuple([Discrete(5), Box(np.array([0,0]),np.array([1,5]))]),
|
Tuple([Discrete(5), Box(np.array([0,0]),np.array([1,5]))]),
|
||||||
Tuple((Discrete(5), Discrete(2), Discrete(2)))
|
Tuple((Discrete(5), Discrete(2), Discrete(2))),
|
||||||
|
HighLow(np.matrix([[0, 1, 0], [0, 1, 0], [0.0, 100.0, 2]])),
|
||||||
)
|
)
|
||||||
def test_roundtripping(space):
|
def test_roundtripping(space):
|
||||||
sample_1 = space.sample()
|
sample_1 = space.sample()
|
||||||
|
4
setup.py
4
setup.py
@@ -22,6 +22,7 @@ setup(name='gym',
|
|||||||
'all': ['atari_py>=0.0.17', 'Pillow', 'PyOpenGL',
|
'all': ['atari_py>=0.0.17', 'Pillow', 'PyOpenGL',
|
||||||
'pachi-py>=0.0.19',
|
'pachi-py>=0.0.19',
|
||||||
'box2d-py',
|
'box2d-py',
|
||||||
|
'doom-py',
|
||||||
'mujoco_py>=0.4.3', 'imageio'],
|
'mujoco_py>=0.4.3', 'imageio'],
|
||||||
|
|
||||||
# Environment-specific dependencies. Keep these in sync with
|
# Environment-specific dependencies. Keep these in sync with
|
||||||
@@ -30,8 +31,9 @@ setup(name='gym',
|
|||||||
'board_game' : ['pachi-py>=0.0.19'],
|
'board_game' : ['pachi-py>=0.0.19'],
|
||||||
'box2d': ['box2d-py'],
|
'box2d': ['box2d-py'],
|
||||||
'classic_control': ['PyOpenGL'],
|
'classic_control': ['PyOpenGL'],
|
||||||
|
'doom': ['doom-py'],
|
||||||
'mujoco': ['mujoco_py>=0.4.3', 'imageio'],
|
'mujoco': ['mujoco_py>=0.4.3', 'imageio'],
|
||||||
},
|
},
|
||||||
package_data={'gym': ['envs/mujoco/assets/*.xml', 'envs/classic_control/assets/*.png']},
|
package_data={'gym': ['envs/mujoco/assets/*.xml', 'envs/classic_control/assets/*.png', 'envs/doom/assets/*.cfg']},
|
||||||
tests_require=['nose2', 'mock'],
|
tests_require=['nose2', 'mock'],
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user