From 817e8586c693a97611a987d140eee321496154a9 Mon Sep 17 00:00:00 2001 From: Brandon Rodriguez <brodriguez8774@gmail.com> Date: Sat, 6 Nov 2021 14:31:18 -0400 Subject: [PATCH] Implement "limited vision" ai setting --- src/systems.py | 142 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 134 insertions(+), 8 deletions(-) diff --git a/src/systems.py b/src/systems.py index ca3088c..99dd9c9 100644 --- a/src/systems.py +++ b/src/systems.py @@ -11,7 +11,7 @@ from abc import ABC # User Imports. from src.entities.system_entities import AI, Movement from src.logging import init_logging -from src.misc import calc_trash_distances, calc_traveling_salesman, get_tile_coord_from_id +from src.misc import calc_trash_distances, calc_traveling_salesman, get_tile_coord_from_id, get_tile_from_id # Initialize logger. @@ -446,7 +446,7 @@ class AISystem(sdl2.ext.Applicator, AbstractMovementSystem): logger.debug('Setting "prev_direction" to {0}'.format(prev_direction)) self.prev_direction = prev_direction - def move_full_sight(self, sprite): + def move_full_sight(self, sprite, path_set=None): """ Move roomba with "full sight" setting. @@ -454,9 +454,10 @@ class AISystem(sdl2.ext.Applicator, AbstractMovementSystem): information. Roomba intelligently attempts to take the "most efficient path" to get to all trash piles. :param sprite: Roomba sprite entity. """ - # Get first set in "calculated ideal path". - end_tile_group_id = self.data_manager.ideal_overall_path['ordering'][1] - path_set = self.data_manager.ideal_trash_paths['roomba'][end_tile_group_id] + if path_set is None: + # Get first set in "calculated ideal path". + end_tile_group_id = self.data_manager.ideal_overall_path['ordering'][1] + path_set = self.data_manager.ideal_trash_paths['roomba'][end_tile_group_id] # Get first tile in path set. curr_tile_id = path_set[0] @@ -489,6 +490,131 @@ class AISystem(sdl2.ext.Applicator, AbstractMovementSystem): raise RuntimeError('Unable to determine where to move.') def move_limited_vision(self, sprite): - """""" - # Move roomba. - self.move_east(sprite) + """ + Move roomba with "limited vision" setting. + + Roomba does not have "full sight", but can see some squares within a certain tile radius. + For sake of easier implementation, roomba has x-ray vision and can see through walls. + + On failure to find any trash within vision radius, roomba defaults to "bump sensor" movement. + :param sprite: Roomba sprite entity. + """ + # Get current radius setting. + vision_radius = self.data_manager.roomba_vision + if vision_radius < 1: + err_msg = 'Roomba "limited vision" setting must have a positive integer for range. Found :{0}'.format( + vision_radius, + ) + raise RuntimeError(err_msg) + + # Compile list of all tiles within current vision range. + tiles_in_vision = [] + roomba_x, roomba_y = sprite.tile + x_index = 0 + while x_index <= vision_radius: + y_index = 0 + + while x_index + y_index <= vision_radius: + + # Handle for (+x/+y) tiles. + tile_x = roomba_x + x_index + tile_y = roomba_y + y_index + + # Skip bad tile coord locations. + if ( + # Skip tile roomba is on. + (roomba_x == tile_x and roomba_y == tile_y) or + # Skip already-checked tiles. + ('{0}, {1}'.format(tile_x, tile_y) in tiles_in_vision) or + # Skip tiles with invalid x-axises. + (tile_x < 0 or tile_x > (self.data_manager.tile_data['tile_w_count'] - 1)) or + # Skip tiles with invalid y-axises. + (tile_y < 0 or tile_y > (self.data_manager.tile_data['tile_h_count'] - 1)) + ): + pass + else: + # Append tile to list. + tiles_in_vision.append('{0}, {1}'.format(tile_x, tile_y)) + + # Handle for (+x/-y) tiles. + tile_x = roomba_x + x_index + tile_y = roomba_y - y_index + + # Skip bad tile coord locations. + if ( + # Skip tile roomba is on. + (roomba_x == tile_x and roomba_y == tile_y) or + # Skip already-checked tiles. + ('{0}, {1}'.format(tile_x, tile_y) in tiles_in_vision) or + # Skip tiles with invalid x-axises. + (tile_x < 0 or tile_x > (self.data_manager.tile_data['tile_w_count'] - 1)) or + # Skip tiles with invalid y-axises. + (tile_y < 0 or tile_y > (self.data_manager.tile_data['tile_h_count'] - 1)) + ): + pass + else: + # Append tile to list. + tiles_in_vision.append('{0}, {1}'.format(tile_x, tile_y)) + + # Handle for (-x/+y) tiles. + tile_x = roomba_x - x_index + tile_y = roomba_y + y_index + + # Skip bad tile coord locations. + if ( + # Skip tile roomba is on. + (roomba_x == tile_x and roomba_y == tile_y) or + # Skip already-checked tiles. + ('{0}, {1}'.format(tile_x, tile_y) in tiles_in_vision) or + # Skip tiles with invalid x-axises. + (tile_x < 0 or tile_x > (self.data_manager.tile_data['tile_w_count'] - 1)) or + # Skip tiles with invalid y-axises. + (tile_y < 0 or tile_y > (self.data_manager.tile_data['tile_h_count'] - 1)) + ): + pass + else: + # Append tile to list. + tiles_in_vision.append('{0}, {1}'.format(tile_x, tile_y)) + + # Handle for (-x/-y) tiles. + tile_x = roomba_x - x_index + tile_y = roomba_y - y_index + + # Skip bad tile coord locations. + if ( + # Skip tile roomba is on. + (roomba_x == tile_x and roomba_y == tile_y) or + # Skip already-checked tiles. + ('{0}, {1}'.format(tile_x, tile_y) in tiles_in_vision) or + # Skip tiles with invalid x-axises. + (tile_x < 0 or tile_x > (self.data_manager.tile_data['tile_w_count'] - 1)) or + # Skip tiles with invalid y-axises. + (tile_y < 0 or tile_y > (self.data_manager.tile_data['tile_h_count'] - 1)) + ): + pass + else: + # Append tile to list. + tiles_in_vision.append('{0}, {1}'.format(tile_x, tile_y)) + + y_index += 1 + + x_index += 1 + + # Ensure no duplicates are in set. + tiles_in_vision = list(set(tiles_in_vision)) + + # Loop through set of tiles and go to first found trash tile (if any). + has_moved = False + for tile_id in tiles_in_vision: + next_tile = get_tile_from_id(self.data_manager, tile_id) + + # Check if trash exists at location. + if next_tile.trashpile.exists: + # Trash exists. Attempt to move to location. + self.move_full_sight(sprite, path_set=['{0}, {1}'.format(roomba_x, roomba_y), tile_id]) + has_moved = True + break + + if has_moved is False: + # Failed to find any tiles within range. Revert to "bump sensor" mode. + self.move_bump_sensor(sprite) -- GitLab