Skip to content

Creating your own environments

Oleg Svidchenko edited this page May 26, 2023 · 4 revisions

Basics

All environment classes should be inherited from marlben.Env class.

To see examples of the existing environments, refer to nmmo/envs

Configuring your environment

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

Custom map generation

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)

Creating heuristic baselines

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()

Clone this wiki locally