| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import numpy as np |
|
|
| |
| THIRD_X = 0.3 |
| BOX_X = 0.7 |
| MAX_X = 1.0 |
| BOX_Y = 0.24 |
| MAX_Y = 0.42 |
|
|
| |
| IDLE = 0 |
| LEFT = 1 |
| TOP_LEFT = 2 |
| TOP = 3 |
| TOP_RIGHT = 4 |
| RIGHT = 5 |
| BOTTOM_RIGHT = 6 |
| BOTTOM = 7 |
| BOTTOM_LEFT = 8 |
| LONG_PASS = 9 |
| HIGH_PASS = 10 |
| SHORT_PASS = 11 |
| SHOT = 12 |
| SPRINT = 13 |
| RELEASE_DIRECTION = 14 |
| RELEASE_SPRINT = 15 |
| SLIDING = 16 |
| DRIBBLE = 17 |
| RELEASE_DRIBBLE = 18 |
| STICKY_LEFT = 0 |
| STICKY_TOP_LEFT = 1 |
| STICKY_TOP = 2 |
| STICKY_TOP_RIGHT = 3 |
| STICKY_RIGHT = 4 |
| STICKY_BOTTOM_RIGHT = 5 |
| STICKY_BOTTOM = 6 |
| STICKY_BOTTOM_LEFT = 7 |
|
|
| RIGHT_ACTIONS = [TOP_RIGHT, RIGHT, BOTTOM_RIGHT, TOP, BOTTOM] |
| LEFT_ACTIONS = [TOP_LEFT, LEFT, BOTTOM_LEFT, TOP, BOTTOM] |
| BOTTOM_ACTIONS = [BOTTOM_LEFT, BOTTOM, BOTTOM_RIGHT, LEFT, RIGHT] |
| TOP_ACTIONS = [TOP_LEFT, TOP, TOP_RIGHT, LEFT, RIGHT] |
| ALL_DIRECTION_ACTIONS = [LEFT, TOP_LEFT, TOP, TOP_RIGHT, RIGHT, BOTTOM_RIGHT, BOTTOM, BOTTOM_LEFT] |
| ALL_DIRECTION_VECS = [(-1, 0), (-1, -1), (0, -1), (1, -1), (1, 0), (1, 1), (0, 1), (-1, 1)] |
|
|
| def get_direction_action(available_action, sticky_actions, forbidden_action, target_action, active_direction, need_sprint): |
| available_action = np.zeros(19) |
| available_action[forbidden_action] = 0 |
| available_action[target_action] = 1 |
|
|
| if need_sprint: |
| available_action[RELEASE_SPRINT] = 0 |
| if sticky_actions[8] == 0: |
| available_action = np.zeros(19) |
| available_action[SPRINT] = 1 |
| else: |
| available_action[SPRINT] = 0 |
| if sticky_actions[8] == 1: |
| available_action = np.zeros(19) |
| available_action[RELEASE_SPRINT] = 1 |
| return available_action |
|
|
| def openrl_obs_deal(obs): |
|
|
| direction_x_bound = 0.03 |
| direction_y_bound = 0.02 |
| ball_direction_x_bound = 0.15 |
| ball_direction_y_bound = 0.07 |
| ball_direction_z_bound = 4 |
| ball_rotation_x_bound = 0.0005 |
| ball_rotation_y_bound = 0.0004 |
| ball_rotation_z_bound = 0.015 |
| active_id = [obs["active"]] |
| assert active_id[0] < 11 and active_id[0] >= 0, "active id is wrong, active id = {}".format(active_id[0]) |
| |
| left_position = np.concatenate(obs["left_team"]) |
| left_direction = np.concatenate(obs["left_team_direction"]) |
| left_tired_factor = obs["left_team_tired_factor"] |
| left_yellow_card = obs["left_team_yellow_card"] |
| left_red_card = ~obs["left_team_active"] |
| left_offside = np.zeros(11) |
| if obs["ball_owned_team"] == 0: |
| left_offside_line = max(0, obs["ball"][0], np.sort(obs["right_team"][:, 0])[-2]) |
| left_offside = obs["left_team"][:, 0] > left_offside_line |
| left_offside[obs["ball_owned_player"]] = False |
|
|
| new_left_direction = left_direction.copy() |
| for counting in range(len(new_left_direction)): |
| new_left_direction[counting] = new_left_direction[counting] / direction_x_bound if counting % 2 == 0 else new_left_direction[counting] / direction_y_bound |
|
|
| left_team = np.concatenate([ |
| left_position, |
| new_left_direction, |
| left_tired_factor, |
| left_yellow_card, |
| left_red_card, |
| left_offside, |
| ]).astype(np.float64) |
|
|
| |
| right_position = np.concatenate(obs["right_team"]) |
| right_direction = np.concatenate(obs["right_team_direction"]) |
| right_tired_factor = obs["right_team_tired_factor"] |
| right_yellow_card = obs["right_team_yellow_card"] |
| right_red_card = ~obs["right_team_active"] |
| right_offside = np.zeros(11) |
| if obs["ball_owned_team"] == 1: |
| right_offside_line = min(0, obs["ball"][0], np.sort(obs["left_team"][:, 0])[1]) |
| right_offside = obs["right_team"][:, 0] < right_offside_line |
| right_offside[obs["ball_owned_player"]] = False |
|
|
| new_right_direction = right_direction.copy() |
| for counting in range(len(new_right_direction)): |
| new_right_direction[counting] = new_right_direction[counting] / direction_x_bound if counting % 2 == 0 else new_right_direction[counting] / direction_y_bound |
|
|
| right_team = np.concatenate([ |
| right_position, |
| new_right_direction, |
| right_tired_factor, |
| right_yellow_card, |
| right_red_card, |
| right_offside, |
| ]).astype(np.float64) |
|
|
| |
| sticky_actions = obs["sticky_actions"][:10] |
| active_position = obs["left_team"][obs["active"]] |
| active_direction = obs["left_team_direction"][obs["active"]] |
| active_tired_factor = left_tired_factor[obs["active"]] |
| active_yellow_card = left_yellow_card[obs["active"]] |
| active_red_card = left_red_card[obs["active"]] |
| active_offside = left_offside[obs["active"]] |
|
|
| new_active_direction = active_direction.copy() |
| new_active_direction[0] /= direction_x_bound |
| new_active_direction[1] /= direction_y_bound |
|
|
| active_player = np.concatenate([ |
| sticky_actions, |
| active_position, |
| new_active_direction, |
| [active_tired_factor], |
| [active_yellow_card], |
| [active_red_card], |
| [active_offside], |
| ]).astype(np.float64) |
|
|
| |
| relative_ball_position = obs["ball"][:2] - active_position |
| distance2ball = np.linalg.norm(relative_ball_position) |
| relative_left_position = obs["left_team"] - active_position |
| distance2left = np.linalg.norm(relative_left_position, axis=1) |
| relative_left_position = np.concatenate(relative_left_position) |
| relative_right_position = obs["right_team"] - active_position |
| distance2right = np.linalg.norm(relative_right_position, axis=1) |
| relative_right_position = np.concatenate(relative_right_position) |
| relative_info = np.concatenate([ |
| relative_ball_position, |
| [distance2ball], |
| relative_left_position, |
| distance2left, |
| relative_right_position, |
| distance2right, |
| ]).astype(np.float64) |
|
|
| active_info = np.concatenate([active_player, relative_info]) |
|
|
| |
| ball_owned_team = np.zeros(3) |
| ball_owned_team[obs["ball_owned_team"] + 1] = 1.0 |
| new_ball_direction = obs["ball_direction"].copy() |
| new_ball_rotation = obs['ball_rotation'].copy() |
| for counting in range(len(new_ball_direction)): |
| if counting % 3 == 0: |
| new_ball_direction[counting] /= ball_direction_x_bound |
| new_ball_rotation[counting] /= ball_rotation_x_bound |
| if counting % 3 == 1: |
| new_ball_direction[counting] /= ball_direction_y_bound |
| new_ball_rotation[counting] /= ball_rotation_y_bound |
| if counting % 3 == 2: |
| new_ball_direction[counting] /= ball_direction_z_bound |
| new_ball_rotation[counting] /= ball_rotation_z_bound |
| ball_info = np.concatenate([ |
| obs["ball"], |
| new_ball_direction, |
| ball_owned_team, |
| new_ball_rotation |
| ]).astype(np.float64) |
| |
| ball_owned_player = np.zeros(23) |
| if obs["ball_owned_team"] == 1: |
| ball_owned_player[11 + obs['ball_owned_player']] = 1.0 |
| ball_owned_player_pos = obs['right_team'][obs['ball_owned_player']] |
| ball_owned_player_direction = obs["right_team_direction"][obs['ball_owned_player']] |
| ball_owner_tired_factor = right_tired_factor[obs['ball_owned_player']] |
| ball_owner_yellow_card = right_yellow_card[obs['ball_owned_player']] |
| ball_owner_red_card = right_red_card[obs['ball_owned_player']] |
| ball_owner_offside = right_offside[obs['ball_owned_player']] |
| elif obs["ball_owned_team"] == 0: |
| ball_owned_player[obs['ball_owned_player']] = 1.0 |
| ball_owned_player_pos = obs['left_team'][obs['ball_owned_player']] |
| ball_owned_player_direction = obs["left_team_direction"][obs['ball_owned_player']] |
| ball_owner_tired_factor = left_tired_factor[obs['ball_owned_player']] |
| ball_owner_yellow_card = left_yellow_card[obs['ball_owned_player']] |
| ball_owner_red_card = left_red_card[obs['ball_owned_player']] |
| ball_owner_offside = left_offside[obs['ball_owned_player']] |
| else: |
| ball_owned_player[-1] = 1.0 |
| ball_owned_player_pos = np.zeros(2) |
| ball_owned_player_direction = np.zeros(2) |
|
|
| relative_ball_owner_position = np.zeros(2) |
| distance2ballowner = np.zeros(1) |
| ball_owner_info = np.zeros(4) |
| if obs["ball_owned_team"] != -1: |
| relative_ball_owner_position = ball_owned_player_pos - active_position |
| distance2ballowner = [np.linalg.norm(relative_ball_owner_position)] |
| ball_owner_info = np.concatenate([ |
| [ball_owner_tired_factor], |
| [ball_owner_yellow_card], |
| [ball_owner_red_card], |
| [ball_owner_offside] |
| ]) |
|
|
| new_ball_owned_player_direction = ball_owned_player_direction.copy() |
| new_ball_owned_player_direction[0] /= direction_x_bound |
| new_ball_owned_player_direction[1] /= direction_y_bound |
|
|
| ball_own_active_info = np.concatenate([ |
| ball_info, |
| ball_owned_player, |
| active_position, |
| new_active_direction, |
| [active_tired_factor], |
| [active_yellow_card], |
| [active_red_card], |
| [active_offside], |
| relative_ball_position, |
| [distance2ball], |
| ball_owned_player_pos, |
| new_ball_owned_player_direction, |
| relative_ball_owner_position, |
| distance2ballowner, |
| ball_owner_info |
| ]) |
|
|
| |
| game_mode = np.zeros(7) |
| game_mode[obs["game_mode"]] = 1.0 |
| goal_diff_ratio = (obs["score"][0] - obs["score"][1]) / 5 |
| steps_left_ratio = obs["steps_left"] / 3001 |
| match_state = np.concatenate([ |
| game_mode, |
| [goal_diff_ratio], |
| [steps_left_ratio], |
| ]).astype(np.float64) |
|
|
| |
| available_action = np.ones(19) |
| available_action[IDLE] = 0 |
| available_action[RELEASE_DIRECTION] = 0 |
| should_left = False |
|
|
|
|
| if obs["game_mode"] == 0: |
| active_x = active_position[0] |
| counting_right_enemy_num = 0 |
| counting_right_teammate_num = 0 |
| counting_left_teammate_num = 0 |
| for enemy_pos in obs["right_team"][1:]: |
| if active_x < enemy_pos[0]: |
| counting_right_enemy_num += 1 |
| for teammate_pos in obs["left_team"][1:]: |
| if active_x < teammate_pos[0]: |
| counting_right_teammate_num += 1 |
| if active_x > teammate_pos[0]: |
| counting_left_teammate_num += 1 |
| |
| if active_x > obs['ball'][0] + 0.05: |
|
|
| if counting_left_teammate_num < 2: |
|
|
| if obs['ball_owned_team'] != 0: |
| should_left = True |
| if should_left: |
| available_action = get_direction_action(available_action, sticky_actions, RIGHT_ACTIONS, [LEFT, BOTTOM_LEFT, TOP_LEFT], active_direction, True) |
|
|
|
|
| if (abs(relative_ball_position[0]) > 0.75 or abs(relative_ball_position[1]) > 0.5): |
| all_directions_vecs = [np.array(v) / np.linalg.norm(np.array(v)) for v in ALL_DIRECTION_VECS] |
| best_direction = np.argmax([np.dot(relative_ball_position, v) for v in all_directions_vecs]) |
| target_direction = ALL_DIRECTION_ACTIONS[best_direction] |
| forbidden_actions = ALL_DIRECTION_ACTIONS.copy() |
| forbidden_actions.remove(target_direction) |
| available_action = get_direction_action(available_action, sticky_actions, forbidden_actions, [target_direction], active_direction, True) |
|
|
|
|
| if_i_hold_ball = (obs["ball_owned_team"] == 0 and obs["ball_owned_player"] == obs['active']) |
| ball_pos_offset = 0.05 |
| no_ball_pos_offset = 0.03 |
|
|
| active_x, active_y = active_position[0], active_position[1] |
| if_outside = False |
| if active_x <= (-1 + no_ball_pos_offset) or (if_i_hold_ball and active_x <= (-1 + ball_pos_offset)): |
| if_outside = True |
| action_index = LEFT_ACTIONS |
| target_direction = RIGHT |
| elif active_x >= (1 - no_ball_pos_offset) or (if_i_hold_ball and active_x >= (1 - ball_pos_offset)): |
| if_outside = True |
| action_index = RIGHT_ACTIONS |
| target_direction = LEFT |
| elif active_y >= (0.42 - no_ball_pos_offset) or (if_i_hold_ball and active_y >= (0.42 - ball_pos_offset)): |
| if_outside = True |
| action_index = BOTTOM_ACTIONS |
| target_direction = TOP |
| elif active_y <= (-0.42 + no_ball_pos_offset) or (if_i_hold_ball and active_x <= (-0.42 + ball_pos_offset)): |
| if_outside = True |
| action_index = TOP_ACTIONS |
| target_direction = BOTTOM |
| if obs["game_mode"] in [1, 2, 3, 4, 5]: |
| left2ball = np.linalg.norm(obs["left_team"] - obs["ball"][:2], axis=1) |
| right2ball = np.linalg.norm(obs["right_team"] - obs["ball"][:2], axis=1) |
| if np.min(left2ball) < np.min(right2ball) and obs["active"] == np.argmin(left2ball): |
| if_outside = False |
| elif obs["game_mode"] in [6]: |
| if obs["ball"][0] > 0 and active_position[0] > BOX_X: |
| if_outside = False |
| if if_outside: |
| available_action = get_direction_action(available_action, sticky_actions, action_index, [target_direction], active_direction, False) |
|
|
| if np.sum(sticky_actions[:8]) == 0: |
| available_action[RELEASE_DIRECTION] = 0 |
| if sticky_actions[8] == 0: |
| available_action[RELEASE_SPRINT] = 0 |
| else: |
| available_action[SPRINT] = 0 |
| if sticky_actions[9] == 0: |
| available_action[RELEASE_DRIBBLE] = 0 |
| else: |
| available_action[DRIBBLE] = 0 |
| if active_position[0] < 0.4 or abs(active_position[1]) > 0.3: |
| available_action[SHOT] = 0 |
|
|
| if obs["game_mode"] == 0: |
| if obs["ball_owned_team"] == -1: |
| available_action[DRIBBLE] = 0 |
| if distance2ball >= 0.05: |
| available_action[SLIDING] = 0 |
| available_action[[LONG_PASS, HIGH_PASS, SHORT_PASS, SHOT]] = 0 |
| elif obs["ball_owned_team"] == 0: |
| available_action[SLIDING] = 0 |
| if distance2ball >= 0.05: |
| available_action[[LONG_PASS, HIGH_PASS, SHORT_PASS, SHOT, DRIBBLE]] = 0 |
| elif obs["ball_owned_team"] == 1: |
| available_action[DRIBBLE] = 0 |
| if distance2ball >= 0.05: |
| available_action[[LONG_PASS, HIGH_PASS, SHORT_PASS, SHOT, SLIDING]] = 0 |
| elif obs["game_mode"] in [1, 2, 3, 4, 5]: |
| left2ball = np.linalg.norm(obs["left_team"] - obs["ball"][:2], axis=1) |
| right2ball = np.linalg.norm(obs["right_team"] - obs["ball"][:2], axis=1) |
| if np.min(left2ball) < np.min(right2ball) and obs["active"] == np.argmin(left2ball): |
| available_action[[SPRINT, RELEASE_SPRINT, SLIDING, DRIBBLE, RELEASE_DRIBBLE]] = 0 |
| else: |
| available_action[[LONG_PASS, HIGH_PASS, SHORT_PASS, SHOT]] = 0 |
| available_action[[SLIDING, DRIBBLE, RELEASE_DRIBBLE]] = 0 |
| elif obs["game_mode"] == 6: |
| if obs["ball"][0] > 0 and active_position[0] > BOX_X: |
| available_action[[LONG_PASS, HIGH_PASS, SHORT_PASS]] = 0 |
| available_action[[SPRINT, RELEASE_SPRINT, SLIDING, DRIBBLE, RELEASE_DRIBBLE]] = 0 |
| else: |
| available_action[[LONG_PASS, HIGH_PASS, SHORT_PASS, SHOT]] = 0 |
| available_action[[SLIDING, DRIBBLE, RELEASE_DRIBBLE]] = 0 |
|
|
|
|
| obs = np.concatenate([ |
| active_id, |
| active_info, |
| ball_own_active_info, |
| left_team, |
| right_team, |
| match_state, |
| ]) |
|
|
| share_obs = np.concatenate([ |
| ball_info, |
| ball_owned_player, |
| left_team, |
| right_team, |
| match_state, |
| ]) |
|
|
| assert available_action.sum() > 0 |
| return dict( |
| obs=obs, |
| share_obs=share_obs, |
| available_action=available_action, |
| ) |
|
|
|
|
| def _t2n(x): |
| return x.detach().cpu().numpy() |
|
|
|
|
|
|
|
|
|
|