-
Notifications
You must be signed in to change notification settings - Fork 0
Creating your own environments
Oleg Svidchenko edited this page May 26, 2023
·
4 revisions
All environment classes should be inherited from marlben.Env class.
To see examples of the existing environments, refer to nmmo/envs
Actual logic should be configured in the Config file, for the example you can inherit from the base Config class from marlben.config.base.config, and then inherit additional modules with configs such as NPC
To add custom generation, MAP_GENERATOR should be overriden in the base config file with a custom class like:
class SingleMapGenerator(MapGenerator):
_map = map
def __init__(self, config):
super().__init__(config)
def generate_all_maps(self):
height = self.config.MAP_HEIGHT
width = self.config.MAP_WIDTH
map_width = width + self.config.TERRAIN_BORDER * 2
map_height = height + self.config.TERRAIN_BORDER * 2
top, left = self.config.TERRAIN_BORDER, self.config.TERRAIN_BORDER
map_template = np.zeros(shape=(map_height, map_width, 3), dtype=np.int32)
tiles = np.array(self._map, dtype=np.int32)
map_template[top:top+height, left:left+width] = tiles
# make rock border so the agent doesn't leave the main map
os.makedirs(self.config.PATH_MAPS, exist_ok=True)
map_template[[top-2, top+height+1], left-2:left+width+2, 0] = 5
map_template[top-2:top+height+2, [left-1, left+width], 0] = 5
path = osp.join(self.config.PATH_MAPS, 'map1')
os.makedirs(path, exist_ok=True)
path = osp.join(path, "map.npy")
np.save(path, map_template)Examples of the scripted agents are located in marlben/scripted/environments
Note that scripted agent do not require passing it's actions to the env.step() method. Actions for scripted agents are sampled by environment.
Example of a simple gathering agent:
class GatheringAgent(Scripted):
name = 'GatheringAgent_'
'''Collects Resourses in a simple Gathering Env'''
def __init__(self, config, idx):
super().__init__(config, idx)
self._current_target = "Water"
self._forest_pos = 13
self._water_pos = 10
self._direction = (-1, 0)
def _switch_direction(self, direction):
return tuple([-1 * d for d in direction])
def _manage_direction(self, r, c):
if self._current_target == "Forest" and r == self._forest_pos:
self._direction = self._switch_direction(self._direction)
self._current_target = "Water"
elif self._current_target == "Water" and r == self._water_pos:
self._direction = self._switch_direction(self._direction)
self._current_target = "Forest"
def gather_actions(self):
agent = self.ob.agent
Entity = marlben.Serialized.Entity
r = marlben.scripting.Observation.attribute(agent, Entity.R)
c = marlben.scripting.Observation.attribute(agent, Entity.C)
self._manage_direction(r, c)
direction = move.towards(self._direction)
self.actions[marlben.action.Move] = {marlben.action.Direction: direction}
return self.actions
def attack_actions(self, npc_only=True):
self.scan_agents(npc_only=npc_only)
if self.closest is not None:
self.target = self.closest
self.targetID = self.closestID
self.targetDist = self.closestDist
self.style = marlben.action.Melee
self.attack()
return self.actions
def __call__(self, obs):
super().__call__(obs)
return self.gather_actions()