def _get_enemy_commands(self): """Get enemy commands based on the 'ai_type' NOTE: Override this function in case you want custom enemy AI. TODO: Initialize func for AI only once. """ cmds = [] func = lambda *args: None if self.ai_type == 'attack_closest': func = utils.get_closest elif self.ai_type == 'attack_weakest': func = utils.get_weakest for unit in self.state2.units[self.state2.player_id]: opp_unit = func(unit, self.state2, self.state1.player_id) if opp_unit is None: continue dist = utils.get_distance(opp_unit.x, opp_unit.y, unit.x, unit.y) vision = tcc.staticvalues['sightRange'][ unit.type] / DISTANCE_FACTOR # Check if the our unit is in range of enemy then attack if (dist <= vision or self.full_vision): cmds.append([ tcc.command_unit_protected, unit.id, tcc.unitcommandtypes.Attack_Unit, opp_unit.id ]) # No-op or empty cmds means in built AI will be emulated return cmds
def _make_observation(self): myself = None enemy = None for uid, ut in self.state['units_myself'].iteritems(): myself = ut for uid, ut in self.state['units_enemy'].iteritems(): enemy = ut obs = np.zeros(self.observation_space.shape) if myself is not None and enemy is not None: obs[0] = myself.health obs[1] = myself.groundCD obs[2] = myself.groundRange / DISTANCE_FACTOR - 1 obs[3] = 0.0 obs[4] = utils.get_degree(myself.x, -myself.y, enemy.x, -enemy.y) / 180 obs[5] = utils.get_distance(myself.x, -myself.y, enemy.x, -enemy.y) / DISTANCE_FACTOR - 1 obs[6] = enemy.health obs[7] = enemy.groundCD obs[8] = enemy.groundRange / DISTANCE_FACTOR - 1 obs[9] = 1.0 else: obs[9] = 1.0 return obs
def _compute_reward(self): reward = np.zeros(self.nagents) enemy_id = self.enemy_ids[0] enemy = self.enemy_current_units[enemy_id] for idx in range(self.nagents): if self.agent_ids[idx] not in self.my_current_units: continue unit = self.my_current_units[self.agent_ids[idx]] dist = utils.get_distance(unit.x, unit.y, enemy.x, enemy.y) if dist <= self.vision: self.near_enemy[idx] = 1 else: self.near_enemy[idx] = 0 for idx in range(self.nagents): if self.agent_ids[idx] not in self.my_current_units: continue if self.near_enemy[idx] == 1: reward[idx] += self.ONPREY_REWARD * (np.count_nonzero(self.near_enemy) ** self.prey_exponent) else: reward[idx] += self.TIMESTEP_PENALTY return reward
def _make_observation(self): myself = None enemy = None factor_list = ["factor "] id_list = ["id "] #help(self.state.units[0][0]) #for command in self.state.unitcommands for unit in self.state.units[0]: myself = unit id_list.append(str(unit.command.targetId)) factor_list.append(str(unit.attacking)) for unit in self.state.units[1]: enemy = unit #print (" ").join(factor_list) #print (" ").join(id_list) obs = np.zeros(self.observation_space.shape) if myself is not None and enemy is not None: obs[0] = myself.health obs[1] = myself.groundCD obs[2] = myself.groundRange / DISTANCE_FACTOR - 1 obs[3] = 0.0 obs[4] = utils.get_degree(myself.x, -myself.y, enemy.x, -enemy.y) / 180 obs[5] = utils.get_distance(myself.x, -myself.y, enemy.x, -enemy.y) / DISTANCE_FACTOR - 1 obs[6] = enemy.health obs[7] = enemy.groundCD obs[8] = enemy.groundRange / DISTANCE_FACTOR - 1 obs[9] = 1.0 else: obs[9] = 1.0 return obs
def get_distance_degree(self, unit): dd = [] for id in self.id_list: t = self.units_dict[id] distance = utils.get_distance(unit.x, unit.y, t.x, t.y) degree = utils.get_degree(unit.x, unit.y, t.x, t.y) / 180. dd += [distance, degree] return dd
def _make_observation(self): myself = None enemy = None full_obs = np.zeros((self.nagents, ) + self.observation_space.shape) for idx in range(self.nagents): agent_id = self.agent_ids[idx] if agent_id in self.my_current_units: myself = self.my_current_units[agent_id] else: myself = None if myself is None: continue curr_obs = full_obs[idx] curr_obs[0] = myself.x / self.state1.map_size[0] curr_obs[1] = myself.y / self.state1.map_size[1] for enemy_idx in range(self.nenemies): enemy_id = self.enemy_ids[enemy_idx] if enemy_id in self.enemy_current_units: enemy = self.enemy_current_units[enemy_id] else: enemy = None if enemy is None: continue if (myself.attacking or myself.starting_attack) and \ self.prev_actions[idx] == enemy_idx + len(self.move_steps): self.attack_map[idx][enemy_idx] = 1 distance = utils.get_distance(myself.x, myself.y, enemy.x, enemy.y) obs_idx = 2 + enemy_idx * 3 if distance <= self.vision or self.full_vision: curr_obs[obs_idx] = (myself.x - enemy.x) / (self.vision) curr_obs[obs_idx + 1] = (myself.y - enemy.y) / (self.vision) curr_obs[obs_idx + 2] = 0 else: curr_obs[obs_idx] = 0 curr_obs[obs_idx + 1] = 0 curr_obs[obs_idx + 2] = 1 return full_obs
def _make_observation(self): myself = None enemy = None full_obs = np.zeros((self.nagents, ) + self.observation_space.shape) for idx in range(self.nagents): agent_id = self.agent_ids[idx] if agent_id in self.my_current_units: myself = self.my_current_units[agent_id] else: myself = None if myself is None: continue curr_obs = full_obs[idx] curr_obs[0] = myself.x / self.state1.map_size[0] curr_obs[1] = myself.y / self.state1.map_size[1] # To simplify add unit's health and shield points curr_obs[2] = (myself.health + myself.shield) / ( myself.max_health + myself.max_shield) cd = getattr(myself, self.unit_attributes[myself.type]['cdAttribute']) curr_obs[3] = cd / self.unit_attributes[myself.type]['maxCD'] curr_obs[4] = self.prev_actions[idx] / self.nactions # Get observation for each enemy for each agent for enemy_idx in range(self.nenemies): enemy_id = self.enemy_ids[enemy_idx] if enemy_id in self.enemy_current_units: enemy = self.enemy_current_units[enemy_id] else: enemy = None if enemy is None: continue if (myself.attacking or myself.starting_attack) and \ self.prev_actions[idx] == enemy_idx + len(self.move_steps): self.attack_map[idx][enemy_idx] = 1 distance = utils.get_distance(myself.x, myself.y, enemy.x, enemy.y) obs_idx = 5 + enemy_idx * 5 if distance <= self.vision or self.full_vision: curr_obs[obs_idx] = (myself.x - enemy.x) / (self.vision) curr_obs[obs_idx + 1] = (myself.y - enemy.y) / (self.vision) curr_obs[obs_idx + 2] = 0 else: curr_obs[obs_idx] = 0 curr_obs[obs_idx + 1] = 0 curr_obs[obs_idx + 2] = 1 curr_obs[obs_idx + 3] = (enemy.health + enemy.shield) / ( enemy.max_health + enemy.max_shield) cd = getattr(enemy, self.unit_attributes[enemy.type]['cdAttribute']) curr_obs[obs_idx + 4] = cd / self.unit_attributes[enemy.type]['maxCD'] return full_obs
def _make_commands(self, actions): cmds = [] if self.state1 is None or actions is None: return cmds # Hack for case when map is not purely cleaned for frame if len(self.state1.units[self.state1.player_id]) > self.nagents: return cmds enemy_unit = None for idx in range(self.nagents): agent_id = self.agent_ids[idx] if agent_id not in self.my_current_units: # Agent is probably dead continue my_unit = self.my_current_units[agent_id] action = actions[idx] prev_action = self.prev_actions[idx] if action < len(self.move_steps): new_x = my_unit.x + self.move_steps[action][0] * self.step_size new_y = my_unit.y + self.move_steps[action][1] * self.step_size new_x = min(new_x, self.init_range_end) new_y = min(new_y, self.init_range_end) new_x = max(new_x, self.init_range_start) new_y = max(new_y, self.init_range_start) # Move commands always override previous commands (required for kiting) cmds.append([ tcc.command_unit, my_unit.id, tcc.unitcommandtypes.Move, -1, int(new_x), int(new_y), -1 ]) else: enemy_id = action - len(self.move_steps) enemy_id = self.enemy_ids[enemy_id] if enemy_id in self.enemy_current_units: enemy_unit = self.enemy_current_units[enemy_id] else: enemy_unit = None if not enemy_unit: continue distance = utils.get_distance(my_unit.x, -my_unit.y, enemy_unit.x, -enemy_unit.y) unit_command = tcc.command_unit_protected # Send protected command only if previous command was attack if prev_action < len(self.move_steps): unit_command = tcc.command_unit range_attribute = self.unit_attributes[ my_unit.type]['rangeAttribute'] # Should be in attack range to attack if distance <= getattr( my_unit, range_attribute) or self.unlimited_attack_range: cmds.append([ unit_command, my_unit.id, tcc.unitcommandtypes.Attack_Unit, enemy_unit.id ]) self.prev_actions = actions return cmds
def test_get_distance(self): self.assertEquals(utils.get_distance(10, -10, 10, -20), 10) self.assertEquals(utils.get_distance(10, -10, 10, -5), 5) self.assertEquals(utils.get_distance(10, -10, 5, -10), 5) self.assertEquals(utils.get_distance(10, -10, 15, -10), 5)