Beispiel #1
0
def get_boundary_walls(x_axis: int, y_axis: int):
    """Get a set of the boundary walls."""
    a = Vec2d(0, 0)
    b = Vec2d(x_axis, 0)
    c = Vec2d(x_axis, y_axis)
    d = Vec2d(0, y_axis)
    return {Line2d(a, b), Line2d(b, c), Line2d(c, d), Line2d(d, a)}
Beispiel #2
0
def create_custom_game(cfg: Config, overwrite=False):
    """ Dummy to create a custom-defined game. """
    # Initial parameters
    game_id = 0

    # Create empty Game instance
    game = Game(config=cfg, game_id=game_id, overwrite=overwrite)

    # Put the target on a fixed position
    game.target = Vec2d(0.5, cfg.game.y_axis - 0.5)

    # Set game path
    p = dict()  # TODO!
    for x in range(0, cfg.game.x_axis * 10 + 1):  # TODO!
        for y in range(0, cfg.game.x_axis * 10 + 1):  # TODO!
            p[(x / 10, y / 10)] = Line2d(game.target,
                                         Vec2d(x / 10, y / 10)).get_length()
    game.path = p

    # Create random player
    game.player = MarXBot(game=game)
    game.set_player_init_angle(a=np.pi / 2)
    game.set_player_init_pos(p=Vec2d(cfg.game.x_axis - 0.5, 0.5))

    # Check if implemented correctly
    game.close()
    game.reset()
    game.get_blueprint()
    game.get_observation()
    game.step(0, 0)

    # Save the final game
    game.save()
Beispiel #3
0
 def __init__(self,
              game,  # Type not specified due to circular imports
              r: float = 0
              ):
     """
     Create a new Robot object.
     
     :param game: Reference to the game in which the robot is created [Game]
     :param r: Radius of the circular robot
     """
     # Game specific parameter
     self.game = game  # Game in which robot runs
     
     # Robot specific parameters (Placeholders)
     self.pos = Vec2d(0, 0)  # Current position
     self.init_pos = Vec2d(0, 0)  # Initial position
     self.prev_pos = Vec2d(0, 0)  # Previous current position
     self.angle: float = 0  # Current angle
     self.init_angle: float = 0  # Initial angle
     self.noisy_init_angle: float = 0  # Initial angle with noise
     self.prev_angle: float = 0  # Previous angle
     self.radius: float = r if r else game.bot_config.radius  # Radius of the bot
     
     # Container of all the sensors
     self.sensors: dict = dict()
     
     # Counters for number of sensors used
     self.n_angular: int = 0
     self.n_delta_distance: int = 0
     self.n_distance: int = 0
     
     # Create the sensors (fixed order!)
     self.create_angular_sensors(cfg=game.bot_config)
     self.create_delta_distance_sensor(cfg=game.bot_config)
     self.create_distance_sensor(cfg=game.bot_config)
Beispiel #4
0
 def set_target_random(self):
     """Put the target on a random location."""
     r = random()
     if r < 1 / 5:  # 1/5th chance
         self.target = Vec2d(self.game_config.x_axis / 2 - 0.5, self.game_config.y_axis - 0.5)  # Top center
     elif r < 2 / 5:  # 1/5th chance
         self.target = Vec2d(0.5, self.game_config.y_axis / 2 - 0.5)  # Center left
     else:  # 3/5th chance
         self.target = Vec2d(0.5, self.game_config.y_axis - 0.5)  # Top left
Beispiel #5
0
 def test_other_angles(self):
     """> Check if drone cannot force itself through a wall."""
     # Folder must be root to load in make_net properly
     if os.getcwd().split('\\')[-1] == 'tests': os.chdir('..')
     
     # Create the lines
     zero = Vec2d(0, 0)
     a = Vec2d(1, 1)
     line1 = Line2d(zero, a)
     
     # Tests
     self.assertTrue(pi / 4 - EPSILON <= line1.get_orientation() % (2 * pi) <= pi / 4 + EPSILON)
Beispiel #6
0
 def create_empty_game(self):
     """Create an empty game that only contains the boundary walls."""
     # Create random set of walls
     self.walls = get_boundary_walls(x_axis=self.game_config.x_axis, y_axis=self.game_config.y_axis)
     self.target = Vec2d(0.5, self.game_config.y_axis - 0.5)
     self.player = MarXBot(game=self)
     self.set_player_init_angle(a=pi / 2)
     self.set_player_init_pos(p=Vec2d(self.game_config.x_axis - 0.5, 0.5))
     
     # Save the new game
     self.save()
     if not self.silent: print(f"New game created under id: {self.id}")
Beispiel #7
0
    def measure(self, close_walls: set = None):
        """
        Get the distance to the closest wall. If all the walls are 'far enough', as determined by self.max_dist, then
        the maximum sensor-distance is returned.
        
        :param close_walls: Walls which fall within ray_distance from the agent, speeds up readings
        :return: Float expressing the distance to the closest wall, if there is any
        """
        # Start and end point of ray
        normalized_offset = Vec2d(cos(self.game.player.angle + self.angle),
                                  sin(self.game.player.angle + self.angle))
        self.start_pos = self.game.player.pos + normalized_offset * self.pos_offset
        self.end_pos = self.game.player.pos + normalized_offset * (
            self.pos_offset + self.max_dist)
        sensor_line = Line2d(x=self.game.player.pos, y=self.end_pos)

        # Check if there is a wall intersecting with the sensor and return the closest distance to a wall
        self.value = self.max_dist
        for wall in close_walls if close_walls else self.game.walls:
            inter, pos = line_line_intersection(sensor_line, wall)
            if inter:
                new_dist = (pos - self.start_pos).get_length()
                if self.value > new_dist:
                    self.end_pos = pos
                    self.value = new_dist

        if self.game.noise:
            self.value += random.gauss(0, self.game.noise_proximity)
            self.value = max(0, min(self.value, self.max_dist))
Beispiel #8
0
 def test_simple_length(self):
     """> Test for simple line-segments."""
     # Folder must be root to load in make_net properly
     if os.getcwd().split('\\')[-1] == 'tests': os.chdir('..')
     
     # Create simple lines
     a = Vec2d(1, 1)
     b = Vec2d(1, 2)
     c = Vec2d(2, 2)
     line1 = Line2d(a, b)
     line2 = Line2d(b, c)
     line3 = Line2d(a, c)
     
     # Test the length
     self.assertTrue(1 - EPSILON <= line1.get_length() <= 1 + EPSILON)
     self.assertTrue(1 - EPSILON <= line2.get_length() <= 1 + EPSILON)
     self.assertTrue(sqrt(2) - EPSILON <= line3.get_length() <= sqrt(2) + EPSILON)
Beispiel #9
0
    def load(self):
        """
        Load in a game, specified by its current id.

        :return: True: game successfully loaded | False: otherwise
        """
        try:
            game = load_pickle(f'{self.save_path}{self}')
            self.player = MarXBot(game=self)  # Create a dummy-player to set values on
            self.set_player_init_angle(game[D_ANGLE])
            self.set_player_init_pos(Vec2d(game[D_POS][0], game[D_POS][1]))
            self.path = {p[0]: p[1] for p in game[D_PATH]}
            self.target = Vec2d(game[D_TARGET][0], game[D_TARGET][1])
            self.walls = {Line2d(Vec2d(w[0][0], w[0][1]), Vec2d(w[1][0], w[1][1])) for w in game[D_WALLS]}
            if not self.silent: print(f"Existing game loaded with id: {self.id}")
            return True
        except FileNotFoundError:
            return False
Beispiel #10
0
    def __init__(
            self,
            game,  # Type not specified due to circular imports
            r: float = 0):
        """
        Create a new FootBot object.
        
        :param game: Reference to the game in which the robot is created [Game]
        :param r: Radius of the circular robot
        """
        # Game specific parameter
        self.game = game  # Game in which robot runs

        # Robot specific parameters (Placeholders)
        self.pos = Vec2d(0, 0)  # Current position
        self.init_pos = Vec2d(0, 0)  # Initial position
        self.prev_pos = Vec2d(0, 0)  # Previous current position
        self.angle: float = 0  # Current angle
        self.init_angle: float = 0  # Initial angle
        self.prev_angle: float = 0  # Previous angle
        self.radius: float = r if r else game.bot_config.radius  # Radius of the bot

        # Container of all the sensors
        self.sensors: dict = dict()

        # Counters for number of sensors used
        self.n_proximity: int = 0
        self.n_angular: int = 0
        self.n_delta_distance: int = 0
        self.n_distance: int = 0

        # Create the sensors (fixed order!)
        self.create_proximity_sensors(cfg=game.bot_config)
        self.create_angular_sensors(cfg=game.bot_config)
        self.create_delta_distance_sensor(cfg=game.bot_config)
        self.add_distance_sensor()

        # Number of distance-sensors must always be equal to 1
        assert self.n_distance == 1

        # Set all the sensors as active initially
        self.active_sensors = set(self.sensors.keys())
Beispiel #11
0
 def test_quadrant_angles(self):
     """> Check if drone cannot force itself through a wall."""
     # Folder must be root to load in make_net properly
     if os.getcwd().split('\\')[-1] == 'tests': os.chdir('..')
     
     # Create the lines
     zero = Vec2d(0, 0)
     a = Vec2d(1, 0)
     b = Vec2d(0, 1)
     c = Vec2d(-1, 0)
     d = Vec2d(0, -1)
     line1 = Line2d(zero, a)
     line2 = Line2d(zero, b)
     line3 = Line2d(zero, c)
     line4 = Line2d(zero, d)
     
     # Tests
     self.assertTrue(0 - EPSILON <= line1.get_orientation() % (2 * pi) <= 0 + EPSILON)
     self.assertTrue(pi / 2 - EPSILON <= line2.get_orientation() % (2 * pi) <= pi / 2 + EPSILON)
     self.assertTrue(pi - EPSILON <= line3.get_orientation() % (2 * pi) <= pi + EPSILON)
     self.assertTrue(3 * pi / 2 - EPSILON <= line4.get_orientation() % (2 * pi) <= 3 * pi / 2 + EPSILON)
Beispiel #12
0
def create_experiment_3(overwrite: bool = True, show: bool = True):
    """
    Experiment 3 tests both the generalization capabilities in adapting to newly spawned targets. In this scenario, new
     targets are spawned ones the previous are found, with the goal to find as many as possible.
    
    TRAINING
     During training, new targets are spawned based on the agent's current position. Each target will lay between 4 and
     8 meters from the agent and will always be positioned inside of the maze.
    
    TESTING
     Testing is done similar as was the case for training, with the main difference that the positions of the targets
     are defined beforehand, this to ensure a fair comparison between the different evaluations. 10 targets are created,
     with the idea that it would be impossible for the drone to ever reach this many targets.
    """
    cfg = get_shared_config()

    # Fixed parameters
    ROBOT_INIT_ANGLE = pi / 2  # Looking up
    ROBOT_INIT_POS = Vec2d(cfg.game.x_axis / 2, cfg.game.y_axis /
                           2)  # Initial position of the drone

    # Create the training game
    spawn_f_train = SpawnRandom(game_config=cfg.game, train=True)
    game = Game(
        config=cfg,
        player_noise=0,
        game_id=get_game_id(0, experiment_id=3),
        overwrite=overwrite,
        spawn_func=spawn_f_train,
        stop_if_reached=False,
        wall_bound=False,
    )
    game.player = Robot(game=game)
    game.set_player_init_angle(a=ROBOT_INIT_ANGLE)
    game.set_player_init_pos(p=ROBOT_INIT_POS)
    check_and_save_game(game, show=show)

    # Create 20 evaluation games
    for i in range(1, 21):
        spawn_f_eval = SpawnRandom(game_config=cfg.game, train=False)
        game = Game(
            config=cfg,
            player_noise=0,
            game_id=get_game_id(i, experiment_id=3),
            overwrite=overwrite,
            spawn_func=spawn_f_eval,
            stop_if_reached=False,
            wall_bound=False,
        )
        game.player = Robot(game=game)
        game.set_player_init_angle(a=ROBOT_INIT_ANGLE)
        game.set_player_init_pos(p=ROBOT_INIT_POS)
        check_and_save_game(game, show=show, randomize=False)
Beispiel #13
0
    def __init__(self):

        # Initialize imported pygame modules.
        pygame.mixer.pre_init(44100, 16, 2, 4096)
        pygame.init()
        pygame.mixer.init()

        # Initialize screen object.
        # All visual game objects will have a refrence to this
        # screen object so they can draw to it.
        self.screen = pygame.display.set_mode(
            (config.screenWidth, config.screenHeight), 0, 32)

        # Clock is used to track and control the framerate of the game.
        self.clock = pygame.time.Clock()

        # Game states
        self.paused = 0
        self.running = 1
        self.gameover = 0

        # Sound objects
        self.initSounds()

        # Game stats
        self.stats = {'score': 0, 'level': 1}

        # Game objects
        initialShipPos = Vec2d(
            (config.screenWidth / 2, config.screenHeight / 2))
        self.ship = Ship(self.screen, initialShipPos)
        self.shipBulletController = BulletController(self.screen, self.ship,
                                                     self.bulletSound)

        self.asteroidController = AsteroidController(self.screen, self.ship)

        # Powerup controller
        self.powerupController = PowerupController(self.screen, self.ship,
                                                   self.shipBulletController)

        # Event spawner
        self.eventSpawner = EventSpawner(self.asteroidController,
                                         self.powerupController, self.stats)

        # Screen visuals
        self.visualsController = VisualsController(self.screen,
                                                   self.asteroidController,
                                                   self.shipBulletController,
                                                   self.ship, self.stats)

        # Ship explosion
        self.explosion = None  # Will initialize during game over sequence.
Beispiel #14
0
    def get_wall_coordinates(self):
        """
        :return: Wall coordinates of final maze (excluding boundaries) in original axis-format.
        """
        wall_list = []
        # Horizontal segments
        for x in range(1, self.x_width - 1, 2):
            for y in range(2, self.y_width, 2):
                if self.maze[y, x] == -1:
                    wall_list.append(
                        Line2d(Vec2d((x - 1) // 2, y // 2),
                               Vec2d((x + 1) // 2, y // 2)))
        # Vertical segments
        for x in range(2, self.x_width, 2):
            for y in range(1, self.y_width - 1, 2):
                if self.maze[y, x] == -1:
                    wall_list.append(
                        Line2d(Vec2d(x // 2, (y - 1) // 2),
                               Vec2d(x // 2, (y + 1) // 2)))

        combine_walls(wall_list)
        return wall_list
Beispiel #15
0
def create_dummy_game(i: int = 0, overwrite: bool = True, show: bool = True):
    cfg = get_shared_config()
    ROBOT_INIT_POS = Vec2d(cfg.game.x_axis / 2, cfg.game.y_axis /
                           2)  # Initial position of the drone
    spawn_f = SpawnSimple(game_config=cfg, train=True)
    spawn_f.add_location((1, 1))
    game = Game(
        config=cfg,
        game_id=get_game_id(i, experiment_id=0),
        overwrite=overwrite,
        spawn_func=spawn_f,
    )
    game.player = Robot(game=game)
    game.set_player_init_pos(p=ROBOT_INIT_POS)
    check_and_save_game(game, show=show)
Beispiel #16
0
 def test_negative_component(self):
     """> Test for line-segments with negative components."""
     # Folder must be root to load in make_net properly
     if os.getcwd().split('\\')[-1] == 'tests': os.chdir('..')
     
     # Create simple lines
     a = Vec2d(1, 1)
     b = Vec2d(1, -1)
     c = Vec2d(-1, -1)
     d = Vec2d(-1, 1)
     line1 = Line2d(a, b)
     line2 = Line2d(b, c)
     line3 = Line2d(c, d)
     line4 = Line2d(d, a)
     diag1 = Line2d(a, c)
     diag2 = Line2d(b, d)
     
     # Test the length
     self.assertTrue(2 - EPSILON <= line1.get_length() <= 2 + EPSILON)
     self.assertTrue(2 - EPSILON <= line2.get_length() <= 2 + EPSILON)
     self.assertTrue(2 - EPSILON <= line3.get_length() <= 2 + EPSILON)
     self.assertTrue(2 - EPSILON <= line4.get_length() <= 2 + EPSILON)
     self.assertTrue(sqrt(8) - EPSILON <= diag1.get_length() <= sqrt(8.) + EPSILON)
     self.assertTrue(sqrt(8) - EPSILON <= diag2.get_length() <= sqrt(8.) + EPSILON)
Beispiel #17
0
def get_game():
    cfg = Config()
    cfg.game.fps = 60
    cfg.game.x_axis = 1
    cfg.game.y_axis = 1
    cfg.update()
    spawn = SpawnSimple(game_config=cfg)
    spawn.add_location((10, 10))  # Dummy location
    game = Game(
            config=cfg,
            game_id=0,
            noise=False,
            overwrite=True,
            save_path="tests/games_db/",
            silent=True,
            spawn_func=spawn,
            wall_bound=True,
    )
    game.set_player_init_pos(Vec2d(0.5, 0.5))
    game.sample_target()
    game.reset()
    return game
Beispiel #18
0
 def test_remain_in_box(self):
     """> Set drone in small box in the middle of the game to check if it stays in this box."""
     # Folder must be root to load in make_net properly
     if os.getcwd().split('\\')[-1] == 'tests': os.chdir('..')
     
     # Create empty game
     game = get_game()
     
     # Do 10 different initialized tests
     for _ in range(10):
         # Set player init positions
         game.set_player_init_pos(Vec2d(0.5, 0.5))
         game.player.angle = random() * np.pi
         
         # Run for one twenty seconds
         for _ in range(20 * game.game_config.fps):
             l = random() * 1.5 - 0.5  # [-0.5..1]
             r = random() * 1.5 - 0.5  # [-0.5..1]
             game.step(l=l, r=r)
         
         # Check if bot still in box
         self.assertTrue(0 <= game.player.pos.x <= 1)
         self.assertTrue(0 <= game.player.pos.y <= 1)
Beispiel #19
0
def create_game(
    cfg: Config,
    game_id: int,
    maze: Maze,
    overwrite: bool = False,
    visualize: bool = False,
):
    """
    Create a game based on a list of walls.
    
    :param cfg: The game config
    :param game_id: ID of the game (Integer)
    :param maze: The maze on which the game is based
    :param overwrite: Overwrite pre-existing games
    :param visualize: Visualize the calculations
    """
    # Create empty Game instance
    game = Game(config=cfg, game_id=game_id, overwrite=overwrite, silent=True)

    # Add additional walls to the game
    game.walls.update(set(maze.get_wall_coordinates()))

    # Set the target on a randomized position
    game.set_target_random()

    # App path to the game
    path_list = maze.get_path_coordinates(target_pos=game.target,
                                          visualize=visualize)
    game.path = {p[0]: p[1] for p in path_list}

    # Create random player
    game.player = MarXBot(game=game)
    game.set_player_init_angle(a=np.pi / 2)
    game.set_player_init_pos(p=Vec2d(cfg.game.x_axis - 0.5, 0.5))

    # Save the final game
    game.save()
Beispiel #20
0
 def set_init_pos(self, p: Vec2d):
     """Set the initial position of the robot."""
     self.init_pos = p.__copy__()
     self.pos = p.__copy__()
     self.prev_pos = p.__copy__()
Beispiel #21
0
def combine_walls(wall_list: list):
    """
    Combine every two wall-segments (Line2d) together that can be represented by only one line segment. This will
    increase the performance later on, since the intersection methods must loop over less wall-segments.

    :param wall_list: List<Line2d>
    :return: List<Line2d>
    """
    i = 0
    while i < len(wall_list) - 1:
        concat = False
        # Check if wall at i can be concatenated with wall after i
        for w in wall_list[i + 1:]:
            # Check if in same horizontal line
            if wall_list[i].x.y == wall_list[i].y.y == w.x.y == w.y.y:
                # Check if at least one point collides
                if wall_list[i].x.x == w.x.x:
                    wall_list[i] = Line2d(Vec2d(wall_list[i].y.x, w.x.y),
                                          Vec2d(w.y.x, w.x.y))
                    concat = True
                elif wall_list[i].y.x == w.x.x:
                    wall_list[i] = Line2d(Vec2d(wall_list[i].x.x, w.x.y),
                                          Vec2d(w.y.x, w.x.y))
                    concat = True
                elif wall_list[i].y.x == w.y.x:
                    wall_list[i] = Line2d(Vec2d(wall_list[i].x.x, w.x.y),
                                          Vec2d(w.x.x, w.x.y))
                    concat = True
                elif wall_list[i].x.x == w.y.x:
                    wall_list[i] = Line2d(Vec2d(wall_list[i].y.x, w.x.y),
                                          Vec2d(w.x.x, w.x.y))
                    concat = True

            # Check if in same vertical line
            elif wall_list[i].x.x == wall_list[i].y.x == w.x.x == w.y.x:
                # Check if at least one point collides
                if wall_list[i].x.y == w.x.y:
                    wall_list[i] = Line2d(Vec2d(w.x.x, wall_list[i].y.y),
                                          Vec2d(w.x.x, w.y.y))
                    concat = True
                elif wall_list[i].y.y == w.x.y:
                    wall_list[i] = Line2d(Vec2d(w.x.x, wall_list[i].x.y),
                                          Vec2d(w.x.x, w.y.y))
                    concat = True
                elif wall_list[i].y.y == w.y.y:
                    wall_list[i] = Line2d(Vec2d(w.x.x, wall_list[i].x.y),
                                          Vec2d(w.x.x, w.x.y))
                    concat = True
                elif wall_list[i].x.y == w.y.y:
                    wall_list[i] = Line2d(Vec2d(w.x.x, wall_list[i].y.y),
                                          Vec2d(w.x.x, w.x.y))
                    concat = True

            # If w concatenated with i'th wall in wall_list, then remove w from list and break for-loop
            if concat:
                wall_list.remove(w)
                break

        # Current wall cannot be extended, go to next wall
        if not concat: i += 1
Beispiel #22
0
    def get_path_coordinates(self, target_pos, visualize: bool = False):
        """Define all free-positions together with their distance to the target."""
        # Expand the maze such that every 10cm gets a tile
        y_tiles = self.cfg.game.y_axis * 11 + 1
        x_tiles = self.cfg.game.x_axis * 11 + 1
        maze_expanded = np.zeros((y_tiles, x_tiles))

        # Copy tiles from current maze to the extended maze
        for row in range(y_tiles):
            for col in range(x_tiles):
                #  Cross-section
                if row % 11 == 0 and col % 11 == 0:
                    maze_expanded[row, col] = -1

                # Horizontal walls
                elif row % 11 == 0 and self.maze[(row // 11) * 2,
                                                 (col // 11) * 2 + 1] < 0:
                    maze_expanded[row, col] = -1

                # Vertical walls
                elif col % 11 == 0 and self.maze[(row // 11) * 2 + 1,
                                                 (col // 11) * 2] < 0:
                    maze_expanded[row, col] = -1

        def update(pos_1, pos_2, dist=0.1):
            """
            Update a single position based on its neighbour position.
            
            :param pos_1: Current position
            :param pos_2: Neighbour position that needs to update
            :param dist: Distance (real-life) between the two positions
            """
            if self.in_maze([pos_2[1], pos_2[0]], maze=maze_expanded) and \
                    0 <= maze_expanded[pos_2[1], pos_2[0]] < maze_expanded[pos_1[1], pos_1[0]] - dist:
                maze_expanded[pos_2[1],
                              pos_2[0]] = maze_expanded[pos_1[1],
                                                        pos_1[0]] - dist
                return True
            return False

        def update_neighbours(p):
            updated = set()
            for i in [-1, 1]:
                if update(p, [p[0] + i, p[1]]):
                    updated.add((p[0] + i, p[1]))  # Horizontal
                if update(p, [p[0], p[1] + i]):
                    updated.add((p[0], p[1] + i))  # Vertical
                if update(p, [p[0] + i, p[1] + i], dist=sqrt(0.02)):
                    updated.add((p[0] + i, p[1] + i))  # Diagonal
                if update(p, [p[0] + i, p[1] - i], dist=sqrt(0.02)):
                    updated.add((p[0] + i, p[1] - i))  # V-shaped
            return updated

        # Constant
        VALUE_START = 100

        # Find distance to target
        if visualize: self.visualize_extend(maze=maze_expanded)
        if target_pos == Vec2d(maze.cfg.game.x_axis / 2 - 0.5,
                               maze.cfg.game.y_axis - 0.5):  # Top center
            target = (x_tiles // 2 - 6, y_tiles - 6)
        elif target_pos == Vec2d(0.5, maze.cfg.game.y_axis / 2 -
                                 0.5):  # Center left
            target = (5, y_tiles // 2 - 6)
        elif target_pos == Vec2d(0.5, maze.cfg.game.y_axis - 0.5):  # Top left
            target = (5, y_tiles - 6)
        else:
            raise Exception("Invalid target_pos input")

        maze_expanded[target[1], target[0]] = VALUE_START
        updated_pos = {target}

        # Keep updating all the set_positions' neighbours while change occurs
        while updated_pos:
            new_pos = set()
            for pos in updated_pos:
                new_updated_pos = update_neighbours(pos)
                if new_updated_pos:
                    new_pos.update(new_updated_pos)
            updated_pos = new_pos
        if visualize: self.visualize_extend(maze=maze_expanded)

        # Invert values such that distance to target @target equals 0, and distance at start equals |X-VALUE_START| / 2
        # Note the /2 since 1m in-game is 2 squared here
        for row in range(1, y_tiles - 1):
            for col in range(1, x_tiles - 1):
                if maze_expanded[row, col] > 0:
                    maze_expanded[row, col] = abs(maze_expanded[row, col] -
                                                  VALUE_START)

        # Put values in list
        values = []
        for row in range(1, y_tiles - 1):
            for col in range(1, x_tiles - 1):
                if row % 11 == 0 or col % 11 == 0: continue
                values.append((((row - row // 11) / 10,
                                (col - col // 11) / 10), maze_expanded[col,
                                                                       row]))

        # Copy the 0.1 to 0 values  (normally, a bot is never on a 0.0 path, but just to be sure)
        for row in range(1, y_tiles - 1):
            if row % 11 == 0: continue
            values.append((((row - row // 11) / 10, 0.0), maze_expanded[1,
                                                                        row]))
        for col in range(1, x_tiles - 1):
            if col % 11 == 0: continue
            values.append(((0.0, (col - col // 11) / 10), maze_expanded[col,
                                                                        1]))
        values.append(((0.0, 0.0), maze_expanded[1, 1]))
        if visualize:
            self.visualize_extend(maze=maze_expanded)
            print("Coordinate (fitness) values:")
            for v in values:
                print(v)
        return values
Beispiel #23
0
 def __init__(self, x: Vec2d = None, y: Vec2d = None):
     self.x: Vec2d = x if x else Vec2d(0, 0)
     self.y: Vec2d = y if y else Vec2d(0, 0)
Beispiel #24
0
def create_experiment_1(overwrite: bool = True, show: bool = True):
    """
    Experiment 1 tests the generalization capabilities of the genomes based on the relative direction the target is
     placed.
    
    TRAINING
     Training is done in a maze where the robot is in the center, and the targets are positioned around the agent. Each
     run has a single target sampled. The targets all are positioned 6 meters from the robot's initial position.
    
    TESTING
     Testing is done similar as was the case for training, however, in this scenario only 20 targets are sampled (where
     there were 36 for training). Only 4 of these 20 sampled target positions overlap with the training set.
    """
    cfg = get_shared_config()

    # Fixed parameters
    ROBOT_INIT_ANGLE = pi / 2  # Looking up
    ROBOT_INIT_POS = Vec2d(cfg.game.x_axis / 2, cfg.game.y_axis /
                           2)  # Initial position of the drone

    # Create the training game
    spawn_f_train = SpawnSimple(game_config=cfg, train=True)
    for i in range(0, 360, 10):  # Positions circular in hops of 10 degree
        angle = i / 180 * pi
        offset_x = 6 * cos(angle)
        offset_y = 6 * sin(angle)
        spawn_f_train.add_location(
            (ROBOT_INIT_POS[0] + offset_x, ROBOT_INIT_POS[1] + offset_y))
    game = Game(
        config=cfg,
        player_noise=0,
        game_id=get_game_id(0, experiment_id=1),
        overwrite=overwrite,
        spawn_func=spawn_f_train,
        stop_if_reached=True,
        wall_bound=False,
    )
    game.player = Robot(game=game)
    game.set_player_init_angle(a=ROBOT_INIT_ANGLE)
    game.set_player_init_pos(p=ROBOT_INIT_POS)
    check_and_save_game(game, show=show)

    # Create the evaluation games, each of those only contains one target
    for i in range(1, 21):
        spawn_f_eval = SpawnSimple(game_config=cfg, train=False)
        angle = i / 10 * pi
        offset_x = 6 * cos(angle)
        offset_y = 6 * sin(angle)
        spawn_f_eval.add_location(
            (ROBOT_INIT_POS[0] + offset_x, ROBOT_INIT_POS[1] + offset_y))
        game = Game(
            config=cfg,
            player_noise=0,
            game_id=get_game_id(i, experiment_id=1),
            overwrite=overwrite,
            spawn_func=spawn_f_eval,
            stop_if_reached=True,
            wall_bound=False,
        )
        game.player = Robot(game=game)
        game.set_player_init_angle(a=ROBOT_INIT_ANGLE)
        game.set_player_init_pos(p=ROBOT_INIT_POS)
        check_and_save_game(game, show=show, randomize=False)
Beispiel #25
0
"""
import pygame
from utils.vec2d import Vec2d

# Game config
screenWidth = 1000
screenHeight = 700
framerate = 60

# Ship config
shipHealth = 3
shipTranslationSpeed = 0.2
shipAcceleration = 0.07
shipDecelerationFactor = 0.97
keyToTranslationVector = {
    pygame.K_j: Vec2d((-shipTranslationSpeed, 0)),  # Left
    pygame.K_l: Vec2d((shipTranslationSpeed, 0)),  # Right
    pygame.K_i: Vec2d((0, -shipTranslationSpeed)),  # Up
    pygame.K_k: Vec2d((0, shipTranslationSpeed))  # Down
}

shipRotationSpeed = 0.3
keyToRotationAngle = {
    pygame.K_a: -shipRotationSpeed,  # Counterclockwise
    pygame.K_d: shipRotationSpeed  # Clockwise
}

invincibilityDuration = 3000.0

# BulletController config
timeBetweenBullets = 150
Beispiel #26
0
def create_experiment_6(overwrite: bool = True, show: bool = True):
    """
    Experiment 6 is another 'simplified' simulation in which the agents are trained on a harder environment than they
     are tested on. The reason why is to keep a lower threshold for the 'solution' genomes (only interested in those).
    
    TRAINING
     During training, new targets are spawned based on the agent's initial position. Each target will lay between 2 and
     10 meters from the agent and will always be positioned inside of the maze.
    
    TESTING
     Testing is done on 18 predefined targets position in a relative angle from the agent of k*20° and a distance of
     either 4, 6, or 8 meters (sequential alternating).
    """
    cfg = get_shared_config()

    # Fixed parameters
    ROBOT_INIT_ANGLE = pi / 2  # Looking up
    ROBOT_INIT_POS = Vec2d(cfg.game.x_axis / 2, cfg.game.y_axis /
                           2)  # Initial position of the drone

    # Create the training game
    spawn_f_train = SpawnRange(game_config=cfg.game,
                               train=True,
                               r_max=8,
                               r_min=4)
    game = Game(
        config=cfg,
        player_noise=0,
        game_id=get_game_id(0, experiment_id=6),
        overwrite=overwrite,
        spawn_func=spawn_f_train,
        stop_if_reached=True,
        wall_bound=False,
    )
    game.player = Robot(game=game)
    game.set_player_init_angle(a=ROBOT_INIT_ANGLE)
    game.set_player_init_pos(p=ROBOT_INIT_POS)
    check_and_save_game(game, show=show)

    # Create 18 evaluation games
    for i in range(1, 19):
        spawn_f_eval = SpawnSimple(game_config=cfg.game, train=False)
        angle = i / 9 * pi  # Hops of 20°
        d = 4 if i % 3 == 0 else 6 if i % 3 == 1 else 8
        offset_x = d * cos(angle)
        offset_y = d * sin(angle)
        spawn_f_eval.add_location(
            (ROBOT_INIT_POS[0] + offset_x, ROBOT_INIT_POS[1] + offset_y))
        game = Game(
            config=cfg,
            player_noise=0,
            game_id=get_game_id(i, experiment_id=6),
            overwrite=overwrite,
            spawn_func=spawn_f_eval,
            stop_if_reached=True,
            wall_bound=False,
        )
        game.player = Robot(game=game)
        game.set_player_init_angle(a=ROBOT_INIT_ANGLE)
        game.set_player_init_pos(p=ROBOT_INIT_POS)
        check_and_save_game(game, show=show, randomize=False)
Beispiel #27
0
def create_experiment_2(overwrite: bool = True, show: bool = True):
    """
    Experiment 2 tests the generalization capabilities of the genomes based on their initial distance from the target.
    
    TRAINING
     Training is done in a maze where the robot is in the center, and the targets are positioned around the agent. Each
     run has a single target sampled. The targets all are positioned 6 meters from the robot's initial position.
    
    TESTING
     Testing is done similar as was the case for training. For testing, half of the training's initial target-
     orientations are used (18 instead of 36). However, each orientation now has two targets, both with a different
     initial position from the robot's starting position. An inner-ring has distance 4, where the outer-ring has a
     distance of 8.
    """
    cfg = get_shared_config()

    # Fixed parameters
    ROBOT_INIT_ANGLE = pi / 2  # Looking up
    ROBOT_INIT_POS = Vec2d(cfg.game.x_axis / 2, cfg.game.y_axis /
                           2)  # Initial position of the drone

    # Create the training game
    spawn_f_train = SpawnSimple(game_config=cfg, train=True)
    for i in range(0, 360, 10):  # Positions circular in hops of 10 degree
        angle = i / 180 * pi
        offset_x = 6 * cos(angle)
        offset_y = 6 * sin(angle)
        spawn_f_train.add_location(
            (ROBOT_INIT_POS[0] + offset_x, ROBOT_INIT_POS[1] + offset_y))
    game = Game(
        config=cfg,
        player_noise=0,
        game_id=get_game_id(0, experiment_id=2),
        overwrite=overwrite,
        spawn_func=spawn_f_train,
        stop_if_reached=True,
        wall_bound=False,
    )
    game.player = Robot(game=game)
    game.set_player_init_angle(a=ROBOT_INIT_ANGLE)
    game.set_player_init_pos(p=ROBOT_INIT_POS)
    check_and_save_game(game, show=show)

    # Create the inner circle of the evaluation games, each of those only contains one target
    for i in range(1, 19):
        spawn_f_eval = SpawnSimple(game_config=cfg, train=False)
        angle = i / 9 * pi  # Hops of 20°
        offset_x = 4 * cos(angle)
        offset_y = 4 * sin(angle)
        spawn_f_eval.add_location(
            (ROBOT_INIT_POS[0] + offset_x, ROBOT_INIT_POS[1] + offset_y))
        game = Game(
            config=cfg,
            player_noise=0,
            game_id=get_game_id(i, experiment_id=2),
            overwrite=overwrite,
            spawn_func=spawn_f_eval,
            stop_if_reached=True,
            wall_bound=False,
        )
        game.player = Robot(game=game)
        game.set_player_init_angle(a=ROBOT_INIT_ANGLE)
        game.set_player_init_pos(p=ROBOT_INIT_POS)
        check_and_save_game(game, show=show, randomize=False)

    # Create the outer circle of the evaluation games, each of those only contains one target
    for i in range(1, 19):
        spawn_f_eval = SpawnSimple(game_config=cfg, train=False)
        angle = i / 9 * pi  # Hops of 20°
        offset_x = 8 * cos(angle)
        offset_y = 8 * sin(angle)
        spawn_f_eval.add_location(
            (ROBOT_INIT_POS[0] + offset_x, ROBOT_INIT_POS[1] + offset_y))
        game = Game(
            config=cfg,
            player_noise=0,
            game_id=get_game_id(i + 100, experiment_id=2),
            overwrite=overwrite,
            spawn_func=spawn_f_eval,
            stop_if_reached=True,
            wall_bound=False,
        )
        game.player = Robot(game=game)
        game.set_player_init_angle(a=ROBOT_INIT_ANGLE)
        game.set_player_init_pos(p=ROBOT_INIT_POS)
        check_and_save_game(game, show=show, randomize=False)