1. Home
  2. Docs
  3. A set of tutorials
  4. The Basics
  5. Create your first world

Create your first world

Here you will learn to create a simple world of your own.


We will create a simple World, with just one agent and a few objects. The purpose of this tutorial is to familiarize you with the usage of the Builder and how it allows you to quickly build an environment of objects and agents. This tutorial is a logical succession of this tutorial, and this series shows more in depth how to create worlds.

This file on our Github contains the full code of this tutorial.

This is the World you will build.

Design your World

A World in MATRX consists out of a grid. The top-left of this grid has the coordinates (0, 0) and the bottom-right (w, h) where w and h is the World’s width and height respectively. In this tutorial we will be making a simple blue maze surrounded by black walls and a yellow block in the middle. In addition we have one Human Agent that starts in the top left.

When creating a new World, it is important to have a clear view how it will look like. It is much easier to draw it first and convert everything in coordinates then try to design your world with code directly. For our maze, I used good old fashioned paper.

First I drew the maze, consisting of a set of walls, then I added the bounds around it and finally added the start location of the agent and that our treasure in the middle! As you can see, I also wrote down the start and end coordinates of each of the walls we need to add to our world. The result is a world of 14 blocks wide and 13 blocks high.


Make a blueprint

Now we have a good idea how our World will look like, we can start coding! First thing we do, is create our python file with a main block and a function that creates an instance of our Builder. We will use this instance to memorize our World’s blueprint.

from matrx import WorldBuilder

def create_builder():
    # Create our builder
    builder = WorldBuilder(shape=[14, 13], run_matrx_api=True, run_matrx_visualizer=True,
                           visualization_bg_img="", tick_duration=0.1)

    # Return the builder
    return builder

if __name__ == "__main__":
    # Call our method that creates our builder
    builder = create_builder()

    # Start the MATRX API we need for our visualisation
    builder.startup()

    # Create a world
    world = builder.get_world()

    # Run that world (and visit http://localhost:3000)
    world.run(api_info=builder.api_info)

So what is happening in this code?

So on line 1 we import the WorldBuilder class, this is the class for every Builder in MATRX. It offers a wide variety of methods to help you make a blueprint for your World. In this tutorial we will only use four of these methods.

Line 3-9 contains the method that creates a Builder instance and returns it. A close look to line 5 reveals that we set the World’s shape to [14, 13] which stands for a width of 14 blocks and a height of 13 blocks. Furthermore, we tell the Builder that any world it creates will try to connect to the API and runs the default Visualizer. We also set no background image and the tick duration to 0.1. A ‘tick’ is one cycle of the World’s game loop and the tick_duration tells the Builder how long each tick should last (at a minimum) for each World it creates. A duration of 0.1 thus means that the World is updated 10 times per second. If this is set to 0.0 all Worlds from this Builder will try to run as fast as your computer allows.

Line 11-22 contains the main block. On line 13 we call our create_builder() method to obtain our very own Builder. On line 16 we tell MATRX to fire up the API. On line 19 we tell the Builder to create one World and on line 22 we run this world. If we run this code, and take a look at localhost:3000/god we see a completely empty world with a gray background. Not that exciting yet, so let us add the boundary walls!

Add a border

The code below shows how we can use our Builder to add the out walls by using its handy add_room method:

def create_builder():
    # Create our builder, here we specify the world size and a nice background image
    builder = WorldBuilder(shape=[14, 13], run_matrx_api=True, run_matrx_visualizer=True,
                           visualization_bg_img="", tick_duration=0.1)

    # Add the walls surrounding the maze
    builder.add_room(top_left_location=[0, 0], width=14, height=13, name="Borders")

    # Return the builder
    return builder

Line 8-9 are new to our create_builder method. It calls the Builder’s add_room method to create room with its top-left location on (0,0) and a width and height of 14 and 13 respectively. Many things in MATRX requires a name, so we provide a name for this ‘room’ and call it “Borders”. Why do we use the add_room method? Well no other reason except that it comes in handy when we need to create a square of square blocks. We could also arrived at the same by adding a square block object at each edge location of our World but we can agree that this is a bit faster. A room with no fancy things such as doors, is in MATRX simply a rectangle surrounded by square blocks an agent cannot pass through (e.g.: walls).

If we add these two lines to our create_builder method and run the script and visit localhost:3000/god again, we will see a nice gray rectangle surrounded by black walls. Let’s take it up a notch and add our maze.

Add the maze

From the design sketch I made we know the coordinates of each wall and we will use the Builder’s handy method of add_line that adds a line of standard blocks from a start coordinate to its end coordinate.

def create_builder():
    # Create our builder, here we specify the world size and a nice background image
    builder = WorldBuilder(shape=[14, 13], run_matrx_api=True, run_matrx_visualizer=True,
                           visualization_bg_img="", tick_duration=0.1)

    # Add the walls surrounding the maze
    builder.add_room(top_left_location=[0, 0], width=14, height=13, name="Borders")

    # Add the walls to our maze
    builder.add_line(start=[2, 2], end=[6, 2], name="Maze wall")
    builder.add_line(start=[8, 2], end=[11, 2], name="Maze wall")
    builder.add_line(start=[2, 3], end=[2, 5], name="Maze wall")
    builder.add_line(start=[11, 3], end=[11, 5], name="Maze wall")
    builder.add_line(start=[6, 4], end=[8, 4], name="Maze wall")
    builder.add_line(start=[9, 4], end=[9, 7], name="Maze wall")
    builder.add_line(start=[6, 5], end=[6, 6], name="Maze wall")
    builder.add_line(start=[4, 4], end=[4, 8], name="Maze wall")
    builder.add_line(start=[5, 8], end=[9, 8], name="Maze wall")
    builder.add_line(start=[2, 7], end=[2, 9], name="Maze wall")
    builder.add_line(start=[11, 7], end=[11, 9], name="Maze wall")
    builder.add_line(start=[2, 10], end=[5, 10], name="Maze wall")
    builder.add_line(start=[7, 10], end=[11, 10], name="Maze wall")

    # Return the builder
    return builder

Line 11-24 add all the walls for our maze to the blueprint in our Builder. These lines don’t look like much, but that is the point! The Builder’s job is to make your life easier. In the case of the add_line method, the Builder calculates all coordinates that are between its start and end coordinates and adds (in this case) a default blue block object. Although we don’t see it in our maze, this method is also quite able to handle lines under any angle. Again, we see that MATRX requires us to name our lines. In this case we simply call every line “Maze wall”.

Now if we add these lines to our script, run it and visit localhost:3000/god again, we see our maze with blue walls!

Add treasure!

We are still missing the treasure in its center though, so let’s add it.

def create_builder():
    # Create our builder, here we specify the world size and a nice background image
    builder = WorldBuilder(shape=[14, 13], run_matrx_api=True, run_matrx_visualizer=True,
                           visualization_bg_img="", tick_duration=0.1)

    # Add the walls surrounding the maze
    builder.add_room(top_left_location=[0, 0], width=14, height=13, name="Borders")

    # Add the walls to our maze
    builder.add_line(start=[2, 2], end=[6, 2], name="Maze wall")
    builder.add_line(start=[8, 2], end=[11, 2], name="Maze wall")
    builder.add_line(start=[2, 3], end=[2, 5], name="Maze wall")
    builder.add_line(start=[11, 3], end=[11, 5], name="Maze wall")
    builder.add_line(start=[6, 4], end=[8, 4], name="Maze wall")
    builder.add_line(start=[9, 4], end=[9, 7], name="Maze wall")
    builder.add_line(start=[6, 5], end=[6, 6], name="Maze wall")
    builder.add_line(start=[4, 4], end=[4, 8], name="Maze wall")
    builder.add_line(start=[5, 8], end=[9, 8], name="Maze wall")
    builder.add_line(start=[2, 7], end=[2, 9], name="Maze wall")
    builder.add_line(start=[11, 7], end=[11, 9], name="Maze wall")
    builder.add_line(start=[2, 10], end=[5, 10], name="Maze wall")
    builder.add_line(start=[7, 10], end=[11, 10], name="Maze wall")

    # Add our treasure chest!
    builder.add_object(location=[7, 5], name="Treasure!", visualize_colour="#fcba03",
                       is_traversable=True)

    # Return the builder
    return builder

Lines 26-28 are new, and calls the Builder’s add_object method. This is the Builder’s most generic and basic method you can use to add objects, hence it is also the most versatile. However, here we simply provide it with a location (7, 5) to add a default block with the name “Treasure!” and dark yellow colour. In addition we also set the is_traversable variable to True. What this means is that agents can walk over this object, it is ‘traversable’.

Now, if again we run our script with this change we see our entire blue maze surrounded by black walls and a dark yellow block in the middle, representing our golden treasure hoard! The only thing missing is an agent. For this tutorial we will add a Human Agent which you can control to reach all that treasure.

Add the agent

To add the Human Agent we make use of the Builder’s handy add_human_agent method.

from matrx import WorldBuilder
from matrx.actions.move_actions import *
from matrx.agents import HumanAgentBrain

def create_builder():
    # Create our builder, here we specify the world size and a nice background image
    builder = WorldBuilder(shape=[14, 13], run_matrx_api=True, run_matrx_visualizer=True,
                           visualization_bg_img="", tick_duration=0.1)

    # Add the walls surrounding the maze
    builder.add_room(top_left_location=[0, 0], width=14, height=13, name="Borders")

    # Add the walls to our maze
    builder.add_line(start=[2, 2], end=[6, 2], name="Maze wall")
    builder.add_line(start=[8, 2], end=[11, 2], name="Maze wall")
    builder.add_line(start=[2, 3], end=[2, 5], name="Maze wall")
    builder.add_line(start=[11, 3], end=[11, 5], name="Maze wall")
    builder.add_line(start=[6, 4], end=[8, 4], name="Maze wall")
    builder.add_line(start=[9, 4], end=[9, 7], name="Maze wall")
    builder.add_line(start=[6, 5], end=[6, 6], name="Maze wall")
    builder.add_line(start=[4, 4], end=[4, 8], name="Maze wall")
    builder.add_line(start=[5, 8], end=[9, 8], name="Maze wall")
    builder.add_line(start=[2, 7], end=[2, 9], name="Maze wall")
    builder.add_line(start=[11, 7], end=[11, 9], name="Maze wall")
    builder.add_line(start=[2, 10], end=[5, 10], name="Maze wall")
    builder.add_line(start=[7, 10], end=[11, 10], name="Maze wall")

    # Add our treasure chest!
    builder.add_object(location=[7, 5], name="Treasure!", visualize_colour="#fcba03",
                       is_traversable=True)

    # Add a human controllable agent with certain controls and a GIF
    key_action_map = {
        'w': MoveNorth.__name__,
        'd': MoveEast.__name__,
        's': MoveSouth.__name__,
        'a': MoveWest.__name__,
    }
    brain = HumanAgentBrain()
    builder.add_human_agent(location=[1, 1], agent=brain, name="Human",
                            key_action_map=key_action_map,
                            img_name="/static/images/agent.gif")

    # Return the builder
    return builder

Lines 3-4 are new and import two things we need; the Human Agent (in fact, only its brain as the Builder will create its body and shoves this brain in it) and all of MATRX’ move actions we need to create a mapping of key-strokes to actions. This mapping is made in the new lines 31-36 which shows the creation of a dictionary with as keys the alphanumeric key-strokes and as values the names of the action classes that should be triggered on that stroke. Here we use the __name__ property of a class to make sure we make no typos, but we might just as well have typed the string “MoveNorth” instead of MoveNorth.__name__ for instance. This mapping represents a straightforward WASD control.

Line 39 shows the creation of a HumanAgentBrain, all agents in MATRX exist out a body and brain. The body is made by the Builder on World creation but it needs a brain to control it. In our case, this is a brain that listens to keystrokes and translates these to actions.

In line 40 this brain we just created is added to the Builder’s blueprint at location (1, 1) with the name “Human”. We also provide the mapping of keystrokes to actions and tell MATRX to visualize the agent with a nice GIF. This GIF links to the set of images that come for free with MATRX, which you can access in the relative path “/static/images” (see this on our Github for the images that are packed with MATRX).

An Agent’s body is made by the Builder when a new World is created. The Builder adds at that moment a brain to that body. So if we tell a Builder to add a new agent, whether a Human Agent or Autonomous Agent, we need to tell it which brain belongs to it. This offers two major advantages:

1) Brains only contain decision logic.
2) Brains exist over different Worlds created by the same Builder.


These come in handy for example, when a brain learns over different Worlds or if you want to plug a brain in a different body. You can read more about this here.

Now, if we add this entire create_builder method to our script with the main block and run it we finished our first World! Take control of your agent by going to the Visualizer’s start view at localhost:3000 and select the Human Agent from the drop down menu. Don’t forget to press play in the God view, otherwise the World won’t start. If you did this you can control your Human Agent in its own view!

See this file on our Github for the complete script we made here.


Was this article helpful to you? Yes No

Leave a Reply

Your email address will not be published. Required fields are marked *