def get_next_direction(self, world, car_id, car): car_x, car_y = index_to_coordinates(car['position'], world['width']) possible_directions = get_possible_directions(world, car['position']) if possible_directions: possible_targets = [] if car['used_capacity'] < car[ 'capacity']: # Case: car has free seats if len(self.get_waiting_customers( world)): # Go to waiting customer closest_customer_id = self.get_closest_waiting_customer( (car_x, car_y), world) closest_customer_pos = world['customers'][ closest_customer_id]['origin'] possible_targets.append(closest_customer_pos) if car['used_capacity'] > 0: # Case: car has customers closest_destination_pos = self.get_closest_destination( (car_x, car_y), car_id, world) possible_targets.append(closest_destination_pos) target_pos = self.get_closest_target((car_x, car_y), possible_targets, world) if target_pos is not None: target_coord = index_to_coordinates(target_pos, world['width']) return self.get_best_direction(world, car_x, car_y, target_coord) return None
def get_closest_waiting_customer(self, position, world): return min( self.get_waiting_customers(world), key=lambda cust_id: self.get_path_length( position, index_to_coordinates(world['customers'][cust_id]['origin'], world['width'])))
def get_next_direction(self, world, car_id, car): car_x, car_y = index_to_coordinates(car['position'], world['width']) possible_directions = get_possible_directions(world, car['position']) if possible_directions: # Case: no waiting customers — we don't move if not len(self.get_waiting_customers(world)): return None target_pos = None # Case: car is empty — move to closest customer state = self.get_next_state(world, car_id, car) self.cars_state[car_id][state] = state if state == 'searching': closest_customer_id = self.get_closest_waiting_customer( (car_x, car_y), world) closest_customer_pos = world['customers'][closest_customer_id][ 'origin'] target_pos = closest_customer_pos self.cars_state[car_id]['curr_customer'] = world['customers'][ closest_customer_id] self.cars_state[car_id]['state'] = 'getting_customer' elif state == 'getting_customer': target_pos = self.cars_state[car_id]['curr_customer']['origin'] elif state == 'delivering': target_pos = self.cars_state[car_id]['curr_customer'][ 'destination'] print(index_to_coordinates(target_pos, world['width'])) elif state == 'switch_delivering': self.cars_state[car_id][ 'curr_customer'] = self.get_closest_delivering_customer( (car_x, car_y), car_id, world) # self.cars_state[car_id]['customers'][-1] target_pos = self.cars_state[car_id]['curr_customer'][ 'destination'] self.cars_state[car_id]['state'] = 'delivering' if target_pos is not None: target_coord = index_to_coordinates(target_pos, world['width']) return self.get_best_direction(world, car_x, car_y, target_coord) return None
def get_closest_target(self, current_coord, target_positions, world): target_positions = [pos for pos in target_positions if pos is not None] if not target_positions: return None if len(target_positions) == 1: return target_positions[0] if len(target_positions) > 1: return min(target_positions, key=lambda position: self.get_path_length( current_coord, index_to_coordinates(position, world['width'])))
def make_graph(world): grid = world['grid'] height, width = world['height'], world['width'] graph: nx.Graph = nx.grid_2d_graph(width, height) for position, status in enumerate(grid): if status is False: x, y = index_to_coordinates(position, width) neighbors = list(graph.neighbors((x, y))) for neighbor in neighbors: graph.remove_edge((x, y), neighbor) return graph
def get_next_state(self, world, car_id, car): state = self.cars_state[car_id]['state'] if state == 'searching': return state elif state == 'getting_customer': if car['position'] == self.cars_state[car_id]['curr_customer'][ 'origin']: self.cars_state[car_id]['customers'].append( self.cars_state[car_id]['curr_customer']) self.cars_state[car_id]['curr_customer'] = None self.cars_state[car_id]['prev_capacity'] += 1 if self.cars_state[car_id]['prev_capacity'] == car['capacity']: state = 'switch_delivering' else: state = 'searching' else: car_x, car_y = index_to_coordinates(car['position'], world['width']) closest_customer_id = self.get_closest_waiting_customer( (car_x, car_y), world) closest_customer_pos = world['customers'][closest_customer_id][ 'origin'] if closest_customer_pos == self.cars_state[car_id][ 'curr_customer']['origin']: state = 'getting_customer' else: state = 'searching' elif state == 'delivering': if car['position'] == self.cars_state[car_id]['curr_customer'][ 'destination']: #self.cars_state[car_id]['customers'].pop() self.cars_state[car_id]['customers'].remove( self.cars_state[car_id]['curr_customer']) self.cars_state[car_id]['prev_capacity'] -= 1 self.cars_state[car_id]['curr_client'] = None if self.cars_state[car_id]['prev_capacity'] > 0: state = 'switch_delivering' else: state = 'searching' else: state = 'delivering' return state
def move_car(self, world, car_id, car, new_direction): if new_direction: old_coordinates = index_to_coordinates(car['position'], world['width']) old_x, old_y = old_coordinates new_coordinates = get_position_after_move(old_x, old_y, new_direction) team_name = world['teams'][str(car['team_id'])]['name'] logging.info( 'Moving car %s of team %s %s (from %s to %s). Score %s', car_id, team_name, new_direction.name, repr(old_coordinates), repr(new_coordinates), world['teams']['0']['score']) move_car(car_id, new_direction, self.token) else: # The car cannot be moved anywhere! A dynamic constraint must have # appeared. Just leave its previous direction as it was logging.info('Car %s cannot move anywhere. Score %s', car_id, world['teams']['0']['score'])
def get_closest_delivering_customer(self, position, car_id, world): return min( self.cars_state[car_id]['customers'], key=lambda cust: self.get_path_length( position, index_to_coordinates(cust['destination'], world['width'])))