def ml_loop(): """ The main loop for the ml process """ # === The execution order of the loop === # # 1. Put the initialization code here # 2. Inform the game process that the ml process is ready comm.ml_ready() # 3. Start an endless loop while True: # 3.1 Receive the scene information sent from the game process scene_info = comm.recv_from_game() # 3.2 If the game is over if scene_info["status"] == "GAME_OVER": # 3.2.1 Do some reset works if needed. # 3.2.2 Inform the game process that ml process # is ready for the next round comm.ml_ready() continue # 3.3 Process the information received here # 3.4 Generate a command for this game information and # send to the game process. comm.send_to_game({"frame": scene_info["frame"], "command": "RIGHT"})
def ml_loop(side: str): init_pygame() print("Invisible joystick is used. " "Press Enter to start the {} ml process.".format(side)) while wait_enter_key(): pass comm.ml_ready() while True: scene_info = comm.recv_from_game() if scene_info["status"] != "GAME_ALIVE": comm.ml_ready() continue key_pressed_list = pygame.key.get_pressed() if key_pressed_list[pygame.K_LEFT]: cmd = "MOVE_LEFT" elif key_pressed_list[pygame.K_RIGHT]: cmd = "MOVE_RIGHT" elif key_pressed_list[pygame.K_PERIOD]: cmd = "SERVE_TO_LEFT" elif key_pressed_list[pygame.K_SLASH]: cmd = "SERVE_TO_RIGHT" else: cmd = "NONE" comm.send_to_game({"frame": scene_info["frame"], "command": cmd}) pygame.event.pump()
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" })
def ml_loop(): """ The main loop of the machine learning process This loop is run in a separate process, and communicates with the game process. Note that the game process won't wait for the ml process to generate the GameInstruction. It is possible that the frame of the GameInstruction is behind of the current frame in the game process. Try to decrease the fps to avoid this situation. """ # === Here is the execution order of the loop === # # 1. Put the initialization code here. ball_served = False # 2. Inform the game process that ml process is ready before start the loop. comm.ml_ready() # 3. Start an endless loop. while True: # 3.1. Receive the scene information sent from the game process. scene_info = comm.recv_from_game() # 3.2. If the game is over or passed, the game process will reset # the scene and wait for ml process doing resetting job. if (scene_info["status"] == "GAME_OVER" or scene_info["status"] == "GAME_PASS"): # Do some stuff if needed ball_served = False # 3.2.1. Inform the game process that ml process is ready comm.ml_ready() continue # 3.3. Put the code here to handle the scene information # 3.4. Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" })
def ml_loop(side: str): print("For {}".format(side)) comm.ml_ready() while True: scene_info = comm.recv_from_game() if (scene_info["status"] == "GAME_1P_WIN" or scene_info["status"] == "GAME_2P_WIN"): comm.ml_ready() continue comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" })
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ H = 200 D = 8 resume = False # resume from previous checkpoint? if resume: model = pickle.load(open('save.p', 'rb')) else: model = {} model['W1'] = np.random.randn(H,D) / np.sqrt(D) # "Xavier" initialization model['W2'] = np.random.randn(H) / np.sqrt(H) grad_buffer = { k : np.zeros_like(v) for k,v in model.items() } # update buffers that add up gradients over a batch rmsprop_cache = { k : np.zeros_like(v) for k,v in model.items() } # rmsprop memory xs,hs,dlogps,drs = [],[],[],[] running_reward = None reward_sum = 0 episode_number = 0 batch_size = 10 # every how many episodes to do a param update? learning_rate = 1e-4 gamma = 0.99 # discount factor for reward decay_rate = 0.99 # decay factor for RMSProp leaky sum of grad^2 # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False def sigmoid(x): return 1.0 / (1.0 + np.exp(-x)) # sigmoid "squashing" function to interval [0,1] def getObs(player): observation = [] observation.append(scene_info['ball'][0]) observation.append(scene_info['ball'][1]) observation.append(scene_info['ball_speed'][0]) observation.append(scene_info['ball_speed'][1]) observation.append(scene_info['blocker'][0]) observation.append(scene_info['blocker'][1]) if player == '1P': observation.append(scene_info['platform_1P'][0]) observation.append(scene_info['platform_1P'][1]) if player == '2P': observation.append(scene_info['platform_2P'][0]) observation.append(scene_info['platform_2P'][1]) observation = np.array(observation) return observation def discount_rewards(r): """ take 1D float array of rewards and compute discounted reward """ discounted_r = np.zeros_like(r) running_add = 0 for t in reversed(range(0, r.size)): if r[t] != 0: running_add = 0 # reset the sum, since this was a game boundary (pong specific!) #print(r[t]) running_add = running_add * gamma + r[t] discounted_r[t] = running_add return discounted_r def policy_backward(eph, epdlogp): """ backward pass. (eph is array of intermediate hidden states) """ dW2 = np.dot(eph.T, epdlogp).ravel() dh = np.outer(epdlogp, model['W2']) dh[eph <= 0] = 0 # backpro prelu dW1 = np.dot(dh.T, epx) return {'W1':dW1, 'W2':dW2} def rl(player): observation = getObs(player) aprob, h = policy_forward(observation) action = 2 if np.random.uniform() < aprob else 3 # record various intermediates (needed later for backprop) xs.append(x) # observation hs.append(h) # hidden state y = 1 if action == 2 else 0 # a "fake label" dlogps.append(y - aprob) # grad that encourages the action that was taken to be taken (see http://cs231n.github.io/neural-networks-2/#losses if confused) if scene_info['status'] == 'GAME_ALIVE': reward = 0 done = False elif scene_info['status'] == 'GAME_1P_WIN': reward = 2 done = True elif scene_info['status'] == 'GAME_DRAW': reward = 1 done = True else: reward = -1 done = True reward_sum += reward drs.append(reward) if done: # an episode finished episode_number += 1 # stack together all inputs, hidden states, action gradients, and rewards for this episode epx = np.vstack(xs) eph = np.vstack(hs) epdlogp = np.vstack(dlogps) epr = np.vstack(drs) xs,hs,dlogps,drs = [],[],[],[] # reset array memory # compute the discounted reward backwards through time discounted_epr = discount_rewards(epr) # standardize the rewards to be unit normal (helps control the gradient estimator variance) discounted_epr -= np.mean(discounted_epr) discounted_epr /= np.std(discounted_epr) epdlogp *= discounted_epr # modulate the gradient with advantage (PG magic happens right here.) grad = policy_backward(eph, epdlogp) for k in model: grad_buffer[k] += grad[k] # accumulate grad over batch # perform rmsprop parameter update every batch_size episodes if episode_number % batch_size == 0: for k,v in model.items(): g = grad_buffer[k] # gradient rmsprop_cache[k] = decay_rate * rmsprop_cache[k] + (1 - decay_rate) * g**2 model[k] += learning_rate * g / (np.sqrt(rmsprop_cache[k]) + 1e-5) grad_buffer[k] = np.zeros_like(v) # reset batch gradient buffer # boring book-keeping running_reward = reward_sum if running_reward is None else running_reward * 0.99 + reward_sum * 0.01 #print('resetting env. episode reward total was %f. running mean: %f' % (reward_sum, running_reward)) if episode_number % 100 == 0: pickle.dump(model, open('save.p', 'wb')) reward_sum = 0 #if reward != 0: # Pong has either +1 or -1 reward exactly when game ends. #print(('ep %d: game finished, reward: %f' % (episode_number, reward)) + ('' if reward == -1 else ' !!!!!!!!')) def policy_forward(x): h = np.dot(model['W1'], x) h[h<0] = 0 # ReLU nonlinearity logp = np.dot(model['W2'], h) p = sigmoid(logp) return p, h # return probability of taking action 2, and hidden state def move_to(player, pred) : #move platform to predicted position to catch ball if player == '1P': if scene_info["platform_1P"][0]+20 > (pred-10) and scene_info["platform_1P"][0]+20 < (pred+10): return 0 # NONE elif scene_info["platform_1P"][0]+20 <= (pred-10) : return 1 # goes right else : return 2 # goes left else : if scene_info["platform_2P"][0]+20 > (pred-10) and scene_info["platform_2P"][0]+20 < (pred+10): return 0 # NONE elif scene_info["platform_2P"][0]+20 <= (pred-10) : return 1 # goes right else : return 2 # goes left def ml_loop_for_1P(): if scene_info['status'] == 'GAME_ALIVE': reward = 0 elif scene_info['status'] == 'GAME_1P_WIN': reward = 2 elif scene_info['status'] == 'GAME_DRAW': reward = 1 else: reward = -1 #print(reward) if scene_info["ball_speed"][1] > 0 : # 球正在向下 # ball goes down x = ( scene_info["platform_1P"][1]-scene_info["ball"][1] ) // scene_info["ball_speed"][1] # 幾個frame以後會需要接 # x means how many frames before catch the ball pred = scene_info["ball"][0]+(scene_info["ball_speed"][0]*x) # 預測最終位置 # pred means predict ball landing site bound = pred // 200 # Determine if it is beyond the boundary if (bound > 0): # pred > 200 # fix landing position if (bound%2 == 0) : pred = pred - bound*200 else : pred = 200 - (pred - 200*bound) elif (bound < 0) : # pred < 0 if (bound%2 ==1) : pred = abs(pred - (bound+1) *200) else : pred = pred + (abs(bound)*200) return move_to(player = '1P',pred = pred) else : # 球正在向上 # ball goes up return move_to(player = '1P',pred = 100) def ml_loop_for_2P(): # as same as 1P if scene_info["ball_speed"][1] > 0 : return move_to(player = '2P',pred = 100) else : x = ( scene_info["platform_2P"][1]+30-scene_info["ball"][1] ) // scene_info["ball_speed"][1] pred = scene_info["ball"][0]+(scene_info["ball_speed"][0]*x) bound = pred // 200 if (bound > 0): if (bound%2 == 0): pred = pred - bound*200 else : pred = 200 - (pred - 200*bound) elif (bound < 0) : if bound%2 ==1: pred = abs(pred - (bound+1) *200) else : pred = pred + (abs(bound)*200) return move_to(player = '2P',pred = pred) # 2. Inform the game process that ml process is ready comm.ml_ready() count = 0 _score = [0,0] _game_over_score = 11 # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({"frame": scene_info["frame"], "command": "SERVE_TO_LEFT"}) ball_served = True else: if side == "1P": observation = getObs("1P") aprob, h = policy_forward(observation) action = 2 if np.random.uniform() < aprob else 3 #print('action' + str(action)) #print('aprob' + str(aprob)) #print('a' + str(np.random.uniform())) if action == 2: comm.send_to_game({"frame": scene_info["frame"], "command": "MOVE_RIGHT"}) else: comm.send_to_game({"frame": scene_info["frame"], "command": "MOVE_LEFT"}) # record various intermediates (needed later for backprop) xs.append(observation) # observation hs.append(h) # hidden state y = 1 if action == 2 else 0 # a "fake label" dlogps.append(y - aprob) # grad that encourages the action that was taken to be taken (see http://cs231n.github.io/neural-networks-2/#losses if confused) if scene_info['status'] == 'GAME_ALIVE': reward = 0 done = False elif scene_info['status'] == 'GAME_1P_WIN': reward = 2 _score[0] += 1 elif scene_info['status'] == 'GAME_DRAW': reward = 1 _score[0] += 1 _score[1] += 1 else: reward = -1 _score[1] += 1 if _score[0] == _game_over_score or _score[1] == _game_over_score: done = True else: done = False reward_sum += reward drs.append(reward) if done: # an episode finished episode_number += 1 _score = [0,0] # stack together all inputs, hidden states, action gradients, and rewards for this episode epx = np.vstack(xs) eph = np.vstack(hs) epdlogp = np.vstack(dlogps) epr = np.vstack(drs) xs,hs,dlogps,drs = [],[],[],[] # reset array memory # compute the discounted reward backwards through time discounted_epr = discount_rewards(epr) discounted_epr = discounted_epr.astype('float') # standardize the rewards to be unit normal (helps control the gradient estimator variance) discounted_epr -= np.mean(discounted_epr).astype('float') discounted_epr /= np.std(discounted_epr).astype('float') epdlogp *= discounted_epr # modulate the gradient with advantage (PG magic happens right here.) grad = policy_backward(eph, epdlogp) for k in model: grad_buffer[k] += grad[k] # accumulate grad over batch # perform rmsprop parameter update every batch_size episodes if episode_number % batch_size == 0: for k,v in model.items(): g = grad_buffer[k] # gradient rmsprop_cache[k] = decay_rate * rmsprop_cache[k] + (1 - decay_rate) * g**2 model[k] += learning_rate * g / (np.sqrt(rmsprop_cache[k]) + 1e-5) grad_buffer[k] = np.zeros_like(v) # reset batch gradient buffer # boring book-keeping running_reward = reward_sum if running_reward is None else running_reward * 0.99 + reward_sum * 0.01 print('resetting env. episode reward total was %f. running mean: %f' % (reward_sum, running_reward)) if episode_number % 100 == 0: pickle.dump(model, open('save.p', 'wb')) reward_sum = 0 if reward != 0: # Pong has either +1 or -1 reward exactly when game ends. print(('ep %d: game finished, reward: %f' % (episode_number, reward)) + ('' if reward == -1 else ' !!!!!!!!')) #command = ml_loop_for_1P() else: command = ml_loop_for_2P() if command == 0: comm.send_to_game({"frame": scene_info["frame"], "command": "NONE"}) elif command == 1: comm.send_to_game({"frame": scene_info["frame"], "command": "MOVE_RIGHT"}) else : comm.send_to_game({"frame": scene_info["frame"], "command": "MOVE_LEFT"}) if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information cur = [0, 0] # a,b cur = list(scene_info["ball"]) vel = list(scene_info["ball_speed"]) plat1 = list(scene_info["platform_1P"]) plat2 = list(scene_info["platform_2P"]) #block = list(scene_info["blocker"]) if (vel[0] == 0): m = 1 else: m = vel[1] / vel[0] #斜率(vy/vx) point1 = cur[0] + ((420 - cur[1]) / m) #1P的落點 point2 = cur[0] - ((cur[1] - 80) / m) #2P的落點 #point1c = [100,260] #point2c = [100,240] #print(cur) #print(vel) if (vel[1] > 0 and cur[1] > 110): point1 = point1_down(point1) elif (vel[1] < 0 and cur[1] > 260): point1 = point1_up(cur, m) elif (vel[1] < 0 and cur[1] < 260): point1 = 100 print(point1) #ml_loop_for_1P(plat1, point1) # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: #comm.send_to_game({"frame": scene_info["frame"], "command": "MOVE_LEFT"}) if (vel[1] == 0): comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) else: if (plat1[0] + 20 > point1): comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" }) elif (plat1[0] + 20 < point1): comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" })
def ml_loop(side: str): # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False filename = path.join(path.dirname(__file__), 'save', 'NORMAL_model.pickle') with open(filename, 'rb') as file: clf = pickle.load(file) def get_direction(speed_x, speed_y): if (speed_x >= 0 and speed_y >= 0): return 0 elif (speed_x > 0 and speed_y < 0): return 1 elif (speed_x < 0 and speed_y > 0): return 2 elif (speed_x < 0 and speed_y < 0): return 3 # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() feature=[] feature.append(scene_info["ball"][0]) feature.append(scene_info["ball"][1]) feature.append(scene_info["platform_1P"][0]+20) feature.append(scene_info["ball_speed"][0]) feature.append(scene_info["ball_speed"][1]) feature.append(get_direction(feature[3],feature[4])) feature=np.array(feature) feature = feature.reshape((-1,6)) # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] !="GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: #comm.send_instruction(scene_info.frame, PlatformAction.SERVE_TO_LEFT) ball_served = True else: y = clf.predict(feature) if y == 0: comm.send_to_game({"frame": scene_info["frame"], "command": "NONE"}) print('NONE') elif y ==1: comm.send_to_game({"frame": scene_info["frame"], "command": "MOVE_LEFT"}) print('LEFT') elif y ==2: comm.send_to_game({"frame": scene_info["frame"], "command": "MOVE_RIGHT"}) print('RIGHT')
def ml_loop(side: str): # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False check = False p1 = False p2 = False person = False dead = True Pdirect = rd.randint(0, 1) def move_to(player, pred): #move platform to predicted position to catch ball if player == '1P': if scene_info["platform_1P"][0] + 20 > pred: return 2 # goes left elif scene_info["platform_1P"][0] + 20 < pred: return 1 # goes right else: return 0 # NONE else: if scene_info["platform_2P"][0] + 20 > pred: return 2 # goes left elif scene_info["platform_2P"][0] + 20 < pred: return 1 # goes right else: return 0 # NONE def cut_the_ball(): tmp = rd.randint(0, 2) if tmp == 2: return 2 # goes left elif tmp == 1: return 1 # goes right else: return 1 # NONE def ml_loop_for_1P(): if scene_info["ball_speed"][1] > 0: # 球正在向下 # ball goes down abs_speedX = abs(scene_info["ball_speed"][0]) #將speed設為正 now_direct = 0 yseg = math.ceil( (scene_info["platform_1P"][1] - scene_info["ball"][1] - 5) / scene_info["ball_speed"][1] ) # 幾個frame以後會需要接 # x means how many frames before catch the ball if scene_info["ball_speed"][0] > 0: #球往右邊跑,等等由左邊開始計算 xseg = math.ceil((195 - scene_info["ball"][0]) / abs_speedX) now_direct = 1 else: #球往左邊跑,等等由右邊開始計算 xseg = math.ceil(scene_info["ball"][0] / abs_speedX) # 目前的xreg now_direct = 0 x_range_seg = math.ceil(195 / abs_speedX) #現在速度的xrangeseg last_reg = abs(int(yseg - xseg) % int(x_range_seg)) #最後的reg bound = abs(int((yseg - xseg) // x_range_seg + now_direct) % 2) pred = abs(195 * bound - last_reg * abs_speedX) if yseg < xseg: pred = scene_info["ball"][ 0] + yseg * scene_info["ball_speed"][0] # print(scene_info["ball_speed"],pred,now_direct,yseg,xseg,last_reg,x_range_seg,bound,scene_info["ball"],scene_info["platform_2P"],scene_info["platform_1P"]) if scene_info["ball"][1] + scene_info["ball_speed"][1] >= 415: # print(scene_info["frame"],scene_info["blocker"],scene_info["ball_speed"],scene_info["ball"],scene_info["platform_1P"],scene_info["platform_2P"]) return cut_the_ball() else: return move_to(player='1P', pred=pred) else: # 球正在向上 # ball goes up # if scene_info["ball"][1]==415: # # print(scene_info["frame"],scene_info["blocker"],scene_info["ball_speed"],scene_info["ball"],scene_info["platform_1P"],scene_info["platform_2P"]) # global p1test # if scene_info["ball"][1]==415: # if scene_info["ball_speed"][0]>0: # p1test=195-scene_info["ball"][0]/2 # else: # p1test=scene_info["ball"][0]/2 return move_to(player='1P', pred=100) def ml_loop_for_2P(): # as same as 1P if scene_info["ball_speed"][1] < 0: abs_speedX = abs(scene_info["ball_speed"][0]) #將speed設為正 now_direct = 0 yseg = math.ceil( (scene_info["platform_2P"][1] + 30 - scene_info["ball"][1]) / scene_info["ball_speed"][1] ) # 幾個frame以後會需要接 # x means how many frames before catch the ball if scene_info["ball_speed"][0] > 0: #球往右邊跑,等等由左邊開始計算 xseg = math.ceil((195 - scene_info["ball"][0]) / abs_speedX) now_direct = 1 else: #球往左邊跑,等等由右邊開始計算 xseg = math.ceil(scene_info["ball"][0] / abs_speedX) # 目前的xreg now_direct = 0 x_range_seg = math.ceil(195 / abs_speedX) #現在速度的xrangeseg last_reg = abs(int(yseg - xseg) % int(x_range_seg)) #最後的reg bound = abs(int((yseg - xseg) // x_range_seg + now_direct) % 2) pred = abs(195 * bound - last_reg * abs_speedX) if yseg < xseg: pred = scene_info["ball"][ 0] + yseg * scene_info["ball_speed"][0] # print(pred,now_direct,yseg,xseg,last_reg,x_range_seg,bound,scene_info["ball"]) if scene_info["ball"][1] - scene_info["ball_speed"][1] <= 80: print(scene_info["frame"], scene_info["ball_speed"], scene_info["ball"], scene_info["platform_1P"], scene_info["platform_2P"]) return cut_the_ball() else: return move_to(player='2P', pred=pred) else: return move_to(player='2P', pred=100) start_frame = rd.randint(0, 20) print(start_frame, "ooooooooo") test = 0 # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() # print(scene_info["blocker"]) # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False if dead == True: start_frame = rd.randint(0, 20) dead = False print(start_frame, "pppppppppp") Pdirect = rd.randint(0, 1) person = True # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.4 Send the instruction for this frame to the game process if not ball_served and scene_info["frame"] >= start_frame: direct = rd.randint(0, 1) if direct == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_RIGHT" }) ball_served = True continue elif scene_info["frame"] < start_frame: person = True if scene_info["ball"][1] > 150: preson = True else: preson = False if person == True and side == "1P" or person == False and side == "2P": if Pdirect == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: dead = True if side == "1P": command = ml_loop_for_1P() else: command = ml_loop_for_2P() if command == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) elif command == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" })
def ml_loop(side: str ): #呼叫此程式的程式中,助教已有設定好1P的板子side會設1P,所以def裡的程式直接依判別side值為何來決定該如何動作 """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False flag = 0 blocker_pre = 0 def move_to(player, pred): #move platform to predicted position to catch ball if (player == '1P'): if scene_info["platform_1P"][0] + 20 > ( pred - 5) and scene_info["platform_1P"][0] + 20 < (pred + 5): return 0 # NONE elif scene_info["platform_1P"][0] + 20 <= (pred - 5): return 1 # goes right else: return 2 # goes left else: if scene_info["platform_2P"][0] + 20 > ( pred - 10) and scene_info["platform_2P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_2P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left def ml_loop_for_1P(blocker_dir): #預測1P該在的位置 global flag if (scene_info["ball"][1] <= 260 and scene_info["ball"][1] >= 240): print("ball_x", scene_info["ball"][1], scene_info["ball"][0]) if scene_info["ball_speed"][1] > 0: # 球正在向下 # ball goes down ball_x = scene_info["ball"][0] ball_y = scene_info["ball"][1] ball_speed_x = scene_info["ball_speed"][0] ball_speed_y = scene_info["ball_speed"][1] #判斷2P回球是否會打到blocker側邊 if (scene_info["ball"][1] <= 240): # print() # x_top = (240-scene_info["ball"][1] ) / scene_info["ball_speed"][1] # x_bottom = (260-scene_info["ball"][1] ) / scene_info["ball_speed"][1] block_x = (240 - scene_info["ball"][1]) / scene_info["ball_speed"][1] # print(x) #print("x_top, x_bottom:", x_top, x_bottom) slope = abs(scene_info["ball_speed"][0] / scene_info["ball_speed"][1]) conflict_pred = scene_info["ball"][0] + ( scene_info["ball_speed"][0] * block_x) bound = conflict_pred // 200 # Determine if it is beyond the boundary if (bound > 0): # pred > 200 # fix landing position #超出右邊邊界 if (bound % 2 == 0): conflict_pred = conflict_pred - bound * 200 flag = 1 #flag 1 表撞到blocker時往右 else: conflict_pred = 200 - (conflict_pred - 200 * bound) flag = 2 #flag 2 表撞到blocker時往左 elif (bound < 0): # pred < 0 超出左邊邊界 if (bound % 2 == 1): conflict_pred = abs(conflict_pred - (bound + 1) * 200) flag = 1 else: conflict_pred = conflict_pred + (abs(bound) * 200) flag = 2 #bias = 20//abs(scene_info["ball_speed"][1]) blocker_pos_pred = scene_info["blocker"][0] + (blocker_dir * block_x) if (blocker_pos_pred > 170): blocker_pos_pred = 170 - (blocker_pos_pred - 170) #-5*bias elif (blocker_pos_pred < 0): blocker_pos_pred = abs(blocker_pos_pred) #+5*bias # else: # if(blocker_dir>0): # blocker_pos_pred += 5*bias # else: # blocker_pos_pred -= 5*bias #確定球會撞到blocker左邊反彈 # print(flag) # print("speed:", ball_speed_x, ball_speed_y) print("conflict_pred", conflict_pred) print("blocker:", scene_info["blocker"][0]) print("blocker_pos_pred", blocker_pos_pred, blocker_pos_pred + 30) if (flag == 1 and conflict_pred < (blocker_pos_pred + 15) and conflict_pred > (blocker_pos_pred - 20 * slope)): print("會撞到左邊") ball_x = blocker_pos_pred ball_y = 240 + ((blocker_pos_pred - conflict_pred) / slope) ball_speed_x = -abs(scene_info["ball_speed"][0]) #確定球會撞到blocker右邊反彈 # print(blocker_pos_pred+30, blocker_pos_pred+30+20*slope) if (flag == 2 and conflict_pred > (blocker_pos_pred + 15) and conflict_pred < (blocker_pos_pred + 30 + 20 * slope)): print("會撞到右邊") ball_x = blocker_pos_pred + 30 ball_y = 240 + ((conflict_pred - (blocker_pos_pred + 30)) / slope) ball_speed_x = abs(scene_info["ball_speed"][0]) x = ( scene_info["platform_1P"][1] - ball_y ) // ball_speed_y # 幾個frame以後會需要接(y距離/ball y速度) # x means how many frames before catch the ball pred = ball_x + (ball_speed_x * x ) # 預測最終位置 # pred means predict ball landing site bound = pred // 200 # Determine if it is beyond the boundary if (bound > 0): # pred > 200 # fix landing position #超出右邊邊界 if (bound % 2 == 0): pred = pred - bound * 200 else: pred = 200 - (pred - 200 * bound) elif (bound < 0): # pred < 0 超出左邊邊界 if (bound % 2 == 1): pred = abs(pred - (bound + 1) * 200) else: pred = pred + (abs(bound) * 200) #對回球瞬間做判斷,決定怎麼回會最好 if (x <= 1): #print("pred:",pred) #print("1p platform", scene_info["platform_1P"][0],scene_info["platform_1P"][0]+40) if (pred < 15): return 2 elif (pred > 185): return 1 dist = (160 + (420 - scene_info["ball"][1]) ) / scene_info["ball_speed"][1] #計算球彈到blocker時的位置 ball_blocker_pred = scene_info["ball"][0] + ( (scene_info["ball_speed"][0]) * dist) ball_blocker_cut_pred = scene_info["ball"][0] + ( (scene_info["ball_speed"][0]) * dist) if (abs(scene_info["ball_speed"][0]) - scene_info["ball_speed"][1] == 0): if (scene_info["ball_speed"][0] < 0): ball_blocker_cut_pred = scene_info["ball"][0] + ( (scene_info["ball_speed"][0] - 3) * dist) else: ball_blocker_cut_pred = scene_info["ball"][0] + ( (scene_info["ball_speed"][0] + 3) * dist) ball_blocker_bound = ball_blocker_pred // 200 ball_blocker_cut_bound = ball_blocker_cut_pred // 200 #假設一般 if (ball_blocker_bound > 0): if (ball_blocker_bound % 2 == 0): ball_blocker_pred = ball_blocker_pred - ball_blocker_bound * 200 else: ball_blocker_pred = 200 - (ball_blocker_pred - 200 * ball_blocker_bound) elif (ball_blocker_bound < 0): if (ball_blocker_bound % 2 == 1): ball_blocker_pred = abs(ball_blocker_pred - (ball_blocker_bound + 1) * 200) else: ball_blocker_pred = ball_blocker_pred + ( abs(ball_blocker_bound) * 200) #假設切球 if (ball_blocker_cut_bound > 0): if (ball_blocker_cut_bound % 2 == 0): ball_blocker_cut_pred = ball_blocker_cut_pred - ball_blocker_cut_bound * 200 else: ball_blocker_cut_pred = 200 - ( ball_blocker_cut_pred - 200 * ball_blocker_cut_bound) elif (ball_blocker_cut_bound < 0): if (ball_blocker_cut_bound % 2 == 1): ball_blocker_cut_pred = abs( ball_blocker_cut_pred - (ball_blocker_cut_bound + 1) * 200) else: ball_blocker_cut_pred = ball_blocker_cut_pred + ( abs(ball_blocker_cut_bound) * 200) #計算球到blocker y座標時,blocker此時位置 blocker_pos_pred = scene_info["blocker"][0] + (blocker_dir * dist) if (blocker_pos_pred > 170): blocker_pos_pred = 170 - (blocker_pos_pred - 170) if (blocker_pos_pred < 0): blocker_pos_pred = abs(blocker_pos_pred) #如果預測切球之後會使得球打到障礙物,則選擇反向反彈,但當反彈或切球都會撞到障礙物時則無法避免 #print("ball_blocker_pred:" ,ball_blocker_pred, "blocker_pos_pred:", blocker_pos_pred, blocker_pos_pred+30) #print("ball_blocker_cut_pred:" ,ball_blocker_cut_pred, "blocker_pos_pred:", blocker_pos_pred, blocker_pos_pred+30) if (pred >= scene_info["platform_1P"][0] + 40): #print("右") return 1 elif (pred <= scene_info["platform_1P"][0]): #print("左") return 2 #blocker預測範圍加15增加容錯率 elif (ball_blocker_cut_pred < blocker_pos_pred - 12 or ball_blocker_cut_pred > blocker_pos_pred + 42): #print("accelerate") if (scene_info["ball_speed"][0] < 0 and not (scene_info["platform_1P"][0] + 40 - 5 < pred)): return 2 elif (scene_info["ball_speed"][0] > 0 and not (scene_info["platform_1P"][0] + 5 > pred)): return 1 elif (ball_blocker_pred < blocker_pos_pred - 12 or ball_blocker_pred > blocker_pos_pred + 42): #print("NONE") return 0 else: #print("reverse") if (scene_info["ball_speed"][0] < 0 and not (scene_info["platform_1P"][0] + 5 > pred)): return 1 elif (scene_info["ball_speed"][0] > 0 and not (scene_info["platform_1P"][0] + 40 - 5 < pred)): return 2 # print("random") # if (rand < 0.33): # return 1 # elif (rand>=0.33 and rand<0.66): # return 2 # else: # return 0 else: #print("normal") return move_to(player='1P', pred=pred) else: # 球正在向上 # ball goes up flag = 0 return move_to(player='1P', pred=100) def ml_loop_for_2P(blocker_dir): # as same as 1P if scene_info["ball_speed"][1] > 0: return move_to(player='2P', pred=100) else: x = (scene_info["platform_2P"][1] + 30 - scene_info["ball"][1]) // scene_info["ball_speed"][1] pred = scene_info["ball"][0] + (scene_info["ball_speed"][0] * x) bound = pred // 200 rand = random.random() if (bound > 0): if (bound % 2 == 0): pred = pred - bound * 200 else: pred = 200 - (pred - 200 * bound) elif (bound < 0): if bound % 2 == 1: pred = abs(pred - (bound + 1) * 200) else: pred = pred + (abs(bound) * 200) if (x <= 1): if (pred >= scene_info["platform_2P"][0] + 25): return 1 elif (pred <= scene_info["platform_2P"][0] + 15): return 2 else: if (rand < 0.33): return 1 elif (rand >= 0.33 and rand < 0.66): return 2 else: return 0 else: return move_to(player='2P', pred=pred) # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() blocker_dir = scene_info["blocker"][0] - blocker_pre blocker_pre = scene_info["blocker"][0] # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) #以dict形式傳入,內有兩個參數 ball_served = True else: #if(scene_info["ball"][0]<=scene_info["blocker"][0]+30 and scene_info["ball"][0]>=scene_info["blocker"][0] and scene_info["ball"][1]>=scene_info["blocker"][1] and scene_info["ball"][1]<=scene_info["blocker"][1]+20): #print("ball pos:",scene_info["ball"][0], scene_info["ball"][1]) if side == "1P": command = ml_loop_for_1P(blocker_dir) else: command = ml_loop_for_2P(blocker_dir) if command == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) elif command == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" })
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ H = 200 D = 8 resume = False # resume from previous checkpoint? RIGHT_ACTION = 2 LEFT_ACTION = 3 if resume: model = pickle.load(open('save.p', 'rb')) else: model = Sequential() model.add(Dense(units=200,input_dim=80*80, activation='relu', kernel_initializer='glorot_uniform')) model.add(Dense(units=1, activation='sigmoid', kernel_initializer='RandomNormal')) model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) gamma = 0.99 # discount factor for reward decay_rate = 0.99 # decay factor for RMSProp leaky sum of grad^2 # initialization of variables used in the main loop x_train, y_train, rewards = [],[],[] reward_sum = 0 episode_nb = 0 # initialize variables resume = True running_reward = None epochs_before_saving = 10 log_dir = './log' + datetime.now().strftime("%Y%m%d-%H%M%S") + "/" # load pre-trained model if exist if (resume and os.path.isfile('my_model_weights.h5')): print("loading previous weights") model.load_weights('my_model_weights.h5') # add a callback tensorboard object to visualize learning tbCallBack = callbacks.TensorBoard(log_dir=log_dir, histogram_freq=0, write_graph=True, write_images=True) # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False def getObs(player): observation = [] observation.append(scene_info['ball'][0]) observation.append(scene_info['ball'][1]) observation.append(scene_info['ball_speed'][0]) observation.append(scene_info['ball_speed'][1]) observation.append(scene_info['blocker'][0]) observation.append(scene_info['blocker'][1]) if player == '1P': observation.append(scene_info['platform_1P'][0]) observation.append(scene_info['platform_1P'][1]) if player == '2P': observation.append(scene_info['platform_2P'][0]) observation.append(scene_info['platform_2P'][1]) observation = np.array(observation) return observation def move_to(player, pred) : #move platform to predicted position to catch ball if player == '1P': if scene_info["platform_1P"][0]+20 > (pred-10) and scene_info["platform_1P"][0]+20 < (pred+10): return 0 # NONE elif scene_info["platform_1P"][0]+20 <= (pred-10) : return 1 # goes right else : return 2 # goes left else : if scene_info["platform_2P"][0]+20 > (pred-10) and scene_info["platform_2P"][0]+20 < (pred+10): return 0 # NONE elif scene_info["platform_2P"][0]+20 <= (pred-10) : return 1 # goes right else : return 2 # goes left def ml_loop_for_1P(): if scene_info['status'] == 'GAME_ALIVE': reward = 0 elif scene_info['status'] == 'GAME_1P_WIN': reward = 2 elif scene_info['status'] == 'GAME_DRAW': reward = 1 else: reward = -1 #print(reward) if scene_info["ball_speed"][1] > 0 : # 球正在向下 # ball goes down x = ( scene_info["platform_1P"][1]-scene_info["ball"][1] ) // scene_info["ball_speed"][1] # 幾個frame以後會需要接 # x means how many frames before catch the ball pred = scene_info["ball"][0]+(scene_info["ball_speed"][0]*x) # 預測最終位置 # pred means predict ball landing site bound = pred // 200 # Determine if it is beyond the boundary if (bound > 0): # pred > 200 # fix landing position if (bound%2 == 0) : pred = pred - bound*200 else : pred = 200 - (pred - 200*bound) elif (bound < 0) : # pred < 0 if (bound%2 ==1) : pred = abs(pred - (bound+1) *200) else : pred = pred + (abs(bound)*200) return move_to(player = '1P',pred = pred) else : # 球正在向上 # ball goes up return move_to(player = '1P',pred = 100) def ml_loop_for_2P(): # as same as 1P if scene_info["ball_speed"][1] > 0 : return move_to(player = '2P',pred = 100) else : x = ( scene_info["platform_2P"][1]+30-scene_info["ball"][1] ) // scene_info["ball_speed"][1] pred = scene_info["ball"][0]+(scene_info["ball_speed"][0]*x) bound = pred // 200 if (bound > 0): if (bound%2 == 0): pred = pred - bound*200 else : pred = 200 - (pred - 200*bound) elif (bound < 0) : if bound%2 ==1: pred = abs(pred - (bound+1) *200) else : pred = pred + (abs(bound)*200) return move_to(player = '2P',pred = pred) # 2. Inform the game process that ml process is ready comm.ml_ready() _score = [0,0] _game_over_score = 11 # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({"frame": scene_info["frame"], "command": "SERVE_TO_LEFT"}) ball_served = True else: if side == "1P": observation = getObs("1P") proba = model.predict(np.expand_dims(observation, axis=1).T) action = RIGHT_ACTION if np.random.uniform() < proba else LEFT_ACTION y = 1 if action == 2 else 0 # 0 and 1 are our labels #print('action' + str(action)) #print('aprob' + str(aprob)) #print('a' + str(np.random.uniform())) if action == 2: comm.send_to_game({"frame": scene_info["frame"], "command": "MOVE_RIGHT"}) else: comm.send_to_game({"frame": scene_info["frame"], "command": "MOVE_LEFT"}) # record various intermediates (needed later for backprop) x_train.append(observation) y_train.append(y) if scene_info['status'] == 'GAME_ALIVE': reward = 0 done = False elif scene_info['status'] == 'GAME_1P_WIN': reward = 2 _score[0] += 1 elif scene_info['status'] == 'GAME_DRAW': reward = 1 _score[0] += 1 _score[1] += 1 else: reward = -1 _score[1] += 1 if _score[0] == _game_over_score or _score[1] == _game_over_score: done = True else: done = False rewards.append(reward) reward_sum += reward if done: # an episode finished print('At the end of episode', episode_nb, 'the total reward was :', reward_sum) # increment episode number episode_nb += 1 # training model.fit(x=np.vstack(x_train), y=np.vstack(y_train), verbose=1, callbacks=[tbCallBack], sample_weight=discount_rewards(rewards, gamma)) # Saving the weights used by our model if episode_nb % epochs_before_saving == 0: model.save_weights('my_model_weights' + datetime.now().strftime("%Y%m%d-%H%M%S") + '.h5') # Log the reward running_reward = reward_sum if running_reward is None else running_reward * 0.99 + reward_sum * 0.01 tflog('running_reward', running_reward, custom_dir=log_dir) # Reinitialization x_train, y_train, rewards = [],[],[] reward_sum = 0 else: command = ml_loop_for_2P() if command == 0: comm.send_to_game({"frame": scene_info["frame"], "command": "NONE"}) elif command == 1: comm.send_to_game({"frame": scene_info["frame"], "command": "MOVE_RIGHT"}) else : comm.send_to_game({"frame": scene_info["frame"], "command": "MOVE_LEFT"}) if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue
def ml_loop(side: str): # === Here is the execution order of the loop === # # 1. Put the initialization code here. ball_served = False filename = path.join(path.dirname(__file__), "random_forest.pickle") with open(filename, 'rb') as file: clf = pickle.load(file) # 2. Inform the game process that ml process is ready before start the loop. comm.ml_ready() s = [93, 93] def get_direction(ball_x, ball_y, ball_pre_x, ball_pre_y): VectorX = ball_x - ball_pre_x VectorY = ball_y - ball_pre_y if (VectorX > 0 and VectorY > 0): return 0 elif (VectorX > 0 and VectorY < 0): return 1 elif (VectorX < 0 and VectorY > 0): return 2 elif (VectorX < 0 and VectorY < 0): return 3 else: return 4 # 3. Start an endless loop. while True: # 3.1. Receive the scene information sent from the game process. scene_info = comm.recv_from_game() #Data = [Commands, Balls, Ball_speed, PlatformPos, Blocker, vectors, direction] #Feature = [Balls, Ball_speed, PlatformPos, Blocker, direction] feature = [] for i in range(0, 2): # feature.append(scene_info["ball"][i]) # feature.append(scene_info["ball_speed"][i]) feature.append(scene_info["platform_1P"][i]) feature.append(scene_info["blocker"][i]) feature.append(feature[0] - s[0]) feature.append(feature[1] - s[1]) feature.append(get_direction(feature[0], feature[1], s[0], s[1])) s = [feature[0], feature[1]] # print(feature) feature = np.array(feature) feature = feature.reshape((-2, 7)) # 3.2. If the game is over or passed, the game process will reset # the scene and wait for ml process doing resetting job. if scene_info["status"] != "GAME_ALIVE": # Do some stuff if needed ball_served = False # 3.2.1. Inform the game process that ml process is ready comm.ml_ready() continue # 3.3. Put the code here to handle the scene information # 3.4. Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: y = clf.predict(feature) if y == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) print('NONE') elif y == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) print('LEFT') elif y == 2: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" }) print('RIGHT')
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False hit_range = 10 pred_range = 3 def move_to(player, pred): #move platform to predicted position to catch ball if player == '1P': if scene_info["platform_1P"][0] + 20 > ( pred - pred_range ) and scene_info["platform_1P"][0] + 20 < (pred + pred_range): return 0 # NONE elif scene_info["platform_1P"][0] + 20 <= (pred - pred_range): return 1 # goes right else: return 2 # goes left else: if scene_info["platform_2P"][0] + 20 > ( pred - pred_range ) and scene_info["platform_2P"][0] + 20 < (pred + pred_range): return 0 # NONE elif scene_info["platform_2P"][0] + 20 <= (pred - pred_range): return 1 # goes right else: return 2 # goes left def get_blocker_direction(bkx, pre_bkx): if bkx > pre_bkx: return 1 elif bkx < pre_bkx: return -1 else: return 0 def ml_loop_for_1P(bkx, bkxdir): if scene_info["ball_speed"][1] > 0 and scene_info["ball"][ 1] < scene_info["blocker"][ 1]: #ball goes down and over blocker for 1P hit_blocker_frames = ( scene_info["blocker"][1] + 10 - scene_info["ball"][1] ) // scene_info["ball_speed"][1] #frames of hit blocker pred = scene_info["ball"][0] + (scene_info["ball_speed"][0] * hit_blocker_frames) turn_head = 0 turn_rear = 0 if pred > 200: pred = 400 - pred turn_rear = 1 elif pred < 0: pred = 0 - pred turn_head = 1 if scene_info["ball_speed"][ 0] > 0 and turn_rear == 0: #ball goes right and not hit wall pred_1P = scene_info["ball"][0] + ( scene_info["platform_1P"][1] - scene_info["ball"][1]) if bkxdir == 1: predic_bkx = bkx + hit_blocker_frames // 2 * 5 if predic_bkx > 170: predic_bkx = 340 - predic_bkx elif bkxdir == -1: predic_bkx = bkx - hit_blocker_frames // 2 * 5 if predic_bkx < 0: predic_bkx = 0 - predic_bkx elif scene_info["ball_speed"][ 0] > 0 and turn_rear == 1: #ball goes right and hit wall pred_1P = scene_info["ball"][0] + ( scene_info["platform_1P"][1] - scene_info["ball"][1]) if bkxdir == 1: predic_bkx = bkx + hit_blocker_frames // 2 * 5 + 30 if predic_bkx > 200: predic_bkx = 400 - predic_bkx elif bkxdir == -1: predic_bkx = bkx - hit_blocker_frames // 2 * 5 + 30 if predic_bkx < 30: predic_bkx = 30 + (30 - predic_bkx) elif scene_info["ball_speed"][ 0] < 0 and turn_head == 0: #ball goes left and not hit wall pred_1P = scene_info["ball"][0] - ( scene_info["platform_1P"][1] - scene_info["ball"][1]) if bkxdir == 1: predic_bkx = bkx + hit_blocker_frames // 2 * 5 + 30 if predic_bkx > 200: predic_bkx = 400 - predic_bkx elif bkxdir == -1: predic_bkx = bkx - hit_blocker_frames // 2 * 5 + 30 if predic_bkx < 30: predic_bkx = 30 + (30 - predic_bkx) elif scene_info["ball_speed"][ 0] < 0 and turn_head == 1: #ball goes left and hit wall pred_1P = scene_info["ball"][0] - ( scene_info["platform_1P"][1] - scene_info["ball"][1]) if bkxdir == 1: predic_bkx = bkx + hit_blocker_frames // 2 * 5 if predic_bkx > 170: predic_bkx = 340 - predic_bkx elif bkxdir == -1: predic_bkx = bkx - hit_blocker_frames // 2 * 5 if predic_bkx < 0: predic_bkx = 0 - predic_bkx if abs(predic_bkx - pred) < hit_range: # hit blocker situation if scene_info["ball_speed"][0] > 0 and turn_rear == 0: pred_1P = predic_bkx - 170 elif scene_info["ball_speed"][0] > 0 and turn_rear == 1: pred_1P = predic_bkx + 170 elif scene_info["ball_speed"][0] < 0 and turn_head == 0: pred_1P = predic_bkx + 170 elif scene_info["ball_speed"][0] < 0 and turn_head == 1: pred_1P = predic_bkx - 170 elif scene_info["ball_speed"][1] > 0: #ball goes down for 1P if scene_info["ball_speed"][0] > 0: #ball goes right pred_1P = scene_info["ball"][0] + ( scene_info["platform_1P"][1] - scene_info["ball"][1]) else: #ball goes left pred_1P = scene_info["ball"][0] - ( scene_info["platform_1P"][1] - scene_info["ball"][1]) elif scene_info["ball_speed"][1] < 0 and scene_info["ball"][ 1] > scene_info["blocker"][ 1] + 20: #ball goes up and below blocker for 1P if scene_info["ball_speed"][0] > 0: #ball goes right px = scene_info["ball"][0] - (scene_info["platform_1P"][1] - scene_info["ball"][1]) if px < -80: pred_1P = 160 elif px < 80: pred_1P = 80 - px else: pred_1P = px - 80 else: #ball goes left px = scene_info["ball"][0] + (scene_info["platform_1P"][1] - scene_info["ball"][1]) if px > 300: pred_1P = 20 elif px > 120: pred_1P = 320 - px else: pred_1P = px + 80 else: pred_1P = 80 bound = pred_1P // 200 # Determine if it is beyond the boundary if (bound > 0): # pred > 200 # fix landing position if (bound % 2 == 0): pred_1P = pred_1P - bound * 200 else: pred_1P = 200 - (pred_1P - 200 * bound) elif (bound < 0): # pred < 0 if (bound % 2 == 1): pred_1P = abs(pred_1P - (bound + 1) * 200) else: pred_1P = pred_1P + (abs(bound) * 200) return move_to(player='1P', pred=pred_1P) def ml_loop_for_2P(bkx, bkxdir): if scene_info["ball_speed"][1] < 0 and scene_info["ball"][ 1] > scene_info["blocker"][ 1] + 20: #ball goes down and over blocker for 2P hit_blocker_frames = ( scene_info["blocker"][1] + 10 - scene_info["ball"][1] ) // scene_info["ball_speed"][1] #frames of hit blocker pred = scene_info["ball"][0] + (scene_info["ball_speed"][0] * hit_blocker_frames) turn_head = 0 turn_rear = 0 if pred > 200: pred = 400 - pred turn_rear = 1 elif pred < 0: pred = 0 - pred turn_head = 1 if scene_info["ball_speed"][ 0] > 0 and turn_rear == 0: #ball goes right and not hit wall pred_2P = scene_info["ball"][0] + ( scene_info["ball"][1] - scene_info["platform_2P"][1] - 30) if bkxdir == 1: predic_bkx = bkx + hit_blocker_frames // 2 * 5 if predic_bkx > 170: predic_bkx = 340 - predic_bkx elif bkxdir == -1: predic_bkx = bkx - hit_blocker_frames // 2 * 5 if predic_bkx < 0: predic_bkx = 0 - predic_bkx elif scene_info["ball_speed"][ 0] > 0 and turn_rear == 1: #ball goes right and hit wall pred_2P = scene_info["ball"][0] + ( scene_info["ball"][1] - scene_info["platform_2P"][1] - 30) if bkxdir == 1: predic_bkx = bkx + hit_blocker_frames // 2 * 5 + 30 if predic_bkx > 200: predic_bkx = 400 - predic_bkx elif bkxdir == -1: predic_bkx = bkx - hit_blocker_frames // 2 * 5 + 30 if predic_bkx < 30: predic_bkx = 30 + (30 - predic_bkx) elif scene_info["ball_speed"][ 0] < 0 and turn_head == 0: #ball goes left and not hit wall pred_2P = scene_info["ball"][0] - ( scene_info["ball"][1] - scene_info["platform_2P"][1] - 30) if bkxdir == 1: predic_bkx = bkx + hit_blocker_frames // 2 * 5 + 30 if predic_bkx > 200: predic_bkx = 400 - predic_bkx elif bkxdir == -1: predic_bkx = bkx - hit_blocker_frames // 2 * 5 + 30 if predic_bkx < 30: predic_bkx = 30 + (30 - predic_bkx) elif scene_info["ball_speed"][ 0] < 0 and turn_head == 1: #ball goes left and hit wall pred_2P = scene_info["ball"][0] - ( scene_info["ball"][1] - scene_info["platform_2P"][1] - 30) if bkxdir == 1: predic_bkx = bkx + hit_blocker_frames // 2 * 5 if predic_bkx > 170: predic_bkx = 340 - predic_bkx elif bkxdir == -1: predic_bkx = bkx - hit_blocker_frames // 2 * 5 if predic_bkx < 0: predic_bkx = 0 - predic_bkx if abs(predic_bkx - pred) < hit_range: # hit blocker situation if scene_info["ball_speed"][0] > 0 and turn_rear == 0: pred_2P = predic_bkx - 170 elif scene_info["ball_speed"][0] > 0 and turn_rear == 1: pred_2P = predic_bkx + 170 elif scene_info["ball_speed"][0] < 0 and turn_head == 0: pred_2P = predic_bkx + 170 elif scene_info["ball_speed"][0] < 0 and turn_head == 1: pred_2P = predic_bkx - 170 elif scene_info["ball_speed"][1] < 0: #ball goes down for 2P if scene_info["ball_speed"][0] > 0: #ball goes right pred_2P = scene_info["ball"][0] + ( scene_info["ball"][1] - scene_info["platform_2P"][1] - 30) else: #ball goes left pred_2P = scene_info["ball"][0] - ( scene_info["ball"][1] - scene_info["platform_2P"][1] - 30) elif scene_info["ball_speed"][1] > 0 and scene_info["ball"][ 1] < scene_info["blocker"][ 1]: #ball goes up and below blocker for 2P if scene_info["ball_speed"][0] > 0: #ball goes right px = scene_info["ball"][0] - ( scene_info["ball"][1] - scene_info["platform_2P"][1] - 30) if px < -80: pred_2P = 160 elif px < 80: pred_2P = 80 - px else: pred_2P = px - 80 else: #ball goes left px = scene_info["ball"][0] + ( scene_info["ball"][1] - scene_info["platform_2P"][1] - 30) if px > 300: pred_2P = 20 elif px > 120: pred_2P = 320 - px else: pred_2P = px + 80 else: pred_2P = 80 bound = pred_2P // 200 if (bound > 0): if (bound % 2 == 0): pred_2P = pred_2P - bound * 200 else: pred_2P = 200 - (pred_2P - 200 * bound) elif (bound < 0): if bound % 2 == 1: pred_2P = abs(pred_2P - (bound + 1) * 200) else: pred_2P = pred_2P + (abs(bound) * 200) return move_to(player='2P', pred=pred_2P) # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop pre_bkx = 80 while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() bkx = scene_info["blocker"][0] # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: if (random.randint(0, 10) >= 5): r1 = 2 else: r1 = 0 if side == "1P": pd1 = get_blocker_direction(bkx, pre_bkx) if pd1 == 0: pd1 = ppd1 command = ml_loop_for_1P(bkx, pd1) pre_bkx = bkx ppd1 = pd1 if command == 0: if abs(scene_info["ball"][1] - scene_info["platform_1P"][1]) < 7 and r1 == 0: if scene_info["ball_speed"][0] > 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) elif command == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" }) else: pd2 = get_blocker_direction(bkx, pre_bkx) if pd2 == 0: pd2 = ppd2 command = ml_loop_for_2P(bkx, pd2) pre_bkx = bkx ppd2 = pd2 if command == 0: if abs(scene_info["ball"][1] - scene_info["platform_2P"][1]) < 7 and r1 == 2: if scene_info["ball_speed"][0] > 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) elif command == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" })
def get_scene_info() -> SceneInfo: """ Get the scene information from the game process """ return comm.recv_from_game()
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False def move_to(player, pred): #move platform to predicted position to catch ball if player == '1P': if scene_info["platform_1P"][0] + 20 > ( pred - 5) and scene_info["platform_1P"][0] + 20 < (pred + 5): return 0 # NONE elif scene_info["platform_1P"][0] + 20 <= (pred - 5): return 1 # goes right else: return 2 # goes left else: if scene_info["platform_2P"][0] + 20 > ( pred - 5) and scene_info["platform_2P"][0] + 20 < (pred + 5): return 0 # NONE elif scene_info["platform_2P"][0] + 20 <= (pred - 5): return 1 # goes right else: return 2 # goes left before_blocker_x = 0 def ml_loop_for_1P(): """ if scene_info["ball_speed"][1] > 0 : # 球正在向下 # ball goes down x = ( scene_info["platform_1P"][1]-scene_info["ball"][1] ) // scene_info["ball_speed"][1] # 幾個frame以後會需要接 # x means how many frames before catch the ball pred = scene_info["ball"][0]+(scene_info["ball_speed"][0]*x) # 預測最終位置 # pred means predict ball landing site bound = pred // 200 # Determine if it is beyond the boundary if (bound > 0): # pred > 200 # fix landing position if (bound%2 == 0) : pred = pred - bound*200 else : pred = 200 - (pred - 200*bound) elif (bound < 0) : # pred < 0 if (bound%2 ==1) : pred = abs(pred - (bound+1) *200) else : pred = pred + (abs(bound)*200) return move_to(player = '1P',pred = pred) else : # 球正在向上 # ball goes up return move_to(player = '1P',pred = 100) """ ball_x = scene_info["ball"][0] ball_y = scene_info["ball"][1] platform_x = scene_info["platform_1P"][0] platform_y = scene_info["platform_1P"][1] blocker_x = scene_info["blocker"][0] blocker_y = scene_info["blocker"][1] ball_speed_x = scene_info["ball_speed"][0] ball_speed_y = vector_y_down = scene_info["ball_speed"][1] blocker_x = scene_info["blocker"][0] if 240 < scene_info["ball"][1] < 260 and scene_info["ball"][ 0] != 0 and scene_info["ball"][ 0] != 195 and ball_x_speed != before_ball_x_speed: scene_info["blocker"][0], "block_y:", scene_info["blocker"][1] now_ball_x = ball_x now_ball_y = ball_y vector_x_right = True if ball_speed_x > 0 else False vector_y_down = True if ball_speed_y > 0 else False hit_y = 0 while hit_y < 415: if vector_x_right: hit_x = 195 else: hit_x = 0 if vector_y_down: hit_y = 415 else: hit_y = 80 if abs(now_ball_x - hit_x) < abs(now_ball_y - hit_y): if vector_y_down: hit_y = ( (abs(now_ball_x - hit_x) - 1) // abs(ball_speed_x) + 1) * abs(ball_speed_y) + now_ball_y if hit_y > 415: hit_y = ( (abs(now_ball_x - hit_x)) / abs(ball_speed_x)) * abs(ball_speed_y) + now_ball_y else: hit_y = -( (abs(now_ball_x - hit_x) - 1) // abs(ball_speed_x) + 1) * abs(ball_speed_y) + now_ball_y if hit_y < 0: hit_y = -( (abs(now_ball_x - hit_x)) / abs(ball_speed_x)) * abs(ball_speed_y) + now_ball_y vector_x_right = not vector_x_right else: #這邊可能會切球 if vector_x_right: hit_x = ( (abs(now_ball_y - hit_y)) / abs(ball_speed_x)) * abs(ball_speed_x) + now_ball_x else: hit_x = -( (abs(now_ball_y - hit_y)) / abs(ball_speed_y)) * abs(ball_speed_x) + now_ball_x vector_y_down = not vector_y_down now_ball_x = hit_x now_ball_y = hit_y should_x2 = hit_x return move_to(player='1P', pred=should_x2) def ml_loop_for_2P(): # as same as 1P ball_x = scene_info["ball"][0] ball_y = scene_info["ball"][1] platform_x = scene_info["platform_1P"][0] platform_y = scene_info["platform_1P"][1] ball_speed_x = scene_info["ball_speed"][0] ball_speed_y = vector_y_down = scene_info["ball_speed"][1] now_ball_x = ball_x now_ball_y = ball_y vector_x_right = True if ball_speed_x > 0 else False vector_y_down = True if ball_speed_y > 0 else False hit_y = 500 while hit_y > 80: if vector_x_right: hit_x = 195 else: hit_x = 0 if vector_y_down: hit_y = 415 else: hit_y = 80 if abs(now_ball_x - hit_x) < abs(now_ball_y - hit_y): if vector_y_down: hit_y = ( (abs(now_ball_x - hit_x) - 1) // abs(ball_speed_x) + 1) * abs(ball_speed_y) + now_ball_y if hit_y > 415: hit_y = ( (abs(now_ball_x - hit_x)) / abs(ball_speed_x)) * abs(ball_speed_y) + now_ball_y else: hit_y = -( (abs(now_ball_x - hit_x) - 1) // abs(ball_speed_x) + 1) * abs(ball_speed_y) + now_ball_y if hit_y < 0: hit_y = -( (abs(now_ball_x - hit_x)) / abs(ball_speed_x)) * abs(ball_speed_y) + now_ball_y vector_x_right = not vector_x_right else: #這邊可能會切球 if vector_x_right: hit_x = ( (abs(now_ball_y - hit_y)) / abs(ball_speed_x)) * abs(ball_speed_x) + now_ball_x else: hit_x = -( (abs(now_ball_y - hit_y)) / abs(ball_speed_y)) * abs(ball_speed_x) + now_ball_x vector_y_down = not vector_y_down now_ball_x = hit_x now_ball_y = hit_y should_x = hit_x return move_to(player='2P', pred=should_x) # 2. Inform the game process that ml process is ready comm.ml_ready() i = 0 ball_x_speed = 100 ball_y_speed = 10 # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served and i < 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) i = i + 1 elif not ball_served and i == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: if side == "1P": command = ml_loop_for_1P() else: command = ml_loop_for_2P() if command == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) elif command == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) #print("right") else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" }) #print("left") """ if scene_info["ball"][0]==195 or scene_info["ball"][0]==0: print("########x:",scene_info["ball"][0],"y:",scene_info["ball"][1]) """ #if scene_info["ball"][1]==80 or scene_info["ball"][1]==415: #if scene_info["ball"][1]==415: # print("******x:",scene_info["ball"][0],"y:",scene_info["ball"][1],"PLATFORM_x:",scene_info["platform_1P"][0],"PLATFORM_y:",scene_info["platform_1P"][1]) #print("x:",scene_info["ball"][0],"y:",scene_info["ball"][1],"ball_speed_x:",scene_info["ball_speed"][0],"ball_speed_y:",scene_info["ball_speed"][1],"PLATFORM_x:",scene_info["platform_1P"][0],"PLATFORM_y:",scene_info["platform_1P"][1]) #print("block_x:",scene_info["blocker"][0],"block_y:",scene_info["blocker"][1]) #print("x:",scene_info["ball"][0],"y:",scene_info["ball"][1],"ball_speed_x:","block_x:",scene_info["blocker"][0],"block_y:",scene_info["blocker"][1],scene_info["ball_speed"][0],"ball_speed_y:",scene_info["ball_speed"][1],"PLATFORM_x:",scene_info["platform_1P"][0],"PLATFORM_y:",scene_info["platform_1P"][1]) before_ball_x_speed = ball_x_speed before_ball_y_speed = ball_y_speed ball_x_speed = scene_info["ball_speed"][0] ball_y_speed = scene_info["ball_speed"][1] if 240 < scene_info["ball"][1] < 260 and scene_info["ball"][ 0] != 0 and scene_info["ball"][ 0] != 195 and ball_x_speed != before_ball_x_speed: print("x:", scene_info["ball"][0], "y:", scene_info["ball"][1], "ball_speed_x:", scene_info["ball_speed"][0], "block_x:", scene_info["blocker"][0], "block_y:", scene_info["blocker"][1], "ball_speed_y:", scene_info["ball_speed"][1], "PLATFORM_x:", scene_info["platform_1P"][0], "PLATFORM_y:", scene_info["platform_1P"][1])
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False def move_to(player, pred): #move platform to predicted position to catch ball if player == '1P': if scene_info["platform_1P"][0] + 20 > ( pred - 10) and scene_info["platform_1P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_1P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left else: if scene_info["platform_2P"][0] + 20 > ( pred - 10) and scene_info["platform_2P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_2P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left def ml_loop_for_1P(): slope = 1 blocker_pred = 0 if (scene_info["ball_speed"][0] != 0): slope = (scene_info["ball_speed"][1] / scene_info["ball_speed"][0]) if (scene_info["ball_speed"][1] < 0): if (scene_info["ball"][1] > 270): blocker_pred = (270 - scene_info["ball"][1] ) / slope + scene_info["ball"][0] while blocker_pred < 0 or blocker_pred > 195: if blocker_pred > 195: blocker_pred = 390 - blocker_pred elif blocker_pred < 0: blocker_pred = -blocker_pred pred = 150 / slope + blocker_pred while pred < 0 or pred > 195: if pred > 195: pred = 390 - pred elif pred < 0: pred = -pred return move_to(player='1P', pred=pred) else: pred = 100 return move_to(player='1P', pred=pred) elif slope != 0: pred = (420 - scene_info["ball"][1]) / slope + scene_info["ball"][0] while pred < 0 or pred > 195: if pred > 195: pred = 390 - pred elif pred < 0: pred = -pred return move_to(player='1P', pred=pred) def ml_loop_for_2P(): # as same as 1P if scene_info["ball_speed"][1] > 0: return move_to(player='2P', pred=100) else: x = (scene_info["platform_2P"][1] + 30 - scene_info["ball"][1]) // scene_info["ball_speed"][1] pred = scene_info["ball"][0] + (scene_info["ball_speed"][0] * x) bound = pred // 200 if (bound > 0): if (bound % 2 == 0): pred = pred - bound * 200 else: pred = 200 - (pred - 200 * bound) elif (bound < 0): if bound % 2 == 1: pred = abs(pred - (bound + 1) * 200) else: pred = pred + (abs(bound) * 200) return move_to(player='2P', pred=pred) # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: if side == "1P": command = ml_loop_for_1P() else: command = ml_loop_for_2P() if command == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) elif command == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" })
def get_scene_info(): """ Get the scene info sent from the game process """ return comm.recv_from_game()
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ ball_served = False filename = path.join(path.dirname(__file__), 'save', 'RANF blocker.pickle') with open(filename, 'rb') as file: # read binary clf = pickle.load(file) ball_prev = [80, 415] # ball's initial point def get_dir(vector_x, vector_y): if (vector_x >= 0 and vector_y >= 0): return [0, 0, 0, 1] elif (vector_x > 0 and vector_y < 0): return [0, 0, 1, 0] elif (vector_x < 0 and vector_y > 0): return [0, 1, 0, 0] else: return [1, 0, 0, 0] # elif(vector_x < 0 and vector_y < 0): # return [1, 0, 0, 0] def move_to(player, pred): # move platform to predicted position to catch ball if player == '1P': if scene_info["platform_1P"][0] + 20 > ( pred - 10) and scene_info["platform_1P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_1P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left else: if scene_info["platform_2P"][0] + 20 > ( pred - 10) and scene_info["platform_2P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_2P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop while True: scene_info = comm.recv_from_game() feature = [] feature.append(scene_info["ball"][0]) feature.append(scene_info["ball"][1]) feature.append(scene_info["blocker"][0]) arr = get_dir(scene_info["ball"][0] - ball_prev[0], scene_info["ball"][1] - ball_prev[1]) feature.append(arr[0]) feature.append(arr[1]) feature.append(arr[2]) feature.append(arr[3]) # if side == "1P": # feature.append(1) # else: # feature.append(2) ball_prev = [scene_info["ball"][0], scene_info["ball"][1]] feature = np.array(feature) feature = feature.reshape((-1, 7)) # reshape array into 7 column # print(feature) if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False comm.ml_ready() continue # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: if side == "1P": command = move_to(player="1P", pred=clf.predict(feature)) else: command = move_to(player="2P", pred=clf.predict(feature)) if command == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) elif command == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" })
def get_scene_info() -> SceneInfo: return comm.recv_from_game()
def ml_loop(side: "1P"): """ The main loop of the machine learning process This loop is run in a separate process, and communicates with the game process. Note that the game process won't wait for the ml process to generate the GameInstruction. It is possible that the frame of the GameInstruction is behind of the current frame in the game process. Try to decrease the fps to avoid this situation. """ # === Here is the execution order of the loop === # # 1. Put the initialization code here. ball_served = False filename = path.join(path.dirname(__file__), "save/KNN.pickle") #filename = "C:\\Users\\HsuanPu_Chang\\Desktop\\ML_Game_File\\ML_Game_MidtermTwo\\MLGame-beta6.0\\clf_SVMClassification_VectorsAndDirection.pickle" with open(filename, 'rb') as file: clf = pickle.load(file) # 2. Inform the game process that ml process is ready before start the loop. comm.ml_ready() """ s = [93,93] def get_direction(ball_x,ball_y,ball_pre_x,ball_pre_y): VectorX = ball_x - ball_pre_x VectorY = ball_y - ball_pre_y if(VectorX>=0 and VectorY>=0): return 0 elif(VectorX>0 and VectorY<0): return 1 elif(VectorX<0 and VectorY>0): return 2 elif(VectorX<0 and VectorY<0): return 3 """ # 3. Start an endless loop. while True: scene_info = comm.recv_from_game() # 3.1. Receive the scene information sent from the game process. feature = [] feature.append(scene_info["ball"]) feature.append(scene_info["ball_speed"]) feature.append(scene_info["blocker"]) feature.append(scene_info["platform_1P"]) feature = np.array(feature) feature = feature.reshape((-1, 8)) print(feature) #feature.append(get_direction(feature[0],feature[1],s[0],s[1])) #s = [feature[0], feature[1]] #feature = np.array(feature) #feature = feature.reshape((-1,4)) # 3.2. If the game is over or passed, the game process will reset # the scene and wait for ml process doing resetting job. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3. Put the code here to handle the scene information # 3.4. Send the instruction for this frame to the game process if scene_info["frame"] > 1500: if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: y = clf.predict(feature) if y <= 0.5: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) print('NONE') elif y > 0.5 and y <= 1.5: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" }) print('LEFT') elif y > 1.5: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) print('RIGHT')
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False """ if side == "1P": filename = path.join(path.dirname(__file__),'save', 'player1.pickle') #filename = "MLGame-master\games\pingpong\save\player1.pickle" with open(filename, 'rb') as file: clf = pickle.load(file) else: filename = path.join(path.dirname(__file__),'save', 'player2.pickle') #filename = "MLGame-master\games\pingpong\save\player2.pickle" with open(filename, 'rb') as file: clf = pickle.load(file) """ filename = path.join(path.dirname(__file__), 'save', 'player1_5.pickle') #filename = "MLGame-master\games\pingpong\save\player1.pickle" with open(filename, 'rb') as file: clf = pickle.load(file) # 2. Inform the game process that ml process is ready comm.ml_ready() s = [85, 250] def get_direction(VectorX, VectorY): if (VectorX >= 0 and VectorY >= 0): return 0 elif (VectorX > 0 and VectorY < 0): return 1 elif (VectorX < 0 and VectorY > 0): return 2 else: return 3 def get_Vx(ball_x, ball_y, ball_pre_x, ball_pre_y): VectorX = ball_x - ball_pre_x return VectorX def get_Vy(ball_x, ball_y, ball_pre_x, ball_pre_y): VectorY = ball_y - ball_pre_y return VectorY # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() feature = [] vector = [] vector.append(scene_info['ball_speed'][0]) vector.append(scene_info['ball_speed'][1]) feature.append(scene_info['ball'][0]) feature.append(scene_info['ball'][1]) feature.append(scene_info['platform_1P'][0]) #feature.append(vector[0]) #feature.append(vector[1]) feature.append(get_direction(vector[0], vector[1])) s = [vector[0], vector[1]] feature = np.array(feature) feature = feature.reshape((-1, 4)) #print(feature) #print(feature) # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: y = clf.predict(feature) #print(y) if y == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) # comm.send_instruction(scene_info.frame, PlatformAction.NONE) # print('NONE') elif y == 1: # comm.send_instruction(scene_info.frame, PlatformAction.MOVE_LEFT) comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" }) #print('LEFT') elif y == 2: # comm.send_instruction(scene_info.frame, PlatformAction.MOVE_RIGHT) comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" })
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False filename = path.join(path.dirname(__file__), 'save', 'forest_reg.pickle') with open(filename, 'rb') as file: # read binary clf = pickle.load(file) ball_prev = [93, 395] # ball's initial point def get_dir(vector_x, vector_y): if (vector_x >= 0 and vector_y >= 0): return 0 elif (vector_x > 0 and vector_y < 0): return 1 elif (vector_x < 0 and vector_y > 0): return 2 elif (vector_x < 0 and vector_y < 0): return 3 def move_to(player, pred): #move platform to predicted position to catch ball if player == '1P': if scene_info["platform_1P"][0] + 20 > ( pred - 1) and scene_info["platform_1P"][0] + 20 < (pred + 1): return 0 # NONE elif scene_info["platform_1P"][0] + 20 <= (pred - 1): return 1 # goes right else: return 2 # goes left else: if scene_info["platform_2P"][0] + 20 > ( pred - 1) and scene_info["platform_2P"][0] + 20 < (pred + 1): return 0 # NONE elif scene_info["platform_2P"][0] + 20 <= (pred - 1): return 1 # goes right else: return 2 # goes left # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() if side == "1P": feature = [] # feature.append(scene_info["platform_1P"][0]) feature.append(scene_info["ball"][0]) feature.append(scene_info["ball"][1]) x = get_dir(scene_info['ball_speed'][0], scene_info['ball_speed'][1]) feature.append(1) for i in range(4): if i == x: feature.append(1) else: feature.append(0) print(feature) feature = np.array(feature) feature = feature.reshape((-1, 7)) # reshape array into 4 column else: feature = [] # feature.append(scene_info["platform_1P"][0]) feature.append(scene_info["ball"][0]) feature.append(scene_info["ball"][1]) x = get_dir(scene_info['ball_speed'][0], scene_info['ball_speed'][1]) feature.append(2) for i in range(4): if i == x: feature.append(1) else: feature.append(0) # print(feature) feature = np.array(feature) feature = feature.reshape((-1, 7)) # reshape array into 4 column # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: if side == "1P": command = move_to(player="1P", pred=clf.predict(feature)) else: command = move_to(player="2P", pred=clf.predict(feature)) if command == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) elif command == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" })
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False def move_to(player, pred): #move platform to predicted position to catch ball if player == '1P': if scene_info["platform_1P"][0] + 20 > ( pred - 10) and scene_info["platform_1P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_1P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left else: if scene_info["platform_2P"][0] + 20 > ( pred - 10) and scene_info["platform_2P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_2P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left def ml_loop_for_1P(): if scene_info["ball_speed"][1] > 0: # 球正在向下 # ball goes down x = ( scene_info["platform_1P"][1] - scene_info["ball"][1] ) // scene_info["ball_speed"][ 1] # 幾個frame以後會需要接 # x means how many frames before catch the ball pred = scene_info["ball"][0] + ( scene_info["ball_speed"][0] * x ) # 預測最終位置 # pred means predict ball landing site bound = pred // 200 # Determine if it is beyond the boundary print("1P predict " + str(pred)) print("1P bound " + str(bound)) if (bound > 0): # pred > 200 # fix landing position if (bound % 2 == 0): pred = pred - bound * 200 else: pred = 200 - (pred - 200 * bound) elif (bound < 0): # pred < 0 if (bound % 2 == 1): pred = abs(pred - (bound + 1) * 200) else: pred = pred + (abs(bound) * 200) print("result " + str(pred)) return move_to(player='1P', pred=pred) else: # 球正在向上 # ball goes up return move_to(player='1P', pred=100) def ml_loop_for_2P(): # as same as 1P if scene_info["ball_speed"][1] > 0: return move_to(player='2P', pred=100) else: x = (scene_info["platform_2P"][1] + 30 - scene_info["ball"][1]) // scene_info["ball_speed"][1] pred = scene_info["ball"][0] + (scene_info["ball_speed"][0] * x) bound = pred // 200 if (bound > 0): if (bound % 2 == 0): pred = pred - bound * 200 else: pred = 200 - (pred - 200 * bound) elif (bound < 0): if bound % 2 == 1: pred = abs(pred - (bound + 1) * 200) else: pred = pred + (abs(bound) * 200) return move_to(player='2P', pred=pred) # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: if side == "1P": command = ml_loop_for_1P() else: command = ml_loop_for_2P() if command == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) elif command == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" })
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False model = tf.keras.models.load_model('saved_model/myModel') # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({"frame": scene_info["frame"], "command": "SERVE_TO_RIGHT"}) ball_served = True else: ballX = scene_info["ball"][0] ballY = scene_info["ball"][1] ball_speed_X = scene_info["ball_speed"][0] ball_speed_Y = scene_info["ball_speed"][1] platform_1P_X = scene_info["platform_1P"][0] blocker_X = scene_info["blocker"][0] features = [[ballX, ballY, ball_speed_X, ball_speed_Y, platform_1P_X, blocker_X]] probabilityModel = tf.keras.Sequential([model, tf.keras.layers.Softmax()]) prediction = probabilityModel.predict(features) awaitCommand = np.argmax(prediction[0]) print(awaitCommand) if awaitCommand == 1: comm.send_to_game({"frame": scene_info["frame"], "command": "NONE"}) print('NONE') elif awaitCommand == 2: comm.send_to_game({"frame": scene_info["frame"], "command": "MOVE_RIGHT"}) print('RIGHT') elif awaitCommand == 0: comm.send_to_game({"frame": scene_info["frame"], "command": "MOVE_LEFT"}) print('LEFT')
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False s = 100 def get_block_direction(block_x, block_pre_x): VectorX = block_x - block_pre_x if (VectorX >= 0): return 1 #障礙物往右 else: return 0 #障礙物往左 def wall_correction(pred, limit_up, limit_down): if (pred > limit_up): x = (limit_up - scene_info["ball"][0]) // scene_info["ball_speed"][0] ball_wall_x = scene_info["ball"][0] + ( scene_info["ball_speed"][0] * x) correction = ball_wall_x + scene_info["ball_speed"][0] - limit_up pred -= correction pred = limit_up - (pred - limit_up) if pred >= limit_down: return pred else: return wall_correction(pred, limit_up, limit_down) elif (pred < limit_down): x = (limit_down - scene_info["ball"][0]) // scene_info["ball_speed"][0] ball_wall_x = scene_info["ball"][0] + ( scene_info["ball_speed"][0] * x) correction = ball_wall_x + scene_info["ball_speed"][0] - limit_down pred -= correction pred = abs(pred) if pred <= limit_up: return pred else: return wall_correction(pred, limit_up, limit_down) else: return pred def move_to(player, pred): #move platform to predicted position to catch ball if player == '1P': if scene_info["platform_1P"][0] + 20 > ( pred - 10) and scene_info["platform_1P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_1P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left else: if scene_info["platform_2P"][0] + 20 > ( pred - 10) and scene_info["platform_2P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_2P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left def ml_loop_for_1P(): if scene_info["ball_speed"][1] > 0: # 球正在向下 # ball goes down x = ( scene_info["platform_1P"][1] - 5 - scene_info["ball"][1] ) // scene_info["ball_speed"][ 1] # 幾個frame以後會需要接 # x means how many frames before catch the ball pred = scene_info["ball"][0] + ( scene_info["ball_speed"][0] * (x + 1)) # 預測最終位置 # pred means predict ball landing site pred = wall_correction(pred, 195, 0) #print(pred, scene_info["ball"], scene_info["frame"]%100) if scene_info["ball"][1] <= 235: pred = hit_blocker_side(pred) return move_to(player='1P', pred=pred) else: # 球正在向上 # ball goes up pred = 100 if scene_info["ball"][1] >= 260: pred = hit_blocker_down() print(pred, scene_info["ball"], scene_info["frame"]) return move_to(player='1P', pred=pred) def ml_loop_for_2P(): # as same as 1P if scene_info["ball_speed"][1] > 0: pred = 100 if scene_info["ball"][1] <= 235: pred = hit_blocker_up() return move_to(player='2P', pred=100) else: x = (scene_info["platform_2P"][1] + 30 - scene_info["ball"][1]) // scene_info["ball_speed"][1] pred = scene_info["ball"][0] + (scene_info["ball_speed"][0] * (x + 1)) pred = wall_correction(pred, 195, 0) if scene_info["ball"][1] >= 260: pred = hit_blocker_side2(pred) return move_to(player='2P', pred=pred) def hit_blocker_side(pred): x = 100 - (scene_info["frame"] % 100) block_frame = (scene_info["blocker"][1] - 5 - scene_info["ball"][1]) // (scene_info["ball_speed"][1]) pred_y = scene_info["ball"][1] + (scene_info["ball_speed"][1] * x) flag = 0 speed = scene_info["ball_speed"] if pred_y >= 235: pred_x = scene_info["ball"][0] + (scene_info["ball_speed"][0] * block_frame) pred_y = scene_info["ball"][1] + (scene_info["ball_speed"][1] * block_frame) else: if scene_info["ball_speed"][0] > 0 and scene_info["ball_speed"][ 1] > 0: speed = tuple(list(scene_info["ball_speed"]) + [1, 1]) elif scene_info["ball_speed"][0] > 0 and scene_info["ball_speed"][ 1] < 0: speed = tuple(list(scene_info["ball_speed"]) + [1, -1]) elif scene_info["ball_speed"][0] < 0 and scene_info["ball_speed"][ 1] > 0: speed = tuple(list(scene_info["ball_speed"]) + [-1, 1]) elif scene_info["ball_speed"][0] < 0 and scene_info["ball_speed"][ 1] < 0: speed = tuple(list(scene_info["ball_speed"]) + [-1, -1]) y = (scene_info["blocker"][1] - 5 - pred_y) // ( speed[1]) # 幾個frame以後會到障礙物的位置( pred_x = scene_info["ball"][0] + (scene_info["ball_speed"][0] * x) + (speed[0] * y) pred_y = scene_info["ball"][1] + (scene_info["ball_speed"][1] * x) + (speed[1] * y) block_frame = x + y flag = 1 block_direction = get_block_direction(scene_info["blocker"][0], s) if block_direction == 1: block_x = scene_info["blocker"][0] + 3 * block_frame else: block_x = scene_info["blocker"][0] - 3 * block_frame bound_block = block_x // 170 if bound_block > 0: if bound_block % 2 == 0: block_x = block_x - (bound_block * 170) else: block_x = 170 - (block_x - 170 * bound_block) block_direction = 0 elif bound_block < 0: if (bound_block % 2 == 1): block_x = abs(block_x - (bound_block + 1) * 170) block_direction = 1 else: block_x = block_x + (abs(bound_block) * 170) if block_direction == 1: block_x_next = block_x + 3 else: block_x_next = block_x - 3 if flag: pred_x_next = pred_x + speed[0] pred_y_next = pred_y + speed[1] else: pred_x_next = pred_x + scene_info["ball_speed"][0] pred_y_next = pred_y + scene_info["ball_speed"][1] flag2 = 1 for i in range(3): if pred_x_next < 0 or pred_x_next > 200: flag2 = -1 pred_x_next2 = wall_correction(pred_x_next, 195, 0) pred = hit_side(pred_x_next2, pred_y_next, flag, block_direction, pred, block_x_next, speed) if block_direction == 1: block_x_next = block_x_next + 3 else: block_x_next = block_x_next - 3 if flag: pred_x_next = pred_x_next + speed[0] pred_y_next = pred_y_next + speed[1] else: pred_x_next = pred_x_next + scene_info["ball_speed"][0] pred_y_next = pred_y_next + scene_info["ball_speed"][1] return pred def hit_side(pred_x_next, pred_y_next, flag, block_direction, pred, block_x_next, speed): #print(pred_x_next, pred_y_next, scene_info["ball"], block_x_next, scene_info["blocker"]) if pred_x_next > block_x_next - 5 and pred_x_next < block_x_next + 30 and pred_y_next >= 235 and pred_y_next <= 260: if block_direction == 1: pred_x_next = block_x_next - 5 else: pred_x_next = block_x_next if not flag: pred_y_next = pred_y_next + scene_info["ball_speed"][1] frame = (scene_info["platform_1P"][1] - 5 - pred_y_next) // (scene_info["ball_speed"][1]) pred2 = pred_x_next + scene_info["ball_speed"][0] * (frame + 1) else: pred_y_next = pred_y_next + speed[1] frame = (scene_info["platform_1P"][1] - 5 - pred_y_next) // (speed[1]) pred2 = pred_x_next + speed[0] * (frame + 1) pred2 = wall_correction(pred, 195, 0) return pred2 else: return pred def hit_blocker_side2(pred): x = 100 - (scene_info["frame"] % 100) block_frame = (scene_info["blocker"][1] + 20 - scene_info["ball"][1]) // (scene_info["ball_speed"][1]) pred_y = scene_info["ball"][1] + (scene_info["ball_speed"][1] * x) flag = 0 speed = scene_info["ball_speed"] if pred_y <= 260: pred_x = scene_info["ball"][0] + (scene_info["ball_speed"][0] * block_frame) pred_y = scene_info["ball"][1] + (scene_info["ball_speed"][1] * block_frame) else: if scene_info["ball_speed"][0] > 0 and scene_info["ball_speed"][ 1] > 0: speed = tuple(list(scene_info["ball_speed"]) + [1, 1]) elif scene_info["ball_speed"][0] > 0 and scene_info["ball_speed"][ 1] < 0: speed = tuple(list(scene_info["ball_speed"]) + [1, -1]) elif scene_info["ball_speed"][0] < 0 and scene_info["ball_speed"][ 1] > 0: speed = tuple(list(scene_info["ball_speed"]) + [-1, 1]) elif scene_info["ball_speed"][0] < 0 and scene_info["ball_speed"][ 1] < 0: speed = tuple(list(scene_info["ball_speed"]) + [-1, -1]) y = (scene_info["blocker"][1] + 20 - pred_y) // ( speed[1]) # 幾個frame以後會到障礙物的位置( pred_x = scene_info["ball"][0] + (scene_info["ball_speed"][0] * x) + (speed[0] * y) pred_y = scene_info["ball"][1] + (scene_info["ball_speed"][1] * x) + (speed[1] * y) block_frame = x + y flag = 1 block_direction = get_block_direction(scene_info["blocker"][0], s) if block_direction == 1: block_x = scene_info["blocker"][0] + 3 * block_frame else: block_x = scene_info["blocker"][0] - 3 * block_frame bound_block = block_x // 170 if bound_block > 0: if bound_block % 2 == 0: block_x = block_x - (bound_block * 170) else: block_x = 170 - (block_x - 170 * bound_block) block_direction = 0 elif bound_block < 0: if (bound_block % 2 == 1): block_x = abs(block_x - (bound_block + 1) * 170) block_direction = 1 else: block_x = block_x + (abs(bound_block) * 170) if block_direction == 1: block_x_next = block_x + 3 else: block_x_next = block_x - 3 if flag: pred_x_next = pred_x + speed[0] pred_y_next = pred_y + speed[1] else: pred_x_next = pred_x + scene_info["ball_speed"][0] pred_y_next = pred_y + scene_info["ball_speed"][1] flag2 = 1 for i in range(3): if pred_x_next < 0 or pred_x_next > 200: flag2 = -1 pred_x_next2 = wall_correction(pred_x_next, 195, 0) pred = hit_side2(pred_x_next2, pred_y_next, flag, block_direction, pred, block_x_next, speed) if block_direction == 1: block_x_next = block_x_next + 3 else: block_x_next = block_x_next - 3 if flag: pred_x_next = pred_x_next + speed[0] pred_y_next = pred_y_next + speed[1] else: pred_x_next = pred_x_next + scene_info["ball_speed"][0] pred_y_next = pred_y_next + scene_info["ball_speed"][1] return pred def hit_side2(pred_x_next, pred_y_next, flag, block_direction, pred, block_x_next, speed): #print(pred_x_next, pred_y_next, scene_info["ball"], block_x_next, scene_info["blocker"]) if pred_x_next > block_x_next - 5 and pred_x_next < block_x_next + 30 and pred_y_next >= 235 and pred_y_next <= 260: if block_direction == 1: pred_x_next = block_x_next - 5 else: pred_x_next = block_x_next if not flag: pred_y_next = pred_y_next + scene_info["ball_speed"][1] frame = (scene_info["platform_2P"][1] + 30 - pred_y_next) // (scene_info["ball_speed"][1]) pred2 = pred_x_next + scene_info["ball_speed"][0] * (frame + 1) else: pred_y_next = pred_y_next + speed[1] frame = (scene_info["platform_2P"][1] + 30 - pred_y_next) // (speed[1]) pred2 = pred_x_next + speed[0] * (frame + 1) pred2 = wall_correction(pred, 195, 0) return pred2 else: return pred def hit_blocker_up(): x = 100 - (scene_info["frame"] % 100) block_frame = (scene_info["blocker"][1] - scene_info["ball"][1]) // (scene_info["ball_speed"][1]) pred_y = scene_info["ball"][1] + (scene_info["ball_speed"][1] * x) flag = 0 speed = scene_info["ball_speed"] if pred_y >= 235: pred_x = scene_info["ball"][0] + (scene_info["ball_speed"][0] * block_frame) pred_y = scene_info["ball"][1] + (scene_info["ball_speed"][1] * block_frame) else: if scene_info["ball_speed"][0] > 0 and scene_info["ball_speed"][ 1] > 0: speed = tuple(list(scene_info["ball_speed"]) + [1, 1]) elif scene_info["ball_speed"][0] > 0 and scene_info["ball_speed"][ 1] < 0: speed = tuple(list(scene_info["ball_speed"]) + [1, -1]) elif scene_info["ball_speed"][0] < 0 and scene_info["ball_speed"][ 1] > 0: speed = tuple(list(scene_info["ball_speed"]) + [-1, 1]) elif scene_info["ball_speed"][0] < 0 and scene_info["ball_speed"][ 1] < 0: speed = tuple(list(scene_info["ball_speed"]) + [-1, -1]) y = (scene_info["blocker"][1] + 20 - pred_y) // (speed[1]) pred_x = scene_info["ball"][0] + (scene_info["ball_speed"][0] * x) + (speed[0] * y) pred_y = scene_info["ball"][1] + (scene_info["ball_speed"][1] * x) + (speed[1] * y) block_frame = x + y flag = 1 block_direction = get_block_direction(scene_info["blocker"][0], s) if block_direction == 1: block_x = scene_info["blocker"][0] + 3 * block_frame else: block_x = scene_info["blocker"][0] - 3 * block_frame block_x = wall_correction(block_x, 170, 0) if block_direction == 1: block_x_next = block_x + 3 else: block_x_next = block_x - 3 if flag: pred_x_next = pred_x + speed[0] pred_y_next = pred_y + speed[1] else: pred_x_next = pred_x + scene_info["ball_speed"][0] pred_y_next = pred_y + scene_info["ball_speed"][1] pred_x_next = wall_correction(pred_x_next, 195, 0) block_x_next = wall_correction(block_x_next, 170, 0) if pred_x_next > block_x_next - 5 and pred_x_next < block_x_next + 30: pred = hit_up(pred_x, speed, flag) pred = wall_correction(pred, 195, 0) return pred else: return 80 def hit_up(pred_x, speed, flag): if not flag: pred_x_next = pred_x + scene_info["ball_speed"][0] pred_y_next = 235 frame = (scene_info["platform_1P"][1] - 5 - 260) // (-scene_info["ball_speed"][1]) pred = pred_x_next + scene_info["ball_speed"][0] * (frame + 1) else: pred_x_next = pred_x + speed[0] pred_y_next = 235 frame = (scene_info["platform_1P"][1] - 5 - 260) // (-speed[1]) pred = pred_x_next + speed[0] * (frame + 1) return pred def hit_blocker_down(): x = 100 - (scene_info["frame"] % 100) block_frame = (scene_info["blocker"][1] + 20 - scene_info["ball"][1]) // (scene_info["ball_speed"][1]) pred_y = scene_info["ball"][1] + (scene_info["ball_speed"][1] * x) flag = 0 speed = scene_info["ball_speed"] if pred_y <= 260: pred_x = scene_info["ball"][0] + (scene_info["ball_speed"][0] * block_frame) pred_y = scene_info["ball"][1] + (scene_info["ball_speed"][1] * block_frame) else: if scene_info["ball_speed"][0] > 0 and scene_info["ball_speed"][ 1] > 0: speed = tuple(list(scene_info["ball_speed"]) + [1, 1]) elif scene_info["ball_speed"][0] > 0 and scene_info["ball_speed"][ 1] < 0: speed = tuple(list(scene_info["ball_speed"]) + [1, -1]) elif scene_info["ball_speed"][0] < 0 and scene_info["ball_speed"][ 1] > 0: speed = tuple(list(scene_info["ball_speed"]) + [-1, 1]) elif scene_info["ball_speed"][0] < 0 and scene_info["ball_speed"][ 1] < 0: speed = tuple(list(scene_info["ball_speed"]) + [-1, -1]) y = (scene_info["blocker"][1] + 20 - pred_y) // (speed[1]) pred_x = scene_info["ball"][0] + (scene_info["ball_speed"][0] * x) + (speed[0] * y) pred_y = scene_info["ball"][1] + (scene_info["ball_speed"][1] * x) + (speed[1] * y) block_frame = x + y flag = 1 block_direction = get_block_direction(scene_info["blocker"][0], s) if block_direction == 1: block_x = scene_info["blocker"][0] + 3 * block_frame else: block_x = scene_info["blocker"][0] - 3 * block_frame block_x = wall_correction(block_x, 170, 0) if block_direction == 1: block_x_next = block_x + 3 else: block_x_next = block_x - 3 if flag: pred_x_next = pred_x + speed[0] pred_y_next = pred_y + speed[1] else: pred_x_next = pred_x + scene_info["ball_speed"][0] pred_y_next = pred_y + scene_info["ball_speed"][1] pred_x_next = wall_correction(pred_x_next, 195, 0) block_x_next = wall_correction(block_x_next, 170, 0) if pred_x_next > block_x_next - 5 and pred_x_next < block_x_next + 30: pred = hit_down(pred_x, speed, flag) pred = wall_correction(pred, 195, 0) return pred else: return 80 def hit_down(pred_x, speed, flag): if not flag: pred_x_next = pred_x + scene_info["ball_speed"][0] pred_y_next = 260 frame = (scene_info["platform_1P"][1] - 5 - 260) // (-scene_info["ball_speed"][1]) pred = pred_x_next + scene_info["ball_speed"][0] * (frame + 1) else: pred_x_next = pred_x + speed[0] pred_y_next = 260 frame = (scene_info["platform_1P"][1] - 5 - 260) // (-speed[1]) pred = pred_x_next + speed[0] * (frame + 1) return pred # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: if side == "1P": command = ml_loop_for_1P() else: command = ml_loop_for_2P() s = scene_info['blocker'][0] if command == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) elif command == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" })
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here last_blocker_pos = (-1, -1) p_blocker = 0 p_frame = -1 ball_served = False def cut_to(player, speedx, way): if player == '1P': if way == 'same': print("same cut") if speedx > 0: return 1 else: return 2 elif way == 'reverse': print("reserve cut") if speedx > 0: return 2 else: return 1 def move_to(player, pred): #move platform to predicted position to catch ball if player == '1P': if scene_info["platform_1P"][0] + 20 > ( pred - 10) and scene_info["platform_1P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_1P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left else: if scene_info["platform_2P"][0] + 20 > ( pred - 10) and scene_info["platform_2P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_2P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left def ml_loop_for_1P(blocker_dir): p_blocker = 0 if scene_info["ball_speed"][1] > 0: # 球正在向下 # ball goes down x = ( scene_info["platform_1P"][1] - scene_info["ball"][1] ) // scene_info["ball_speed"][ 1] # 幾個frame以後會需要接 # x means how many frames before catch the ball pred = scene_info["ball"][0] + ( scene_info["ball_speed"][0] * x ) # 預測最終位置 # pred means predict ball landing site bound = pred // 200 # Determine if it is beyond the boundary if (bound > 0): # pred > 200 # fix landing position if (bound % 2 == 0): pred = pred - bound * 200 else: pred = 200 - (pred - 200 * bound) elif (bound < 0): # pred < 0 if (bound % 2 == 1): pred = abs(pred - (bound + 1) * 200) else: pred = pred + (abs(bound) * 200) if abs( scene_info["ball"][1] + 5 - scene_info["platform_1P"][1] ) < scene_info["ball_speed"][ 1]: #scene_info["ball_speed"][1] > abs(scene_info["platform_1P"][1]-scene_info["ball"][1]-5) print("close to 1p plat") print("frame: ", scene_info["frame"]) f = (160) // abs(scene_info["ball_speed"][1]) print(f) speed_range = scene_info["frame"] // 100 p_blocker = f if (scene_info["frame"] + f) // 100 > speed_range: f_n = (160 - ((speed_range + 1) * 100 - scene_info["frame"]) * abs(scene_info["ball_speed"][1])) // ( abs(scene_info["ball_speed"][1]) + 1) f = (speed_range + 1) * 100 - scene_info["frame"] + f_n p_blocker = f print("new f", f) blocker_pred = scene_info["blocker"][0] + (5 * blocker_dir * f) blocker_bound = blocker_pred // 200 # Determine if it is beyond the boundary if (blocker_bound > 0): # pred > 200 # fix landing position if (blocker_bound % 2 == 0): blocker_pred = blocker_pred - blocker_bound * 200 else: blocker_pred = 200 - (blocker_pred - 200 * blocker_bound) elif (blocker_bound < 0): # pred < 0 if (blocker_bound % 2 == 1): blocker_pred = abs(blocker_pred - (blocker_bound + 1) * 200) else: blocker_pred = blocker_pred + (abs(blocker_bound) * 200) print("blocker now: ", scene_info["blocker"][0]) print("blocker pred: ", blocker_pred) print("ball now: ", scene_info["ball"]) print("ball speed now: ", abs(scene_info["ball_speed"][1])) cut_r = False cut_s = False if scene_info["ball_speed"][0] > 0: ball_pred = scene_info["ball"][0] + abs( scene_info["ball"][1] + 5 - scene_info["platform_1P"][1]) + ( (scene_info["ball_speed"][0] + 3) * f) else: ball_pred = scene_info["ball"][0] - abs( scene_info["ball"][1] + 5 - scene_info["platform_1P"][1]) + ( (scene_info["ball_speed"][0] - 3) * f) ball_bound = ball_pred // 200 # Determine if it is beyond the boundary if (ball_bound > 0): # pred > 200 # fix landing position if (ball_bound % 2 == 0): ball_pred = ball_pred - ball_bound * 200 else: ball_pred = 200 - (ball_pred - 200 * ball_bound) elif (ball_bound < 0): # pred < 0 if (ball_bound % 2 == 1): ball_pred = abs(ball_pred - (ball_bound + 1) * 200) else: ball_pred = ball_pred + (abs(ball_bound) * 200) cut_svalue = 0 if (ball_pred + 5 < blocker_pred - 15 or ball_pred > blocker_pred + 45): cut_s = True if ball_pred + 5 < blocker_pred - 10: cut_svalue = blocker_pred - ball_pred + 5 else: cut_svalue = ball_pred - blocker_pred + 30 print("cut s ball pred: ", ball_pred) if scene_info["ball_speed"][0] > 0: ball_pred = scene_info["ball"][0] + abs( scene_info["ball"][1] + 5 - scene_info["platform_1P"][1]) + ( -scene_info["ball_speed"][0] * f) else: ball_pred = scene_info["ball"][0] - abs( scene_info["ball"][1] + 5 - scene_info["platform_1P"][1]) + ( -scene_info["ball_speed"][0] * f) ball_bound = ball_pred // 200 # Determine if it is beyond the boundary if (ball_bound > 0): # pred > 200 # fix landing position if (ball_bound % 2 == 0): ball_pred = ball_pred - ball_bound * 200 else: ball_pred = 200 - (ball_pred - 200 * ball_bound) elif (ball_bound < 0): # pred < 0 if (ball_bound % 2 == 1): ball_pred = abs(ball_pred - (ball_bound + 1) * 200) else: ball_pred = ball_pred + (abs(ball_bound) * 200) cut_rvalue = 0 if (ball_pred + 5 < blocker_pred - 15 or ball_pred > blocker_pred + 45): cut_r = True if ball_pred + 5 < blocker_pred - 10: cut_rvalue = blocker_pred - ball_pred + 5 else: cut_rvalue = ball_pred - blocker_pred + 30 print("cut r ball pred: ", ball_pred) if cut_r and cut_s: if cut_rvalue >= cut_svalue: return cut_to(player='1P', speedx=scene_info["ball_speed"][0], way='reverse'), p_blocker else: return cut_to(player='1P', speedx=scene_info["ball_speed"][0], way='same'), p_blocker elif cut_r: return cut_to(player='1P', speedx=scene_info["ball_speed"][0], way='reverse'), p_blocker elif cut_s: return cut_to(player='1P', speedx=scene_info["ball_speed"][0], way='same'), p_blocker else: return move_to(player='1P', pred=pred), p_blocker else: if pred > 180: return move_to(player='1P', pred=185), 0 elif pred < 20: return move_to(player='1P', pred=15), 0 else: return move_to(player='1P', pred=pred), 0 else: # 球正在向上 # ball goes up return move_to(player='1P', pred=100), 0 def ml_loop_for_2P(): # as same as 1P if scene_info["ball_speed"][1] > 0: return move_to(player='2P', pred=100) else: x = (scene_info["platform_2P"][1] + 30 - scene_info["ball"][1]) // scene_info["ball_speed"][1] pred = scene_info["ball"][0] + (scene_info["ball_speed"][0] * x) bound = pred // 200 if (bound > 0): if (bound % 2 == 0): pred = pred - bound * 200 else: pred = 200 - (pred - 200 * bound) elif (bound < 0): if bound % 2 == 1: pred = abs(pred - (bound + 1) * 200) else: pred = pred + (abs(bound) * 200) return move_to(player='2P', pred=pred) # 2. Inform the game process that ml process is ready comm.ml_ready() t1 = 0 t2 = 0 # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() if (scene_info["ball"][0]+5 >= scene_info["blocker"][0] and scene_info["ball"][0] < scene_info["blocker"][0]+30) and \ abs(scene_info["ball"][1]-(scene_info["blocker"][1]+20)) < abs(scene_info["ball_speed"][1]) and scene_info["ball_speed"][1]<0: print("crush frame", scene_info["frame"], ": ball x: ", scene_info["ball"], " blocker: ", scene_info["blocker"]) print("ball speed now: ", abs(scene_info["ball_speed"][1])) print("crush!!!") if scene_info["frame"] == 0: t1 = time.monotonic() # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False last_blocker_pos = (-1, -1) p_blocker = 0 p_frame = -1 # 3.2.1 Inform the game process that # the ml process is ready for the next round t2 = time.monotonic() print("game time: {:8.3f}seconds".format(t2 - t1)) print("final speed: " + str(abs(scene_info["ball_speed"][1]))) comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: blocker_direct = 0 if last_blocker_pos[0] - scene_info["blocker"][0] > 0: blocker_direct = 1 else: blocker_direct = -1 #print("blocker speed",abs(last_blocker_pos[0] - scene_info["blocker"][0])) print("current frame :", scene_info["frame"], " ball: ", scene_info["ball"], " blocker: ", scene_info["blocker"]) last_blocker_pos = scene_info["blocker"] if p_frame != -1 and scene_info["frame"] == p_frame: print("close frame", scene_info["frame"], ": ball x: ", scene_info["ball"], " blocker: ", scene_info["blocker"]) p_frame = -1 if side == "1P": command, p_blocker = ml_loop_for_1P(-blocker_direct) if p_blocker != 0: p_frame = scene_info["frame"] + p_blocker print("p frame: ", p_frame) p_blocker = 0 else: command = ml_loop_for_2P() if command == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) elif command == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" })
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False def transformCommand(command): if 'RIGHT' in str(command): return 2 elif 'LEFT' in str(command): return 1 else: return 0 pass def get_ArkanoidData(filename): Frames = [] Balls = [] Commands = [] PlatformPos = [] log = pickle.load((open(filename, 'rb'))) for sceneInfo in log: Frames.append(sceneInfo.frame) Balls.append([sceneInfo.ball[0], sceneInfo.ball[1]]) PlatformPos.append(sceneInfo.platform) Commands.append(transformCommand(sceneInfo.command)) commands_ary = np.array([Commands]) commands_ary = commands_ary.reshape((len(Commands), 1)) frame_ary = np.array(Frames) frame_ary = frame_ary.reshape((len(Frames), 1)) data = np.hstack((frame_ary, Balls, PlatformPos, commands_ary)) return data def move_to(player, pred): #move platform to predicted position to catch ball if player == '1P': if scene_info["platform_1P"][0] + 20 > ( pred - 10) and scene_info["platform_1P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_1P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left else: if scene_info["platform_2P"][0] + 20 > ( pred - 10) and scene_info["platform_2P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_2P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left def cut_ball(cut_dirc): """ 0加速 1原路徑 2向右 3向左 """ if cut_dirc == 0: #切球反方向 if scene_info["ball_speed"][0] > 0: return 1 else: return 2 elif cut_dirc == 1: if scene_info["ball_speed"][0] > 0: return 2 else: return 1 elif cut_dirc == 2: return 1 else: return 2 def pred_block_1P(): if scene_info["ball_speed"][1] > 0 and scene_info["ball"][ 1] > 420 and scene_info["ball"][1] < 240: x = ( scene_info["ball"][1] - scene_info["blocker"][1] + 180 ) // scene_info["ball_speed"][ 1] # 幾個frame以後會遇到block # x means how many frames before catch the ball pred_nc = scene_info["ball"][0] + x * scene_info["ball_speed"][0] bound = pred_nc // 200 block_pos = scene_info["blocker"][0] bound_b = block_pos // 200 print("xx") if bound > 0: if bound % 2 == 0: pred_nc = pred_nc - 200 * bound else: pred_nc = 200 - (pred_nc - 200 * bound) else: if bound % 2 == 1: pred_nc = abs(pred_nc - (bound + 1) * 200) else: pred_nc = pred_nc + (abs(bound) * 200) if bound_b > 0: if bound_b % 2 == 0: block_pos = block_pos - 200 * bound_b else: block_pos = 200 - (block_pos - 200 * bound_b) else: if bound_b % 2 == 1: block_pos = abs(block_pos - (bound_b + 1) * 200) else: block_pos = block_pos + (abs(bound_b) * 200) print("blcok ", block_pos, " ball ", pred_nc) if (block_pos + 30 - pred_nc) < 35 and (block_pos + 30 - pred_nc) > -5: return 1 else: return 0 def block_speed(x, pre_x): vector_x = x - pre_x return vector_x def ml_loop_for_1P(): if scene_info["ball_speed"][1] > 0: # 球正在向下 # ball goes down x = ( scene_info["platform_1P"][1] - scene_info["ball"][1] ) // scene_info["ball_speed"][ 1] # 幾個frame以後會需要接 # x means how many frames before catch the ball pred = scene_info["ball"][0] + ( scene_info["ball_speed"][0] * x ) # 預測最終位置 # pred means predict ball landing site bound = pred // 200 # Determine if it is beyond the boundary if (bound > 0): # pred > 200 # fix landing position if (bound % 2 == 0): pred = pred - bound * 200 else: pred = 200 - (pred - 200 * bound) elif (bound < 0): # pred < 0 if (bound % 2 == 1): pred = abs(pred - (bound + 1) * 200) else: pred = pred + (abs(bound) * 200) if x <= 1 and move_to('1P', pred) == 0: if (scene_info["blocker"][0] > 135 or scene_info["blocker"][0] < 35) and scene_info["frame"] < 1000: return cut_ball(0) elif scene_info["frame"] > 1000: return cut_ball(1) return move_to(player='1P', pred=pred) else: # 球正在向上 # ball goes up # pred = return move_to(player='1P', pred=100) def ml_loop_for_2P(): # as same as 1P if scene_info["ball_speed"][1] > 0: return move_to(player='2P', pred=100) else: x = (scene_info["platform_2P"][1] + 30 - scene_info["ball"][1]) // scene_info["ball_speed"][1] pred = scene_info["ball"][0] + (scene_info["ball_speed"][0] * x) bound = pred // 200 if (bound > 0): if (bound % 2 == 0): pred = pred - bound * 200 else: pred = 200 - (pred - 200 * bound) elif (bound < 0): if bound % 2 == 1: pred = abs(pred - (bound + 1) * 200) else: pred = pred + (abs(bound) * 200) if x <= 2 and move_to('2P', pred) == 0: if scene_info['platform_2P'][0] < 50 and scene_info['blocker'][ 0] > 150: return cut_ball(1) elif scene_info['platform_2P'][0] < 100 and scene_info[ 'blocker'][0] > 100: return cut_ball(1) elif scene_info['platform_2P'][0] < 150 and scene_info[ 'blocker'][0] > 75: return cut_ball(1) elif scene_info['platform_2P'][0] < 180 and scene_info[ 'blocker'][0] > 80: return cut_ball(1) else: return cut_ball(0) else: return move_to(player='2P', pred=pred) # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() feature = [] feature.append(scene_info["blocker"][0]) feature.append(scene_info["ball"][0]) feature.append(scene_info["ball"][1]) feature.append(scene_info["ball_speed"][0]) feature.append(scene_info["ball_speed"][1]) print(feature) # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: if side == "1P": command = ml_loop_for_1P() else: command = ml_loop_for_2P() if command == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) elif command == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" })
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False blocker_last_x = 0 class Pred: pred = 100 blocker_pred_x = 0 last_command = 0 blocker_vx = 0 def move_to(player, pred): #move platform to predicted position to catch ball if player == '1P': if scene_info["platform_1P"][0] + 20 > ( pred - 10) and scene_info["platform_1P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_1P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left else: if scene_info["platform_2P"][0] + 20 > ( pred - 10) and scene_info["platform_2P"][0] + 20 < (pred + 10): return 0 # NONE elif scene_info["platform_2P"][0] + 20 <= (pred - 10): return 1 # goes right else: return 2 # goes left def ml_loop_for_1P(): # ball slicing if scene_info["ball_speed"][1] > 0 and ( scene_info["ball"][1] + scene_info["ball_speed"][1]) >= 415 and Pred.last_command == 0: print("------") ball_x = scene_info["ball"][0] ball_y = scene_info["ball"][1] ball_vx = scene_info["ball_speed"][0] ball_slice_vx = scene_info["ball_speed"][0] + np.sign( scene_info["ball_speed"][0]) * 3 ball_vy = scene_info["ball_speed"][1] blocker_x = scene_info['blocker'][0] + Pred.blocker_vx y = abs((415 - ball_y) // ball_vy) pred_ball_1P = ball_x + ball_vx * y y = abs((415 - 260) // ball_vy) pred_ball_blocker = pred_ball_1P + ball_slice_vx * y bound = pred_ball_blocker // 200 # Determine if it is beyond the boundary if (bound > 0): # pred > 200 # fix landing position if (bound % 2 == 0): pred_ball_blocker = pred_ball_blocker - bound * 200 else: pred_ball_blocker = 200 - (pred_ball_blocker - 200 * bound) elif (bound < 0): # pred < 0 if (bound % 2 == 1): pred_ball_blocker = abs(pred_ball_blocker - (bound + 1) * 200) else: pred_ball_blocker = pred_ball_blocker + (abs(bound) * 200) y = abs((415 - 260) // ball_vy) Pred.blocker_pred_x = blocker_x + Pred.blocker_vx * y if Pred.blocker_pred_x < 0: Pred.blocker_pred_x = abs(Pred.blocker_pred_x) elif Pred.blocker_pred_x > 170: Pred.blocker_pred_x = 170 - (Pred.blocker_pred_x - 170) if pred_ball_blocker >= Pred.blocker_pred_x - 10 and pred_ball_blocker < Pred.blocker_pred_x + 40: print("slice will hit blicker") # don't slice # use origin ball vx to predict will hit blocker or not # if will hit blicker let ball go reverse direction y = abs((415 - 260) // ball_vy) pred_ball_blocker = pred_ball_1P + ball_vx * y bound = pred_ball_blocker // 200 # Determine if it is beyond the boundary if (bound > 0): # pred > 200 # fix landing position if (bound % 2 == 0): pred_ball_blocker = pred_ball_blocker - bound * 200 else: pred_ball_blocker = 200 - (pred_ball_blocker - 200 * bound) elif (bound < 0): # pred < 0 if (bound % 2 == 1): pred_ball_blocker = abs(pred_ball_blocker - (bound + 1) * 200) else: pred_ball_blocker = pred_ball_blocker + (abs(bound) * 200) if pred_ball_blocker >= Pred.blocker_pred_x - 10 and pred_ball_blocker < Pred.blocker_pred_x + 40: print("will hit blocker, hit reversed direction") if scene_info["ball_speed"][0] > 0: return 2 else: return 1 else: print("will not hit blicker, do nothing") return 0 else: # slice print("slice will not hit blocker") if scene_info["ball_speed"][0] > 0: return 1 else: return 2 elif scene_info["ball_speed"][1] > 0: # 球正在向下 # ball goes down x = ( scene_info["platform_1P"][1] - scene_info["ball"][1] ) // scene_info["ball_speed"][ 1] # 幾個frame以後會需要接 # x means how many frames before catch the ball Pred.pred = scene_info["ball"][0] + ( scene_info["ball_speed"][0] * x ) # 預測最終位置 # pred means predict ball landing site bound = Pred.pred // 200 # Determine if it is beyond the boundary if (bound > 0): # pred > 200 # fix landing position if (bound % 2 == 0): Pred.pred = Pred.pred - bound * 200 else: Pred.pred = 200 - (Pred.pred - 200 * bound) elif (bound < 0): # pred < 0 if (bound % 2 == 1): Pred.pred = abs(Pred.pred - (bound + 1) * 200) else: Pred.pred = Pred.pred + (abs(bound) * 200) return move_to(player='1P', pred=Pred.pred) else: # 球正在向上 # ball goes up return move_to(player='1P', pred=100) def ml_loop_for_2P(): # as same as 1P if scene_info["ball_speed"][1] > 0: return move_to(player='2P', pred=100) else: x = (scene_info["platform_2P"][1] + 30 - scene_info["ball"][1]) // scene_info["ball_speed"][1] pred = scene_info["ball"][0] + (scene_info["ball_speed"][0] * x) bound = pred // 200 if (bound > 0): if (bound % 2 == 0): pred = pred - bound * 200 else: pred = 200 - (pred - 200 * bound) elif (bound < 0): if bound % 2 == 1: pred = abs(pred - (bound + 1) * 200) else: pred = pred + (abs(bound) * 200) return move_to(player='2P', pred=pred) # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) blocker_last_x = scene_info["blocker"][0] Pred.last_command = 0 ball_served = True else: if side == "1P": Pred.blocker_vx = scene_info["blocker"][0] - blocker_last_x if scene_info["blocker"][0] == 0: Pred.blocker_vx = 5 elif scene_info["blocker"][0] == 170: Pred.blocker_vx = -5 command = ml_loop_for_1P() blocker_last_x = scene_info["blocker"][0] Pred.last_command = command else: command = ml_loop_for_2P() if command == 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" }) elif command == 1: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" })
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False curPath = os.path.abspath(os.path.dirname(__file__)) model = tf.keras.models.load_model(curPath + '/saved_model/myModel') # 2. Inform the game process that ml process is ready comm.ml_ready() # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": return "RESET" # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_RIGHT" }) ball_served = True else: ballX = scene_info["ball"][0] ballY = scene_info["ball"][1] ball_speed_X = scene_info["ball_speed"][0] ball_speed_Y = scene_info["ball_speed"][1] platform_1P_X = scene_info["platform_1P"][0] blocker_X = scene_info["blocker"][0] features = [[ ballX, ballY, ball_speed_X, ball_speed_Y, platform_1P_X, blocker_X ]] prediction = model.predict(features) if prediction > 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) print("MOVE_RIGHT") elif prediction < 0: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" }) print("MOVE_LEFT") else: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_RIGHT" }) print("NONE")
def ml_loop(side: str): """ The main loop for the machine learning process The `side` parameter can be used for switch the code for either of both sides, so you can write the code for both sides in the same script. Such as: ```python if side == "1P": ml_loop_for_1P() else: ml_loop_for_2P() ``` @param side The side which this script is executed for. Either "1P" or "2P". """ # === Here is the execution order of the loop === # # 1. Put the initialization code here ball_served = False # 2. Inform the game process that ml process is ready comm.ml_ready() c = 0 X = [] Y = [] dis = 100 # 3. Start an endless loop while True: # 3.1. Receive the scene information sent from the game process scene_info = comm.recv_from_game() mid = scene_info["platform_1P"][0] + 20 if c == 0: filename = path.join(path.dirname(__file__), 'Predict.pickle') with open(filename, "rb") as f: knn = pickle.load(f) filename = path.join(path.dirname(__file__), 'T0.pickle') with open(filename, "rb") as f: knn0 = pickle.load(f) filename = path.join(path.dirname(__file__), 'T1.pickle') with open(filename, "rb") as f: knn1 = pickle.load(f) filename = path.join(path.dirname(__file__), 'T2.pickle') with open(filename, "rb") as f: knn2 = pickle.load(f) filename = path.join(path.dirname(__file__), 'T3.pickle') with open(filename, "rb") as f: knn3 = pickle.load(f) filename = path.join(path.dirname(__file__), 'T4.pickle') with open(filename, "rb") as f: knn4 = pickle.load(f) filename = path.join(path.dirname(__file__), 'T5.pickle') with open(filename, "rb") as f: knn5 = pickle.load(f) box_px = -1 c = 1 box_x = scene_info["blocker"][0] if scene_info["frame"] > 2: if box_x > box_px: s = 1 if box_x < box_px: s = -1 feature = [] feature.append(scene_info["ball"][0]) feature.append(scene_info["ball"][1]) feature.append(scene_info["ball_speed"][0]) feature.append(scene_info["ball_speed"][1]) feature.append(scene_info["blocker"][0]) feature.append(s) feature = np.array(feature) feature = feature.reshape((-1, 6)) t = knn.predict(feature) feature1 = [] feature1.append(scene_info["ball"][0]) feature1.append(scene_info["ball"][1]) feature1.append(scene_info["ball_speed"][0]) feature1.append(scene_info["ball_speed"][1]) feature1 = np.array(feature1) feature1 = feature1.reshape((-1, 4)) if t == 0: dis = knn0.predict(feature1) if t == 1: dis = knn1.predict(feature) if t == 2: dis = knn2.predict(feature) if t == 3: dis = knn3.predict(feature) if t == 4: dis = knn4.predict(feature) if t == 5: dis = knn5.predict(feature1) if dis < 20: dis = 20 if dis > 180: dis = 180 box_px = box_x # 3.2. If either of two sides wins the game, do the updating or # resetting stuff and inform the game process when the ml process # is ready. if scene_info["status"] != "GAME_ALIVE": # Do some updating or resetting stuff ball_served = False # 3.2.1 Inform the game process that # the ml process is ready for the next round comm.ml_ready() continue # 3.3 Put the code here to handle the scene information # 3.4 Send the instruction for this frame to the game process if not ball_served: comm.send_to_game({ "frame": scene_info["frame"], "command": "SERVE_TO_LEFT" }) ball_served = True else: if dis < mid - 7: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_LEFT" }) elif dis > mid + 7: comm.send_to_game({ "frame": scene_info["frame"], "command": "MOVE_RIGHT" }) else: comm.send_to_game({ "frame": scene_info["frame"], "command": "NONE" })