<jupyter_start><jupyter_text>Buiding playgroundsIn this tutorial, we will see how to build playgrounds with differennt rooms, and how to place objects randomly in the playgrounds.First, we build an empty playground:<jupyter_code>from simple_playgrounds.playgrounds import SingleRoom
from simple_playgrounds import Engine

%matplotlib inline
import matplotlib.pyplot as plt

def plt_image(img):
    plt.axis('off')
    plt.imshow(img)
    plt.show()

my_playground = SingleRoom(size=(300, 300))

# we use the option screen=True to use a keyboard controlled agent later on.
engine = Engine(time_limit=10000, playground= my_playground, screen=False)

plt_image(engine.generate_playground_image(plt_mode=True))<jupyter_output><empty_output><jupyter_text>Placing an element at a random position in the Environment.The initial position of a scene element have to be specified.Instead of a position, you can define an area where the position will be sampled uniformly.In the following, we create a circular area sampler centered at (50, 50) and of radius.We generate 10 objects. Note that we add them without overlapping, meaning that if the playgroundcan't find a suitable position, it will raise an error.<jupyter_code>from simple_playgrounds.playgrounds.scene_elements import Basic
from simple_playgrounds.utils import PositionAreaSampler

area = PositionAreaSampler((50, 50), area_shape='circle', radius=60)
for i in range(10):
    circular_object = Basic(area, physical_shape='circle', radius=5, texture = [120, 230, 0], allow_overlapping = False)
    try:
        my_playground.add_scene_element(circular_object)
    except:
        print('Failed to place object')

plt_image(engine.generate_playground_image(plt_mode=True))<jupyter_output><empty_output><jupyter_text>Area sampler of different shapes and sizes.Other possibe shapes are rectangle, or gaussian.We will allow overlapping for the following added element.<jupyter_code># gaussian area
area = PositionAreaSampler((250, 50), area_shape='gaussian', radius = 80, variance=100)
for i in range(20):
    circular_object = Basic(area, physical_shape='circle', radius=5, texture = [120, 0, 240])
    my_playground.add_scene_element(circular_object)

area = PositionAreaSampler((150, 50), area_shape='rectangle', width_length=(70, 40))
for i in range(20):
    circular_object = Basic(area, physical_shape='circle', radius=5, texture = [120, 230, 0])
    my_playground.add_scene_element(circular_object)


plt_image(engine.generate_playground_image(plt_mode=True))<jupyter_output><empty_output><jupyter_text>Playground provide their own areasWe will see in a following tutorial that playgrounds are formed of different rooms, and that each room has coordinates as a tuple.In the case of a single room, its coordinates are (0,0).Different methods are provided for easily building areas.<jupyter_code>center_area, size_area = my_playground.area_rooms[(0,0)]
area_all = PositionAreaSampler(center=center_area, area_shape='rectangle', width_length=size_area)
for i in range(20):
    circular_object = Basic(area_all, physical_shape='circle', radius=5, texture = [250, 100, 0], allow_overlapping=False)
    try:
        my_playground.add_scene_element(circular_object)
    except:
        print('Failed to place object')

plt_image(engine.generate_playground_image(plt_mode=True))<jupyter_output><empty_output><jupyter_text>Quarter areasFor even more convenience, playgrounds provide quarter areas of rooms.<jupyter_code>center_area, size_area = my_playground.get_quarter_area((0,0), 'up-left')
area_all = PositionAreaSampler(center=center_area, area_shape='rectangle', width_length=size_area)
for i in range(20):
    circular_object = Basic(area_all, physical_shape='circle', radius=5, texture = [0, 100, 250], allow_overlapping=False)
    try:
        my_playground.add_scene_element(circular_object)
    except:
        print('Failed to place object')

plt_image(engine.generate_playground_image(plt_mode=True))<jupyter_output><empty_output><jupyter_text>Reset PlaygroundFinally, Reseting the playground place the added elements in new random positions, sampled in their area.Note that if you placed too many objects which don't allow overlapping, reset might fail.You can always try to reset multiple times until it works.<jupyter_code>engine.reset()

plt_image(engine.generate_playground_image(plt_mode=True))
engine.terminate()<jupyter_output><empty_output><jupyter_text>Playground with roomsOther more advanced playgrounds are available: Linear Rooms and Connected Rooms 2D<jupyter_code>from simple_playgrounds.playgrounds import LinearRooms, ConnectedRooms2D
from simple_playgrounds import Engine
from simple_playgrounds.playgrounds.scene_elements import OpenCloseSwitch

my_playground = LinearRooms(size=(400, 200), n_rooms=2, doorstep_type='middle')
engine = Engine(time_limit=10000, playground= my_playground, screen=False)

plt_image(engine.generate_playground_image(plt_mode=True))<jupyter_output><empty_output><jupyter_text>Once a playground is created, you can access the different doorsteps, and easily add a door and a switch.<jupyter_code># Generate a door for a doorstep
door = my_playground.add_door(((0,0), (1,0)))

position_switch = my_playground.random_position_on_wall(area_coordinates=(0,0), wall_location='right', size_object=30)
switch = OpenCloseSwitch(initial_position=position_switch, door=door, radius = 30)
my_playground.add_scene_element(switch)

plt_image(engine.generate_playground_image(plt_mode=True))<jupyter_output><empty_output><jupyter_text>Opening a door with an agentWe add an agent, that you can control with a keyboard.Go to the switch and activate it with A.<jupyter_code>from simple_playgrounds.agents.controllers import Keyboard
from simple_playgrounds.agents.agents import BaseAgent
from simple_playgrounds.agents.parts.platform import ForwardPlatform

my_agent = BaseAgent(initial_position=(50, 50, 0), controller=Keyboard(), interactive=True, platform=ForwardPlatform)
my_playground.add_agent(my_agent)

engine = Engine(time_limit=10000, playground= my_playground, screen=True)

plt_image(engine.generate_playground_image(plt_mode=True))

engine.run(update_screen=True)
engine.terminate()<jupyter_output><empty_output><jupyter_text>Complex MazesWe can build playgrounds with any number of rooms.We can also set the type of doorsteps, their size, and select from a list of wall themes.<jupyter_code>engine.terminate()
my_playground = ConnectedRooms2D(size=(400, 400), n_rooms=(3,3), doorstep_type='random')
engine = Engine(time_limit=10000, playground= my_playground, screen=False)

plt_image(engine.generate_playground_image(plt_mode=True))<jupyter_output><empty_output><jupyter_text>Let say that we want an object to always appear in the middle-left room.<jupyter_code>position_center, shape = my_playground.area_rooms[(2,1)]
area = PositionAreaSampler(center=position_center, area_shape='rectangle', width_length=shape )
circular_object = Basic(area, physical_shape='circle', radius=5, texture = [120, 230, 0])
my_playground.add_scene_element(circular_object)

plt_image(engine.generate_playground_image(plt_mode=True))
engine.reset()

plt_image(engine.generate_playground_image(plt_mode=True))
engine.terminate()<jupyter_output><empty_output><jupyter_text>Different wall types are available: classic, light, dark, colorful.Nothing prevents you from creating your own using wall_texture.<jupyter_code>my_playground = SingleRoom(size=(300, 300), wall_type='light')
engine = Engine(time_limit=10000, playground= my_playground, screen=False)

plt_image(engine.generate_playground_image(plt_mode=True))
engine.terminate()
my_playground = SingleRoom(size=(300, 300), wall_type='dark')
engine = Engine(time_limit=10000, playground= my_playground, screen=False)

plt_image(engine.generate_playground_image(plt_mode=True))
engine.terminate()
my_playground = SingleRoom(size=(300, 300), wall_type='colorful')
engine = Engine(time_limit=10000, playground= my_playground, screen=False)

plt_image(engine.generate_playground_image(plt_mode=True))
engine.terminate()
my_playground = ConnectedRooms2D(size=(600, 600), n_rooms=(4,4), wall_type='colorful')
engine = Engine(time_limit=10000, playground= my_playground, screen=False)

plt_image(engine.generate_playground_image(plt_mode=True))
engine.terminate()<jupyter_output><empty_output><jupyter_text>Modifying texture of the wallsFinally, we can change texture parameters on the go, by providing additional arguments.<jupyter_code>from simple_playgrounds.utils.texture import UniqueRandomTilesTexture


custom_tecture=UniqueRandomTilesTexture(color_min=(0, 100, 0), color_max=(250, 100, 0), n_colors=4, radius = 100)

my_playground = ConnectedRooms2D(size=(600, 600), n_rooms=(3,3),  wall_texture=custom_tecture)
engine = Engine(time_limit=10000, playground= my_playground, screen=False)

plt_image(engine.generate_playground_image(plt_mode=True))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09357118815213733, 'fraction_numerical': 0.026141590934589926, 'mean_word_length': 8.266112266112266, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 53, '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}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '395512', 'license': 'MIT', 'n_tokens_mistral': 2963, 'n_tokens_neox': 2713, 'n_words': 679, 'path': 'tutorials/jupyter/02_Playgrounds_and_positions.ipynb', 'repo_name': 'Asjidkalam/simple-playgrounds', 'size': '8913'}