def moveShipSmart(self, ship, target, unsafe=False): # Used for seen and keeps track of which cell the best path came from # Except for initial cells which contain direction prevCell = dict() # Cells still to be searched toSearch = list() def cost(halite, distance): adjustedInv = (ship.halite_amount - halite) / fastPow( GROWTH, distance) return ship.halite_amount - adjustedInv def heuristic(pos, halite, distance): furtherDistance = self.game_map.calculate_distance(target, pos) newDistance = distance + furtherDistance expHalite = int((MINE_T + MINE_T * (1.0 - 1.0 / constants.EXTRACT_RATIO)) / 2.0) newHalite = halite + furtherDistance * expHalite // constants.MOVE_COST_RATIO return cost(newHalite, newDistance) # Add initial cells to search space for dir in Direction.get_all_cardinals(): newPos = self.game_map.normalize( ship.position.directional_offset(dir)) halite = self.game_map[ ship.position].halite_amount // constants.MOVE_COST_RATIO distance = 1 Cost = cost(halite, distance) heapq.heappush(toSearch, (heuristic( newPos, halite, distance), halite, distance, newPos)) prevCell[newPos] = (Cost, ship.position, dir) curr = target # Search for target while toSearch: adjCost, halite, distance, pos = heapq.heappop(toSearch) if pos == target: curr = pos break for dir in Direction.get_all_cardinals(): newPos = self.game_map.normalize(pos.directional_offset(dir)) newHalite = halite + self.game_map[ pos].halite_amount // constants.MOVE_COST_RATIO newDistance = distance + 1 Cost = cost(newHalite, newDistance) if newPos not in prevCell: heapq.heappush(toSearch, (heuristic(newPos, newHalite, newDistance), newHalite, newDistance, newPos)) prevCell[newPos] = (Cost, pos, dir) else: prevCell[newPos] = min(prevCell[newPos], (Cost, pos, dir)) logging.info(prevCell) # Find original cell while prevCell[curr][1] != ship.position: logging.info(curr) curr = prevCell[curr][1] return self.moveShip(ship, prevCell[curr][2])
def getClosestSpot(ship): possible = [] cleanPlaces(targetArea) for i in targetArea: if i != ship.position: pickDir = game_map.get_unsafe_moves(ship.position, i)[0] if ((pickDir).__ne__(Direction.Still)) and (ship.position.__ne__( i)) and game_map[i].halite_amount > 100: possible.append(i) if len(possible) > 0: closest = possible[0] for i in possible: if game_map.calculate_distance(ship.position, i) < game_map.calculate_distance( ship.position, closest): if game_map.get_unsafe_moves(ship.position, i)[0] != Direction.Still: closest = i return Direction.convert( game_map.get_unsafe_moves(ship.position, closest)[0]) else: for i in Direction.get_all_cardinals(): if (game_map[ship.position.directional_offset(i)].is_occupied == False): return Direction.convert( game_map.get_unsafe_moves( ship.position, ship.position.directional_offset(i))[0])
def moveShipSmart(self, ship, target, unsafe=False): seen = set() toSearch = list() # Priority Queue def cost(pos): return squareCost(self.getHalitePos(pos)) def heuristic(pos): return self.game_map.calculate_distance(target, pos) * 10 # Initialize queue for dir in Direction.get_all_cardinals(): newPos = self.game_map.normalize( ship.position.directional_offset(dir)) heapq.heappush(toSearch, (cost(ship.position) + heuristic(newPos) - heuristic(ship.position), newPos, dir)) # Go through the search queue while toSearch: c, pos, dir = heapq.heappop(toSearch) if pos in seen: continue seen.add(pos) if pos == target: if self.moveShip(ship, dir): return True return False else: for d in Direction.get_all_cardinals(): newPos = self.game_map.normalize(pos.directional_offset(d)) if newPos not in seen: heapq.heappush(toSearch, ((c + cost(pos) + heuristic(newPos) - heuristic(pos), newPos, dir)))
def get_random_move(ship): moveChoice = random.choice(["n", "s", "e", "w"]) #logging.info("Ship - get_random_move() - ship {} moveChoice2: {}".format(ship.id, moveChoice)) moveOffset = ship.position.directional_offset(DIRECTIONS[moveChoice]) #logging.info("Ship - get_random_move() - ship {} moveOffset2: {}".format(ship.id, moveOffset)) move = Direction.convert(game_map.naive_navigate(ship, moveOffset)) #logging.info("Ship - get_random_move() - ship {} final move2: {}".format(ship.id, move)) if move == "o": original_move = move for i in range(4): # get char direction vs alt code below so we can log consistent msg # alt code: ship.move(random.choice([Direction.North, Direction.South, Direction.East, Direction.West])) moveChoice = random.choice(["n", "s", "e", "w"]) moveOffset = ship.position.directional_offset( DIRECTIONS[moveChoice]) move = Direction.convert(game_map.naive_navigate(ship, moveOffset)) if move != "o": break if move == "o": logging.info( "Ship - get_random_move() - ship {} Collision, original {}, correct failed" .format(ship.id, original_move)) else: logging.info( "Ship - get_random_move() - ship {} Collision, original {}, corrected {}" .format(ship.id, original_move, move)) return move
def resolve_halite_move(game, collision): """ :param collision [0:ship1 1:ship2 2:move 3:dest1 4:res_func] :returns Returns the 'o' or the lateral move based on the one with the most halite. 'o' gets a 10% preference. """ ship = collision[0] move = collision[2] position = collision[3] if DEBUG & (DEBUG_NAV): logging.info("Nav - ship {} - Resolving density move".format(ship.id)) move_offsets = Direction.laterals(DIRECTIONS[move]) move_offsets.append(Direction.Still) move_offsets.append(Direction.invert(DIRECTIONS[move])) best_moves = [] for o in move_offsets: pos = ship.position.directional_offset(o) cell = game.game_map[pos] if o == Direction.Still: val = cell.halite_amount * 1.1 elif o == Direction.invert(DIRECTIONS[move]): val = cell.halite_amount * .5 else: val = cell.halite_amount best_moves.append((cell, val, o)) best_moves.sort(key=lambda item: item[1], reverse=True) new_offset = None new_cell = None # try the cells to the left/right of the direction orginally attempted in order of # desirability. Additionally check staying still. for m in best_moves: if not m[0].is_occupied: new_offset = m[2] new_cell = m[0] break; # if no cell available, we know ship lost it's original cell, and the two lateral moves are # blocked, try the only remaining option, the inverse of the original, otherwise rewind if new_offset is None: cnt = unwind(game, ship) if DEBUG & (DEBUG_NAV): logging.info("Nav - ship {} - Resolve failed, Unwinding {} ships and using 'o'".format(ship.id, cnt)) #game_map[ship].mark_unsafe(ship) # unwind will mark the cell unsafe move = 'o' else: if DEBUG & (DEBUG_NAV): logging.info("Nav - ship {} - Resolved by best cell {}".format(ship.id, new_cell.position)) new_cell.mark_unsafe(ship) move = Direction.convert(new_offset) if DEBUG & (DEBUG_NAV): logging.info("Nav - ship {} - Successfully resolved density move collision. Move: {}".format(ship.id, move)) return move
def side_or_side(ship, destination, game_map): possible_moves = Direction.get_all_cardinals() direct_move = game_map.get_unsafe_moves(ship.position, destination) possible_moves.remove(direct_move[0]) possible_moves.remove(Direction.invert(direct_move[0])) next_step = random.choice(possible_moves) if game_map[ship.position.directional_offset( next_step)].is_occupied is True: possible_moves.remove(next_step) return possible_moves[0] else: return next_step
def getShipMove(ship,sy): bestSpot = [] best = 0 amount = 820 if game_map[game_map.normalize(ship.position)].halite_amount < constants.MAX_HALITE / 35 and (ship.halite_amount < amount ): for i in Direction.get_all_cardinals(): if(game_map[ship.position.directional_offset(i)].is_occupied == False): bestSpot.append(game_map[ship.position.directional_offset(i)]) for i in bestSpot: if(i.halite_amount > best): #bestDir = game_map.naive_navigate(ship, i.position) best = i.halite_amount bestDir = game_map.get_unsafe_moves(ship.position, i.position)[0] if best < 50: bestDir = Direction.convertStr(random.choice(["n", "s","e","w"])) place = game_map[ship.position.directional_offset((bestDir))].position inPicked = False for i in placepicked: if (i.__eq__(place)): inPicked = True if inPicked == False and game_map[ship.position.directional_offset(bestDir)].is_occupied == False: placepicked.append(ship.position.directional_offset(bestDir)) command_queue.append((ship.move(bestDir))) else: placepicked.append(ship.position) command_queue.append(ship.stay_still()) #returnCommand = (ship.move(bestDir)) else: if ship.is_full or ship.halite_amount > amount: #command_queue.append(game_map.get_unsafe_moves(ship.position, Shipyard)[0]) placeVal = game_map[ship.position.directional_offset(game_map.get_unsafe_moves(ship.position, Shipyard)[0])].position inPicked = False for e in placepicked: if (placeVal.__eq__(e)): inPicked = True if inPicked == True: command_queue.append(ship.stay_still()) placepicked.append(ship.position) else: command_queue.append(ship.move(game_map.naive_navigate(ship, Shipyard))) placepicked.append(placeVal) else: command_queue.append(ship.stay_still()) placepicked.append(ship.position)
def get_dense_move(ship): moves = [] for d in ship.position.get_surrounding_cardinals(): if game_map[ d].halite_amount > constants.MAX_HALITE / 10 and not ship.is_full: moves.append((d.x, d.y, game_map[d].halite_amount)) sorted_moves = sorted(moves, key=lambda item: item[2], reverse=True) logging.info( "Ship - get_dense_move() - sorted_moves {}".format(sorted_moves)) if len(sorted_moves) == 0: move = get_random_move(ship) else: pos = Position(sorted_moves[0][0] - ship.position.x, sorted_moves[0][1] - ship.position.y) logging.info("Ship - ship {} get_dense_move() - pos {}".format( ship.id, pos)) moveOffset = game_map.normalize(pos) logging.info("Ship - ship {} get_dense_move() - moveOffset {}".format( ship.id, moveOffset)) move = Direction.convert( game_map.naive_navigate(ship, ship.position + moveOffset)) logging.info("Ship - ship {} get_dense_move() - move {}".format( ship.id, move)) if move == "o": for i in range(1, len(sorted_moves)): moveOffset = game_map.normalize( Position(sorted_moves[i][0] - ship.position.x, sorted_moves[i][1] - ship.position.y)) logging.info( "Ship - ship {} get_dense_move() - moveOffset {}".format( ship.id, moveOffset)) move = Direction.convert( game_map.naive_navigate(ship, moveOffset)) if move != "o": break if move == "o": logging.info("Ship - ship {} get_dense_move() - noop".format(ship.id)) return move
def findNearTarget(self, ship, maxDis=10): toSearch = deque() seen = set() toSearch.append((0, ship.position)) seen.add(ship.position) def metric(pos): halite = self.command.getHalitePos(pos) # - MINE_T #distance = (self.command.game_map.calculate_distance(pos, self.command.shipyard.position) + self.command.game_map.calculate_distance(pos, ship.position) + 1) distance = ( self.command.game_map.calculate_distance(pos, ship.position) + 1) return halite / distance bestSquare = (metric(ship.position), ship.position) while toSearch: depth, pos = toSearch.popleft() if not self.posAssigned(pos): bestSquare = max((metric(pos), pos), bestSquare) if depth < maxDis: for dir in Direction.get_all_cardinals(): newPos = self.command.game_map.normalize( pos.directional_offset(dir)) if newPos not in seen: seen.add(newPos) toSearch.append((depth + 1, newPos)) if bestSquare[1] != ship.position: return bestSquare[1] return None
def findTarget(self, startHalite, start, maxDis=10): toSearch = deque() seen = set() def evalPoint(halite, distance, pos): r_dis = self.game_map.calculate_distance(pos, start) adjHalite = halite - r_dis * MINE_T // constants.MOVE_COST_RATIO return adjHalite / pow(GROWTH_RATE, distance + r_dis) # Format = (halite, distance, pos) dHal, dDis = squareCost(self.command.game_map[start].halite_amount) toSearch.append((startHalite + dHal, dDis, start)) seen.add(start) best = (evalPoint(halite + dHal, dDis, start), start) while toSearch: halite, dis, pos = heapq.heappop(toSearch) if self.command.game_map.calculateDistance( pos, start) < maxDis and newHalite < RETURN_T: for dir in Direction.get_all_cardinals(): newPos = self.command.game_map.normalize( pos.get_directional_offset(dir)) squareHalite = self.command.game_map[newPos].halite_amount dHalite, dDis = squareCost(squareHalite) newDis = dis + dDis newHalite = min(halite + dHalite, constants.MAX_HALITE) best = max(best, (evalPoint(newHalite, newDis, pos), pos)) if newPos not in seen: toSearch.append((newHalite, newDis, newPos)) seen.add(newPos) if best[1] != start: return best[1] return start
def findNearTargets(self, ship, maxDis=5): toSearch = deque() seen = set() toSearch.append((0, ship.position)) seen.add(tup(ship.position)) bestSquare = (self.command.game_map[ship.position].halite_amount, tup(ship.position)) while toSearch: depth, pos = toSearch.popleft() tPos = tup(pos) #TODO: modify structure of targets so that it is dict for easier search by position or ship id bestSquare = max( (self.command.game_map[pos].halite_amount, tup(pos)), bestSquare) if depth < maxDis: for dir in Direction.get_all_cardinals(): newPos = self.command.game_map.normalize( pos.directional_offset(dir)) newTPos = tup(newPos) if newTPos not in seen: seen.add(newTPos) toSearch.append((depth + 1, newPos)) if bestSquare[1] != tup(ship.position): return bestSquare[1] return None
def get_backoff_point(game, ship, destination): destinationMoves = game.game_map.get_unsafe_moves(ship.position, destination) if len(destinationMoves) == 0: return ship.position choice = random.choice(destinationMoves) backoffDirection = Direction.invert(choice) mult = random.randint(1, 8) backoffPoint = ship.position + Position(backoffDirection[0] * mult, backoffDirection[1] * mult) # if the backup point wrap, truncate it to the edge to prevent simple nav from failing if backoffPoint.x > game.game_map.width - 1: backoffPoint.x = game.game_map.width - 1 if backoffPoint.x < 0: backoffPoint.x = 0 if backoffPoint.y > game.game_map.height - 1: backoffPoint.y = game.game_map.height - 1 if backoffPoint.y < 0: backoffPoint.y = 0 logging.info("Ship - Ship {} backoffPoint {}".format( ship.id, backoffPoint)) return backoffPoint
def get_backoff_point(game, ship, destination): destinationMoves = game.game_map.get_unsafe_moves(ship.position, destination) if len(destinationMoves) == 0: return ship.position choice = random.choice(destinationMoves) backoffDirection = Direction.invert(choice) # when there's a collion, we backoff between 1 and nShips/2 cells mult = random.randint(1, max(1, round(len(game.me.get_ships()) / 2))) backoffPoint = ship.position + Position(backoffDirection[0] * mult, backoffDirection[1] * mult) # if the backup point wrap, truncate it to the edge to prevent simple nav from failing if backoffPoint.x > game.game_map.width - 1: backoffPoint.x = game.game_map.width - 1 if backoffPoint.x < 0: backoffPoint.x = 0 if backoffPoint.y > game.game_map.height - 1: backoffPoint.y = game.game_map.height - 1 if backoffPoint.y < 0: backoffPoint.y = 0 if DEBUG & (DEBUG_NAV): logging.info( "Nav.get_backoff_point() - ship {} has backoffPoint {}".format( ship.id, backoffPoint)) return backoffPoint
def moveShipSmart(self, ship, target, unsafe = False, maxDepth = 10): # Used for seen and keeps track of which cell the best path came from # Except for initial cells which contain direction prevCell = dict() # Cells still to be searched toSearch = list() # We account for cost of current square upon landing in it. # So distance is one less than actual distance def cost(halite, distance): adjustedInv = (ship.halite_amount - halite)/fastPow(GROWTH, distance - 1) return ship.halite_amount - adjustedInv # Estimate total cost as cost up to this point plus cost assuming # some minimum amount of halite in remaining squares def heuristic(pos, halite, distance): furtherDistance = self.game_map.calculate_distance(target, pos) newDistance = distance + furtherDistance expHalite = MINE_T newHalite = halite + furtherDistance * expHalite // constants.MOVE_COST_RATIO return cost(newHalite, newDistance) # Add initial cells to search space for dir in Direction.get_all_cardinals(): newPos = self.game_map.normalize(ship.position.directional_offset(dir)) halite = (self.game_map[ship.position].halite_amount + self.game_map[newPos].halite_amount) // constants.MOVE_COST_RATIO distance = 1 Cost = cost(halite, distance) heapq.heappush(toSearch, (heuristic(newPos, halite, distance), halite, distance, newPos)) prevCell[newPos] = (Cost, ship.position, dir) curr = target # Search for target while toSearch: adjCost, halite, distance, pos = heapq.heappop(toSearch) if pos == target: curr = pos break for dir in self.game_map.get_unsafe_moves(pos, target): newPos = self.game_map.normalize(pos.directional_offset(dir)) newHalite = halite + self.game_map[newPos].halite_amount // constants.MOVE_COST_RATIO newDistance = distance + 1 Cost = cost(newHalite, newDistance) if newPos not in prevCell: heapq.heappush(toSearch, (heuristic(newPos, newHalite, newDistance), newHalite, newDistance, newPos)) prevCell[newPos] = (Cost, pos, dir) else: prevCell[newPos] = min(prevCell[newPos], (Cost, pos, dir)) logging.info(prevCell) # Find original cell while prevCell[curr][1] != ship.position: logging.info(curr) curr = prevCell[curr][1] return self.moveShip(ship, prevCell[curr][2])
def get_surrounding_cardinals(pos): """ :return: Returns a list of all positions around this specific position in each cardinal direction """ return [ pos.directional_offset(current_direction) for current_direction in Direction.get_all_cardinals() ]
def check_cycle(self): if len(self) == 4: if self[0] == self[2] and self[1] == self[3] and Direction.invert( self[0]) == self[1]: return True if self[0] == self[1] == self[2] == self[3] == Direction.Still: return True return False
def get_valid_position(self, vertex): directions = Direction.get_all_cardinals() shuffle(directions) possible_positions = [ vertex.directional_offset(direction) for direction in directions ] for index, position in enumerate(possible_positions): if self.tup(position) not in utils.tiles_visited: return directions[index]
def navigateShip(): if safeMoveCheck(): command_queue.append( ship.move(game_map.naive_navigate(ship, ship_target[ship.id]))) else: command_queue.append( ship.move( Direction.invert( game_map.naive_navigate(ship, ship_target[ship.id]))))
def dir_to_dest(self, pos, dest): """ Precondition: position one move away """ normalized_dest = self.game_map.normalize(dest) for d in Direction.get_all_cardinals(): new_pos = self.game_map.normalize(pos.directional_offset(d)) if new_pos == normalized_dest: return d return Direction.Still # should never happen
def get_random_direction(self, ship=None): direction_list = Direction.get_all_cardinals() direction = random.choice(direction_list) if ship is not None: if ship.position.directional_offset(direction) == self.game.me.shipyard.position: direction_list.remove(direction) direction = random.choice(direction_list) return direction
def navigateShip(): if game_map[ship.position].halite_amount * .1 <= ship.halite_amount: if safeMoveCheck(): command_queue.append( ship.move(game_map.naive_navigate(ship, ship_target[ship.id]))) else: command_queue.append( ship.move( Direction.invert( game_map.naive_navigate(ship, ship_target[ship.id]))))
def get_best_move(self, move_dict, description, crash_base=False): for ship in move_dict: if ship.id in self.can_not_move: #Can't move self.commands.append(f'm {ship.id} o') self.moves.append(str(ship.position)) continue for i in range(len(move_dict[ship])): if self.valid_move(move_dict[ship][i][2]): # logging.info(f"VALID MOVE {description} Ship ID: {ship.id} H/M/P: {move_dict[ship][i]}") self.moves.append(str(move_dict[ship][i][2])) direction = Direction.convert(move_dict[ship][i][1]) self.commands.append(f'm {ship.id} {direction}') break else: if crash_base == True and move_dict[ship][i][0] == 0: self.moves.append(str(move_dict[ship][i][2])) direction = Direction.convert(move_dict[ship][i][1]) self.commands.append(f'm {ship.id} {direction}') break
def get_jiggle_dirs(moves): all = {Direction.North, Direction.South, Direction.East, Direction.West} if len(moves) == 0: return set() elif len(moves) == 1: return all - {moves[0], Direction.invert(moves[0])} else: return all - set(moves)
def _get_homing_next_move(self, shippos, gmap): drops = self.game.me.get_dropoffs() drops.append(self.game.me.shipyard) # trying to add shipyard near_drop = drops[0] for drop in drops: if gmap.calculate_distance( shippos, drop.position) < gmap.calculate_distance( shippos, near_drop.position): near_drop = drop return Direction.convert( gmap.naive_navigate(self.ship, near_drop.position))
def get_safe_random_direction(ship: Ship, game_map: GameMap): safe_choices = [] for direction in Direction.get_all_cardinals(): if not game_map[ship.position.directional_offset( direction)].is_occupied: safe_choices.append(direction) if safe_choices: chosen_direction = random.choice(safe_choices) game_map[ship.position.directional_offset( chosen_direction)].mark_unsafe(ship) return chosen_direction return None
def go_home(): home_position = find_closest_home(ship_position) moves = game_map.get_unsafe_moves( ship_position, home_position)[::-1] # invert x/y priority on return for move in moves: assign(move) if len(moves) == 1: assign_still() my_move = moves[0] to_assign.discard( Direction.invert(my_move) ) # don't walk back, but you can go on the sides
def decision(ship): # returns a list of priority moves with corresponding destination rep = [] ship_position = ship.position ship_halite = ship.halite_amount to_assign = set( chain([Direction.Still], Direction.get_all_cardinals())) for one_move in to_assign.copy(): if normalize_position( ship_position.directional_offset( one_move)) in basic_occupied_cells: to_assign.remove(one_move) map_to_cell = { d: ship_position.directional_offset(d) for d in to_assign } def assign(move): if move in to_assign: rep.append((move, normalize_position(map_to_cell[move]))) to_assign.remove(move) def assign_still(): assign(Direction.Still) def go_home(): home_position = find_closest_home(ship_position) moves = game_map.get_unsafe_moves( ship_position, home_position)[::-1] # invert x/y priority on return for move in moves: assign(move) if len(moves) == 1: assign_still() my_move = moves[0] to_assign.discard( Direction.invert(my_move) ) # don't walk back, but you can go on the sides if ship_halite >= 0: go_home() assign_still() # learn to wait in line # return rep else: for move in to_assign: assign(move) return rep
def get_move_d(ship, game_map, safe_map): r = 1 max = 0 pos = ship.position all_pos = get_surrounding_cardinals(pos) max_dir = Direction.Still for p in all_pos: distance = Position(abs(p.x - pos.x), abs(p.y - pos.y)) y_cardinality, x_cardinality = _get_target_direction(pos, p) p = game_map.normalize(p) if safe_map[p.y][p.x] < 1 and game_map[p].halite_amount >= max: max = game_map[p].halite_amount if distance.x != 0: max_dir = (x_cardinality if distance.x < (game_map.width / 2) else Direction.invert(x_cardinality)) if distance.y != 0: max_dir = (y_cardinality if distance.y < (game_map.height / 2) else Direction.invert(y_cardinality)) #return max_dir return max_dir
def get_unsafe_moves(game_map, source, destination): """ Return the Direction(s) to move closer to the target point, or empty if the points are the same. This move mechanic does not account for collisions. The multiple directions are if both directional movements are viable. :param source: The starting position :param destination: The destination towards which you wish to move your object. :return: A list of valid (closest) Directions towards your target. """ possible_moves = [] #distance = abs(destination - source) distance = Position(abs(destination.x - source.x), abs(destination.y - source.y)) y_cardinality, x_cardinality = _get_target_direction(source, destination) if distance.x != 0: possible_moves.append(x_cardinality if distance.x < ( game_map.width / 2) else Direction.invert(x_cardinality)) if distance.y != 0: possible_moves.append(y_cardinality if distance.y < ( game_map.height / 2) else Direction.invert(y_cardinality)) return possible_moves
def get_move_max(ship, game_map, safe_map, other_ships): r = 1 max = 0.25 * game_map[ship.position].halite_amount pos = ship.position all_pos = get_surrounding_cardinals(pos) max_dir = None pct = 0.35 if game_map.width > 40: pct = 0.4 if ship.halite_amount < 0.1 * game_map[ship.position].halite_amount: return max_dir for p in all_pos: distance = Position(abs(p.x - pos.x), abs(p.y - pos.y)) y_cardinality, x_cardinality = _get_target_direction(pos, p) p = game_map.normalize(p) if game_map[p].halite_amount < 50: continue if is_inspired(p, other_ships): new_amt = 0.5 * game_map[p].halite_amount - pct * game_map[ ship.position].halite_amount else: new_amt = 0.25 * game_map[p].halite_amount - pct * game_map[ ship.position].halite_amount if safe_map[p.y][p.x] != 2 and (new_amt) > max: #max_pos = p max = new_amt if distance.x != 0: max_dir = (x_cardinality if distance.x < (game_map.width / 2) else Direction.invert(x_cardinality)) if distance.y != 0: max_dir = (y_cardinality if distance.y < (game_map.height / 2) else Direction.invert(y_cardinality)) #return max_dir return max_dir