def populate_kamikaze(self, ship, potential_support_IDs, explore_destination, enemy_position): support_ships = OrderedSet() for support_id in sorted(potential_support_IDs): if support_id in self.data.mySets.ships_to_move: support_ships.add(support_id) s = KamikazeShip(ship.halite_amount, ship.id, support_ships, explore_destination, enemy_position) heapq.heappush(self.heap_kamikaze, s)
def __init__(self, game): self.ships_all = OrderedSet(sorted( game.me._ships.keys())) ## ALL SHIPS self.ships_to_move = OrderedSet(sorted(game.me._ships.keys( ))) ## SHIPS TO MOVE (SORTING TO MATCH ORDER ONLINE) self.ships_returning = OrderedSet() ## SHIPS RETURNING HALITE self.ships_kicked = OrderedSet() self.ships_died = set() self.ships_ally_collision = set() self.ships_enemy_collision = set() self.ships_building = set() self.dock_coords = set() self.deposit_ships = OrderedSet()
def get_neighbor_IDs(self, ship): """ GET NEXT ALLY NEIGHBORS IN THE GIVEN SHIP :return: SET OF IDs """ ally_IDs = OrderedSet() for direction in MyConstants.DIRECTIONS: destination = self.get_destination(ship, direction) id = self.data.myMatrix.locations.myShipsID[destination.y][ destination.x] if id > Matrix_val.ZERO: ally_IDs.add(id) return ally_IDs
def __init__(self, data, prev_data): Moves.__init__(self, data, prev_data) self.heap_set = set() self.heap_explore = [] self.ships_kicked_temp = OrderedSet() self.halite_matrix = self.data.myMatrix.halite.updated_enemyCargo self.average_matrix = self.data.myMatrix.cell_average.enemyCargo if data.myVars.explore_disable_bonus: # self.harvest_matrix = copy.deepcopy(self.data.myMatrix.halite.enemyCargo_harvest) #self.harvest_matrix = self.data.myMatrix.halite.updated_enemyCargo_harvest self.harvest_matrix = self.data.myMatrix.halite.updated_enemyCargo_harvest * MyConstants.explore.score_harvest_ratio \ + self.average_matrix * MyConstants.explore.score_average_ratio else: # self.harvest_matrix = self.data.myMatrix.halite.enemyCargo_harvest_with_bonus #self.harvest_matrix = self.data.myMatrix.halite.updated_enemyCargo_harvest_with_bonus self.harvest_matrix = self.data.myMatrix.halite.updated_enemyCargo_harvest_with_bonus * MyConstants.explore.score_harvest_ratio \ + self.average_matrix * MyConstants.explore.score_average_ratio #self.harvest_matrix = copy.deepcopy(self.data.myMatrix.halite.enemyCargo_harvest) self.taken_matrix = np.zeros( (self.data.game.game_map.height, self.data.game.game_map.width), dtype=np.int16) self.taken_matrix.fill(1) ## ZERO WILL BE FOR TAKEN CELL # r, c = np.where(self.data.myMatrix.locations.safe == Matrix_val.UNSAFE) # self.taken_matrix[r, c] = Matrix_val.ZERO # # self.taken_destinations = set() self.move_ships()
def __init__(self, data, prev_data): Moves.__init__(self, data, prev_data) # self.halite_matrix = self.data.myMatrix.halite.updated_amount # self.average_matrix = self.data.myMatrix.cell_average.halite self.harvest_matrix = self.get_harvest_matrix() self.taken_matrix = np.zeros( (self.data.game.game_map.height, self.data.game.game_map.width), dtype=np.int16) self.taken_matrix.fill(1) ## ZERO WILL BE FOR TAKEN CELL r, c = np.where(self.data.myMatrix.locations.safe == Matrix_val.UNSAFE) self.taken_matrix[r, c] = Matrix_val.ZERO self.taken_destinations = set() self.considered_already = OrderedSet() self.move_ships()
def go_towards_building(self): """ MOVE SHIPS TOWARD BUILDING DOCK """ heap_halite = [] if MyConstants.build.dock_manhattan > 2: for i in range(MyConstants.build.dock_manhattan - 2, 0, -1): ## MOVES SHIPS CLOSEST TO DOCK FIRST r, c = np.where(self.data.myMatrix.docks.manhattan == i) matrixIDs = OrderedSet( self.data.myMatrix.locations.myShipsID[r, c]) ships_going_dock = matrixIDs & self.data.mySets.ships_to_move logging.debug("ship going to dock: {} at i {}".format( ships_going_dock, i)) ## POPULATE HEAP for ship_id in sorted(ships_going_dock): ship = self.data.game.me._ships.get(ship_id) s = BuildShip(ship.halite_amount, ship_id) heapq.heappush(heap_halite, s) while heap_halite: s = heapq.heappop(heap_halite) logging.debug(s) ship = self.data.game.me._ships.get(s.ship_id) dock_coord = self.get_closest_dock_coord( ship) ## DOCK COORD IS NONE IF ENEMY BUILT THERE self.data.myDicts.ships_building_dock.setdefault( dock_coord, set()) #if dock_coord and (ship.halite_amount >= 1000 or ship_id in self.prev_data.ships_building): if dock_coord and ship.halite_amount >= MyConstants.build.min_halite_amount \ and len(self.data.myDicts.ships_building_dock[dock_coord]) < MyConstants.build.ships_per_dock \ and self.withinLimit_ships(): self.data.myVars.isBuilding = True dock_position = Position(dock_coord[1], dock_coord[0]) directions = self.get_directions_target( ship, dock_position) if self.data.game.me.halite_amount < 5000: self.data.myVars.isSaving = True ## PREVENT SPAWNING SHIPS ## OLD WAY #direction = self.best_direction(ship, directions, mode=MoveMode.BUILDING, avoid_enemy=False, avoid_potential_enemy=False) ## A STAR WAY direction = self.get_Astar_direction( ship, dock_position, directions) ## RECORD INFO ALSO SHIP COUNTER PER DOCK self.data.mySets.ships_building.add(ship_id) self.data.myDicts.ships_building_dock[dock_coord].add( ship.id) self.move_mark_unsafe(ship, direction)
def building_now(self): """ MOVE SHIPS BUILDING NOW (CURRENTLY AT DOCK POSITION) """ r, c = np.where(self.data.myMatrix.docks.manhattan == MyConstants.build.dock_manhattan) ships_on_docks = OrderedSet(self.data.myMatrix.locations.myShipsID[r, c]) ships_building = ships_on_docks & self.data.mySets.ships_to_move for ship_id in sorted(ships_building): ship = self.data.game.me._ships.get(ship_id) cell_halite_amount = self.data.myMatrix.halite.amount[ ship.position.y][ship.position.x] if self.withinLimit_ships(): self.data.myVars.isBuilding = True if ship.halite_amount + self.data.game.me.halite_amount + cell_halite_amount >= 4000: ## HAVE ENOUGH HALITE TO BUILD DOCK self.data.game.me.halite_amount -= (4000 - ship.halite_amount - cell_halite_amount) logging.debug( "Shid id: {} building dock at position: {}".format( ship.id, ship.position)) self.data.halite_stats.record_spent(BuildType.DOCK) command = ship.make_dropoff() self.data.command_queue.append(command) ## CLEAR DOCK AREA, SO THAT OTHER SHIPS WILL NOT TRY TO BUILD ON IT populate_manhattan(self.data.myMatrix.docks.manhattan, Matrix_val.ZERO, ship.position, MyConstants.build.dock_manhattan, Option.REPLACE) self.data.init_data.myMatrix.docks.placement[ ship.position.y][ship.position.x] = Matrix_val.ZERO self.data.init_data.myMatrix.docks.order[ship.position.y][ ship.position.x] = Matrix_val.NINETY else: ## NOT ENOUGH HALITE YET, STAY STILL self.data.myVars.isSaving = True ## PREVENT SPAWNING SHIPS direction = Direction.Still command = ship.move(direction) self.data.command_queue.append(command) ## RECORD INFO ALSO SHIP COUNTER PER DOCK dock_coord = (ship.position.y, ship.position.x) self.data.myDicts.ships_building_dock.setdefault( dock_coord, set()) self.data.myDicts.ships_building_dock[dock_coord].add(ship.id) self.mark_unsafe(ship, ship.position) self.data.mySets.ships_to_move.remove(ship.id)
def build_on_high_halite(self): """ BUILD A DOCK RIGHT AWAY ON A HIGH COLLISION CELL, TO PREVENT ENEMY FROM HARVESTING IT """ ## BUILD ANYWHERE WHERE HALITE IS HIGH r, c = np.where(self.data.myMatrix.halite.amount >= MyConstants.build.dock_anywhere_halite) ships_on_high_halite = OrderedSet( self.data.myMatrix.locations.myShipsID[r, c]) ships_building = ships_on_high_halite & self.data.mySets.ships_to_move self.building_aggressively(ships_building, check_close_docks=False) ## BUILD WHERE HALITE IS MEDIUM AND NO CLOSE DOCKS r, c = np.where(self.data.myMatrix.halite.amount >= MyConstants.build.dock_far_halite) ships_on_high_halite = OrderedSet( self.data.myMatrix.locations.myShipsID[r, c]) ships_building = ships_on_high_halite & self.data.mySets.ships_to_move self.building_aggressively(ships_building, check_close_docks=True)
def move_ships(self): print_heading("Moving attack ships......") allowAttack = (constants.MAX_TURNS * MyConstants.attack.allowed_turns_lower_limit <= self.data.game.turn_number <= constants.MAX_TURNS * MyConstants.attack.allowed_turns_upper_limit) \ and len(self.data.mySets.ships_all) > MyConstants.attack.min_ships_before_attacking ## MOVE SHIPS CLOSEST TO ENEMY FIRST (WITH ITS SUPPORT SHIP) if allowAttack: considered_prev_i = OrderedSet( ) ## USED TO NOT CONSIDER PREVIOUS i for i in range( 1, MyConstants.attack.engage_enemy_distance ): ## DONT NEED TO MOVE FURTHEST ONES (WILL BE MOVED AS SUPPORT) matrixIDs = self.data.myMatrix.locations.engage_enemy[ i] * self.data.myMatrix.locations.myShipsID r, c = np.where(matrixIDs > Matrix_val.ZERO) ships_engaging = OrderedSet( self.data.myMatrix.locations.myShipsID[ r, c]) - considered_prev_i ships_attacking = ships_engaging & self.data.mySets.ships_to_move considered_prev_i.update(ships_attacking) self.considered_already.update(ships_attacking) logging.debug("i {} ships_attacking {}".format( i, ships_attacking)) self.heap_kamikaze = [] self.heap_support = [] ## RESET PER ITERATION for ship_id in sorted(ships_attacking): self.populate_heap(ship_id, i) ## MOVE ATTACK/SUPPORT SHIPS self.move_attack_suppport() ## MOVE KAMIKAZE SHIPS self.move_kamikaze()
def building_later(self): """ MOVE SHIPS RIGHT NEXT TO DOCK POSITION """ i = MyConstants.build.dock_manhattan - 1 ## CURRENTLY RIGHT NEXT TO THE DOCK r, c = np.where(self.data.myMatrix.docks.manhattan == i) matrixIDs = OrderedSet(self.data.myMatrix.locations.myShipsID[r, c]) ships_going_dock = matrixIDs & self.data.mySets.ships_to_move logging.debug("ship next to dock: {}".format(ships_going_dock)) for ship_id in sorted(ships_going_dock): ship = self.data.game.me._ships.get(ship_id) dock_coord = self.get_closest_dock_coord( ship) ## DOCK COORD IS NONE IF ENEMY BUILT THERE self.data.myDicts.ships_building_dock.setdefault(dock_coord, set()) if dock_coord \ and len(self.data.myDicts.ships_building_dock[dock_coord]) < MyConstants.build.ships_per_dock \ and self.withinLimit_ships(): self.data.myVars.isBuilding = True if self.data.game.me.halite_amount < 5000: self.data.myVars.isSaving = True ## PREVENT SPAWNING SHIPS dock_position = Position(dock_coord[1], dock_coord[0]) directions = self.get_directions_target(ship, dock_position) dock_halite_amount = self.data.myMatrix.halite.amount[ dock_position.y][dock_position.x] if ship.halite_amount + self.data.game.me.halite_amount + dock_halite_amount >= 4000 \ and self.data.myMatrix.locations.safe[dock_position.y][dock_position.x] != Matrix_val.UNSAFE: ## ENOUGH HALITE TO BUILD direction = self.best_direction( ship, directions, mode=MoveMode.BUILDING, avoid_enemy=True, avoid_potential_enemy=False) self.move_mark_unsafe( ship, direction) ## DIRECTION IS A LIST OF DIRECTIONS else: ## POPULATE UNSAFE AROUND DOCK SO NO OTHER SHIPS WILL GO TOWARDS IT # self.data.myMatrix.locations.safe[dock_position.y][dock_position.x] = Matrix_val.UNSAFE self.move_mark_unsafe(ship, Direction.Still) ## SHIP COUNTER PER DOCK self.data.myDicts.ships_building_dock[dock_coord].add(ship.id)
def __init__(self, data, prev_data): Moves.__init__(self, data, prev_data) self.heap_set = set() self.heap_explore = [] self.ships_kicked_temp = OrderedSet() if self.data.game.turn_number <= constants.MAX_TURNS * MyConstants.explore.enable_bonus_turns_above: self.harvest_matrix = copy.deepcopy( self.data.myMatrix.halite.harvest) else: self.harvest_matrix = copy.deepcopy( self.data.myMatrix.halite.harvest_with_bonus) self.taken_matrix = np.zeros( (self.data.game.game_map.height, self.data.game.game_map.width), dtype=np.int16) self.taken_matrix.fill(1) ## ZERO WILL BE FOR TAKEN CELL r, c = np.where(self.data.myMatrix.locations.safe == Matrix_val.UNSAFE) self.taken_matrix[r, c] = Matrix_val.ZERO self.taken_destinations = set() self.move_ships()
def get_move_points_collision(Moves, ship, directions, all_directions): """ GET POINTS FOR IMMINENT COLLISION PREVENTION :param ship: :param directions: DIRECTIONS SHIP WAS ORIGINALLY GOING :return: """ points = [] ## SET FIRST PRIORITY DIRECTIONS try: first_priority = OrderedSet(directions) except: first_priority = OrderedSet() ## SET SECOND PRIORITY DIRECTIONS second_priority = OrderedSet() if directions: for direction in directions: directions = set(get_adjacent_directions(direction)) second_priority.update(directions) if all_directions: DIRECTIONS = MyConstants.ALL_DIRECTIONS else: DIRECTIONS = MyConstants.DIRECTIONS for direction in DIRECTIONS: ## HAS NO STILL (KICKED, NEED TO MOVE) destination = Moves.get_destination(ship, direction) safe = Moves.data.myMatrix.locations.safe[destination.y][destination.x] occupied = Moves.data.myMatrix.locations.occupied[destination.y][destination.x] priority_direction = 2 if direction in first_priority else 1 if direction in second_priority else 0 cost = Moves.data.myMatrix.halite.cost[ship.position.y][ship.position.x] harvest = Moves.data.myMatrix.halite.harvest_with_bonus[destination.y][destination.x] harvest_amnt = harvest - cost c = CollisionPoints(safe, occupied, priority_direction, harvest_amnt, direction) points.append(c) logging.debug(points) return points
def populate_heap(self, ship_id, i): """ POPULATE HEAP, SHIP WITH LEAST SUPPORT WILL MOVE FIRST SO SHIPS WITH 2 SUPPORT WILL NOT TAKE A SUPPORT FOR ANOTHER WILL NOT BE ADDED TO HEAP IF IT HAS TOO MUCH HALITE CARGO """ ship = self.data.game.me._ships.get(ship_id) directions_to_enemy, enemy_position = self.get_closest_enemy_position( ship) ship_distance = calculate_distance(ship.position, enemy_position, self.data) enemy_ship, enemy_shipID = self.get_enemy_ship(enemy_position) potential_support = get_manhattan( self.data.myMatrix.locations.myShipsID, enemy_position, MyConstants.attack.engage_enemy_distance) potential_support_IDs = potential_support - { -1 } - self.considered_already ## myShipsID contains -1 num_enemy_ships = count_manhattan( self.data.myMatrix.locations.enemyShips, Matrix_val.ONE, enemy_position, MyConstants.attack.enemy_backup_distance) enemy_halite = self.data.myMatrix.locations.shipsCargo[ enemy_position.y][enemy_position.x] my_halite = ship.halite_amount logging.debug( "Populate heap for attack. ship {} enemy_position {} potential_support_IDs {} num_enemy_ships {}" .format(ship, enemy_position, potential_support_IDs, num_enemy_ships)) canHarvest, harvest_direction = self.check_harvestNow( ship_id, moveNow=False, avoid_enemy=True, avoid_potential_enemy=True) # if not (canHarvest): canHarvest, harvest_direction = self.check_harvestLater(ship_id, # MyConstants.DIRECTIONS, # kicked=False, # moveNow=False, # avoid_enemy=True, # avoid_potential_enemy=True) matrix_highest_ratio, max_ratio, explore_destination, harvest_value = self.get_matrix_ratio( ship) # directions = self.get_directions_target(ship, explore_destination) # explore_direction, points = self.best_direction(ship, directions, mode=MoveMode.EXPLORE, avoid_enemy=False) harvest_destination = self.get_destination(ship, harvest_direction) harvest_ratio = matrix_highest_ratio[harvest_destination.y][ harvest_destination.x] ## POPULATE KAMIKAZE if ((len(self.data.game.players) == 2) and (i == 1 or i == 2)) \ or i == 2: ## FOR 2 PLAYERS, CHECK i = 1 or 2 ## FOR 4 PLAYERS, JUST CHECK i = 2 self.populate_kamikaze(ship, potential_support_IDs, explore_destination, enemy_position) ## POPULATE SUPPORT if max_ratio > harvest_ratio * self.data.myVars.harvest_ratio_to_explore \ and len(potential_support_IDs) > num_enemy_ships: ## ATTACKING (NOT HARVESTING) support_ships = OrderedSet() for support_id in sorted(potential_support_IDs): support_ship = self.data.game.me._ships.get(support_id) support_distance = calculate_distance(support_ship.position, enemy_position, self.data) canHarvest, harvest_direction = self.check_harvestNow( support_id, moveNow=False, avoid_enemy=True, avoid_potential_enemy=True) # if not (canHarvest): canHarvest, harvest_direction = self.check_harvestLater(support_id, # MyConstants.DIRECTIONS, # kicked=False, # moveNow=False, # avoid_enemy=True, # avoid_potential_enemy=True) matrix_highest_ratio, max_ratio, explore_destination, harvest_value = self.get_matrix_ratio( support_ship) # directions = self.get_directions_target(ship, explore_destination) # explore_direction, points = self.best_direction(support_ship, directions, mode=MoveMode.EXPLORE, avoid_enemy=False) harvest_destination = self.get_destination( support_ship, harvest_direction) harvest_ratio = matrix_highest_ratio[harvest_destination.y][ harvest_destination.x] ## HAVE TO BE JUST 1 DISTANCE AWAY OR CLOSER if support_id in self.data.mySets.ships_to_move \ and support_distance <= ship_distance + 1: #and harvest_ratio < max_ratio * MyConstants.attack.support_harvest_ratio: potental_harvest = ( my_halite + enemy_halite) * 0.25 ## POTENTIAL HARVEST total_halite = support_ship.halite_amount + potental_harvest real_gain = potental_harvest if total_halite < 1000 else ( 1000 - support_ship.halite_amount) ## CAN ONLY GET MAX 1000 if real_gain > my_halite * self.data.myVars.support_gain_ratio: ## MORE THAN 20% GAIN THAN WHAT WE LOST support_ships.add(support_id) num_support = len(support_ships) # if my_halite < enemy_halite * MyConstants.ATTACK_ENEMY_HALITE_RATIO and num_support >= 1: if num_support >= 1: ## ATTACK EVEN WHEN HAS HIGH CARGO s = SupportShip(num_support, ship.id, support_ships, directions_to_enemy, enemy_position) heapq.heappush(self.heap_support, s)
class Attack(Moves, Attacks, Harvests, Explores): def __init__(self, data, prev_data): Moves.__init__(self, data, prev_data) # self.halite_matrix = self.data.myMatrix.halite.updated_amount # self.average_matrix = self.data.myMatrix.cell_average.halite self.harvest_matrix = self.get_harvest_matrix() self.taken_matrix = np.zeros( (self.data.game.game_map.height, self.data.game.game_map.width), dtype=np.int16) self.taken_matrix.fill(1) ## ZERO WILL BE FOR TAKEN CELL r, c = np.where(self.data.myMatrix.locations.safe == Matrix_val.UNSAFE) self.taken_matrix[r, c] = Matrix_val.ZERO self.taken_destinations = set() self.considered_already = OrderedSet() self.move_ships() def get_harvest_matrix(self): """ POPULATE HARVEST MATRIX TO BE USED FOR ATTACK """ matrixes = [ self.data.myMatrix.halite.harvest_with_bonus, self.data.myMatrix.halite.enemyCargo_harvest_with_bonus ] #matrixes = [self.data.myMatrix.halite.updated_harvest_with_bonus, self.data.myMatrix.halite.enemyCargo_harvest_with_bonus] return myMaxValueMatrix(*matrixes) def move_ships(self): print_heading("Moving attack ships......") allowAttack = (constants.MAX_TURNS * MyConstants.attack.allowed_turns_lower_limit <= self.data.game.turn_number <= constants.MAX_TURNS * MyConstants.attack.allowed_turns_upper_limit) \ and len(self.data.mySets.ships_all) > MyConstants.attack.min_ships_before_attacking ## MOVE SHIPS CLOSEST TO ENEMY FIRST (WITH ITS SUPPORT SHIP) if allowAttack: considered_prev_i = OrderedSet( ) ## USED TO NOT CONSIDER PREVIOUS i for i in range( 1, MyConstants.attack.engage_enemy_distance ): ## DONT NEED TO MOVE FURTHEST ONES (WILL BE MOVED AS SUPPORT) matrixIDs = self.data.myMatrix.locations.engage_enemy[ i] * self.data.myMatrix.locations.myShipsID r, c = np.where(matrixIDs > Matrix_val.ZERO) ships_engaging = OrderedSet( self.data.myMatrix.locations.myShipsID[ r, c]) - considered_prev_i ships_attacking = ships_engaging & self.data.mySets.ships_to_move considered_prev_i.update(ships_attacking) self.considered_already.update(ships_attacking) logging.debug("i {} ships_attacking {}".format( i, ships_attacking)) self.heap_kamikaze = [] self.heap_support = [] ## RESET PER ITERATION for ship_id in sorted(ships_attacking): self.populate_heap(ship_id, i) ## MOVE ATTACK/SUPPORT SHIPS self.move_attack_suppport() ## MOVE KAMIKAZE SHIPS self.move_kamikaze() def move_attack_suppport(self): while self.heap_support: s = heapq.heappop(self.heap_support) logging.debug(s) first_ship = self.data.game.me._ships.get(s.ship_id) direction = self.best_direction(first_ship, s.directions, mode=MoveMode.ATTACKING) if direction != Direction.Still and s.ship_id in self.data.mySets.ships_to_move: ## IF STAYING STILL, NO NEED TO MOVE ## FIRST SHIP WILL JUST HARVEST/EXPLORE ## SUPPORT SHIP MOVE WILL BE DETERMINED LATER destination = self.get_destination(first_ship, direction) ## OLD WAY (MARK TAKEN) #self.mark_taken_udpate_top_halite(destination) ## NEW WAY (DEDUCT HALITE TO BE HARVESTED) #self.update_harvest_matrix(s.ship_id, destination) self.move_mark_unsafe(first_ship, direction) logging.debug("Attacking ship id: {} support ships: {}".format( first_ship.id, s.support_ships)) for support_id in s.support_ships: if support_id in self.data.mySets.ships_to_move: support_ship = self.data.game.me._ships.get(support_id) #support_directions = self.get_directions_target(support_ship, first_ship.position) support_directions = self.get_directions_target( support_ship, s.enemy_position) direction = self.best_direction( support_ship, support_directions, mode=MoveMode.SUPPORTING) destination = self.get_destination( support_ship, direction) ## OLD WAY (MARK TAKEN) #self.mark_taken_udpate_top_halite(destination) ## NEW WAY (DEDUCT HALITE TO BE HARVESTED) #self.update_harvest_matrix(support_id, destination) self.move_mark_unsafe(support_ship, direction) def move_kamikaze(self): while self.heap_kamikaze: s_kamikaze = heapq.heappop(self.heap_kamikaze) logging.debug(s_kamikaze) s_exploreTarget = self.data.myDicts.explore_ship[ s_kamikaze.ship_id] logging.debug("s_kamikaze.ship_id {}".format(s_kamikaze.ship_id)) ship = self.data.game.me._ships.get(s_kamikaze.ship_id) if s_kamikaze.ship_id in self.data.mySets.ships_to_move: canHarvest, harvest_direction = self.check_harvestLater( s_kamikaze.ship_id, MyConstants.DIRECTIONS, kicked=False, moveNow=False, avoid_enemy=False, avoid_potential_enemy=False) harvest_destination = self.get_destination( ship, harvest_direction) harvest_halite = self.data.myMatrix.halite.harvest_with_bonus[ harvest_destination.y][harvest_destination.x] logging.debug( "harvest_destination {} s_kamikaze.explore_destination {} ship.halite_amount {} harvest_halite {}" .format(harvest_destination, s_kamikaze.destination, ship.halite_amount, harvest_halite)) if ship.halite_amount <= MyConstants.attack.kamikaze_halite_max \ and harvest_halite >= ship.halite_amount * self.data.myVars.kamikaze_halite_ratio \ and ( ((len(self.data.game.players) == 2) and (harvest_destination == s_kamikaze.destination or harvest_destination == s_exploreTarget.destination)) \ or harvest_destination == s_kamikaze.destination ): ## IF 2 PLAYERS, CHECK EITHER KAMIKAZE OR EXPLORE DESTINATION self.move_mark_unsafe(ship, harvest_direction) for support_id in s_kamikaze.support_ships: if support_id in self.data.mySets.ships_to_move: support_ship = self.data.game.me._ships.get( support_id) #support_directions = self.get_directions_target(support_ship, ship.position) support_directions = self.get_directions_target( support_ship, s_kamikaze.enemy_position) direction = self.best_direction( support_ship, support_directions, mode=MoveMode.SUPPORTING) destination = self.get_destination( support_ship, direction) ## OLD WAY (MARK TAKEN) #self.mark_taken_udpate_top_halite(destination) ## NEW WAY (DEDUCT HALITE TO BE HARVESTED) #self.update_harvest_matrix(support_id, destination) self.move_mark_unsafe(support_ship, direction) def populate_heap(self, ship_id, i): """ POPULATE HEAP, SHIP WITH LEAST SUPPORT WILL MOVE FIRST SO SHIPS WITH 2 SUPPORT WILL NOT TAKE A SUPPORT FOR ANOTHER WILL NOT BE ADDED TO HEAP IF IT HAS TOO MUCH HALITE CARGO """ ship = self.data.game.me._ships.get(ship_id) directions_to_enemy, enemy_position = self.get_closest_enemy_position( ship) ship_distance = calculate_distance(ship.position, enemy_position, self.data) enemy_ship, enemy_shipID = self.get_enemy_ship(enemy_position) potential_support = get_manhattan( self.data.myMatrix.locations.myShipsID, enemy_position, MyConstants.attack.engage_enemy_distance) potential_support_IDs = potential_support - { -1 } - self.considered_already ## myShipsID contains -1 num_enemy_ships = count_manhattan( self.data.myMatrix.locations.enemyShips, Matrix_val.ONE, enemy_position, MyConstants.attack.enemy_backup_distance) enemy_halite = self.data.myMatrix.locations.shipsCargo[ enemy_position.y][enemy_position.x] my_halite = ship.halite_amount logging.debug( "Populate heap for attack. ship {} enemy_position {} potential_support_IDs {} num_enemy_ships {}" .format(ship, enemy_position, potential_support_IDs, num_enemy_ships)) canHarvest, harvest_direction = self.check_harvestNow( ship_id, moveNow=False, avoid_enemy=True, avoid_potential_enemy=True) # if not (canHarvest): canHarvest, harvest_direction = self.check_harvestLater(ship_id, # MyConstants.DIRECTIONS, # kicked=False, # moveNow=False, # avoid_enemy=True, # avoid_potential_enemy=True) matrix_highest_ratio, max_ratio, explore_destination, harvest_value = self.get_matrix_ratio( ship) # directions = self.get_directions_target(ship, explore_destination) # explore_direction, points = self.best_direction(ship, directions, mode=MoveMode.EXPLORE, avoid_enemy=False) harvest_destination = self.get_destination(ship, harvest_direction) harvest_ratio = matrix_highest_ratio[harvest_destination.y][ harvest_destination.x] ## POPULATE KAMIKAZE if ((len(self.data.game.players) == 2) and (i == 1 or i == 2)) \ or i == 2: ## FOR 2 PLAYERS, CHECK i = 1 or 2 ## FOR 4 PLAYERS, JUST CHECK i = 2 self.populate_kamikaze(ship, potential_support_IDs, explore_destination, enemy_position) ## POPULATE SUPPORT if max_ratio > harvest_ratio * self.data.myVars.harvest_ratio_to_explore \ and len(potential_support_IDs) > num_enemy_ships: ## ATTACKING (NOT HARVESTING) support_ships = OrderedSet() for support_id in sorted(potential_support_IDs): support_ship = self.data.game.me._ships.get(support_id) support_distance = calculate_distance(support_ship.position, enemy_position, self.data) canHarvest, harvest_direction = self.check_harvestNow( support_id, moveNow=False, avoid_enemy=True, avoid_potential_enemy=True) # if not (canHarvest): canHarvest, harvest_direction = self.check_harvestLater(support_id, # MyConstants.DIRECTIONS, # kicked=False, # moveNow=False, # avoid_enemy=True, # avoid_potential_enemy=True) matrix_highest_ratio, max_ratio, explore_destination, harvest_value = self.get_matrix_ratio( support_ship) # directions = self.get_directions_target(ship, explore_destination) # explore_direction, points = self.best_direction(support_ship, directions, mode=MoveMode.EXPLORE, avoid_enemy=False) harvest_destination = self.get_destination( support_ship, harvest_direction) harvest_ratio = matrix_highest_ratio[harvest_destination.y][ harvest_destination.x] ## HAVE TO BE JUST 1 DISTANCE AWAY OR CLOSER if support_id in self.data.mySets.ships_to_move \ and support_distance <= ship_distance + 1: #and harvest_ratio < max_ratio * MyConstants.attack.support_harvest_ratio: potental_harvest = ( my_halite + enemy_halite) * 0.25 ## POTENTIAL HARVEST total_halite = support_ship.halite_amount + potental_harvest real_gain = potental_harvest if total_halite < 1000 else ( 1000 - support_ship.halite_amount) ## CAN ONLY GET MAX 1000 if real_gain > my_halite * self.data.myVars.support_gain_ratio: ## MORE THAN 20% GAIN THAN WHAT WE LOST support_ships.add(support_id) num_support = len(support_ships) # if my_halite < enemy_halite * MyConstants.ATTACK_ENEMY_HALITE_RATIO and num_support >= 1: if num_support >= 1: ## ATTACK EVEN WHEN HAS HIGH CARGO s = SupportShip(num_support, ship.id, support_ships, directions_to_enemy, enemy_position) heapq.heappush(self.heap_support, s) def populate_kamikaze(self, ship, potential_support_IDs, explore_destination, enemy_position): support_ships = OrderedSet() for support_id in sorted(potential_support_IDs): if support_id in self.data.mySets.ships_to_move: support_ships.add(support_id) s = KamikazeShip(ship.halite_amount, ship.id, support_ships, explore_destination, enemy_position) heapq.heappush(self.heap_kamikaze, s)