def is_route_efficient_to_chunk(route, chunk): distance_w2o = distance(route.w.pos, route.o.pos) for ch_route in chunk.routes: distance_o2o = distance(ch_route.o.pos, route.o.pos) if (distance_w2o < distance_o2o): return False return True
def update(self): self._i -= 1 if distance(self.owner, self.target) > self.owner.shoot_range: self.chase_target() elif self._i > 0: self.stop() else: self.owner.attack(self.target) self._i = self.reload_time super().update()
def o_fulfilment_cost(o_fulfilment): cost = 0 o, o_fulfilment = o_fulfilment # give me all the warehouse IDs from which this fulfilment would # get the product w_ids = [o_item_fulfilment[1] for o_item_fulfilment in o_fulfilment] for w_id in w_ids: cost += 2 * distance(initial_state.warehouses[w_id].pos, o.pos) return cost
def find_drone_action_for_warehouse(state, d, w): o_deliverable_fully = [] o_other = [] for o in state.open_orders: if o.delivered(): continue o_deliverable_weight = 0 o_deliverable_items = [] o_undeliverable_weight = 0 # lets create copy of warehouse so we can check that the stock # is enough temp_w = copy.deepcopy(w) for item in o.items: if o.delivered(): continue if item.delivered: continue pt_weight = world.pt_weights[item.pt_id] if temp_w.stock[item.pt_id] > 0: # item in warehouse stock temp_w.stock[item.pt_id] -= 1 o_deliverable_weight += pt_weight o_deliverable_items.append(item) else: # item not in warehouse stock o_undeliverable_weight += pt_weight # print('@') # print(str(o.id)) # print(str(o_deliverable_weight)) # print((o_undeliverable_weight == 0 and o_deliverable_weight < world.d_max_payload)) if o_deliverable_weight == 0: # nothing in this warehouse for the order pass elif o_undeliverable_weight == 0 and o_deliverable_weight < world.d_max_payload: # lets log orders which we can fully deliver from this warehouse # by just one drone flight o_deliverable_fully.append(o) else: o_other.append((o, o_deliverable_items, o_deliverable_weight, o_undeliverable_weight)) # if there are some orders which can be delivered fully, do that! if len(o_deliverable_fully) > 0: o_deliverable_fully.sort(key = lambda o: distance(o.pos, d.pos)) o = o_deliverable_fully[0] return (w, o, [i for i in o.items if not i.delivered]) if len(o_other) == 0: # there is no order, we got it all! return None # otherwise find the order with lowest deliverable weight o_other.sort(key = lambda x: x[2]) o, o_deliverable_items, a, b = o_other[0] # and limit the number of items based on max payload deliver_items = [] deliver_weight = 0 for item in o_deliverable_items: pt_weight = world.pt_weights[item.pt_id] if (deliver_weight + pt_weight) <= world.d_max_payload: deliver_items.append(item) deliver_weight += pt_weight return (w, o, deliver_items)
idle_drones = [d for d in state.drones if d.turns_to_pos == 0] for d in idle_drones: # find action to do action = find_drone_action(state, d) if action == None: continue w, o, items_to_deliver = action turns_till_idle_again = 0 # drone has to get to the warehouse first turns_till_idle_again += distance(d.pos, w.pos) print(" * sending drone " + str(d.id) + " to warehouse " + str(w.id) + " at " + str(w.pos[0]) + "-" + str(w.pos[1]) + " (distance: " + str(distance(d.pos, w.pos)) + ")") # load stuff from warehouse for item in items_to_deliver: output.load(d.id, w.id, item.pt_id, 1) print(" * loading drone " + str(d.id) + " with product " + str(item.pt_id)) print(" $ stock of " + str(item.pt_id) + " at warehouse " + str(w.id) + " was " + str(w.stock[item.pt_id]) + ", is now " + str(w.stock[item.pt_id] - 1)) w.stock[item.pt_id] -= 1 # every load command takes one turn turns_till_idle_again += 1 # drone has to get to order turns_till_idle_again += distance(w.pos, o.pos)
def warehouses_closest_first(warehouses, o_pos): return sorted(warehouses, key = lambda w: distance(w.pos, o_pos))
def chunk_routes(world, routes): routes_by_w = grouped_routes_by_warehouse_id(routes) chunks = [] for w_id, w_routes in routes_by_w.items(): w_routes_heaviest_first = sorted_routes_heaviest_first(w_routes) w = w_routes_heaviest_first[0].w chunk = RoutesChunk() chunk.w = w chunk.routes = [] chunk.weight = 0 while True: rel_route = w_routes_heaviest_first.pop(0) chunk.routes.append(rel_route) chunk.weight += rel_route.weight routes_with_closest_o = sorted(w_routes_heaviest_first, key = lambda r: distance(r.o.pos, rel_route.o.pos)) for route in routes_with_closest_o: if (chunk.weight + route.weight) > world.d_max_payload: continue if distance(route.o.pos, rel_route.o.pos) > distance(route.o.pos, route.w.pos): continue # TODO: also! if we will chunk together routes with same products, # it will in the end save turns on loading (might be interesting?) # print("distance " + str(distance(route.o.pos, rel_route.o.pos))) w_routes_heaviest_first.remove(route) chunk.routes.append(route) chunk.weight += route.weight chunks.append(chunk) chunk = RoutesChunk() chunk.w = w chunk.routes = [] chunk.weight = 0 if len(w_routes_heaviest_first) == 0: break for chunk in chunks: chunk.items_by_o_id_and_pt_id = {} chunk.items_by_pt_id = {} for route in chunk.routes: if route.o.id not in chunk.items_by_o_id_and_pt_id: chunk.items_by_o_id_and_pt_id[route.o.id] = {} for item in route.items: if item.pt_id not in chunk.items_by_o_id_and_pt_id[route.o.id]: chunk.items_by_o_id_and_pt_id[route.o.id][item.pt_id] = [] if item.pt_id not in chunk.items_by_pt_id: chunk.items_by_pt_id[item.pt_id] = [] chunk.items_by_o_id_and_pt_id[route.o.id][item.pt_id].append(item) chunk.items_by_pt_id[item.pt_id].append(item) for chunk in chunks: chunk.avg_routes_per_order = 0 chunk.min_routes_per_order = chunk.routes[0].routes_per_order for route in chunk.routes: chunk.avg_routes_per_order += route.routes_per_order if route.routes_per_order < chunk.min_routes_per_order: chunk.min_routes_per_order = route.routes_per_order chunk.avg_routes_per_order = chunk.avg_routes_per_order / len(chunk.routes) # chunks1 = sorted(chunks, key = lambda ch: ch.weight, reverse = True) # for chunk in chunks1: # print(str(chunk.weight) + " " + str(len(chunk.routes))) # print('all: ' + str(len(chunks))) # # chunks2 = list(filter(lambda ch: ch.weight == world.d_max_payload, chunks)) # print('full weight: ' + str(len(chunks2))) # # chunks3 = list(filter(lambda ch: ch.weight > 190, chunks)) # print('> 190: ' + str(len(chunks3))) # # chunks4 = list(filter(lambda ch: ch.weight > 180, chunks)) # print('> 180: ' + str(len(chunks4))) # # chunks5 = list(filter(lambda ch: ch.weight > 170, chunks)) # print('> 170: ' + str(len(chunks5))) # # sys.exit(0) return chunks