class ScoutVecFeatureV1(VecFeature): def __init__(self): super(ScoutVecFeatureV1, self).__init__() self._dest = None self._src = None def reset(self, env): super(ScoutVecFeatureV1, self).reset(env) self._dest = DestRange(env.unwrapped.enemy_base()) self._src = DestRange(env.unwrapped.owner_base()) def obs_space(self): low = np.zeros(4) high = np.ones(4) return Box(low, high) def extract(self, env, obs): scout = env.unwrapped.scout() features = [] features.append(scout.float_attr.health / scout.float_attr.health_max) if self._have_enemies(obs): features.append(float(1)) else: features.append(float(0)) if self._src.in_range( (scout.float_attr.pos_x, scout.float_attr.pos_y)): features.append(float(1)) else: features.append(float(0)) if self._dest.in_range( (scout.float_attr.pos_x, scout.float_attr.pos_y)): features.append(float(1)) else: features.append(float(0)) #print("vec_feature=", features) return np.array(features) def _have_enemies(self, obs): enemy_count = 0 units = obs.observation['units'] for u in units: if (u.int_attr.alliance == sm.AllianceType.ENEMY.value): if (u.unit_type in sm.COMBAT_UNITS or u.unit_type in sm.COMBAT_AIR_UNITS): enemy_count += 1 if enemy_count > 0: return True else: return False
class ScoutVecFeature(VecFeature): def __init__(self): super(ScoutVecFeature, self).__init__() self._dest = None self._src = None def reset(self, env): super(ScoutVecFeature, self).reset(env) self._dest = DestRange(env.unwrapped.enemy_base()) self._src = DestRange(env.unwrapped.owner_base()) def obs_space(self): low = np.zeros(8) high = np.ones(8) return Box(low, high) def extract(self, env, obs): scout = env.unwrapped.scout() scout_raw_pos = (scout.float_attr.pos_x, scout.float_attr.pos_y) home_pos = env.unwrapped.owner_base() enemy_pos = env.unwrapped.enemy_base() scout_pos = self._pos_transfer(scout_raw_pos[0], scout_raw_pos[1]) home_pos = self._pos_transfer(home_pos[0], home_pos[1]) enemy_pos = self._pos_transfer(enemy_pos[0], enemy_pos[1]) features = [] features.append(float(scout_pos[0]) / self._map_size[0]) features.append(float(scout_pos[1]) / self._map_size[1]) #features.append(float(home_pos[0]) / self._map_size[0]) #features.append(float(home_pos[1]) / self._map_size[1]) #features.append(float(enemy_pos[0]) / self._map_size[0]) #features.append(float(enemy_pos[1]) / self._map_size[1]) features.append( float(abs(home_pos[0] - scout_pos[0])) / self._map_size[0]) features.append( float(abs(home_pos[1] - scout_pos[1])) / self._map_size[1]) features.append( float(abs(enemy_pos[0] - scout_pos[0])) / self._map_size[0]) features.append( float(abs(enemy_pos[1] - scout_pos[1])) / self._map_size[1]) if self._dest.in_range(scout_raw_pos): features.append(float(1)) else: features.append(float(0)) if self._src.in_range(scout_raw_pos): features.append(float(1)) else: features.append(float(0)) return features
class BackwardRwd(Reward): def __init__(self, weight=1): super(BackwardRwd, self).__init__(weight) self._dest = None self._last_dist = None self._home = None def reset(self, obs, env): scout = env.unwrapped.scout() self._home = env.unwrapped.owner_base() self._dest = DestRange(self._home, dest_range=16) self._last_dist = None def compute_rwd(self, obs, reward, done, env): scout = env.unwrapped.scout() if self._last_dist is None: self._last_dist = self._compute_dist(scout) if not self._dest.in_range( (scout.float_attr.pos_x, scout.float_attr.pos_y)): tmp_dist = self._compute_dist(scout) if tmp_dist > self._last_dist: self.rwd = self.w * -1 else: self.rwd = 0 self._last_dist = tmp_dist else: self.rwd = 0 print('backreward=', self.rwd) def _compute_dist(self, scout): dist = sm.calculate_distance(scout.float_attr.pos_x, scout.float_attr.pos_y, self._home[0], self._home[1]) return dist
class FullGameVecAllV1(FullGameVecAll): def __init__(self, target_range): super(FullGameVecAllV1, self).__init__() self._target_range = target_range self._target = None def reset(self, env): super(FullGameVecAllV1, self).reset(env) self._target = DestRange(env.unwrapped.enemy_base(), dest_range=self._target_range) def obs_space(self): low = np.zeros(14) high = np.ones(14) return Box(low, high) def extract(self, env, obs): features = super(FullGameVecAllV1, self).extract(env, obs) scout = env.unwrapped.scout() if self._target.in_range((scout.float_attr.pos_x, scout.float_attr.pos_y)): features.append(float(1)) else: features.append(float(0)) return features
class FullGameLocalImgV1(ImgLocalFeatExtractor): def __init__(self, compress_width, local_range, target_range): super(FullGameLocalImgV1, self).__init__(compress_width, local_range) self._channel_num = GLOBAL_CHANNEL self._target_range = target_range self._target = None def reset(self, env): super(FullGameLocalImgV1, self).reset(env) self._target = DestRange(env.unwrapped.enemy_base(), dest_range=self._target_range) def extract(self, env, obs): image = np.zeros( [self._compress_width, self._compress_width, self._channel_num]) scout = env.unwrapped.scout() if self._target.in_range( (scout.float_attr.pos_x, scout.float_attr.pos_y)): enemys = self.unit_dispatch(obs) channel_base = self.enemy_channel(enemys, image, 0) #print('local image: channel total number=', channel_base) #print('image=', image) return image def obs_space(self): low = np.zeros( [self._compress_width, self._compress_width, self._channel_num]) high = np.ones( [self._compress_width, self._compress_width, self._channel_num]) return Box(low, high) def enemy_channel(self, enemys, image, channel_base): for u in enemys: u_pos = (u.float_attr.pos_x, u.float_attr.pos_y) if not self.check_in_range(u_pos): continue i, j = self.pos_2_2d(u_pos) #print('enemy coordinate={},{}'.format(i, j)) if u.unit_type in sm.COMBAT_AIR_UNITS: image[i, j, channel_base + 0] += (1.0 / MAX_UNIT_NUM) #print('enemy air:[{},{},{}] = {}'.format( # i, j, channel_base, image[i, j, channel_base])) else: image[i, j, channel_base + 1] += (1.0 / MAX_UNIT_NUM) #print('enemy unit:[{},{},{}] = {}'.format( # i, j, channel_base + 1, image[i, j, channel_base + 1])) return channel_base + 2 def unit_dispatch(self, obs): units = obs.observation['units'] enemys = [] for u in units: if u.int_attr.alliance == sm.AllianceType.ENEMY.value: enemys.append(u) else: continue return enemys
class BackwardRwd(Reward): def __init__(self, weight=1): super(BackwardRwd, self).__init__(weight) self._dest = None def reset(self, obs, env): home = env.unwrapped.owner_base() self._dest = DestRange(home, dest_range=16) def compute_rwd(self, obs, reward, done, env): scout = env.unwrapped.scout() if self._dest.in_range( (scout.float_attr.pos_x, scout.float_attr.pos_y)): self.rwd = 0 else: self.rwd = -1 * self.w
class TargetTerminalWrapperC1(gym.Wrapper): def __init__(self, env, compress_width, range_width, explore_step): super(TargetTerminalWrapperC1, self).__init__(env) self._status = None self._compress_width = compress_width self._range_width = range_width self._explore_step = explore_step def _reset(self): obs = self.env._reset() map_size = self.env.unwrapped.map_size() x_per_unit = map_size[0] / self._compress_width y_per_unit = map_size[1] / self._compress_width home_pos = self.env.unwrapped.owner_base() enemy_pos = self.env.unwrapped.enemy_base() x_range = x_per_unit * self._range_width y_range = y_per_unit * self._range_width self._status = TripCourseC1(home_pos, enemy_pos, (x_range, y_range), self._explore_step) self._status.reset() self._home_base = DestRange(self.env.unwrapped.owner_base()) return obs def _step(self, action): obs, rwd, done, info = self.env._step(action) return obs, rwd, self._check_terminal(obs, done), info def _check_terminal(self, obs, done): if done: return done survive = self.env.unwrapped.scout_survive() if not survive: return True scout = self.env.unwrapped.scout() status = self._status.check_status( (scout.float_attr.pos_x, scout.float_attr.pos_y)) if status == TripStatus.TERMINAL: return True elif status == TripStatus.BACKWORD: if self._home_base.in_range( (scout.float_attr.pos_x, scout.float_attr.pos_y)): print("backward return_HOME,", status) return True return done
class FullGameRwdWrapperV3(FullGameRoundTripRwd): def __init__(self, env, target_range): super(FullGameRwdWrapperV3, self).__init__(env) self._target_range = target_range self._target = None def _assemble_reward(self): self._target = DestRange(self.env.unwrapped.enemy_base(), dest_range=self._target_range) self._first_rewards = [fr.FullGameMoveToTarget(self._target_range)] self._second_rewards = [ ir.EvadeUnderAttackRwd(), fr.FullGameInTargetRangeRwd(self._target_range), fr.FullGameViewRwdV1() ] self._final_rewards = [fr.FullGameFinalRwd()] def _condition_judge(self, env): scout = env.unwrapped.scout() scout_pos = (scout.float_attr.pos_x, scout.float_attr.pos_y) return self._target.in_range(scout_pos)
class ScoutVecFeature(FeatureExtractor): def __init__(self): super(ScoutVecFeature, self).__init__() self._dest = None self._src = None self._reverse = False self._map_size = None self.env = None def reset(self, env): self.env = env self._dest = DestRange(env.unwrapped.enemy_base()) self._src = DestRange(env.unwrapped.owner_base()) self._map_size = self.env.unwrapped.map_size() self._reverse = self._judge_reverse(env) def obs_space(self): low = np.zeros(8) high = np.ones(8) return Box(low, high) def extract(self, env, obs): scout = env.unwrapped.scout() scout_raw_pos = (scout.float_attr.pos_x, scout.float_attr.pos_y) home_pos = env.unwrapped.owner_base() enemy_pos = env.unwrapped.enemy_base() scout_pos = self._pos_transfer(scout_raw_pos[0], scout_raw_pos[1]) home_pos = self._pos_transfer(home_pos[0], home_pos[1]) enemy_pos = self._pos_transfer(enemy_pos[0], enemy_pos[1]) features = [] features.append(float(scout_pos[0]) / self._map_size[0]) features.append(float(scout_pos[1]) / self._map_size[1]) #features.append(float(home_pos[0]) / self._map_size[0]) #features.append(float(home_pos[1]) / self._map_size[1]) #features.append(float(enemy_pos[0]) / self._map_size[0]) #features.append(float(enemy_pos[1]) / self._map_size[1]) features.append( float(abs(home_pos[0] - scout_pos[0])) / self._map_size[0]) features.append( float(abs(home_pos[1] - scout_pos[1])) / self._map_size[1]) features.append( float(abs(enemy_pos[0] - scout_pos[0])) / self._map_size[0]) features.append( float(abs(enemy_pos[1] - scout_pos[1])) / self._map_size[1]) if self._dest.in_range(scout_raw_pos): features.append(float(1)) else: features.append(float(0)) if self._src.in_range(scout_raw_pos): features.append(float(1)) else: features.append(float(0)) return features def _judge_reverse(self, env): scout = self.env.unwrapped.scout() if scout.float_attr.pos_x < scout.float_attr.pos_y: return False else: return True def _pos_transfer(self, x, y): if not self._reverse: return (x, y) cx = self._map_size[0] / 2 cy = self._map_size[1] / 2 pos_x = 0.0 pos_y = 0.0 if x > cx: pos_x = cx - abs(x - cx) else: pos_x = cx + abs(x - cx) if y > cy: pos_y = cy - abs(y - cy) else: pos_y = cy + abs(y - cy) return (pos_x, pos_y)
class FullGameGlobalImgV2(ImgFeatExtractor): def __init__(self, compress_width, target_range): super(FullGameGlobalImgV2, self).__init__(compress_width) self._channel_num = GLOBAL_CHANNEL self._target_range = target_range self._target = None def reset(self, env): super(FullGameGlobalImgV2, self).reset(env) self._target = DestRange(env.unwrapped.enemy_base(), dest_range=self._target_range) print('FullGameGlobalImgV2 radius=({},{}), per_unit=({},{})'.format( self._x_radius, self._y_radius, self._x_per_unit, self._y_per_unit)) def extract(self, env, obs): image = np.zeros([self._compress_width, self._compress_width, self._channel_num]) '''update status''' scout = env.unwrapped.scout() if self._target.in_range((scout.float_attr.pos_x, scout.float_attr.pos_y)): owners, neutrals, enemys = self.unit_dispatch(obs) channel_base = self.home_pos_channel(env, image, 0) channel_base = self.target_pos_channel(env, image, channel_base) channel_base = self.scout_attr_channel(env, image, channel_base) channel_base = self.nertral_attr_channel(neutrals, image, channel_base) channel_base = self.owner_attr_channel(owners, image, channel_base) channel_base = self.enemy_attr_channel(enemys, image, channel_base) #print('global_image, channel total number=', channel_base) #print('image=', image) return image def obs_space(self): low = np.zeros([self._compress_width, self._compress_width, self._channel_num]) high = np.ones([self._compress_width, self._compress_width, self._channel_num]) return Box(low, high) def home_pos_channel(self, env, image, channel_num): home = env.unwrapped.owner_base() i, j = self.pos_2_2d(home[0], home[1]) #print("fullgame home coordinate({}, {}), home={}".format(i, j, home)) image[i, j, channel_num] += 1 return channel_num + 1 def target_pos_channel(self, env, image, channel_num): target = env.unwrapped.enemy_base() i, j = self.pos_2_2d(target[0], target[1]) #print("fullgame target coordinate({}, {}), target={}".format(i, j, target)) image[i, j, channel_num] += 1 return channel_num + 1 def scout_attr_channel(self, env, image, channel_base): scout = env.unwrapped.scout() i, j = self.pos_2_2d(scout.float_attr.pos_x, scout.float_attr.pos_y) image[i, j, channel_base + 0] = 1 # scout in this position #print("fullgame scout coordinate({}, {}), scout=({},{})".format( # i, j, scout.float_attr.pos_x, scout.float_attr.pos_y)) return channel_base + 1 def nertral_attr_channel(self, neutrals, image, channel_base): resource_count = 0 for u in neutrals: i, j = self.pos_2_2d(u.float_attr.pos_x, u.float_attr.pos_y) if u.unit_type in sm.MINERAL_UNITS or u.unit_type in sm.VESPENE_UNITS: resource_count += 1 image[i, j, channel_base + 0] += (1.0 / MAX_UNIT_NUM) #print("nertral_attr:[{},{},{}]={} ".format( # i, j, channel_base, image[i, j, channel_base])) #print("***resource_count***,", resource_count) return channel_base + 1 def owner_attr_channel(self, owners, image, channel_base): for u in owners: i, j = self.pos_2_2d(u.float_attr.pos_x, u.float_attr.pos_y) image[i, j, channel_base] += (1.0 / MAX_UNIT_NUM) #print("owner_attr:[{},{},{}]={}".format( # i, j, channel_base, image[i, j, channel_base])) #print("***owner_count***,", len(owners)) return channel_base + 1 def enemy_attr_channel(self, enemys, image, channel_base): for u in enemys: i, j = self.pos_2_2d(u.float_attr.pos_x, u.float_attr.pos_y) #print('enemy coordinate={},{}'.format(i, j)) if u.unit_type in sm.COMBAT_AIR_UNITS: image[i, j, channel_base + 0] += (1.0 / MAX_UNIT_NUM) #print("enemy air=", image[i, j, channel_base + 0]) else: image[i, j, channel_base + 1] += (1.0 / MAX_UNIT_NUM) #print("enemy unit=", image[i, j, channel_base + 1]) #print("enemy_attr:[{},{},{}]={}".format( # i, j, channel_base, image[i, j, channel_base:channel_base+2])) #print("***enemy_count***,", len(enemys)) return channel_base + 2 def unit_dispatch(self, obs): units = obs.observation['units'] owners = [] neutrals = [] enemys = [] for u in units: if u.int_attr.alliance == sm.AllianceType.SELF.value: owners.append(u) elif u.int_attr.alliance == sm.AllianceType.NEUTRAL.value: neutrals.append(u) elif u.int_attr.alliance == sm.AllianceType.ENEMY.value: enemys.append(u) else: continue return owners, neutrals, enemys
class FullGameVecV1(VecFeature): def __init__(self, target_range): super(FullGameVecV1, self).__init__() self._base_num = 0 self._force_num = 0 self._other_num = 0 self._building_type_num = 0 self._target_range = target_range self._target = None self._unit_set = set([]) self._building_type_set = set([]) self._base_id_set = set([]) def reset(self, env): super(FullGameVecV1, self).reset(env) self._target = DestRange(env.unwrapped.enemy_base(), dest_range=self._target_range) self._base_num = 0 self._force_num = 0 self._other_num = 0 self._building_type_num = 0 self._unit_set = set([]) self._building_type_set = set([]) self._base_id_set = set([]) def obs_space(self): low = np.zeros(14) high = np.ones(14) return Box(low, high) def extract(self, env, obs): features = [] enemys = self._unit_dispatch(obs) features = self._normal_feature(features, env) features = self._status_feature(features, env) features = self._count_feature(features, enemys, env) return features def _normal_feature(self, features, env): scout = env.unwrapped.scout() scout_raw_pos = (scout.float_attr.pos_x, scout.float_attr.pos_y) home_pos = env.unwrapped.owner_base() enemy_pos = env.unwrapped.enemy_base() scout_pos = self._pos_transfer(scout_raw_pos[0], scout_raw_pos[1]) home_pos = self._pos_transfer(home_pos[0], home_pos[1]) enemy_pos = self._pos_transfer(enemy_pos[0], enemy_pos[1]) features.append(float(scout_pos[0]) / self._map_size[0]) features.append(float(scout_pos[1]) / self._map_size[1]) features.append( float(abs(home_pos[0] - scout_pos[0])) / self._map_size[0]) features.append( float(abs(home_pos[1] - scout_pos[1])) / self._map_size[1]) features.append( float(abs(enemy_pos[0] - scout_pos[0])) / self._map_size[0]) features.append( float(abs(enemy_pos[1] - scout_pos[1])) / self._map_size[1]) features.append(scout.float_attr.facing / MAX_RADIUS_NUM) features.append(scout.float_attr.health / scout.float_attr.health_max) features.append( float(env.unwrapped.step_number() / env.unwrapped.max_step_number())) return features def _status_feature(self, features, env): scout = env.unwrapped.scout() if self._target.in_range( (scout.float_attr.pos_x, scout.float_attr.pos_y)): features.append(float(1)) else: features.append(float(0)) return features def _count_feature(self, features, enemys, env): for u in enemys: if not self._check_view(env, u): continue if u.unit_type in sm.BASE_UNITS: bid = env.unwrapped.get_id_by_pos( (u.float_attr.pos_x, u.float_attr.pos_y)) #print('find_bid=', bid) if bid in self._base_id_set: pass else: self._base_num += 1 self._base_id_set.add(bid) elif u.unit_type in sm.BUILDING_UNITS: if u.unit_type in self._building_type_set: pass else: self._building_type_num += 1 self._building_type_set.add(u.unit_type) elif u.unit_type in sm.COMBAT_ATTACK_UNITS: if u.tag in self._unit_set: pass else: self._force_num += 1 self._unit_set.add(u.tag) else: if u.tag in self._unit_set: pass else: self._other_num += 1 self._unit_set.add(u.tag) features.append(float(self._base_num / MAX_BASE_NUM)) features.append(float(self._building_type_num / MAX_UNIT_NUM)) features.append(float(self._force_num / MAX_UNIT_NUM)) features.append(float(self._other_num / MAX_UNIT_NUM)) #print('FULLGAME_VEC base={},building={},force={},other={}'.format( # self._base_num, self._building_type_num, # self._force_num, self._other_num)) return features def _check_view(self, env, unit): scout = env.unwrapped.scout() dist = sm.calculate_distance(scout.float_attr.pos_x, scout.float_attr.pos_y, unit.float_attr.pos_x, unit.float_attr.pos_y) if dist <= MAX_VIEW_RANGE: return True else: return False def _unit_dispatch(self, obs): units = obs.observation['units'] enemys = [] for u in units: if u.int_attr.alliance == sm.AllianceType.ENEMY.value: enemys.append(u) else: continue return enemys