<commit_before>====================
Creating experiments
====================
One of the most common tasks when using EnactiveAgents is the creation of new experiments.
When creating a new experiment, you do not change the *model*.
You simply use the model to define a new simulation.

What do experiments consist of?
===============================
Most basically, an experiment consists of a world and a number of agents. In the case of enactive agents, this amounts to four main things each experiment should do:

- define the world layout;
- define the (types of) agents that are in that world;
- define the primitive interactions agents can take, and assign these interactions to the agents;
- define the agent-world interaction logic.


Defining the world
==================
To define a world, first instantiate the ``World`` class:

::
    
    world = model.world.World()
    
In the default model supplied in EnactiveAgents, worlds are rectangular. Set a width and height:

::

    world.set_width(5)
    world.set_height(6)
    
Of course, the world only becomes interesting once we add entities (e.g., structures, agents) to the world. For example, to add a wall at the top-left corner we can do the following:

::

    wall = model.structure.Wall()
    wall.set_position((0,0))
    world.add_entity(wall)
    
Adding an agent is straightforward as well:

::

    agent = model.agent.ConstructiveAgent()
    agent.set_position((2,3))
    world.add(agent)

Automatic world generation
--------------------------
Instead of defining worlds by hand, we can automate the process.
For example, the :doc:`experiment.experiment` modules defines a ``Experiment`` class with a ``parse_world`` method.
This method takes as input a list of strings, and optionally a function to map characters in the strings to objects.
To use it, we create a child of the ``Experiment`` class.
With the default mapper, the above world could be automatically parsed from the semi-graphic representation:

::

    class Exp1(experiment.Experiment):
        world_representation = [
            "w....",
            ".....",
            ".....",
            "..a..",
            ".....",
            ".....",
            ]
        
        def __init__(self):
            super(Exp1, self).__init__()
            world = self.parse_world(world_representation)
    <commit_msg>Fix typo.<commit_after>====================
Creating experiments
====================
One of the most common tasks when using EnactiveAgents is the creation of new experiments.
When creating a new experiment, you do not change the *model*.
You simply use the model to define a new simulation.

What do experiments consist of?
===============================
Most basically, an experiment consists of a world and a number of agents. In the case of enactive agents, this amounts to four main things each experiment should do:

- define the world layout;
- define the (types of) agents that are in that world;
- define the primitive interactions agents can take, and assign these interactions to the agents;
- define the agent-world interaction logic.


Defining the world
==================
To define a world, first instantiate the ``World`` class:

::
    
    world = model.world.World()
    
In the default model supplied in EnactiveAgents, worlds are rectangular. Set a width and height:

::

    world.set_width(5)
    world.set_height(6)
    
Of course, the world only becomes interesting once we add entities (e.g., structures, agents) to the world. For example, to add a wall at the top-left corner we can do the following:

::

    wall = model.structure.Wall()
    wall.set_position((0,0))
    world.add_entity(wall)
    
Adding an agent is straightforward as well:

::

    agent = model.agent.ConstructiveAgent()
    agent.set_position((2,3))
    world.add(agent)

Automatic world generation
--------------------------
Instead of defining worlds by hand, we can automate the process.
For example, the :doc:`experiment.experiment` modules defines an ``Experiment`` class with a ``parse_world`` method.
This method takes as input a list of strings, and optionally a function to map characters in the strings to objects.
To use it, we create a child of the ``Experiment`` class.
With the default mapper, the above world could be automatically parsed from the semi-graphic representation:

::

    class Exp1(experiment.Experiment):
        world_representation = [
            "w....",
            ".....",
            ".....",
            "..a..",
            ".....",
            ".....",
            ]
        
        def __init__(self):
            super(Exp1, self).__init__()
            world = self.parse_world(world_representation)
    
{'fraction_non_alphanumeric': 0.12975153960501168, 'fraction_numerical': 0.0033977489912932683, 'mean_word_length': 2.954659949622166, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2457088', 'n_tokens_mistral': 1207, 'n_tokens_neox': 1172, 'n_words': 539}