def prepare(self): # get best score self.main.gameApp.cursor.execute(self.bestQuery) rows = self.main.gameApp.cursor.fetchall() for row in rows: self.data.best = row[0] # create foods self.data.foods.clear() for _ in range(768): x = random.randint(0, 31) y = random.randint(0, 23) newFood = GameTile(x, y) self.data.foods.append(newFood) if self.data.turn > 1 and self.evolution and self.data.doEvolution: self.evolution.generatePopulation(self.data.population) self.data.generation += 1 self.evolution.doMutation() # create snake(s) self.data.population = self.data.tempPopulation self.data.snakes.clear() for i in range(self.data.population): newWeights = None if self.data.turn > 1 and self.evolution and self.data.doEvolution: newWeights = self.evolution.newGeneration.weights[i] elif self.data.turn > 1: # if no evolution use old weights newWeights = self.weights[i] elif self.data.turn == 1 and self.data.isTrained: # apply trained weights to first turn snakes newWeights = self.data.weights snake = Snake(self.data.startSize, self.data.foods, self.type, newWeights, self.main.gameApp.db) if self.type % 2 == 0: snake.aiSensor = AiSensor(snake, 1) else: snake.aiSensor = AiSensor(snake, 2) self.data.snakes.append(snake) self.data.displayedSnake = self.data.snakes[0] self.data.state = 1 self.data.dead = 0 self.map.prepare() self.update()
def __init__(self, root, res=20): self.root = root width, height = self.root.get_size() self.cols = int(width / res) self.rows = int(height / res) self.res = res self.gen_food() self.player = Snake(self.root, (400, 300), res=self.res)
def __init__(self, weights, apple_position=None): self.__snake = Snake() self.__apple = Apple(numpy.array([0, 0])) self.__score = 0 self.__clock = pygame.time.Clock() self.__weights = weights self.__remaining_moves = config.MOVES self.__display_manager = DisplayManager(self.__snake, self.__apple) self.__time_alive = 0 self.__apple_position = apple_position self.__neural_network = NeuralNetwork(self.__weights)
def __init__(self, width, height): self._width = width self._height = height self.game_state = 'init' self.action_list = ['u','d','l','r',None] self.snake = Snake(width, height) self.candy = Candy(width, height) self.world_map = Map(width, height) self.world_map.make_lst(self.snake, self.candy) self.done = False
def reset(self): ''' Reset state (e.g. Game over) and return init state ''' self.game_state = 'init' self.snake = Snake(self.width, self.height) self.candy = Candy(self.width, self.height) self.world_map = Map(self.width, self.height) self.world_map.make_lst(self.snake, self.candy) self.done = False return self.state
def on_join(data): global thread_lock this_user = user.findById(data['user_id']) room_id = data['room_id'] room = game_rooms[room_id] join_room(room_id) if this_user is not None and len(room.snakes) < 5: user_ids[request.sid] = data['user_id'] user_snakes[request.sid] = Snake(name=this_user[1], is_ai=False, sid=request.sid, uid=data['user_id']) room.removeSnake(request.sid) room.addSnake(user_snakes[request.sid]) socketio.emit('status_update', user_snakes[request.sid].colour) else: socketio.emit('status_update', 'spectating') def send_room_state(): while True: time.sleep(0.1) for room_id, room in game_rooms.items(): old_board = [] # Don't need to send an update if the board's the same if not old_board == room.board: socketio.emit('board_changed', {'board': room.board}, room=room_id) old_board = [x[:] for x in room.board] # Deep copies the list def send_scores(): while True: time.sleep(0.1) for room_id, room in game_rooms.items(): old_snakes = [] snakes = [{ 'name': s.name, 'colour': s.colour, 'score': s.score } for s in sorted(room.snakes, reverse=True)] # Don't need to send an update if snakes hasn't changed if not old_snakes == snakes: socketio.emit('scores_changed', {'snakes': snakes}, room=room_id) old_snakes = snakes.copy() # Deep copies the list if thread_lock == None: thread_lock = True socketio.start_background_task(target=send_room_state) socketio.start_background_task(target=send_scores)
def __init__(self, code_id, log=False, visualization=False, fps=60): self.code_id = code_id self.snake = Snake(WINDOW_WIDTH, WINDOW_HEIGHT, PIXEL_SIZE, WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2) self.food = Food(WINDOW_WIDTH, WINDOW_HEIGHT, PIXEL_SIZE) self.food.spawn(self.snake) self.log = log self.visualization = visualization self.window, self.clock = self.init_visualization() self.fps = fps # basic infos self.alive = True self.score = 0 self.step = 0 # useful infos self.s_obstacles = self.get_surrounding_obstacles() self.food_angle = self.get_food_angle() self.food_distance = self.get_food_distance()
def __init__(self, visible=True, waitForEyes=False): self.visible= visible self.waitForEyes= waitForEyes self.iterations_count = 0 self.score = 0 #self.main_snake = Snake(4, 4 ) self.main_snake = Snake(random.randint(4,11), random.randint(3,4) ) self.apple_eaten = False self.apple = self.spawn_apple() self.running = True # self.last_info = self.get_info() self.grow_snake = False pygame.init() pygame.display.set_caption("Snake") pygame.font.init() if (not self.visible): pygame.display.iconify() random.seed() self.main_screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.HWSURFACE) self.score_font = pygame.font.Font(None, 25) self.score_area_font = pygame.font.Font(None, 25) self.game_over_font = pygame.font.Font(None, 45) self.play_again_font = self.score_area_font self.score_msg = self.score_font.render("Score:", 1, pygame.Color("white")) self.score_msg_size = self.score_font.size("Score") self.background_color = pygame.Color(100, 100, 100) image_path = os.path.dirname(__file__) self.apple_image = pygame.transform.scale( pygame.image.load(os.path.join(image_path, "apple.png")).convert_alpha(), (BLOCK_SIZE, BLOCK_SIZE)) self.snake_image = pygame.transform.scale( pygame.image.load(os.path.join(image_path, "snake_box.jpg")).convert_alpha(), (BLOCK_SIZE, BLOCK_SIZE))
class GameManager(): game_over = False food = None def __init__(self, root, res=20): self.root = root width, height = self.root.get_size() self.cols = int(width / res) self.rows = int(height / res) self.res = res self.gen_food() self.player = Snake(self.root, (400, 300), res=self.res) def reset(self): del self.player self.player = Snake(self.root, (400, 300), res=self.res) self.gen_food() self.game_over = False def gen_food(self): fx = randint(0, self.cols - 1) fy = randint(0, self.rows - 1) self.food = pygame.Rect(fx * self.res, fy * self.res, self.res, self.res) def draw_food(self): if self.food: food_color = (200, 34, 34) pygame.draw.rect(self.root, food_color, self.food) def _draw_map(self): cell_color = (200, 200, 200, 10) for row in range(self.rows): for col in range(self.cols): cell = pygame.Rect(col * self.res, row * self.res, self.res, self.res) pygame.draw.rect(self.root, cell_color, cell, 1) def update(self, dt, events): for event in events: if event.key == pygame.K_ESCAPE: self.reset() return self.player.update(dt, events) head = self.player.body[-1] if head and head.colliderect(self.food): self.player.grow() self.gen_food() def draw(self): # self._draw_map() self.draw_food() self.player.draw()
def player_init(menu): """ Visszaadja a létrehozott játékosok listáját Paraméterek: menu: létrehozott menü """ players = [] colors = [Color.GREEN, Color.ORANGE] control = [[pygame.K_LEFT, pygame.K_RIGHT, pygame.K_DOWN, pygame.K_UP], [pygame.K_a, pygame.K_d, pygame.K_s, pygame.K_w]] for i in range(menu.player_num): player = Snake(menu.player_names[i], 0, 0, Image.snake_heads[i], colors[i], control[i]) players.append(player) return players
def main(): # initial direction is right direction = Direction.RIGHT # init board size, snake and food position board = Board(11, 20, Snake(10, 8), Food(5, 10)) # parse command line arguments args = parse_arguments() # init LCD and Pillow lcd = NokiaLCD() pillow = Pillow(lcd.width, lcd.height) # output the board output_board(board, args.output, lcd, pillow) try: last_update = time.time() with Raw(sys.stdin): with NonBlocking(sys.stdin): while True: # read input key from stdin key = sys.stdin.read(1) if key in ['w', 's', 'a', 'd']: direction = Direction.from_key(key) elif key == '\x1b': # x1b is ESC - ends the game break time.sleep(0.05) # once in a specified turn_time, move the board and redraw it if time.time() - last_update > (1 / int(args.speed)): board.next_turn(direction) output_board(board, args.output, lcd, pillow) last_update = time.time() except CollisionException: output_game_over(board, args.output, lcd, pillow) except IOError: print("I/O not ready.") except KeyboardInterrupt: pass
def main(): window = pygame.display.set_mode( (WINDOW_WIDTH * PIXEL_SIZE, WINDOW_HEIGHT * PIXEL_SIZE)) pygame.display.set_caption('SNAKE GAME') clock = pygame.time.Clock() score = 0 snake = Snake(WINDOW_WIDTH, WINDOW_HEIGHT, PIXEL_SIZE, WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2) food = Food(WINDOW_WIDTH, WINDOW_HEIGHT, PIXEL_SIZE) run = True while run: for event in pygame.event.get(): if event.type == pygame.QUIT: run = False break elif event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: snake.change_direction(-1) break elif event.key == pygame.K_RIGHT: snake.change_direction(+1) break snake.move() if snake.collision_food(food.location): score += 1 food.state = False food.spawn(snake) if snake.collision_obstacles(): print('over') run = False if snake.get_length() == WINDOW_WIDTH * WINDOW_HEIGHT: print('win') run = False window.fill((0, 0, 0)) food.render(window) snake.render(window) pygame.display.set_caption('SNAKE GAME | Score: ' + str(score)) pygame.display.update() clock.tick(FPS)
def __init__(self): for _ in range(GEN_SIZE): self.snakes.append(Snake()) self.NNs.append(NN()) self.apples.append(Apple())
class SnakeEnvironment(object): def __init__(self, width, height): self._width = width self._height = height self.game_state = 'init' self.action_list = ['u','d','l','r',None] self.snake = Snake(width, height) self.candy = Candy(width, height) self.world_map = Map(width, height) self.world_map.make_lst(self.snake, self.candy) self.done = False @property def height(self): return self._height @property def width(self): return self._width def _replace_item_map(self, x): if x in 'v^><': return 0 elif x == '@': return 1 elif x == '*': return 2 else: return 3 @property def state(self): ''' Return state from raw map wall - 0 snake - 1 candy - 2 ''' state_map = self.world_map.map.copy() for i in range(self.height): state_map[i] = list(map(self._replace_item_map, state_map[i])) return np.array(state_map) def reset(self): ''' Reset state (e.g. Game over) and return init state ''' self.game_state = 'init' self.snake = Snake(self.width, self.height) self.candy = Candy(self.width, self.height) self.world_map = Map(self.width, self.height) self.world_map.make_lst(self.snake, self.candy) self.done = False return self.state def step(self, action): ''' Input: Int - action Output: Float - reward Move an act, return state, reward & done ''' self.snake.move(self.candy, self.action_list[action]) self.candy.candy_update(self.snake) self.world_map.make_lst(self.snake, self.candy) if self.candy.candy_eaten: return self.state, 5, self.snake.dead, None if self.snake.dead: self.done = True # The training process will negative it return self.state, 5, self.snake.dead, None return self.state, 0, self.snake.dead, None def render(self): ''' Render game from map ''' clear() for stri in self.world_map.map: for char in stri: print(char, end='') print('')
def setup(self) -> NoReturn: self.snake: Snake = Snake() self.start_key = False self.points = 0 self.apple = Apple(COMPONENT_SIZE, COMPONENT_SIZE)
def reset(self): del self.player self.player = Snake(self.root, (400, 300), res=self.res) self.gen_food() self.game_over = False
class Agent: def __init__(self, code_id, log=False, visualization=False, fps=60): self.code_id = code_id self.snake = Snake(WINDOW_WIDTH, WINDOW_HEIGHT, PIXEL_SIZE, WINDOW_WIDTH / 2, WINDOW_HEIGHT / 2) self.food = Food(WINDOW_WIDTH, WINDOW_HEIGHT, PIXEL_SIZE) self.food.spawn(self.snake) self.log = log self.visualization = visualization self.window, self.clock = self.init_visualization() self.fps = fps # basic infos self.alive = True self.score = 0 self.step = 0 # useful infos self.s_obstacles = self.get_surrounding_obstacles() self.food_angle = self.get_food_angle() self.food_distance = self.get_food_distance() def init_visualization(self): if self.visualization: window = pygame.display.set_mode( (WINDOW_WIDTH * PIXEL_SIZE, WINDOW_HEIGHT * PIXEL_SIZE)) fps = pygame.time.Clock() return window, fps else: return None, None def get_random_move(self, random_n=10): # real random move, 1/random_n if random_n is not 0 and random.randint(1, random_n) == 1: return random.randint(-1, 1) s, a, d = self.get_state() # random move depend on state ops = [] # select move based on following the food angle and avoiding the obstacles if not s[0] and a < 0: ops.insert(-1, -1) if not s[1] and a == 0: ops.insert(-1, 0) if not s[2] and a > 0: ops.insert(-1, +1) # if no option if not ops: # select move based on avoiding obstacles if not s[0]: ops.insert(-1, -1) if not s[1]: ops.insert(-1, 0) if not s[2]: ops.insert(-1, +1) # again, if no option -> just die if not ops: return random.randint(-1, 1) else: return ops[random.randint(0, len(ops) - 1)] else: return ops[random.randint(0, len(ops) - 1)] def next_state(self, move_direction): self.step += 1 info = 'CodeID: {} | Step: {} | Score: {}'.format( self.code_id, self.step, self.score) self.snake.change_direction(move_direction) self.snake.move() if self.snake.collision_food(self.food.location): self.score += 1 self.food.state = False self.food.spawn(self.snake) if self.snake.collision_obstacles(): info += ' >> Game Over!' self.alive = False if self.snake.get_length() == WINDOW_WIDTH * WINDOW_HEIGHT: info += ' >> Win!' self.alive = False if self.log: print(info) if self.visualization: self.window.fill((0, 0, 0)) self.food.render(self.window) self.snake.render(self.window) pygame.display.set_caption(info) pygame.display.update() pygame.event.get() self.clock.tick(self.fps) return self.get_state() def get_state(self): return self.get_surrounding_obstacles(), self.get_food_angle( ), self.get_food_distance() def get_surrounding_obstacles(self): # check front snake_head = self.snake.head snake_heading_direction = self.snake.heading_direction left = self.snake.moves[(snake_heading_direction - 1) % len(self.snake.moves)] front = self.snake.moves[snake_heading_direction] right = self.snake.moves[(snake_heading_direction + 1) % len(self.snake.moves)] l_location = [snake_head[0] + left[0], snake_head[1] + left[1]] f_location = [snake_head[0] + front[0], snake_head[1] + front[1]] r_location = [snake_head[0] + right[0], snake_head[1] + right[1]] s_locations = [l_location, f_location, r_location] self.s_obstacles = [0, 0, 0] # check wall for i in range(0, len(s_locations)): if s_locations[i][0] < 0 or s_locations[i][0] >= WINDOW_WIDTH \ or s_locations[i][1] < 0 or s_locations[i][1] >= WINDOW_HEIGHT: self.s_obstacles[i] = 1 # check body for b in self.snake.body: if b in s_locations: self.s_obstacles[s_locations.index(b)] = 1 return self.s_obstacles def get_food_angle(self): # get direction of heading heading_direction = numpy.array( self.snake.moves[self.snake.heading_direction]) # get direction of food (distant) food_direction = numpy.array(self.food.location) - numpy.array( self.snake.head) h = heading_direction / numpy.linalg.norm(heading_direction) f = food_direction / numpy.linalg.norm(food_direction) fa = math.atan2(h[0] * f[1] - h[1] * f[0], h[0] * f[0] + h[1] * f[1]) / math.pi if fa == -1 or fa == 1: fa = 1 self.food_angle = fa return self.food_angle def get_food_distance(self): head = numpy.array(self.snake.head) food = numpy.array(self.food.location) max_dis = numpy.linalg.norm( numpy.array([0, 0]) - numpy.array([WINDOW_WIDTH - 1, WINDOW_HEIGHT - 1])) dis = numpy.linalg.norm(head - food) # normalize distance to the range 0 - 1 self.food_distance = dis / max_dis return self.food_distance
def main_game(genomes, config): gameSpeed = 5 gameOver = False nets = [] genomes_track = [] snakes = [] for _, genome in genomes: net = neat.nn.FeedForwardNetwork.create(genome, config) nets.append(net) snake_initial_coord = unique_coords(snakes) snakes.append(Snake(snake_initial_coord, gameSpeed)) genome.fitness = 0 genomes_track.append(genome) #snake = Snake((int(BOARD_ROWS / 2), int(BOARD_COLS / 2)), gameSpeed) tile_coord = unique_coords(snakes) tile = Tile(tile_coord) board = Board(screen) score = Score(screen) #last_obstacle = pygame.sprite.Group() while not gameOver: for event in pygame.event.get(): if event.type == QUIT: gameOver = True quit() if event.type == KEYDOWN: if event.key == K_UP: for snake in snakes: snake.move_up() if event.key == K_DOWN: for snake in snakes: snake.move_down() if event.key == K_RIGHT: for snake in snakes: snake.move_right() if event.key == K_LEFT: for snake in snakes: snake.move_left() for snake in snakes: snake.update() check_collide(snakes, tile, genomes_track, nets) if tile.is_dead(): score.update() #snake.eat_tile() tile_coord = unique_coords(snakes) tile = Tile(tile_coord) if len(snakes) == 0: gameOver = True quit() board.clean_board() for snake in snakes: board.display_snake(snake.get_body()) board.display_tile(tile.get_coord()) update_fitness(snakes, tile, genomes_track, nets) if pygame.display.get_surface() != None: screen.fill(BG_COLOR) board.draw() score.draw() pygame.display.update() clock.tick(FPS)
class GameManager: def __init__(self, weights, apple_position=None): self.__snake = Snake() self.__apple = Apple(numpy.array([0, 0])) self.__score = 0 self.__clock = pygame.time.Clock() self.__weights = weights self.__remaining_moves = config.MOVES self.__display_manager = DisplayManager(self.__snake, self.__apple) self.__time_alive = 0 self.__apple_position = apple_position self.__neural_network = NeuralNetwork(self.__weights) def directions_distance_objects(self): front_direction_vector = self.__snake.position[ 0] - self.__snake.position[1] left_direction_vector = numpy.array( [front_direction_vector[1], -front_direction_vector[0]]) right_direction_vector = numpy.array( [-front_direction_vector[1], front_direction_vector[0]]) vision = numpy.zeros((0, 1)) for vector in [ left_direction_vector, front_direction_vector, right_direction_vector ]: objects = self.get_objects_by_direction(vector) vision = numpy.append(vision, objects[0]) vision = numpy.append(vision, objects[1]) vision = numpy.append(vision, objects[2]) return vision def get_objects_by_direction(self, direction): end = False found_apple = False found_self = False distance = 0 objects = numpy.zeros((3, 1)) while not end: distance += 1 snake_position = self.__snake.position[0] + direction * distance if collision_manager.collision_with_wall(snake_position): objects[0] = 1 / distance end = True if not found_apple and collision_manager.collision_with_apple( self.__apple.position, snake_position): objects[1] = 1 / distance found_apple = True if not found_self and collision_manager.collision_with_self( snake_position, self.__snake): objects[2] = 1 / distance found_self = True return objects def angle_with_apple(self): apple_direction_vector = numpy.array( self.__apple.position) - numpy.array(self.__snake.position[0]) snake_direction_vector = numpy.array( self.__snake.position[0]) - numpy.array(self.__snake.position[1]) norm_of_apple_direction_vector = numpy.linalg.norm( apple_direction_vector) norm_of_snake_direction_vector = numpy.linalg.norm( snake_direction_vector) if norm_of_apple_direction_vector == 0: norm_of_apple_direction_vector = 10 if norm_of_snake_direction_vector == 0: norm_of_snake_direction_vector = 10 apple_direction_vector_normalized = apple_direction_vector / norm_of_apple_direction_vector snake_direction_vector_normalized = snake_direction_vector / norm_of_snake_direction_vector angle = numpy.math.atan2( apple_direction_vector_normalized[1] * snake_direction_vector_normalized[0] - apple_direction_vector_normalized[0] * snake_direction_vector_normalized[1], apple_direction_vector_normalized[1] * snake_direction_vector_normalized[1] + apple_direction_vector_normalized[0] * snake_direction_vector_normalized[0]) / numpy.math.pi return angle def check_if_game_ended(self): result = False next_position = self.__snake.position[0] + numpy.array([0, 0]) if self.__remaining_moves <= 0: result = True if collision_manager.collision_with_wall(self.__snake.position[0]): result = True if collision_manager.collision_with_self(next_position, self.__snake): result = True return result def spawn_apple(self): apple_position = numpy.array([ random.randint(1, config.GRID_SIZE[0] - 1) * config.RECT_SIZE[0], random.randint(1, config.GRID_SIZE[1] - 1) * config.RECT_SIZE[1] ]) while collision_manager.collision_with_self(apple_position, self.__snake): apple_position = numpy.array([ random.randint(1, config.GRID_SIZE[0] - 1) * config.RECT_SIZE[0], random.randint(1, config.GRID_SIZE[1] - 1) * config.RECT_SIZE[1] ]) return apple_position def get_action_from_nn(self): vision = self.directions_distance_objects() vision = numpy.append(vision, self.angle_with_apple()) self.__neural_network.update_parameters(vision) nn_output = self.__neural_network.get_action() new_direction = numpy.array(self.__snake.position[0]) - numpy.array( self.__snake.position[1]) if nn_output == 0: new_direction = numpy.array([new_direction[1], -new_direction[0]]) if nn_output == 2: new_direction = numpy.array([-new_direction[1], new_direction[0]]) if new_direction.tolist() == [config.RECT_SIZE[0], 0]: action = Action.RIGHT elif new_direction.tolist() == [-config.RECT_SIZE[0], 0]: action = Action.LEFT elif new_direction.tolist() == [0, config.RECT_SIZE[1]]: action = Action.DOWN else: action = Action.UP return action def calculate_fitness(self): fitness = self.__time_alive + ((2**self.__snake.length) + (self.__snake.length**2.1) * 500) - ( ((.25 * self.__time_alive)**1.3) * (self.__snake.length**1.2)) fitness = max(fitness, .1) return fitness def collision_with_apple(self): self.__score += 1 self.__remaining_moves += config.APPLE_EXTRA_MOVES self.__snake.add_piece() if self.__remaining_moves > config.MAX_MOVES: self.__remaining_moves = config.MAX_MOVES if self.__apple_position is not None: self.__apple.position = self.__apple_position[self.__score] else: self.__apple.position = self.spawn_apple() return self.__apple.position def play_game(self): apple_position = [] if self.__apple_position is not None: self.__apple.position = self.__apple_position[self.__score] else: self.__apple.position = self.spawn_apple() apple_position.append(self.__apple.position) ended_game = False while ended_game is not True: self.__display_manager.draw(self.__score) self.__snake.move_snake(self.get_action_from_nn()) self.__remaining_moves -= 1 self.__time_alive += 1 if collision_manager.collision_with_apple( self.__apple.position, self.__snake.position[0]): apple_position.append(self.collision_with_apple()) ended_game = self.check_if_game_ended() for event in pygame.event.get(): if event.type == pygame.QUIT: ended_game = True self.__clock.tick(config.FPS) return self.calculate_fitness(), apple_position
class Game: def __init__(self, visible=True, waitForEyes=False): self.visible= visible self.waitForEyes= waitForEyes self.iterations_count = 0 self.score = 0 #self.main_snake = Snake(4, 4 ) self.main_snake = Snake(random.randint(4,11), random.randint(3,4) ) self.apple_eaten = False self.apple = self.spawn_apple() self.running = True # self.last_info = self.get_info() self.grow_snake = False pygame.init() pygame.display.set_caption("Snake") pygame.font.init() if (not self.visible): pygame.display.iconify() random.seed() self.main_screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.HWSURFACE) self.score_font = pygame.font.Font(None, 25) self.score_area_font = pygame.font.Font(None, 25) self.game_over_font = pygame.font.Font(None, 45) self.play_again_font = self.score_area_font self.score_msg = self.score_font.render("Score:", 1, pygame.Color("white")) self.score_msg_size = self.score_font.size("Score") self.background_color = pygame.Color(100, 100, 100) image_path = os.path.dirname(__file__) self.apple_image = pygame.transform.scale( pygame.image.load(os.path.join(image_path, "apple.png")).convert_alpha(), (BLOCK_SIZE, BLOCK_SIZE)) self.snake_image = pygame.transform.scale( pygame.image.load(os.path.join(image_path, "snake_box.jpg")).convert_alpha(), (BLOCK_SIZE, BLOCK_SIZE)) def get_info(self): closest_right = 1 closest_left = 1 closest_up = 1 closest_down = 1 head = self.main_snake.elements[0] while closest_right <= BOARD_WIDTH - head.x: if self.main_snake.collides_with_body(Segment(head.x + closest_right, head.y)): break closest_right += 1 while closest_left <= head.x + 1: if self.main_snake.collides_with_body(Segment(head.x - closest_left, head.y)): break closest_left += 1 while closest_down <= BOARD_HEIGHT - head.y: if self.main_snake.collides_with_body(Segment(head.x, head.y + closest_down)): break closest_down += 1 while closest_up <= head.y + 1: if self.main_snake.collides_with_body(Segment(head.x, head.y - closest_up)): break closest_up += 1 closest_right = min(closest_right, BOARD_WIDTH - head.x) closest_left = min(closest_left, head.x + 1) closest_down = min(closest_down, BOARD_HEIGHT - head.y) closest_up = min(closest_up, head.y + 1) apple_x_dist = abs(self.main_snake.elements[0].x - self.apple.x) apple_y_dist = abs(self.main_snake.elements[0].y - self.apple.y) info = { "right_crash": closest_right, "left_crash": closest_left, "down_crash": closest_down, "up_crash": closest_up, "reward": 0, "lost_game": False, "apple_x": apple_x_dist, "apple_y": apple_y_dist, "score": self.score, "iterations_count": self.iterations_count } print("\nRight crash: {0}, left crash: {1}, up crash: {2}, " "down crash: {3}. Reward: {4}, lost game: {5}. Apple x: {6}, " "apple y: {7}, score: {8}, number of iterations {9}".format(info["right_crash"], info["left_crash"], info["up_crash"], info["down_crash"], info["reward"], info["lost_game"], info["apple_x"], info["apple_y"], info["score"], info["iterations_count"])) return info def get_action(self, action): if action == KEY["UP"]: event = pygame.event.Event(pygame.KEYDOWN, key=pygame.K_UP) elif action == KEY["DOWN"]: event = pygame.event.Event(pygame.KEYDOWN, key=pygame.K_DOWN) elif action == KEY["LEFT"]: event = pygame.event.Event(pygame.KEYDOWN, key=pygame.K_LEFT) elif action == KEY["RIGHT"]: event = pygame.event.Event(pygame.KEYDOWN, key=pygame.K_RIGHT) # make the move pygame.event.post(event) def wait_for_action(self): while True: event = pygame.event.wait() if event.type == pygame.KEYDOWN: if event.key == pygame.K_UP: return KEY["UP"] elif event.key == pygame.K_DOWN: return KEY["DOWN"] elif event.key == pygame.K_LEFT: return KEY["LEFT"] elif event.key == pygame.K_RIGHT: return KEY["RIGHT"] elif event.key == pygame.K_ESCAPE: return KEY["EXIT"] elif event.key == pygame.K_y: return KEY["YES"] elif event.key == pygame.K_n: return KEY["NO"] if event.type == pygame.QUIT: sys.exit() def spawn_apple(self): valid_apple = False x = 0 y = 0 while not valid_apple: valid_apple = True x = random.randint(0, BOARD_WIDTH - 1) y = random.randint(0, BOARD_HEIGHT - 1) for segment in self.main_snake.elements: if check_collision(segment, Segment(x, y)): valid_apple = False break return Apple(x, y, True) def rerun(self): self.__init__(self.visible, self.waitForEyes) def end_game(self): # self.get_info() self.running = False def get_snake_size(self): return len(self.main_snake.elements) def draw_score(self): score_area = self.score_area_font.render(str(self.score), 1, pygame.Color("white")) self.main_screen.blit(self.score_msg, (SCREEN_WIDTH - self.score_msg_size[0] - 60, 10)) self.main_screen.blit(score_area, (SCREEN_WIDTH - 45, 10)) def redraw_game(self): self.main_screen.fill(self.background_color) if self.apple.exists: self.apple.draw(self.main_screen, self.apple_image) self.main_snake.draw(self.main_screen, self.snake_image) self.draw_score() if DISPLAY: pygame.display.flip() pygame.display.update() def action(self, action_key): if action_key == KEY["EXIT"]: self.running = False # Move snake if self.grow_snake: self.main_snake.grow() if action_key: self.main_snake.set_direction(action_key) self.main_snake.move() return self.last_info def run(self, action): # Draw game self.redraw_game() # print(self.send_state(), action) # Check apple availability self.grow_snake = False if self.apple.exists: if check_collision(self.main_snake.get_head(), self.apple): self.grow_snake = True self.apple.exists = False self.score += 5 self.apple_eaten = True # Spawn apple if self.apple_eaten: self.apple_eaten = False self.apple = self.spawn_apple() print("Wow, you've eaten an apple! Next apple: ({0}, {1})".format(self.apple.x, self.apple.y)) self.redraw_game() # Wait for user input (here goes agent's move) # self.main_snake.display_log() self.iterations_count += 1 if self.waitForEyes: time.sleep(0.3) # Here agent is telling what to do self.get_action(action) key_pressed = self.wait_for_action() if key_pressed == "exit": self.running = False if (key_pressed != action): print("error when getting key presed", key_pressed, action) # Move snake if self.grow_snake: self.main_snake.grow() if key_pressed in range(0, 4): self.main_snake.set_direction(key_pressed) self.main_snake.move() # Check collisions (walls and self) if self.main_snake.check_crash(): self.end_game() reward = self.send_reward() return (self.send_state(), reward) def send_reward(self): # reward = 0 # apple_part =0 # apple_distance = abs(self.apple.x - self.main_snake.get_head().x) + abs(self.apple.y - self.main_snake.get_head().y) # if apple_distance==1: # apple_part= REWARD["EAT"] # if self.running: # reward= REWARD["LIVE"] + apple_part # else: # reward = REWARD["DEATH"]+ apple_part # return reward apple_part =0 if(self.running == False): return REWARD["DEATH"] apple_distance = abs(self.apple.x - self.main_snake.get_head().x) + abs(self.apple.y - self.main_snake.get_head().y) # ------DIFFICULT SCENARIO--------- if apple_distance == 0: apple_part = REWARD["EAT"] # --------------------------------- #if self.apple.x == self.main_snake.get_head().x || self.apple.y == self.main_snake.get_head().y: # apple_part+=REWARD["EAT"]*0.2 # # -------EASIER SCENARIO----------- # apple_part = (1-(apple_distance/(BOARD_HEIGHT+BOARD_WIDTH))) * REWARD["EAT"] # # --------------------------------- return REWARD["LIVE"] + apple_part # when snake eats an apple => true # that is when the head of the snake is on the apple def snake_eating(self): return self.apple.x == self.main_snake.get_head().x and self.apple.y == self.main_snake.y # Sends state to agent # List of collisions (U, R, D L) and apple distances (U, R, D, L) def send_state(self): collisions = self.check_collisions_all_directions() apple_distance = self.check_apple_all_directions() if len(collisions) != 4 or len(apple_distance) != 4: print(collisions) print(apple_distance) return collisions + apple_distance def check_apple_all_directions(self): # distance = [0,0,0,0] distance = [] # snake is eating the apple now => no reward for that if self.snake_eating(): return [TOOBIG,TOOBIG,TOOBIG,TOOBIG] #return self.check_apple() # UP distance.append(self.distance_calc(self.apple.x, self.apple.y,self.main_snake.get_head().x, self.main_snake.get_head().y-1)) #distance.append(self.distance_give(self.apple.x, self.apple.y,self.main_snake.get_head().x, self.main_snake.get_head().y,KEY["UP"])) # DOWN distance.append(self.distance_calc(self.apple.x,self.apple.y, self.main_snake.get_head().x, self.main_snake.get_head().y+1)) #distance.append(self.distance_give(self.apple.x,self.apple.y, self.main_snake.get_head().x, self.main_snake.get_head().y, KEY["DOWN"])) # LEFT distance.append(self.distance_calc(self.apple.x,self.apple.y, self.main_snake.get_head().x-1, self.main_snake.get_head().y)) #distance.append(self.distance_give(self.apple.x,self.apple.y, self.main_snake.get_head().x, self.main_snake.get_head().y, KEY["LEFT"])) # RIGHT distance.append(self.distance_calc(self.apple.x, self.apple.y,self.main_snake.get_head().x+1, self.main_snake.get_head().y)) #distance.append(self.distance_give(self.apple.x, self.apple.y,self.main_snake.get_head().x, self.main_snake.get_head().y, KEY["RIGHT"])) colissions= self.check_collisions_all_directions() for i in range(len(colissions)): if(colissions[i]<=0): distance[i]=TOOBIG print(distance) return distance def distance_calc(self, applex, appley, snakex, snakey): return abs(applex - snakex) + abs(appley - snakey) def distance_give(self, applex, appley, snakex,snakey, direction): #distances= [] snake_elements_without_tail = self.main_snake.elements[:-1] if direction == KEY["UP"] : if applex==snakex and appley <= snakey: for segment in snake_elements_without_tail: if segment.x == applex and segment.y < snakey and segment.y > appley: return 0 return 1 return 0 if direction == KEY["DOWN"]: if applex==snakex and appley >= snakey: for segment in snake_elements_without_tail: if segment.x == applex and segment.y > snakey and segment.y < appley: return 0 return 1 return 0; if direction == KEY["LEFT"]: if appley==snakey and applex <= snakex: for segment in snake_elements_without_tail: if segment.y == appley and segment.x < snakex and segment.x > applex: return 0 return 1 return 0 if direction == KEY["RIGHT"]: if appley==snakey and applex >= snakex: for segment in snake_elements_without_tail: if segment.y == appley and segment.x > snakex and segment.x < applex: return 0 return 1 return 0 def check_apple(self): apple = [] applex = self.apple.x appley = self.apple.y # UP distance = TOOBIG new_head = (self.main_snake.get_head().x, self.main_snake.get_head().y - 1) if applex==new_head[0] and appley <= new_head[1]: distance= abs(new_head[1]- appley) apple.append(distance) # DOWN distance = TOOBIG new_head = (self.main_snake.get_head().x, self.main_snake.get_head().y + 1) if applex==new_head[0] and appley >= new_head[1]: distance= abs(new_head[1]- appley) apple.append(distance) # LEFT distance = TOOBIG new_head = (self.main_snake.get_head().x - 1, self.main_snake.get_head().y) if appley==new_head[1] and applex <= new_head[0]: distance= abs(new_head[0]- applex) apple.append(distance) # RIGHT distance = TOOBIG new_head = (self.main_snake.get_head().x + 1, self.main_snake.get_head().y) if appley==new_head[1] and applex >= new_head[0]: distance= abs(new_head[0]- applex) apple.append(distance) return apple def check_collisions_all_directions(self): collision = [] # UP distance = self.main_snake.get_head().y new_head = (self.main_snake.get_head().x, self.main_snake.get_head().y - 1) snake_elements_without_tail = self.main_snake.elements[:-1] for segment in snake_elements_without_tail: if segment.x == new_head[0] and segment.y < self.main_snake.get_head().y: distance = min(distance, abs(segment.y - new_head[1])) collision.append(distance) # DOWN distance = BOARD_HEIGHT - self.main_snake.get_head().y - 1 new_head = (self.main_snake.get_head().x, self.main_snake.get_head().y + 1) for segment in snake_elements_without_tail: if segment.x == new_head[0] and segment.y > self.main_snake.get_head().y: distance = min(distance, abs(segment.y - new_head[1])) collision.append(distance) # LEFT distance = self.main_snake.get_head().x new_head = (self.main_snake.get_head().x - 1, self.main_snake.get_head().y) for segment in snake_elements_without_tail: if segment.y == new_head[1] and segment.x < self.main_snake.get_head().x: distance = min(distance, abs(new_head[0] - segment.x)) collision.append(distance) # RIGHT distance = BOARD_WIDTH - self.main_snake.get_head().x - 1 new_head = (self.main_snake.get_head().x + 1, self.main_snake.get_head().y) for segment in snake_elements_without_tail: if segment.y == new_head[1] and segment.x > self.main_snake.get_head().x: distance = min(distance, abs(new_head[0] - segment.x)) collision.append(distance) return collision