def assign_to_quadrant(gc, unit, unit_loc): """ Assigns knight to a quadrant in need of help. """ quadrant_battles = variables.quadrant_battle_locs assigned_knights = variables.assigned_knights if variables.curr_planet == bc.Planet.Earth: diagonal = (variables.earth_diagonal) else: diagonal = (variables.mars_diagonal) best_quadrant = (None, None) best_coeff = -float('inf') for quadrant in quadrant_battles: q_info = quadrant_battles[quadrant] if q_info.target_loc is not None: coeff = q_info.urgency_coeff("knight") bfs_array = variables.bfs_array our_coords_val = Ranger.get_coord_value(unit_loc) target_coords_val = Ranger.get_coord_value(q_info.target_loc) if bfs_array[our_coords_val, target_coords_val] != float('inf'): distance = bfs_array[our_coords_val, target_coords_val] coeff += 3 * (1 - distance / diagonal) if coeff > best_coeff: best_quadrant = quadrant best_coeff = coeff if best_coeff > 0: assigned_knights[unit.id] = quadrant_battles[best_quadrant].target_loc return True, assigned_knights[unit.id] return False, None
def assign_to_quadrant(gc, unit, unit_loc): """ Assigns knight to a quadrant in need of help. """ quadrant_battles = variables.quadrant_battle_locs assigned_healers = variables.assigned_healers best_quadrant = (None, None) best_coeff = -float('inf') for quadrant in quadrant_battles: q_info = quadrant_battles[quadrant] coeff = q_info.urgency_coeff("healer") # distance = ADD DISTANCE COEFF TOO if coeff > best_coeff and q_info.healer_loc is not None: bfs_array = variables.bfs_array our_coords_val = Ranger.get_coord_value(unit_loc) target_coords_val = Ranger.get_coord_value(q_info.healer_loc) if bfs_array[our_coords_val, target_coords_val] != float('inf'): best_quadrant = quadrant best_coeff = coeff if best_coeff > 0: assigned_healers[unit.id] = quadrant_battles[best_quadrant].healer_loc quadrant_battles[best_quadrant].assigned_healers.add(unit.id) return True, assigned_healers[unit.id] return False, None
def is_accessible(unit_loc, target_loc): bfs_array = variables.bfs_array our_coords_val = Ranger.get_coord_value(unit_loc) target_coords_val = Ranger.get_coord_value(target_loc) if bfs_array[our_coords_val, target_coords_val] != float('inf'): return True return False
def go_to_mars_sense(gc, unit, battle_locs, location, enemies, direction_to_coord, bfs_array, targeting_units, rocket_locs): # print('GOING TO MARS') signals = {} dir = None attack = None blink = None closest_enemy = None move_then_attack = False visible_enemies = False if len(enemies) > 0: visible_enemies = True attack = Ranger.get_attack(gc, unit, location, targeting_units) start_coords = (location.x, location.y) # # rocket was launched if unit.id not in variables.which_rocket or variables.which_rocket[ unit.id][1] not in variables.rocket_locs: variables.mage_roles["go_to_mars"].remove(unit.id) return dir, attack, blink, move_then_attack, visible_enemies, closest_enemy, signals target_loc = variables.which_rocket[unit.id][0] # # rocket was destroyed if not gc.has_unit_at_location(target_loc): variables.mage_roles["go_to_mars"].remove(unit.id) return dir, attack, blink, move_then_attack, visible_enemies, closest_enemy, signals # print(unit.id) # print('MY LOCATION:', start_coords) # print('GOING TO:', target_loc) if max(abs(target_loc.x - start_coords[0]), abs(target_loc.y - start_coords[1])) == 1: rocket = gc.sense_unit_at_location(target_loc) if gc.can_load(rocket.id, unit.id): gc.load(rocket.id, unit.id) else: target_coords = (target_loc.x, target_loc.y) start_coords_val = Ranger.get_coord_value(start_coords) target_coords_val = Ranger.get_coord_value(target_coords) # target_coords_thirds = (int(target_loc.x / bfs_fineness), int(target_loc.y / bfs_fineness)) if bfs_array[start_coords_val, target_coords_val] != float('inf'): best_dirs = Ranger.use_dist_bfs(start_coords, target_coords, bfs_array) choice_of_dir = random.choice(best_dirs) shape = direction_to_coord[choice_of_dir] options = sense_util.get_best_option(shape) for option in options: if gc.can_move(unit.id, option): dir = option break # print(dir) return dir, attack, blink, move_then_attack, visible_enemies, closest_enemy, signals
def mage_sense(gc, unit, battle_locs, queued_paths): dir = None attack = None blink = None move_then_attack = False visible_enemies = False location = unit.location.map_location() enemies = gc.sense_nearby_units_by_team(location, unit.vision_range, sense_util.enemy_team(gc)) if len(enemies) > 0: if unit.id in queued_paths: del queued_paths[unit.id] visible_enemies = True sorted_enemies = sorted(enemies, key=lambda x: x.location.map_location(). distance_squared_to(location)) closest_enemy = ranger.closest_among_ungarrisoned(sorted_enemies) print('closest enemy:', closest_enemy) attack = ranger.get_attack(gc, unit, location) print(attack) if attack is not None: print('found it here') if closest_enemy is not None: if (ranger.exists_bad_enemy(enemies) and (closest_enemy.location.map_location().distance_squared_to( location))**(0.5) + 2 < unit.attack_range()** (0.5)) or not gc.can_attack(unit.id, attack.id): dir = sense_util.best_available_direction( gc, unit, enemies) else: if gc.is_move_ready(unit.id): if closest_enemy is not None: dir = ranger.optimal_direction_towards( gc, unit, location, closest_enemy.location.map_location()) next_turn_loc = location.add(dir) attack = ranger.get_attack(gc, unit, next_turn_loc) if attack is not None: move_then_attack = True else: dir = ranger.get_explore_dir(gc, unit) else: if unit.id in queued_paths: if location != queued_paths[unit.id]: dir = ranger.optimal_direction_towards(gc, unit, location, queued_paths[unit.id]) return dir, attack, blink, move_then_attack, visible_enemies else: del queued_paths[unit.id] if len(battle_locs) > 0: dir, target = ranger.go_to_battle(gc, unit, battle_locs) queued_paths[unit.id] = target else: dir = ranger.get_explore_dir(gc, unit) return dir, attack, blink, move_then_attack, visible_enemies
def is_accessible_from_init_loc(self, coords): """ Determines if location 'coords' is accessible from any of our initial locations. """ accessible = False if variables.curr_planet == bc.Planet.Earth: for init_loc in variables.our_init_locs: bfs_array = variables.bfs_array our_coords_val = Ranger.get_coord_value( (init_loc.x, init_loc.y)) target_coords_val = Ranger.get_coord_value(coords) if bfs_array[our_coords_val, target_coords_val] != float('inf'): accessible = True else: accessible = True return accessible
def try_move_smartly(unit, map_loc1, map_loc2): if variables.gc.is_move_ready(unit.id): our_coords = map_loc1 target_coords = map_loc2 bfs_array = variables.bfs_array our_coords_val = Ranger.get_coord_value(our_coords) target_coords_val = Ranger.get_coord_value(target_coords) if bfs_array[our_coords_val, target_coords_val]!=float('inf'): best_dirs = Ranger.use_dist_bfs(our_coords, target_coords, bfs_array) choice_of_dir = random.choice(best_dirs) shape = variables.direction_to_coord[choice_of_dir] options = sense_util.get_best_option(shape) for option in options: if variables.gc.can_move(unit.id, option): variables.gc.move_robot(unit.id, option) add_new_location(unit.id, our_coords, option) break
def update_healer_ideal_loc(self): if variables.curr_planet == bc.Planet.Earth: passable_locations = variables.passable_locations_earth else: passable_locations = variables.passable_locations_mars neighbor_quadrants = self.get_neighboring_quadrants() enemies = set() most_enemies = 0 worst_quadrant = None for quadrant in neighbor_quadrants: if quadrant in variables.quadrant_battle_locs: q_enemies = variables.quadrant_battle_locs[quadrant].enemies enemies.update(q_enemies) if len(q_enemies) > most_enemies: most_enemies = len(q_enemies) worst_quadrant = quadrant if len(enemies) == 0: return worst_middle = variables.quadrant_battle_locs[worst_quadrant].middle furthest_away = sorted( list(self.quadrant_locs), key=lambda x: sense_util.distance_squared_between_coords( x, worst_middle), reverse=True) for loc in furthest_away: accessible = False if variables.curr_planet == bc.Planet.Earth: for init_loc in variables.our_init_locs: bfs_array = variables.bfs_array our_coords_val = Ranger.get_coord_value( (init_loc.x, init_loc.y)) target_coords_val = Ranger.get_coord_value(loc) if bfs_array[our_coords_val, target_coords_val] != float('inf'): accessible = True else: accessible = True if passable_locations[loc] and accessible: self.healer_loc = loc break
def get_attack(gc, unit, location, targeting_units, priority = knight_unit_priority): enemy_team = variables.enemy_team vuln_enemies = gc.sense_nearby_units_by_team(location, unit.attack_range(), enemy_team) if len(vuln_enemies)==0: return None #return vuln_enemies[0] best = None lowest_health = float('inf') for enemy in vuln_enemies: if enemy.id in targeting_units: if enemy.unit_type == variables.unit_types["knight"]: mult = 30 - enemy.knight_defense() else: mult = 30 remaining_health = enemy.health - targeting_units[enemy.id] * mult if remaining_health > 0 and remaining_health < lowest_health: best = enemy lowest_health = remaining_health if best is not None: return best return max(vuln_enemies, key=lambda x: Ranger.coefficient_computation(gc, unit, x, x.location.map_location(), location))
def timestep(unit): # last check to make sure the right unit type is running this if unit.unit_type != bc.UnitType.Healer: return # print('HEALER ID: ', unit.id) gc = variables.gc composition = variables.info direction_to_coord = variables.direction_to_coord bfs_array = variables.bfs_array enemy_team = variables.enemy_team my_team = variables.my_team assigned_healers = variables.assigned_healers ## healer id: (cluster, best_healer_loc) assigned_overcharge = variables.assigned_overcharge overcharge_targets = variables.overcharge_targets quadrant_battles = variables.quadrant_battle_locs if variables.curr_planet == bc.Planet.Earth: quadrant_size = variables.earth_quadrant_size else: quadrant_size = variables.mars_quadrant_size unit_locations = variables.unit_locations best_dir = None best_loc = None best_heal_target = None best_overcharge_target = None heal = False overcharge = False location = unit.location if location.is_on_map(): #print(location.map_location()) ## Add new ones to unit_locations, else just get the location if unit.id not in unit_locations: loc = unit.location.map_location() unit_locations[unit.id] = (loc.x, loc.y) f_f_quad = (int(loc.x / quadrant_size), int(loc.y / quadrant_size)) quadrant_battles[f_f_quad].add_ally(unit.id, "healer") unit_loc = unit_locations[unit.id] ## Assign role if unit.id not in assigned_overcharge and unit.id not in assigned_healers: overcharge_to_total = 1 total = len(assigned_healers) + len(assigned_overcharge) if total > 0: overcharge_to_total = len(assigned_overcharge) / total # Assign to overcharge if there are targets and ratio is good if variables.research.get_level( variables.unit_types["healer"] ) == 3 and overcharge_to_total < 0.2 and len( overcharge_targets) > 0: best_overcharge_target = gc.unit(overcharge_targets.pop()) assigned_overcharge[unit.id] = best_overcharge_target best_heal_target = get_best_target(gc, unit, unit_loc, my_team) if best_heal_target is not None: heal = True assigned, best_loc = assign_to_quadrant(gc, unit, unit_loc) # print('assigned? ', assigned) # print('assigned loc: ', best_loc) if not assigned: nearby = gc.sense_nearby_units_by_team( bc.MapLocation(variables.curr_planet, unit_loc[0], unit_loc[1]), 8, variables.my_team) best_dir = sense_util.best_available_direction( gc, unit, nearby) ## Overcharge if unit.id in assigned_overcharge: ally = assigned_overcharge[unit.id] if gc.can_overcharge(unit.id, ally.id): overcharge = True best_overcharge_target = ally if best_heal_target is None: best_heal_target = get_best_target(gc, unit, unit_loc, my_team) if best_heal_target is not None: heal = True ## Movement # If sees enemies close enough then tries to move away from them loc = bc.MapLocation(variables.curr_planet, unit_loc[0], unit_loc[1]) enemies = gc.sense_nearby_units_by_team(loc, unit.vision_range, enemy_team) if len(enemies) > 0: enemies = sorted(enemies, key=lambda x: x.location.map_location(). distance_squared_to(loc)) enemy_loc = enemies[0].location.map_location() best_dir = dir_away_from_enemy(gc, unit, loc, enemy_loc) elif variables.curr_round > 650: best_dir = Ranger.move_to_rocket(gc, unit, loc, variables.direction_to_coord, variables.bfs_array) # Otherwise, goes to locations in need of healers else: if unit.id in assigned_overcharge: ally = assigned_overcharge[unit.id] best_loc_map = ally.location.map_location() best_loc = (best_loc_map.x, best_loc_map.y) elif unit.id in assigned_healers: best_loc = assigned_healers[unit.id][1] ## Do shit #print(best_dir) #print(best_loc) if best_overcharge_target is not None: if overcharge and gc.is_overcharge_ready(unit.id): gc.overcharge(unit.id, best_overcharge_target.id) overcharged_unit = gc.unit(best_overcharge_target.id) if overcharged_unit.unit_type == variables.unit_types[ "ranger"]: Ranger.timestep(overcharged_unit) if best_heal_target is not None: if heal and gc.is_heal_ready(unit.id) and gc.can_heal( unit.id, best_heal_target.id): gc.heal(unit.id, best_heal_target.id) if best_dir is not None and gc.is_move_ready(unit.id) and gc.can_move( unit.id, best_dir): gc.move_robot(unit.id, best_dir) add_new_location(unit.id, unit_loc, best_dir) elif best_loc is not None and gc.is_move_ready( unit.id) and unit_loc != best_loc: try_move_smartly(unit, unit_loc, best_loc)
try: worker.timestep(gc, unit, info, karbonite_locations, blueprinting_queue, blueprinting_assignment, building_assignment, current_worker_roles) except Exception as e: print('Error:', e) # use this to show where the error was traceback.print_exc() elif unit.unit_type == bc.UnitType.Knight: knight.timestep(gc, unit, info, knight_to_cluster, seen_knights_ids, KNIGHT_CLUSTER_MIN, constants) elif unit.unit_type == bc.UnitType.Ranger: ranger.timestep(gc, unit, info, last_turn_battle_locs, next_turn_battle_locs, queued_paths, ranger_roles, constants, direction_to_coord, precomputed_bfs) elif unit.unit_type == bc.UnitType.Mage: mage.timestep(gc, unit, info, last_turn_battle_locs, next_turn_battle_locs, queued_paths) elif unit.unit_type == bc.UnitType.Healer: healer.timestep(gc, unit, info, last_turn_battle_locs, constants) elif unit.unit_type == bc.UnitType.Factory: factory.timestep(gc, unit, info, building_assignment, last_turn_battle_locs, constants, mining_rate=3 *
def mage_sense(gc, unit, battle_locs, mage_roles, location, direction_to_coord, bfs_array, targeting_units, rocket_locs): enemies = gc.sense_nearby_units_by_team(location, unit.vision_range, variables.enemy_team) if unit.id in mage_roles["go_to_mars"]: return go_to_mars_sense(gc, unit, battle_locs, location, enemies, direction_to_coord, bfs_array, targeting_units, rocket_locs) signals = {} dir = None attack = None blink = None closest_enemy = None move_then_attack = False visible_enemies = False start_time = time.time() # if variables.print_count < 10: # print("Sensing nearby units:", time.time() - start_time) if len(enemies) > 0: visible_enemies = True start_time = time.time() closest_enemy = None closest_dist = float('inf') for enemy in enemies: loc = enemy.location if loc.is_on_map(): dist = sense_util.distance_squared_between_maplocs( loc.map_location(), location) if dist < closest_dist: closest_dist = dist closest_enemy = enemy # if variables.print_count < 10: # print("Getting closest enemy:", time.time() - start_time) # sorted_enemies = sorted(enemies, key=lambda x: x.location.map_location().distance_squared_to(location)) # closest_enemy = closest_among_ungarrisoned(sorted_enemies) start_time = time.time() attack = Ranger.get_attack(gc, unit, location, targeting_units) # if variables.print_count < 10: # print("Getting attack:", time.time() - start_time) if attack is not None: if closest_enemy is not None: start_time = time.time() if Ranger.check_radius_squares_factories(gc, location): dir = Ranger.optimal_direction_towards( gc, unit, location, closest_enemy.location.map_location()) elif (Ranger.exists_bad_enemy(closest_enemy) ) or not gc.can_attack(unit.id, closest_enemy.id): # if variables.print_count < 10: # print("Checking if condition:", time.time() - start_time) start_time = time.time() dir = sense_util.best_available_direction( gc, unit, [closest_enemy]) # if variables.print_count < 10: # print("Getting best available direction:", time.time() - start_time) # and (closest_enemy.location.map_location().distance_squared_to(location)) ** ( # 0.5) + 2 < unit.attack_range() ** (0.5)) or not gc.can_attack(unit.id, attack.id): else: if gc.is_move_ready(unit.id): if closest_enemy is not None: dir = Ranger.optimal_direction_towards( gc, unit, location, closest_enemy.location.map_location()) next_turn_loc = location.add(dir) attack = Ranger.get_attack(gc, unit, next_turn_loc, targeting_units) if attack is not None: move_then_attack = True else: dir = Ranger.run_towards_init_loc_new( gc, unit, location, direction_to_coord) # if variables.print_count < 10: # print("Getting direction:", time.time() - start_time) else: # if there are no enemies in sight, check if there is an ongoing battle. If so, go there. if len(rocket_locs) > 0 and gc.round( ) > 660 and variables.curr_planet == bc.Planet.Earth: dir = Ranger.move_to_rocket(gc, unit, location, direction_to_coord, bfs_array) if dir is not None: return dir, attack, blink, move_then_attack, visible_enemies, closest_enemy, signals if len(battle_locs) > 0: # print('IS GOING TO BATTLE') dir = Ranger.go_to_battle_new(gc, unit, battle_locs, location, direction_to_coord) # queued_paths[unit.id] = target else: # dir = move_away(gc, unit, battle_locs) if variables.curr_planet == bc.Planet.Earth: # print('IS RUNNING TOWARDS INIT LOC') dir = Ranger.run_towards_init_loc_new(gc, unit, location, direction_to_coord) else: # print('EXPLORING') dir = Ranger.get_explore_dir(gc, unit, location) # if variables.print_count < 10: # print("regular movement:", time.time() - start_time) return dir, attack, blink, move_then_attack, visible_enemies, closest_enemy, signals
def timestep(unit): # last check to make sure the right unit type is running this if unit.unit_type != bc.UnitType.Knight: # prob should return some kind of error return gc = variables.gc assigned_knights = variables.assigned_knights quadrant_battles = variables.quadrant_battle_locs unit_locations = variables.unit_locations info = variables.info my_team = variables.my_team enemy_team = variables.enemy_team directions = variables.directions best_loc = None ## (x,y) best_dir = None best_target = None location = unit.location if variables.curr_planet == bc.Planet.Earth: quadrant_size = variables.earth_quadrant_size else: quadrant_size = variables.mars_quadrant_size if location.is_on_map(): if unit.id not in unit_locations: loc = unit.location.map_location() unit_locations[unit.id] = (loc.x, loc.y) f_f_quad = (int(loc.x / quadrant_size), int(loc.y / quadrant_size)) quadrant_battles[f_f_quad].add_ally(unit.id, "knight") variables.knight_attacks[unit.id] = 0 unit_loc = unit_locations[unit.id] ## Movement # If new knight assign to location if unit.id not in assigned_knights: assigned, best_loc = assign_to_quadrant(gc, unit, unit_loc) if not assigned: unit_loc_map = bc.MapLocation(variables.curr_planet, unit_loc[0], unit_loc[1]) best_dir = Ranger.run_towards_init_loc_new( gc, unit, unit_loc_map, variables.direction_to_coord) #nearby = gc.sense_nearby_units_by_team(bc.MapLocation(variables.curr_planet, unit_loc[0], unit_loc[1]), 8, variables.my_team) #best_dir = sense_util.best_available_direction(gc,unit,nearby) else: best_loc = assigned_knights[unit.id] ## Attack based on if in quadrant if best_loc is not None: curr_quadrant = (int(unit_loc[0] / quadrant_size), int(unit_loc[1] / quadrant_size)) best_loc_quadrant = (int(best_loc[0] / quadrant_size), int(best_loc[1] / quadrant_size)) ## If in best quadrant already, then get best_loc towards the target if curr_quadrant == best_loc_quadrant: best_target, best_loc = get_best_target_in_quadrant( gc, unit, unit_loc, knight_unit_priority) else: best_target = get_best_target(gc, unit, unit_loc, knight_unit_priority) ## Do shit # Attack if best_target is not None and gc.can_attack( unit.id, best_target.id ): # checked if ready to attack in get best target gc.attack(unit.id, best_target.id) variables.knight_attacks[unit.id] += 1 # Move if best_loc is not None and gc.is_move_ready( unit.id) and unit_loc != best_loc: try_move_smartly(unit, unit_loc, best_loc) elif best_dir is not None and gc.is_move_ready( unit.id) and gc.can_move(unit.id, best_dir): gc.move_robot(unit.id, best_dir) add_new_location(unit.id, unit_loc, best_dir)
def update_variables(): gc = variables.gc ## **************************************** GENERAL **************************************** ## ## Constants variables.curr_round = gc.round() variables.num_enemies = 0 variables.print_count = 0 variables.research = gc.research_info() ## Battle locations variables.last_turn_battle_locs = variables.next_turn_battle_locs.copy() variables.next_turn_battle_locs = {} if variables.curr_round % 3 == 0: variables.update_quadrant_healer_loc = True else: variables.update_quadrant_healer_loc = False # variables.quadrant_battle_locs = {} ## Units variables.my_units = gc.my_units() variables.my_unit_ids = set([unit.id for unit in variables.my_units]) variables.units = gc.units() num_workers= num_knights=num_rangers= num_mages= num_healers= num_factory= num_rocket = 0 if variables.ranged_enemies >= 5: variables.ranged_enemies = 5 else: variables.ranged_enemies = 0 if variables.switch_to_rangers: current = gc.research_info() if current.get_level(variables.unit_types["knight"]) < 2: gc.reset_research() if variables.curr_planet == bc.Planet.Earth and len(variables.dists) == 0: gc.queue_research(bc.UnitType.Rocket) if current.get_level(variables.unit_types["worker"]) != 1: gc.queue_research(bc.UnitType.Worker) if current.get_level(variables.unit_types["ranger"]) != 1: gc.queue_research(bc.UnitType.Ranger) # 25: 50 gc.queue_research(bc.UnitType.Healer) # 25: 75 if current.get_level(variables.unit_types["rocket"]) != 1: gc.queue_research(bc.UnitType.Rocket) # 50: 125 gc.queue_research(bc.UnitType.Healer) # 100: 225 gc.queue_research(bc.UnitType.Healer) # 100: 325 gc.queue_research(bc.UnitType.Ranger) # 100: 425 gc.queue_research(bc.UnitType.Ranger) # 200: 625 gc.queue_research(bc.UnitType.Worker) # 75: 700 variables.switch_to_rangers = False # Update which ally unit id's are still alive & deaths per quadrant # start_time = time.time() update_quadrants() # Updates enemies in quadrant & resets num dead allies # print('update quadrants time: ', time.time()-start_time) if variables.curr_planet == bc.Planet.Earth: quadrant_size = variables.earth_quadrant_size else: quadrant_size = variables.mars_quadrant_size remove = set() for unit_id in variables.unit_locations: if unit_id not in variables.my_unit_ids: remove.add(unit_id) for unit_id in remove: loc = variables.unit_locations[unit_id] del variables.unit_locations[unit_id] f_f_quad = (int(loc[0] / quadrant_size), int(loc[1] / quadrant_size)) variables.quadrant_battle_locs[f_f_quad].remove_ally(unit_id) # Update % health of fighting allies in quadrant for quadrant in variables.quadrant_battle_locs: q_info = variables.quadrant_battle_locs[quadrant] q_info.update_ally_health_coefficient(gc) # Something something enemies for poss_enemy in variables.units: if poss_enemy.team != variables.my_team and poss_enemy.unit_type in variables.attacker: variables.num_enemies += 1 # Update num of ally units of each type unit_types = variables.unit_types variables.producing = [0, 0, 0, 0, 0] variables.in_order_units = [] workers = [] rangers = [] knights = [] mages = [] healers = [] factories = [] rockets = [] for unit in variables.my_units: if unit.unit_type == unit_types["worker"]: num_workers+=1 workers.append(unit) elif unit.unit_type == unit_types["knight"]: num_knights+=1 rangers.append(unit) elif unit.unit_type == unit_types["ranger"]: num_rangers+=1 knights.append(unit) elif unit.unit_type == unit_types["mage"]: num_mages+=1 mages.append(unit) elif unit.unit_type == unit_types["healer"]: num_healers+=1 healers.append(unit) elif unit.unit_type == unit_types["factory"]: num_factory+=1 factories.append(unit) if unit.is_factory_producing(): type = unit.factory_unit_type() if type == variables.unit_types["worker"]: variables.producing[0]+=1 elif type == variables.unit_types["knight"]: variables.producing[1]+=1 elif type == variables.unit_types["ranger"]: variables.producing[2]+=1 elif type == variables.unit_types["mage"]: variables.producing[3]+=1 else: variables.producing[4]+=1 elif unit.unit_type == unit_types["rocket"]: num_rocket+=1 rockets.append(unit) variables.info = [num_workers, num_knights, num_rangers, num_mages, num_healers, num_factory, num_rocket] variables.in_order_units.extend(rangers) variables.in_order_units.extend(workers) variables.in_order_units.extend(knights) variables.in_order_units.extend(mages) variables.in_order_units.extend(healers) variables.in_order_units.extend(factories) variables.in_order_units.extend(rockets) ## **************************************** UNITS **************************************** ## ## Worker variables.my_karbonite = gc.karbonite() ## Income variables.worker_harvest_amount = 0 variables.past_karbonite_gain = variables.current_karbonite_gain + max(0,10 - int(variables.my_karbonite/40)) variables.current_karbonite_gain = 0 # reset counter if not worker.check_if_saviour_died(): variables.saviour_worker_id = None variables.saviour_worker = False variables.saviour_blueprinted = False variables.saviour_blueprinted_id = None variables.num_unsuccessful_savior = 0 variables.saviour_time_between = 0 # start_time = time.time() worker.designate_roles() # print("designating roles time: ",time.time() - start_time) ## Rangers variables.targeting_units = {} ranger.update_rangers() ## Knights knight.update_battles() ## Healers healer.update_healers() ## Rockets rocket.update_rockets() ## Factories factory.evaluate_stockpile()
def timestep(unit): # last check to make sure the right unit type is running this if unit.unit_type != bc.UnitType.Mage: # prob should return some kind of error return # start_time = time.time() gc = variables.gc mage_roles = variables.mage_roles info = variables.info next_turn_battle_locs = variables.next_turn_battle_locs if unit.id in mage_roles["go_to_mars"] and info[6] == 0: mage_roles["go_to_mars"].remove(unit.id) if unit.id not in mage_roles["fighter"]: mage_roles["fighter"].append(unit.id) # if variables.print_count<10: # print("Preprocessing:", time.time()-start_time) location = unit.location my_team = variables.my_team targeting_units = variables.targeting_units quadrant_battles = variables.quadrant_battle_locs if variables.curr_planet == bc.Planet.Earth: quadrant_size = variables.earth_quadrant_size else: quadrant_size = variables.mars_quadrant_size if location.is_on_map(): ## Add new ones to unit_locations, else just get the location if unit.id not in variables.unit_locations: loc = unit.location.map_location() variables.unit_locations[unit.id] = (loc.x, loc.y) f_f_quad = (int(loc.x / quadrant_size), int(loc.y / quadrant_size)) quadrant_battles[f_f_quad].add_ally(unit.id, "mage") # start_time = time.time() map_loc = location.map_location() if variables.curr_planet == bc.Planet.Earth and len(mage_roles["go_to_mars"]) < 14 and unit.id not in \ mage_roles["go_to_mars"] and unit.id in mage_roles["fighter"]: for rocket in variables.rocket_locs: target_loc = variables.rocket_locs[rocket] if sense_util.distance_squared_between_maplocs( map_loc, target_loc) < 150: variables.which_rocket[unit.id] = (target_loc, rocket) mage_roles["go_to_mars"].append(unit.id) mage_roles["fighter"].remove(unit.id) break # if variables.print_count < 10: # print("Preprocessing inside:", time.time() - start_time) # start_time = time.time() dir, attack_target, snipe, move_then_attack, visible_enemies, closest_enemy, signals = mage_sense( gc, unit, variables.last_turn_battle_locs, ranger_roles, map_loc, variables.direction_to_coord, variables.bfs_array, targeting_units, variables.rocket_locs) # print("middlepart",time.time() - start_coord) # if variables.print_count < 10: # print("Sensing:", time.time() - start_time) # start_time = time.time() if visible_enemies and closest_enemy is not None: enemy_loc = closest_enemy.location.map_location() f_f_quad = (int(enemy_loc.x / 5), int(enemy_loc.y / 5)) if f_f_quad not in next_turn_battle_locs: next_turn_battle_locs[f_f_quad] = (map_loc, 1) else: next_turn_battle_locs[f_f_quad] = ( next_turn_battle_locs[f_f_quad][0], next_turn_battle_locs[f_f_quad][1] + 1) if move_then_attack: if dir != None and gc.is_move_ready(unit.id) and gc.can_move( unit.id, dir): gc.move_robot(unit.id, dir) ## CHANGE LOC IN NEW DATA STRUCTURE Ranger.add_new_location(unit.id, (map_loc.x, map_loc.y), dir) if attack_target is not None and gc.is_attack_ready( unit.id) and gc.can_attack(unit.id, attack_target.id): if attack_target.id not in targeting_units: targeting_units[attack_target.id] = 1 else: targeting_units[attack_target.id] += 1 gc.attack(unit.id, attack_target.id) else: if attack_target is not None and gc.is_attack_ready( unit.id) and gc.can_attack(unit.id, attack_target.id): if attack_target.id not in targeting_units: targeting_units[attack_target.id] = 1 else: targeting_units[attack_target.id] += 1 gc.attack(unit.id, attack_target.id) if dir != None and gc.is_move_ready(unit.id) and gc.can_move( unit.id, dir): gc.move_robot(unit.id, dir) ## CHANGE LOC IN NEW DATA STRUCTURE Ranger.add_new_location(unit.id, (map_loc.x, map_loc.y), dir) """
start_time = time.time() worker.timestep(unit) time_workers += (time.time() - start_time) except Exception as e: print('Error:', e) # use this to show where the error was traceback.print_exc() elif unit.unit_type == unit_types["knight"]: #start_time = time.time() knight.timestep(unit) #time_knights+=(time.time()-start_time) elif unit.unit_type == unit_types["ranger"]: try: start_time = time.time() ranger.timestep(unit) time_rangers += (time.time() - start_time) except Exception as e: #print('RANGER ERROR.') if ranger in variables.ranger_roles["go_to_mars"]: variables.ranger_roles["go_to_mars"].remove(ranger) elif ranger in variables.ranger_roles["fighter"]: variables.ranger_roles["fighter"].remove(ranger) elif ranger in variables.ranger_roles["sniper"]: variables.ranger_roles["sniper"].remove(ranger) traceback.print_exc() elif unit.unit_type == unit_types["mage"]: mage.timestep(unit) elif unit.unit_type == unit_types["healer"]: start_time = time.time()
#print("TIME LEFT:", gc.get_time_left_ms()) for poss_enemy in variables.units: if poss_enemy.team != variables.my_team and poss_enemy.unit_type in variables.attacker: variables.num_enemies += 1 start_time = time.time() knight.update_battles() #if time.time()-start_time > 0.02: # print('KNIGHT UPDATE BATTLES:', time.time()-start_time) start_time = time.time() healer.update_healers() #if time.time() - start_time > 0.02: # print('HEALER UPDATE TIME:', time.time()-start_time) start_time = time.time() ranger.update_rangers() #if time.time() - start_time > 0.02: # print('RANGER UPDATE TIME: ', time.time()-start_time) start_time = time.time() worker.designate_roles() #if time.time() - start_time > 0.02: # print('DESIGNATING ROLES TIME:', time.time()-start_time) factory.evaluate_stockpile() #time_workers = 0 #time_rangers = 0 #time_healers = 0 # time_factories = 0 # time_knights = 0
def update_variables(): gc = variables.gc ## **************************************** GENERAL **************************************** ## ## Constants variables.curr_round = gc.round() variables.num_enemies = 0 variables.print_count = 0 variables.research = gc.research_info() ## Battle locations variables.last_turn_battle_locs = variables.next_turn_battle_locs.copy() variables.next_turn_battle_locs = {} # variables.quadrant_battle_locs = {} ## Units variables.my_units = gc.my_units() variables.my_unit_ids = set([unit.id for unit in variables.my_units]) variables.units = gc.units() num_workers= num_knights=num_rangers= num_mages= num_healers= num_factory= num_rocket = 0 # Update which ally unit id's are still alive & deaths per quadrant update_quadrants() # Updates enemies in quadrant & resets num dead allies if variables.curr_planet == bc.Planet.Earth: quadrant_size = variables.earth_quadrant_size else: quadrant_size = variables.mars_quadrant_size remove = set() for unit_id in variables.unit_locations: if unit_id not in variables.my_unit_ids: remove.add(unit_id) for unit_id in remove: loc = variables.unit_locations[unit_id] del variables.unit_locations[unit_id] f_f_quad = (int(loc[0] / quadrant_size), int(loc[1] / quadrant_size)) variables.quadrant_battle_locs[f_f_quad].remove_ally(unit_id) # Update % health of fighting allies in quadrant for quadrant in variables.quadrant_battle_locs: q_info = variables.quadrant_battle_locs[quadrant] q_info.update_ally_health_coefficient(gc) # Something something enemies for poss_enemy in variables.units: if poss_enemy.team != variables.my_team and poss_enemy.unit_type in variables.attacker: variables.num_enemies += 1 # Update num of ally units of each type unit_types = variables.unit_types for unit in variables.my_units: if unit.unit_type == unit_types["worker"]: num_workers+=1 elif unit.unit_type == unit_types["knight"]: num_knights+=1 elif unit.unit_type == unit_types["ranger"]: num_rangers+=1 elif unit.unit_type == unit_types["mage"]: num_mages+=1 elif unit.unit_type == unit_types["healer"]: num_healers+=1 elif unit.unit_type == unit_types["factory"]: num_factory+=1 elif unit.unit_type == unit_types["rocket"]: num_rocket+=1 variables.info = [num_workers, num_knights, num_rangers, num_mages, num_healers, num_factory, num_rocket] ## **************************************** UNITS **************************************** ## ## Worker variables.my_karbonite = gc.karbonite() variables.producing= [0, 0, 0, 0, 0] if not worker.check_if_saviour_died(): variables.saviour_worker_id = None variables.saviour_worker = False variables.saviour_blueprinted = False variables.saviour_blueprinted_id = None variables.num_unsuccessful_savior = 0 variables.saviour_time_between = 0 worker.designate_roles() ## Rangers variables.targeting_units = {} ranger.update_rangers() ## Knights knight.update_battles() ## Healers healer.update_healers() # Rockets rocket.update_rockets() ## Mages ## Factories factory.evaluate_stockpile()
info = [ num_workers, num_knights, num_rangers, num_mages, num_healers, num_factory, num_rocket ] for unit in gc.my_units(): # resepective unit types execute their own AI if unit.unit_type == bc.UnitType.Worker: worker.timestep(gc, unit, info, karbonite_locations, locs_next_to_terrain, blueprinting_queue, building_assignment, current_worker_roles) elif unit.unit_type == bc.UnitType.Knight: knight.timestep(gc, unit, info, knight_to_cluster, seen_knights_ids, KNIGHT_CLUSTER_MIN) elif unit.unit_type == bc.UnitType.Ranger: ranger.timestep(gc, unit, info, last_turn_battle_locs, next_turn_battle_locs, queued_paths, ranger_roles) elif unit.unit_type == bc.UnitType.Mage: mage.timestep(gc, unit, info, last_turn_battle_locs, next_turn_battle_locs, queued_paths) elif unit.unit_type == bc.UnitType.Healer: healer.timestep(gc, unit, info, last_turn_battle_locs) elif unit.unit_type == bc.UnitType.Factory: factory.timestep(gc, unit, info, building_assignment, mining_rate=3 * len(current_worker_roles["miner"])) elif unit.unit_type == bc.UnitType.Rocket: rocket.timestep(gc, unit, info)
def knight_sense(gc, unit, battle_locs, knight_roles, location, direction_to_coord, bfs_array, targeting_units, rocket_locs): enemies = gc.sense_nearby_units_by_team(location, unit.vision_range, variables.enemy_team) if unit.id in knight_roles["go_to_mars"]: return go_to_mars_sense(gc, unit, battle_locs, location, enemies, direction_to_coord, bfs_array, targeting_units, rocket_locs) signals = {} dir = None attack = None javelin = None closest_enemy = None move_then_attack = False visible_enemies = False # if variables.print_count < 10: # print("Sensing nearby units:", time.time() - start_time) if len(enemies) > 0: visible_enemies = True closest_enemy = None closest_dist = -float('inf') for enemy in enemies: enemy_loc = enemy.location if enemy_loc.is_on_map(): enemy_map_loc = enemy_loc.map_location() coeff = Ranger.coefficient_computation(gc, unit, enemy, enemy_map_loc, location) # dist = sense_util.distance_squared_between_maplocs(loc.map_location(), location) if coeff > closest_dist: closest_dist = coeff closest_enemy = enemy # if variables.print_count < 10: # print("Getting closest enemy:", time.time() - start_time) # sorted_enemies = sorted(enemies, key=lambda x: x.location.map_location().distance_squared_to(location)) # closest_enemy = closest_among_ungarrisoned(sorted_enemies) attack = get_attack(gc, unit, location, targeting_units, knight_unit_priority) if attack is not None: if closest_enemy is not None: dir = Ranger.go_to_loc(unit, location, closest_enemy.location.map_location()) # optimal_direction_towards(gc, unit, location, closest_enemy.location.map_location()) else: if gc.is_move_ready(unit.id): if closest_enemy is not None: dir = Ranger.go_to_loc(unit, location, closest_enemy.location.map_location()) # optimal_direction_towards(gc, unit, location, closest_enemy.location.map_location()) if dir is None or dir == variables.directions[8]: dir = Ranger.optimal_direction_towards(gc, unit, location, closest_enemy.location.map_location()) next_turn_loc = location.add(dir) attack = get_attack(gc, unit, next_turn_loc, targeting_units, knight_unit_priority) if attack is not None: move_then_attack = True else: if variables.curr_planet == bc.Planet.Earth: # print('IS RUNNING TOWARDS INIT LOC') dir = Ranger.run_towards_init_loc_new(gc, unit, location, direction_to_coord) else: # print('EXPLORING') dir = Ranger.get_explore_dir(gc, unit, location) # if variables.print_count < 10: # print("Getting direction:", time.time() - start_time) else: # if there are no enemies in sight, check if there is an ongoing battle. If so, go there. if len(rocket_locs) > 0 and gc.round() > 660 and variables.curr_planet == bc.Planet.Earth: dir = Ranger.move_to_rocket(gc, unit, location, direction_to_coord, bfs_array) if dir is not None: return dir, attack, javelin, move_then_attack, visible_enemies, closest_enemy, signals if len(battle_locs) > 0: # print('IS GOING TO BATTLE') dir = Ranger.go_to_battle_new(gc, unit, battle_locs, location, direction_to_coord) # queued_paths[unit.id] = target else: # dir = move_away(gc, unit, battle_locs) if variables.curr_planet == bc.Planet.Earth: # print('IS RUNNING TOWARDS INIT LOC') dir = Ranger.run_towards_init_loc_new(gc, unit, location, direction_to_coord) else: # print('EXPLORING') dir = Ranger.get_explore_dir(gc, unit, location) # if variables.print_count < 10: # print("regular movement:", time.time() - start_time) return dir, attack, javelin, move_then_attack, visible_enemies, closest_enemy, signals