def fitness(self, logical_swarm_pos, phys_swarm): #account for own health, enemy health/splash&anti air damage/ # upgrade this function... # revert this back to a regular one unit function and apply the pyswarm evaluate method cost = [] if self.known_enemy_units.exists: for logical_pos in logical_swarm_pos: cost.append(self.known_enemy_units.closest_distance_to(Point2(Pointlike((logical_pos[0], logical_pos[1]))))) else: for logical_pos in logical_swarm_pos: cost.append(1 / phys_swarm.center.distance2_to(Point2(Pointlike((logical_pos[0], logical_pos[1]))))) return np.array(cost)
def _find_creep_placement(self, target: Point2) -> Point2: nearest_spot = self.creep_map[np.sum( np.square(np.abs(self.creep_map - np.array([[target.x, target.y]]))), 1, ).argmin()] pos = Point2(Pointlike((nearest_spot[0], nearest_spot[1]))) return pos
def fitness(self, logical_swarm_pos, phys_swarm): #account for own health, enemy health/splash&anti air damage/ # upgrade this function... # revert this back to a regular one unit function and apply the pyswarm evaluate method cost = [] # the coefficients within can be optimized... if self.known_enemy_units.exists: for logical_pos in logical_swarm_pos: target_point = Point2(Pointlike((logical_pos[0], logical_pos[1]))) cost.append( \ self.known_enemy_units.closest_distance_to(target_point) + \ (5 * self.known_enemy_units.closer_than(10, target_point).amount - 5 * phys_swarm.closer_than(10, target_point).amount) \ ) else: for logical_pos in logical_swarm_pos: cost.append(40 / phys_swarm.center.distance2_to(Point2(Pointlike((logical_pos[0], logical_pos[1]))))) return np.array(cost)
def __init__(self): self.Chaining = False # If Chaining Grenades self.Spot = Pointlike((23, 23)) self.Destination = Point2(self.Spot) # Where we initially move to self.Bomb = Pointlike((20, 20)) self.Target = Point2(self.Bomb) # Where initial bomb lands # state self.Enemy_Units = () self.Available_Reapers = () self.Cooldown_Reapers = () self.cg = () # Control Groups self.SCV_counter = 0 # Base Building self.refinerys = 0 self.barracks_started = False self.made_workers_for_gas = False self.attack_groups = set() self.Ideal_Workers = False
async def move_unit(self, unit_to_move, direction): current_pos = unit_to_move.position target_destination = current_pos if direction == 0: target_destination = [current_pos.x, current_pos.y + 5] elif direction == 1: target_destination = [current_pos.x + 5, current_pos.y] elif direction == 2: target_destination = [current_pos.x, current_pos.y - 5] elif direction == 3: target_destination = [current_pos.x - 5, current_pos.y] self.action_buffer.append(unit_to_move.move(Point2(Pointlike(target_destination))))
def _find_closest_to_target(self, from_pos: Point2, grid: np.ndarray) -> Point2: try: nearest_spot = grid[np.sum( np.square(np.abs(grid - np.array([[from_pos.x, from_pos.y]]))), 1, ).argmin()] pos = Point2(Pointlike((nearest_spot[0], nearest_spot[1]))) return pos except ValueError: return from_pos.towards(self.bot.start_location, 1)
async def attack(self, phys_swarm): if phys_swarm.amount > 5: orders = [] # reinitialize swarm if needed if phys_swarm.amount != self.swarm_size: self.swarm_size = phys_swarm.amount self.phys_swarm_pos = [] for unit in phys_swarm: self.phys_swarm_pos.append( [unit.position.x, unit.position.y]) self.phys_swarm_pos = np.array(self.phys_swarm_pos) self.logical_swarm = P.create_swarm( n_particles=phys_swarm.amount, dimensions=2, options=self.my_options, bounds=([0, 0], [ self.game_info.map_size[0], self.game_info.map_size[1] ]), init_pos=self.phys_swarm_pos, clamp=(0, 5.6)) self.logical_swarm.current_cost = self.fitness( self.logical_swarm.position, phys_swarm) self.logical_swarm.pbest_cost = self.fitness( self.logical_swarm.pbest_pos, phys_swarm) self.logical_swarm.pbest_pos, self.logical_swarm.pbest_cost = P.compute_pbest( self.logical_swarm) if np.min(self.logical_swarm.pbest_cost ) < self.logical_swarm.best_cost: self.logical_swarm.best_pos, self.logical_swarm.best_cost = self.my_topology.compute_gbest( self.logical_swarm) self.logical_swarm.velocity = self.my_topology.compute_velocity( self.logical_swarm) self.logical_swarm.position = self.my_topology.compute_position( self.logical_swarm) # Extract positions from above and issue movement/attack orders # loop through np array compiling positions and appending them to orders list. # The mutas are still ignoring nearby enemies. for row, unit in zip(self.logical_swarm.position, phys_swarm): if self.known_enemy_units.closer_than(unit.radar_range, unit.position).exists: orders.append( unit.attack( self.known_enemy_units.closest_to(unit.position))) else: orders.append( unit.move(Point2(Pointlike((row[0], row[1]))))) await self.do_actions(orders)
async def attack(self, phys_swarm, iteration): if phys_swarm.amount > 10: orders = [] # reinitialize swarm if needed if phys_swarm.amount > self.swarm_size + 3 or iteration > self.iter_of_last_update + 75: self.swarm_size = phys_swarm.amount self.phys_swarm_pos = [] for unit in phys_swarm: self.phys_swarm_pos.append([unit.position.x, unit.position.y]) self.phys_swarm_pos = np.array(self.phys_swarm_pos) self.logical_swarm = P.create_swarm(n_particles=phys_swarm.amount, dimensions=2, options=self.my_options, bounds=([0,0], [self.game_info.map_size[0], self.game_info.map_size[1]]) , init_pos=self.phys_swarm_pos, clamp=(0,4.0)) self.iter_of_last_update = iteration self.logical_swarm.current_cost = self.fitness(self.logical_swarm.position, phys_swarm) self.logical_swarm.pbest_cost = self.fitness(self.logical_swarm.pbest_pos, phys_swarm) self.logical_swarm.pbest_pos, self.logical_swarm.pbest_cost = P.compute_pbest(self.logical_swarm) if np.min(self.logical_swarm.pbest_cost) < self.logical_swarm.best_cost: self.logical_swarm.best_pos, self.logical_swarm.best_cost = self.my_topology.compute_gbest(self.logical_swarm) self.logical_swarm.velocity = self.my_topology.compute_velocity(self.logical_swarm) self.logical_swarm.position = self.my_topology.compute_position(self.logical_swarm) # Extract positions from above and issue movement/attack orders # loop through np array compiling positions and appending them to orders list. wounded_units = phys_swarm.filter(lambda u: u.health_percentage <= .7) phys_swarm = phys_swarm.filter(lambda u: u.health_percentage > .7) for unit in wounded_units: unit.move(self.townhalls.first.position) # The mutas are still ignoring nearby enemies. for row, unit in zip(self.logical_swarm.position, phys_swarm): if self.known_enemy_units.closer_than(unit.radar_range, unit.position).exists: orders.append(unit.stop()) orders.append(unit.attack(self.known_enemy_units.closest_to(unit.position).position)) elif self.known_enemy_units.exists: orders.append(unit.attack(self.known_enemy_units.closest_to(Point2(Pointlike((row[0], row[1])))))) else: orders.append(unit.move(Point2(Pointlike((row[0], row[1]))))) await self.do_actions(orders)
async def attack(self, phys_swarm, iteration): if phys_swarm.amount > 10: orders = [] # I should be able to dynamically add and subtract particles from the swarm... should only init once at beginning... if # The business of adding/subrtracting from swarm should be done in on created/destroyed methods... # do a comprehension that deletes matches positions and alive units? # calcuate the current self.log_swarm.current_cost = self.fitness( self.log_swarm.position, phys_swarm ) self.log_swarm.pbest_cost = self.fitness( self.log_swarm.pbest_pos, phys_swarm ) self.log_swarm.pbest_pos, self.log_swarm.pbest_cost = P.compute_pbest( self.log_swarm ) # if np.min( self.log_swarm.pbest_cost ) < self.log_swarm.best_cost: self.log_swarm.best_pos, self.log_swarm.best_cost = self.my_topology.compute_gbest( self.log_swarm ) # self.logical_swarm.velocity = self.my_topology.compute_velocity( self.log_swarm ) self.logical_swarm.position = self.my_topology.compute_position( self.log_swarm ) #this should be parameterized as aggression... wounded_units = phys_swarm.filter(lambda u: u.health_percentage <= .7) for unit in wounded_units: unit.move(self.townhalls.first.position) phys_swarm = phys_swarm.filter(lambda u: u.health_percentage > .7) for row, unit in zip(self.logical_swarm.position, phys_swarm): orders.append(unit.attack(Point2(Pointlike((row[0], row[1]))))) # might need to get the nearest unit to do this... also check to make sure nearest unit not already assigned a task await self.do_actions(orders)
def away(this: Pointlike, from_this: Pointlike, this_much_more: float): distance_total = from_this.distance_to(this) + this_much_more return from_this.towards(this, distance_total)
async def test_positions(self): p1 = Pointlike((2.3, 2.7)) p2 = Point2((-5.3, -7.9)) p3 = Point3((-2.7, 5.4, 133.2)) # Testing Pointlike assert p1 == Pointlike((2.3, 2.7)) assert p1.rounded == Pointlike((2, 3)) assert p1.position == p1 assert p1.distance_to(Pointlike((-0.7, 6.7))) == 5 assert p1.closest([ Pointlike((2, 2)), Pointlike((-2, -2)) ]) == Pointlike((2, 2)) assert p1.furthest([ Pointlike((2, 2)), Pointlike((-2, -2)) ]) == Pointlike((-2, -2)) assert p1.offset(Pointlike((-1, -1))) == Pointlike((1.3, 1.7)) assert p1.offset(Pointlike((-1, 1))) == Pointlike((1.3, 3.7)) assert p1.towards(Pointlike((2.3, 50)), 5) == Pointlike((2.3, 7.7)) # testing backwards aswell assert p1.towards(Pointlike((2.3, 50)), -5) == Pointlike((2.3, -2.3)) # Testing Point2 assert p2.x == -5.3 assert p2.y == -7.9 assert p2.to2 == p2 assert p2.to3 == Point3((-5.3, -7.9, 0)) assert (p2.neighbors4 == { Point2((-5.3, -6.9)), Point2((-5.3, -8.9)), Point2((-4.3, -7.9)), Point2((-6.3, -7.9)), }) assert p2.neighbors8 == (p2.neighbors4 | { Point2((-4.3, -6.9)), Point2((-4.3, -8.9)), Point2((-6.3, -6.9)), Point2((-6.3, -8.9)), }) # Testing Point3 assert p3.z == 133.2 assert p3.to3 == p3
class TestPosition(unittest.TestCase): @classmethod def setUpClass(cls): pass @classmethod def tearDownClass(cls): pass def setUp(self): self.p = Pointlike((2.3, 2.7)) self.p2 = Point2((-5.3, -7.9)) self.p3 = Point3((-2.7, 5.4, 133.2)) def tearDown(self): pass def test_Pointlike(self): self.assertEqual(self.p, Pointlike((2.3, 2.7))) self.assertEqual(self.p.rounded, Pointlike((2, 3))) self.assertEqual(self.p.position, self.p) self.assertEqual(self.p.distance_to(Pointlike((-0.7, 6.7))), 5) self.assertEqual( self.p.closest([Pointlike((2, 2)), Pointlike((-2, -2))]), Pointlike((2, 2))) self.assertEqual( self.p.furthest([Pointlike((2, 2)), Pointlike((-2, -2))]), Pointlike((-2, -2))) self.assertEqual(self.p.offset(Pointlike((-1, -1))), Pointlike((1.3, 1.7))) self.assertEqual(self.p.offset(Pointlike((-1, 1))), Pointlike((1.3, 3.7))) self.assertEqual(self.p.towards(Pointlike((2.3, 50)), 5), Pointlike((2.3, 7.7))) # testing backwards aswell self.assertEqual(self.p.towards(Pointlike((2.3, 50)), -5), Pointlike((2.3, -2.3))) def test_Point2(self): self.assertEqual(self.p2.x, -5.3) self.assertEqual(self.p2.y, -7.9) self.assertEqual(self.p2.to2, self.p2) self.assertEqual(self.p2.to3, Point3((-5.3, -7.9, 0))) self.assertEqual( self.p2.neighbors4, { Point2((-5.3, -6.9)), Point2((-5.3, -8.9)), Point2((-4.3, -7.9)), Point2((-6.3, -7.9)), }) self.assertEqual( self.p2.neighbors8, self.p2.neighbors4 | { Point2((-4.3, -6.9)), Point2((-4.3, -8.9)), Point2((-6.3, -6.9)), Point2((-6.3, -8.9)), }) def test_Point3(self): self.assertEqual(self.p3.z, 133.2) self.assertEqual(self.p3.to3, self.p3)
def test_Pointlike(self): self.assertEqual(self.p, Pointlike((2.3, 2.7))) self.assertEqual(self.p.rounded, Pointlike((2, 3))) self.assertEqual(self.p.position, self.p) self.assertEqual(self.p.distance_to(Pointlike((-0.7, 6.7))), 5) self.assertEqual( self.p.closest([Pointlike((2, 2)), Pointlike((-2, -2))]), Pointlike((2, 2))) self.assertEqual( self.p.furthest([Pointlike((2, 2)), Pointlike((-2, -2))]), Pointlike((-2, -2))) self.assertEqual(self.p.offset(Pointlike((-1, -1))), Pointlike((1.3, 1.7))) self.assertEqual(self.p.offset(Pointlike((-1, 1))), Pointlike((1.3, 3.7))) self.assertEqual(self.p.towards(Pointlike((2.3, 50)), 5), Pointlike((2.3, 7.7))) # testing backwards aswell self.assertEqual(self.p.towards(Pointlike((2.3, 50)), -5), Pointlike((2.3, -2.3)))
def setUp(self): self.p = Pointlike((2.3, 2.7)) self.p2 = Point2((-5.3, -7.9)) self.p3 = Point3((-2.7, 5.4, 133.2))
async def on_step(self, iteration): if iteration == 0: if iteration == 0: await self.chat_send("(glhf)") #creates control groups of 14 reapers if self.units(REAPER).idle.amount > 14: cg = ControlGroup(self.units(REAPER).idle) self.attack_groups.add(cg) # trains workers for cc in self.units(UnitTypeId.COMMANDCENTER).ready.noqueue: if self.can_afford( SCV) and self.workers.amount < 20 and cc.noqueue: await self.do(cc.train(SCV)) cc = self.units(COMMANDCENTER).ready.first bobthebuilder = self.units(SCV)[0] #build supply depots if self.supply_left < 2: if self.can_afford( SUPPLYDEPOT) and self.already_pending(SUPPLYDEPOT) < 2: await self.build(SUPPLYDEPOT, near=cc.position.towards( self.game_info.map_center, 5)) #build barracks if self.units( BARRACKS ).amount < 1: # or (self.minerals > 400 and self.units(BARRACKS).amount < 5): if self.can_afford(BARRACKS): err = await self.build(BARRACKS, near=cc.position.towards( self.game_info.map_center, 5)) #train reapers elif self.units(BARRACKS).ready.exists and self.units( REFINERY).ready.exists and self.units(REAPER).amount < 1: barracks = self.units(BARRACKS).ready if self.can_afford(REAPER) and barracks.noqueue: await self.do(barracks.random.train(REAPER)) #build refinerys if self.refinerys < 2: if self.can_afford(REFINERY): worker = self.workers.random target = self.state.vespene_geyser.closest_to(worker.position) err = await self.do(bobthebuilder.build(REFINERY, target)) if not err: self.refinerys += 1 #workers in the mines/gas for a in self.units(REFINERY): if a.assigned_harvesters < a.ideal_harvesters: w = self.workers.closer_than(20, a) if w.exists: await self.do(w.random.gather(a)) #send out reapers if self.units(REAPER).amount > 0: for reaper in self.units(REAPER).idle: #randomize where bomb lands a bit x = self.Target.x - .5 y = self.Target.y - .5 rand = random.random() * 100 randx = (rand / 100) + x rand = random.random() * 100 randy = (rand / 100) + y lz = Pointlike((randx, randy)) boom = Point2(lz) #use grenade abilities = await self.get_available_abilities(reaper) if AbilityId.KD8CHARGE_KD8CHARGE in abilities: await self.do(reaper(KD8CHARGE_KD8CHARGE, boom))
def __init__(self): self.point = Pointlike((20,20)) self.nextpoint = Point2(self.point) #where we send our noobs self.workers = 12 self.noob = False #keep count of noobs
async def on_step(self, iteration): # State Available_Reapers = [] Cooldown_Reapers = [] Enemy_Units = [] for reaper in self.units(REAPER): abilities = await self.get_available_abilities(reaper) if AbilityId.KD8CHARGE_KD8CHARGE in abilities: Available_Reapers.append(reaper) else: Cooldown_Reapers.append(reaper) for enemy in self.known_enemy_units: if (enemy in self.prev_Enemy) == False and enemy.is_structure == False: Enemy_Units.append(enemy) current_state = [ Available_Reapers, Cooldown_Reapers, Enemy_Units, ] # Reward reward = 0 if self.prev_action != None: for bomber in Cooldown_Reapers: reward += 1000 for lazy in Available_Reapers: reward += -100 for enemy in Enemy_Units: reward += 100 self.qlearn.learn(str(self.prev_state), self.prev_action, reward, str(current_state)) # Choose action rl_action = self.qlearn.choose_action(str(current_state)) smart_action = smart_actions[rl_action] # Prep next step self.prev_score = reward self.prev_state = current_state self.prev_action = rl_action self.prev_Enemy = Enemy_Units # Actions if smart_action == ACTION_DO_NOTHING: # Run Away for reaper in self.units(REAPER): targetx = (random.randrange(0, 100))/20 targety = (random.randrange(0, 100))/20 home = Pointlike((24 + targetx, 24 + targety)) moveto = reaper.position await self.do(reaper.move(moveto)) if smart_action == ACTION_KD8_CHARGE: # default spot on the map targetx = (random.randrange(0, 100))/20 targety = (random.randrange(0, 100))/20 home = Pointlike((20 + targetx, 20 + targety)) moveto = Point2(home) # throw grenade at enemy if len(Available_Reapers) > 5 and len(Enemy_Units) > 0: for reaper in Available_Reapers: if reaper == self.units(REAPER).closest_to(Enemy_Units[0].position): bomb = Point3(Enemy_Units[0].position) await self.do(reaper(KD8CHARGE_KD8CHARGE, bomb)) else: await self.do(reaper.move(moveto)) else: for reaper in Available_Reapers: await self.do(reaper.move(moveto)) if iteration == 0: if iteration == 0: await self.chat_send("(glhf)") #creates control groups of 14 reapers if self.units(REAPER).idle.amount > 14: cg = ControlGroup(self.units(REAPER).idle) self.attack_groups.add(cg) # trains workers for cc in self.units(UnitTypeId.COMMANDCENTER).ready.noqueue: if self.can_afford(SCV) and self.workers.amount < 20 and cc.noqueue: await self.do(cc.train(SCV)) cc = self.units(COMMANDCENTER).ready.first bobthebuilder = self.units(SCV)[0] #build supply depots if self.supply_left < 2: if self.can_afford(SUPPLYDEPOT) and self.already_pending(SUPPLYDEPOT) < 2: await self.build(SUPPLYDEPOT, near=cc.position.towards(self.game_info.map_center, 5)) #build barracks if self.units(BARRACKS).amount < 3: # or (self.minerals > 400 and self.units(BARRACKS).amount < 5): if self.can_afford(BARRACKS): err = await self.build(BARRACKS, near=cc.position.towards(self.game_info.map_center, 5)) #train reapers elif self.units(BARRACKS).ready.exists and self.units(REAPER).amount < 28: barracks = self.units(BARRACKS).ready if self.can_afford(REAPER) and barracks.noqueue: await self.do(barracks.random.train(REAPER)) #build refinerys if self.refinerys < 2: if self.can_afford(REFINERY): worker = self.workers.random target = self.state.vespene_geyser.closest_to(worker.position) err = await self.do(bobthebuilder.build(REFINERY, target)) if not err: self.refinerys += 1 #workers in the mines/gas for a in self.units(REFINERY): if a.assigned_harvesters < a.ideal_harvesters: w = self.workers.closer_than(20, a) if w.exists: await self.do(w.random.gather(a))