def __init__(self, fps: int, game_over_score: int, record_progress): """ Constructor @param fps The fps of the game @param game_over_score The game will stop when either side reaches this score @param record_progress Whether to record the game process or not """ self._ml_1P = "ml_1P" self._ml_2P = "ml_2P" self._ml_execute_time = 1.0 / fps self._frame_delayed = [0, 0] # 1P, 2P self._score = [0, 0] # 1P, 2P self._game_over_score = game_over_score self._cmd_receiver = CommandReceiver( \ GameCommand, { "command": PlatformAction }, GameCommand(-1, PlatformAction.NONE)) self._record_handler = get_record_handler( record_progress, {"status": (GameStatus.GAME_1P_WIN, GameStatus.GAME_2P_WIN)}, get_log_dir()) self._init_display() self._scene = Scene()
def __init__(self, fps: int, difficulty, game_over_score: int, record_progress): """ Constructor @param fps The fps of the game @param difficulty The difficulty of the game @param game_over_score The game will stop when either side reaches this score @param record_progress Whether to record the game process or not """ self._ml_1P = "ml_1P" self._ml_2P = "ml_2P" self._ml_execute_time = 1.0 / fps self._frame_delayed = [0, 0] # 1P, 2P self._score = [0, 0] # 1P, 2P self._game_over_score = game_over_score self._cmd_receiver = CommandReceiver( GameCommand, {"command": PlatformAction}, GameCommand(-1, PlatformAction.NONE)) self._record_handler = get_record_handler(record_progress, "ml_" + str(difficulty)) self._scene = Scene(difficulty) self._screen = Screen(Scene.area_rect.size, self._scene.draw_gameobjects)
def __init__(self, fps, one_shot_mode, record_progress): self._init_pygame() self._scene = Scene() self._ml_name = "ml" self._ml_execution_time = 1 / fps self._frame_delayed = 0 self._cmd_receiver = CommandReceiver( GameCommand, { "command": SnakeAction, }, GameCommand(-1, SnakeAction.NONE)) self._one_shot_mode = one_shot_mode self._record_handler = get_record_handler(record_progress, "ml")
def __init__(self, fps: int, difficulty, level: int, \ record_progress: bool, one_shot_mode: bool): self._ml_name = "ml" self._ml_execute_time = 1.0 / fps self._frame_delayed = 0 self._cmd_receiver = CommandReceiver( \ GameCommand, { "command": PlatformAction }, GameCommand(-1, PlatformAction.NONE)) self._record_handler = get_record_handler(record_progress, \ "ml_" + str(difficulty) + "_" + str(level)) self._one_shot_mode = one_shot_mode self._scene = Scene(difficulty, level) self._screen = Screen(Scene.area_rect.size, self._scene.draw_gameobjects)
def __init__(self, fps: int, level: int, \ record_progress: bool, one_shot_mode: bool): self._ml_name = "ml" self._ml_execute_time = 1.0 / fps self._frame_delayed = 0 self._instruct_receiver = CommandReceiver( \ GameInstruction, { "command": \ [PlatformAction.MOVE_LEFT, PlatformAction.MOVE_RIGHT, PlatformAction.NONE], \ }, GameInstruction(-1, PlatformAction.NONE)) self._record_handler = get_record_handler(record_progress, { \ "status": (GameStatus.GAME_OVER, GameStatus.GAME_PASS) \ }, get_log_dir()) self._one_shot_mode = one_shot_mode self._init_display() self._scene = gamecore.Scene(level, True)
def __init__(self, fps: int, level: int, \ record_progress: bool, one_shot_mode: bool): self._ml_name = "ml" self._ml_execute_time = 1.0 / fps self._frame_delayed = 0 self._cmd_receiver = CommandReceiver( \ GameCommand, { "command": PlatformAction }, GameCommand(-1, PlatformAction.NONE)) self._record_handler = get_record_handler(record_progress, { \ "status": (GameStatus.GAME_OVER, GameStatus.GAME_PASS) \ }, get_log_dir()) self._one_shot_mode = one_shot_mode self._init_display() self._scene = Scene(level)
class Snake: """ The game execution manager """ def __init__(self, fps, one_shot_mode, record_progress): self._init_pygame() self._scene = Scene() self._ml_name = "ml" self._ml_execution_time = 1 / fps self._frame_delayed = 0 self._cmd_receiver = CommandReceiver( GameCommand, { "command": SnakeAction, }, GameCommand(-1, SnakeAction.NONE)) self._one_shot_mode = one_shot_mode self._record_handler = get_record_handler(record_progress, "ml") def _init_pygame(self): """ Initialize the required pygame module """ pygame.display.init() pygame.display.set_caption("Snake") self._screen = pygame.display.set_mode( (Scene.area_rect.width, Scene.area_rect.height + 25)) pygame.font.init() self._font = pygame.font.Font(None, 22) self._font_pos = (1, Scene.area_rect.width + 5) def game_loop(self): """ The game execution loop """ # Wait for the ml process comm.wait_ml_ready(self._ml_name) while not quit_or_esc(): # Generate the scene information scene_info = self._scene.get_scene_info() # Send the scene information to the ml process # and wait the command sent from it command = self._make_ml_execute(scene_info) # Record the scene information scene_info.command = command self._record_handler(scene_info) # Update the scene game_status = self._scene.update(command) # If the game is over, reset the scene or # quit the game loop if one shot mode is set. if game_status == GameStatus.GAME_OVER: # Send the scene info with the game over status # and record that scene info scene_info = self._scene.get_scene_info() comm.send_to_ml(scene_info, self._ml_name) self._record_handler(scene_info) if self._one_shot_mode: return self._scene.reset() self._frame_delayed = 0 # Wait for the ml process for the next round comm.wait_ml_ready(self._ml_name) # Draw the scene to the display self._draw_scene() def _make_ml_execute(self, scene_info): """ Send the scene info to the ml process and receive the command from it The method will wait the ml process to execute the command for a period which is decided by the `_ml_execution_time`. If the ml process can't send the command in time, the method will return a default command. """ comm.send_to_ml(scene_info, self._ml_name) time.sleep(self._ml_execution_time) game_cmd = self._cmd_receiver.recv(self._ml_name) # Check and update the frame delayed if (game_cmd.frame != -1 and scene_info.frame - game_cmd.frame > self._frame_delayed): self._frame_delayed = scene_info.frame - game_cmd.frame return game_cmd.command def _draw_scene(self): """ Draw the scene to the display """ self._screen.fill((50, 50, 50)) self._screen.fill((0, 0, 0), Scene.area_rect) self._scene.draw_gameobjects(self._screen) # Draw score font_surface = self._font.render( "Score: {}, Frame delayed: {}".format(self._scene.score, self._frame_delayed), True, (255, 255, 255)) self._screen.blit(font_surface, self._font_pos) pygame.display.flip()
class Arkanoid: """The game for the machine learning mode """ def __init__(self, fps: int, level: int, \ record_progress: bool, one_shot_mode: bool): self._ml_name = "ml" self._ml_execute_time = 1.0 / fps self._frame_delayed = 0 self._instruct_receiver = CommandReceiver( \ GameInstruction, { "command": \ [PlatformAction.MOVE_LEFT, PlatformAction.MOVE_RIGHT, PlatformAction.NONE], \ }, GameInstruction(-1, PlatformAction.NONE)) self._record_handler = get_record_handler(record_progress, { \ "status": (GameStatus.GAME_OVER, GameStatus.GAME_PASS) \ }, get_log_dir()) self._one_shot_mode = one_shot_mode self._init_display() self._scene = gamecore.Scene(level, True) def _init_display(self): pygame.display.init() pygame.display.set_caption("Arkanoid") self._screen = pygame.display.set_mode(gamecore.scene_area_size) def game_loop(self): """The main loop of the game in machine learning mode The execution order in the loop: 1. Send the SceneInfo to the machine learning process. 2. Wait for the key frame (During this period, machine learning process can process the SceneInfo and generate the GameInstruction.) 3. Check if there has a GameInstruction to receive. If it has, receive the instruction. Otherwise, generate a dummy one. 4. Pass the GameInstruction to the game and update the scene (and frame no.) 5. If the game is over or passed, send the SceneInfo containing the game status to the machine learning process, and reset the game. 6. Back to 1. """ keep_going = lambda: not quit_or_esc() comm.wait_ml_ready(self._ml_name) while keep_going(): scene_info = self._scene.fill_scene_info_obj(SceneInfo()) self._record_handler(scene_info) instruction = self._make_ml_execute(scene_info) game_status = self._scene.update(instruction.command) self._draw_scene() if game_status == GameStatus.GAME_OVER or \ game_status == GameStatus.GAME_PASS: scene_info = self._scene.fill_scene_info_obj(SceneInfo()) self._record_handler(scene_info) comm.send_to_ml(scene_info, self._ml_name) if self._one_shot_mode: return self._scene.reset() self._frame_delayed = 0 # Wait for ml process doing resetting jobs comm.wait_ml_ready(self._ml_name) pygame.quit() def _make_ml_execute(self, scene_info): """Send the scene_info to the ml process and wait for the instruction """ comm.send_to_ml(scene_info, self._ml_name) time.sleep(self._ml_execute_time) instruction = self._instruct_receiver.recv(self._ml_name) if instruction.frame != -1 and \ scene_info.frame - instruction.frame > self._frame_delayed: self._frame_delayed = scene_info.frame - instruction.frame print("Delayed {} frame(s)".format(self._frame_delayed)) return instruction def _draw_scene(self): """Draw the scene to the display """ self._screen.fill((0, 0, 0)) self._scene.draw_gameobjects(self._screen) pygame.display.flip()
class Arkanoid: """ The game for the machine learning mode """ def __init__(self, fps: int, difficulty, level: int, \ record_progress: bool, one_shot_mode: bool): self._ml_name = "ml" self._ml_execute_time = 1.0 / fps self._frame_delayed = 0 self._cmd_receiver = CommandReceiver( \ GameCommand, { "command": PlatformAction }, GameCommand(-1, PlatformAction.NONE)) self._record_handler = get_record_handler(record_progress, \ "ml_" + str(difficulty) + "_" + str(level)) self._one_shot_mode = one_shot_mode self._scene = Scene(difficulty, level) self._screen = Screen(Scene.area_rect.size, self._scene.draw_gameobjects) def game_loop(self): """ The main loop of the game in machine learning mode The execution order in the loop: 1. Send the SceneInfo to the machine learning process. 2. Wait for the key frame (During this period, machine learning process can process the SceneInfo and generate the GameInstruction.) 3. Check if there has a command to receive. If it has, receive the command. Otherwise, generate a dummy one. 4. Pass the command received to the game and update the scene. 5. If the game is over or passed, send the SceneInfo containing the game status to the machine learning process, and reset the game. 6. Back to 1. """ comm.wait_ml_ready(self._ml_name) while not quit_or_esc(): scene_info = self._scene.get_scene_info() command = self._make_ml_execute(scene_info) scene_info.command = command self._record_handler(scene_info) game_status = self._scene.update(command) self._screen.update(self._scene.catch_ball_times) if game_status == GameStatus.GAME_OVER or \ game_status == GameStatus.GAME_PASS: scene_info = self._scene.get_scene_info() self._record_handler(scene_info) comm.send_to_ml(scene_info, self._ml_name) print(game_status.value) if self._one_shot_mode: return self._scene.reset() self._frame_delayed = 0 # Wait for ml process doing resetting jobs comm.wait_ml_ready(self._ml_name) def _make_ml_execute(self, scene_info): """ Send the scene_info to the ml process and wait for the instruction """ comm.send_to_ml(scene_info, self._ml_name) time.sleep(self._ml_execute_time) game_cmd = self._cmd_receiver.recv(self._ml_name) if game_cmd.frame != -1 and \ scene_info.frame - game_cmd.frame > self._frame_delayed: self._frame_delayed = scene_info.frame - game_cmd.frame print("Delayed {} frame(s)".format(self._frame_delayed)) return game_cmd.command
class PingPong: """ The game core for the machine learning mode """ def __init__(self, fps: int, difficulty, game_over_score: int, record_progress): """ Constructor @param fps The fps of the game @param difficulty The difficulty of the game @param game_over_score The game will stop when either side reaches this score @param record_progress Whether to record the game process or not """ self._ml_1P = "ml_1P" self._ml_2P = "ml_2P" self._ml_execute_time = 1.0 / fps self._frame_delayed = [0, 0] # 1P, 2P self._score = [0, 0] # 1P, 2P self._game_over_score = game_over_score self._cmd_receiver = CommandReceiver( \ GameCommand, { "command": PlatformAction }, GameCommand(-1, PlatformAction.NONE)) self._record_handler = get_record_handler(record_progress, "ml_" + str(difficulty)) self._scene = Scene(difficulty) self._screen = Screen(Scene.area_rect.size, self._scene.draw_gameobjects) def game_loop(self): """ The main loop of the game execution """ comm.wait_all_ml_ready() while not quit_or_esc(): scene_info = self._scene.get_scene_info() # Send the scene info to the ml processes and wait for commands command_1P, command_2P = self._make_ml_execute(scene_info) scene_info.command_1P = command_1P scene_info.command_2P = command_2P self._record_handler(scene_info) # Update the scene game_status = self._scene.update(command_1P, command_2P) self._screen.update(self._score, self._scene._ball.speed) # If either of two sides wins, reset the scene and wait for ml processes # getting ready for the next round if game_status != GameStatus.GAME_ALIVE: scene_info = self._scene.get_scene_info() self._record_handler(scene_info) comm.send_to_all_ml(scene_info) print("Frame: {}, Status: {}" \ .format(scene_info.frame, game_status.value)) if self._game_over(game_status): break self._scene.reset() self._frame_delayed = [0, 0] # Wait for ml processes doing their resetting jobs comm.wait_all_ml_ready() self._print_result() def _make_ml_execute(self, scene_info): """ Send the scene_info to the ml process and wait for the instructions """ comm.send_to_all_ml(scene_info) time.sleep(self._ml_execute_time) instructions = self._cmd_receiver.recv_all() self._check_frame_delayed(0, self._ml_1P, \ scene_info.frame, instructions[self._ml_1P].frame) self._check_frame_delayed(1, self._ml_2P, \ scene_info.frame, instructions[self._ml_2P].frame) return instructions[self._ml_1P].command, instructions[self._ml_2P].command def _check_frame_delayed(self, ml_index, ml_name, scene_frame, instruct_frame): """ Update the `frame_delayed` if the received instruction frame is delayed """ if instruct_frame != -1 and \ scene_frame - instruct_frame > self._frame_delayed[ml_index]: self._frame_delayed[ml_index] = scene_frame - instruct_frame print("{} delayed {} frame(s)" \ .format(ml_name, self._frame_delayed[ml_index])) def _game_over(self, status): if status == GameStatus.GAME_1P_WIN: self._score[0] += 1 elif status == GameStatus.GAME_2P_WIN: self._score[1] += 1 else: # Draw game self._score[0] += 1 self._score[1] += 1 return self._score[0] == self._game_over_score or \ self._score[1] == self._game_over_score def _print_result(self): if self._score[0] > self._score[1]: win_side = "1P" elif self._score[0] == self._score[1]: win_side = "No one" else: win_side = "2P" print("{} wins! Final score: {}-{}".format(win_side, *self._score))
class PingPong: """ The game core for the machine learning mode """ def __init__(self, fps: int, game_over_score: int, record_progress): """ Constructor @param fps The fps of the game @param game_over_score The game will stop when either side reaches this score @param record_progress Whether to record the game process or not """ self._ml_1P = "ml_1P" self._ml_2P = "ml_2P" self._ml_execute_time = 1.0 / fps self._frame_delayed = [0, 0] # 1P, 2P self._score = [0, 0] # 1P, 2P self._game_over_score = game_over_score self._cmd_receiver = CommandReceiver( \ GameCommand, { "command": PlatformAction }, GameCommand(-1, PlatformAction.NONE)) self._record_handler = get_record_handler( record_progress, {"status": (GameStatus.GAME_1P_WIN, GameStatus.GAME_2P_WIN)}, get_log_dir()) self._init_display() self._scene = Scene() def _init_display(self): """ Initialize the display of pygame """ pygame.display.init() pygame.display.set_caption("PingPong") self._screen = pygame.display.set_mode(Scene.area_rect.size) pygame.font.init() self._font = pygame.font.Font(None, 22) self._font_pos_1P = (1, self._screen.get_height() - 21) self._font_pos_2P = (1, 4) self._font_pos_speed = (self._screen.get_width() - 75, \ self._screen.get_height() - 21) def game_loop(self): """ The main loop of the game execution """ comm.wait_all_ml_ready() while not quit_or_esc(): scene_info = self._scene.get_scene_info() # Send the scene info to the ml processes and wait for commands command_1P, command_2P = self._make_ml_execute(scene_info) scene_info.command_1P = command_1P.value scene_info.command_2P = command_2P.value self._record_handler(scene_info) # Update the scene game_status = self._scene.update(command_1P, command_2P) self._draw_scene() # If either of two sides wins, reset the scene and wait for ml processes # getting ready for the next round if game_status == GameStatus.GAME_1P_WIN or \ game_status == GameStatus.GAME_2P_WIN: scene_info = self._scene.get_scene_info() self._record_handler(scene_info) comm.send_to_all_ml(scene_info) print("Frame: {}, Status: {}" \ .format(scene_info.frame, game_status.value)) if self._game_over(game_status): break self._scene.reset() self._frame_delayed = [0, 0] # Wait for ml processes doing their resetting jobs comm.wait_all_ml_ready() self._print_result() def _make_ml_execute(self, scene_info): """ Send the scene_info to the ml process and wait for the instructions """ comm.send_to_all_ml(scene_info) time.sleep(self._ml_execute_time) instructions = self._cmd_receiver.recv_all() self._check_frame_delayed(0, self._ml_1P, \ scene_info.frame, instructions[self._ml_1P].frame) self._check_frame_delayed(1, self._ml_2P, \ scene_info.frame, instructions[self._ml_2P].frame) return instructions[self._ml_1P].command, instructions[ self._ml_2P].command def _check_frame_delayed(self, ml_index, ml_name, scene_frame, instruct_frame): """ Update the `frame_delayed` if the received instruction frame is delayed """ if instruct_frame != -1 and \ scene_frame - instruct_frame > self._frame_delayed[ml_index]: self._frame_delayed[ml_index] = scene_frame - instruct_frame print("{} delayed {} frame(s)" \ .format(ml_name, self._frame_delayed[ml_index])) def _draw_scene(self): """ Draw the scene and status to the display """ self._screen.fill((0, 0, 0)) self._scene.draw_gameobjects(self._screen) font_surface_1P = self._font.render( \ "1P score: {}".format(self._score[0]), True, gamecore.color_1P) font_surface_2P = self._font.render( \ "2P score: {}".format(self._score[1]), True, gamecore.color_2P) font_surface_speed = self._font.render( \ "Speed: {}".format(abs(self._scene._ball._speed[0])), True, (255, 255, 255)) self._screen.blit(font_surface_1P, self._font_pos_1P) self._screen.blit(font_surface_2P, self._font_pos_2P) self._screen.blit(font_surface_speed, self._font_pos_speed) pygame.display.flip() def _game_over(self, status): if status == GameStatus.GAME_1P_WIN: self._score[0] += 1 else: self._score[1] += 1 return self._score[0] == self._game_over_score or \ self._score[1] == self._game_over_score def _print_result(self): if self._score[0] > self._score[1]: win_side = "1P" elif self._score[0] == self._score[1]: win_side = "No one" else: win_side = "2P" print("{} wins! Final score: {}-{}".format(win_side, *self._score))