def compile(self): # note: for now, only weapons define the entity's action space # note: for now, assets that a given entity can hold a single weapon self.action_space = [] self.attack_action_space = [] self.patrol_action_space = [] self.attack_actions = [] self.patrol_actions = [] if len(self.weapons): # attack action map, constrained by the entity's weapon(s) attack_cells = coverage((10, 10), self.weapons[0]['weapon_range']) self.attack_action_space = [ 'attack_{}x{}'.format(x, y) for (x, y) in attack_cells ] self.attack_actions = list(range(0, len(attack_cells))) # patrol action map, constrained by the entity's properties patrol_cells = coverage((10, 10), self.properties['mobility']) self.patrol_action_space = [ 'patrol_{}x{}'.format(x, y) for (x, y) in patrol_cells ] self.patrol_actions = list( range(len(self.attack_actions), len(self.attack_actions) + len(patrol_cells))) self.action_space = self.attack_action_space + self.patrol_action_space self.n_actions = len(self.action_space)
def encode_objectives(objectives, minimap, detections, shape): xys = {} for obj in objectives: # if a single objective has multiple areas of interest if isinstance(obj.aoi, list): for aoi in obj.aoi: for (x, y) in coverage(aoi['xy'], aoi['radius'], shape): xys[(x, y)] = obj.obj_type if not isinstance(obj.aoi, list) and obj.aoi: xys = { (x, y): obj.obj_type for (x, y) in coverage(obj.aoi['xy'], obj.aoi['radius'], shape) } # only encode an aoi if it is not attached to an eoi that we have not detected if obj.eoi: for xy, obj_type in xys.items(): if xy in [ent.xy for ent in detections]: xys[xy] = obj_type for ((x, y), obj_type) in xys.items(): minimap[ global_features.index('{}_area_of_interest'.format(obj_type)), x, y] += 1 return minimap
def filter_objectives(objectives): xys = [] for obj in objectives: # if a single objective has multiple areas of interest if isinstance(obj.aoi, list): for aoi in obj.aoi: for xy in coverage(aoi['xy'], aoi['radius'], shape): xys += [xy] else: xys += [ xy for xy in coverage(obj.aoi['xy'], obj.aoi['radius'], shape) ] return xys
def __call__(self, entities, timer, *args, **kwargs): enemies = kwargs['enemies'] whites = [ ent.xy in coverage(self.aoi['xy'], self.aoi['radius']) for ent in entities.values() if ent.operational ] blacks = [ ent.xy in coverage(self.aoi['xy'], self.aoi['radius']) for ent in enemies.values() if ent.operational ] self.reward = len(whites) - len(blacks) return False
def __call__(self, entities, *args, **kwargs): if any([ ent.xy in coverage(self.aoi['xy'], self.aoi['radius']) for ent in entities.values() ]): self.reward += 1 return True return False
def observe_detections(self): self.white_detections, self.black_detections = [], [] for white in self.whites.values(): for black in self.blacks.values(): operational = white.operational and black.operational white_cells = coverage(white.xy, white.properties['visibility'], self.shape) black_cells = coverage(black.xy, black.properties['visibility'], self.shape) if black.xy in white_cells and operational: self.white_detections += [black] if white.xy in black_cells and operational: self.white_detections += [white] self.white_detections = set(self.white_detections) self.black_detections = set(self.black_detections)
def __call__(self, entities, *args, **kwargs): self.reward = 0 self.eoi = kwargs['enemies'] self.aoi = [{'xy':ent.xy, 'radius':1} for ent in self.eoi.values()] drones = [ent for ent in entities.values() if ent.entity_type == 'drone'] for xy in [target.xy for target in self.eoi.values()]: for drone in drones: if xy in coverage(drone.xy, drone.properties['visibility']): self.reward += 1 return False
def patrol(entity, action, terrain, verbose=False): idx = entity.patrol_actions.index(action) cells = coverage(entity.xy, entity.properties['mobility'], terrain[0].shape) try: cell = cells[idx] except: cell = entity.xy if not len(cells) else cells[0] return cell
def attack(entity, action, damage_map, verbose=False): idx = entity.attack_actions.index(action) weapon_model = entity.weapons[0] cells = coverage(entity.xy, weapon_model['weapon_range'], damage_map.shape) try: if len(cells) < action: ij = random.choice(cells) else: ij = cells[action] for (x, y) in coverage(ij, weapon_model['weapon_radius'], damage_map.shape): if weapon_model['weapon_accuracy'] < np.random.random(): damage_map[x, y] += weapon_model['weapon_power'] except: pass return damage_map
def __call__(self, entities, timer, *args, **kwargs): if any([ ent.xy in coverage(self.aoi['xy'], self.aoi['radius']) for ent in entities.values() if ent.operational ]): self.reward = 1 else: self.reward = 0 if self.reward > self.criterion: return True else: return False
def __call__(self, entities, *args, **kwargs): self.reward = 0 self.eoi = kwargs['enemies'] cells = [] for ent in self.eoi.values(): for xy in coverage(ent.xy, ent.properties['visibility']): cells.append(xy) for xy in [ ent.xy for ent in entities.values() if ent.entity_type not in ['drone'] ]: if xy in set(cells): self.reward -= 0.1 if self.reward / 10 == len([ ent for ent in entities.values() if ent.entity_type not in ['drone'] and ent.operational ]): return True return False
def observation(self, positive, negative=None): minimap = np.zeros((len(global_features), *self.shape)) minimap[global_features.index('land'), :] = self.land minimap[global_features.index('air'), :] = self.air minimap[global_features.index('sea'), :] = self.sea for ent in positive.values(): x, y = ent.xy[0], ent.xy[1] minimap[global_features.index(ent.entity_type), x, y] += 1 if ent.weapons: weapon_model = ent.weapons[0] minimap[global_features.index('weapon_power'), x, y] += weapon_model['weapon_power'] for xy in coverage(ent.xy, weapon_model['weapon_range'], self.shape): for (i, j) in coverage(xy, weapon_model['weapon_radius'], self.shape): minimap[global_features.index('weapon_radius'), i, j] += weapon_model['weapon_radius'] for (x, y) in coverage(ent.xy, weapon_model['weapon_range'], self.shape): minimap[global_features.index('weapon_range'), x, y] += weapon_model['weapon_range'] if ent.sensors: sensor_model = ent.sensors[0] minimap[global_features.index('sensor_coverage'), x, y] += sensor_model['sensor_coverage'] for (x, y) in coverage(ent.xy, sensor_model['sensor_range'], self.shape): minimap[global_features.index('sensor_range'), x, y] += weapon_model['sensor_range'] minimap[global_features.index('durability'), x, y] += ent.properties['durability'] for (x, y) in coverage(ent.xy, ent.properties['mobility'], self.shape): minimap[global_features.index('mobility'), x, y] += (1 - ent.properties['mobility']) for (x, y) in coverage(ent.xy, ent.properties['visibility'], self.shape): minimap[global_features.index('visibility'), x, y] += ent.properties['visibility'] if any([ent.id in self.blacks.keys() for ent in positive.values()]): dets, kills, casts = self.white_detections, self.white_casualties, self.black_casualties else: dets, kills, casts = self.black_detections, self.black_casualties, self.white_casualties minimap = encode_objectives(self.objectives, minimap, self.white_detections, self.shape) for ent in dets: x, y = ent.xy minimap[global_features.index(ent.entity_type + '_detections'), x, y] += 1 for ent in kills: x, y = ent.xy minimap[global_features.index('positive_casualties'), x, y] += 1 for ent in casts: x, y = ent.xy minimap[global_features.index('negative_casualties'), x, y] += 1 return minimap