def step(self): super().before_step() if self.at_base() and self.cargo: self.emit_event(0, "ORE_DELIVERY", self.cargo, BASE) self.cargo = 0 if self.full(): self.state = "MOVE_TO_TARGET" self.target = self.base.pos() if self.state == 'IDLE': # Look for explorers and follow one of the nearest ones. # If there are none, go to the base. agents = self.box_scan(self.mp.P // 2) self.energy -= self.mp.P explorers = [a for a in agents if EXPLORER in a.group_ids] transporters = [a for a in agents if TRANSPORTER in a.group_ids] if explorers: self.target = random.choice(explorers).pos() if transporters: if random.random() < 1 - 1 / (len(transporters) + 1): v = random.choice(transporters).vec_to(self.pos()) v = v.normalize( ) if not v.is_zero_vec() else Vec2D.random_dir() v *= 10 self.target = self.world.torus(self.pos() + v.round()) else: self.target = self.base.pos() self.target = self.base.pos() # TODO: temp self.state = 'MOVE_TO_TARGET' elif self.state == 'MOVE_TO_TARGET': if self.reached_target(): self.state = 'IDLE' if not self.ores else 'COLLECT_ORES' else: if self.move_towards(self.target) or self.move_in_dir( Vec2D.random_grid_dir()): self.energy -= self.mp.Q elif self.state == 'COLLECT_ORES': ore_idx, ore_pos = self.ores[0] if ore_pos == self.pos(): self.ores.pop(0) if self.try_collect_ore(ore_idx): self.cargo += 1 else: self.failed_collect_attempts += 1 if self.failed_collect_attempts >= 2: # two failed attempts in a row self.ores = [] if len(self.ores) == 0: self.state = 'IDLE' self.energy -= 1 else: if self.move_towards(ore_pos) or self.move_in_dir( Vec2D.random_grid_dir()): self.energy -= 1 else: assert False, "shouldn't reach unknown state: '{}'".format( self.state) super().after_step()
def main(): l = [Vec2D(0, 0), Vec2D(10, 10), Vec2D(0, 0), Vec2D(10, 10)] tsm_idx = iterative_inf_norm_tsm(l) ll = [l[i] for i in tsm_idx] old_dist = calc_travel_inf_dist(l) new_dist = calc_travel_inf_dist(ll) assert old_dist == 30 assert new_dist == 10 print('test succeeded')
def create_world(mp: MasParams): world = World(w=mp.G, h=mp.G, torus_enabled=True) n_ores = round(mp.G**2 * mp.D) for _ in range(n_ores): world.add_agent(Ore()) positions = [] for x in range(mp.G): for y in range(mp.G): positions.append(Vec2D(x, y)) base_positions = random.sample(positions, mp.N) if mp.M == 1: # cooperation company_ids = [0] * mp.N else: # competitive company_ids = list(range(mp.N)) for base_pos, comp_id in zip(base_positions, company_ids): base = Base(mp, comp_id) world.add_agent(base, base_pos) for _ in range(mp.X): world.add_agent(Explorer(base, mp, comp_id), pos=base_pos) for _ in range(mp.Y): world.add_agent(Transporter(base, mp, comp_id), pos=base_pos) return world
def initialize(self): # Create a target a bit off center to view the torus effect # self.world is set on the agent when added to a world, # so the world can be accessed within the agent methods self.start_target = Vec2D( math.floor(self.world.w * 0.25), math.floor(self.world.h * 0.25) )
def step(self): if not self.reached_target: self.move_towards(self.start_target) self.reached_target = self.pos() == self.start_target else: near_agents = self.box_scan(10, sort=False) if near_agents: self.color = Colors.RED if random.random() < 0.2: self.move_rel(Vec2D.random_grid_dir()) else: other_agent = random.choice(near_agents) self.move_away_from(other_agent.pos()) else: self.color = Colors.BLUE
def initialize(self): self.group_collision_ids = {2, 3} self.color = Colors.RED self.destination = Vec2D(random.randint(0,world.h), random.randint(0,world.h)) self.current_ore = [] self.ore_to_pick_up = [] self.ore_in_inventory = [] self.state = "Searching" self.counter = 0 self.current_energy = self.energy_capacity self.bases = [] for i in range(len(world.agents)): if world.agents[i].group_ids == {0}: self.bases.append(world.agents[i]) self.memory_capacity = self.memory_capacity - len(self.bases) pass
def initialize(self): self.group_collision_ids = {2, 3} self.color = Colors.GREEN self.destination = Vec2D(random.randint(0,world.h), random.randint(0,world.h)) self.temp_ore = set() self.current_energy = self.energy_capacity self.state = "Exploring" self.counter = 0 self.bases = [] self.perception_radius = P self.communication_radius = I for i in range(len(world.agents)): if world.agents[i].group_ids == {0}: self.bases.append(world.agents[i]) self.memory_capacity = self.memory_capacity - len(self.bases) pass
def draw_sample(T): #world = World(200, 200, max_steps=T) world = World(w=mining.G, h=mining.G, torus_enabled=True, max_steps=T) # Add the agents to the world. base_logger = AgentCountLogger() BaseLog = base_logger.bind(mining.Base) for _ in range(mining.N): world.add_agent(BaseLog(), pos = Vec2D(random.randint(0,world.h), random.randint(0,world.h))) # Dispurse robots equally amongst bases initially explorer_logger = AgentCountLogger() ExplorerLog = explorer_logger.bind(mining.Explorer) for _ in range(mining.X): for j in range(mining.N): world.add_agent(ExplorerLog(), pos = world.agents[j].pos()) transporter_logger = AgentCountLogger() TransporterLog = transporter_logger.bind(mining.Transporter) for _ in range(mining.Y): for j in range(mining.N): world.add_agent(TransporterLog(), pos = world.agents[j].pos()) # Add ore on the map (as agents) ore_total = world.w * world.h * mining.D # The density of ores is multiplied with the mapsize to make the correct amount of ore ore_logger = AgentCountLogger() OreLog = ore_logger.bind(mining.Ore) for _ in range(int(ore_total)): world.add_agent(OreLog()) explorer_counts = [] transporter_counts = [] base_counts = [] ore_counts = [] while not world.ended: explorer_counts.append(explorer_logger.count) transporter_counts.append(transporter_logger.count) base_counts.append(base_logger.count) ore_counts.append(ore_total - ore_logger.count) world.step() #vis = Visualizer(world, target_speed=25) #vis.start() return [explorer_counts, transporter_counts, ore_counts] # [explorer_counts, transporter_counts, base_counts]
def step(self): ##################################################################################### if self.dist(self.bases[self.find_nearest_base()].pos()) + 10 > self.current_energy: #print("Explorer " + str(self.idx) + " almost out of energy. Returning to base") self.state = "Returning" if self.state == "Exploring": if self.counter < 15 : self.move_towards(self.destination) self.group_collision_ids = {2, 3} self.consume_energy(Q) self.counter = self.counter + 1 else: self.temp_ore = self.box_scan(rng = self.perception_radius, group_id = 1) #Only performs scans when moving while len(self.temp_ore) > self.memory_capacity: self.temp_ore.pop() self.consume_energy(self.perception_radius) #Consuming energy due to perception radius if self.temp_ore != None: self.emit_event(self.communication_radius, "Pickup request", self.temp_ore) self.consume_energy(1) # Consume energy due to communication # Reset the counter and make a new destination self.counter = 0 self.destination = Vec2D(random.randint(0,world.h), random.randint(0,world.h)) ##################################################################################### elif self.state == "Returning": self.destination = world.agents[self.find_nearest_base()].pos() self.move_towards(self.destination) self.consume_energy(Q) if self.pos() == self.destination: self.group_collision_ids = set() #print("Explorer reached base. Recharging energy") self.current_energy = self.energy_capacity self.counter = 0 self.state = "Exploring" if self.current_energy <= 0: print("Agent " + str(self.idx) + " died") world.remove_agent(self.idx) pass
def main(): world = World(w=G, h=G, torus_enabled=True, max_steps=T) # create world, torus or not # Add the agents to the world. for _ in range(N): world.add_agent(Base(), pos = Vec2D(random.randint(0,world.h), random.randint(0,world.h))) # Dispurse robots equally amongst bases initially for _ in range(X): for j in range(N): world.add_agent(Explorer(), pos = world.agents[j].pos()) for _ in range(Y): for j in range(N): world.add_agent(Transporter(), pos = world.agents[j].pos()) # Add ore on the map (as agents) ore_total = world.w * world.h * D # The density of ores is multiplied with the mapsize to make the correct amount of ore for _ in range(int(ore_total)): world.add_agent(Ore()) # The world proceeds by calling 'world.step()' while not world.ended: world.step()
def initialize(self): self.group_collision_ids = {2, 3} self.color = Colors.GREEN self.destination = Vec2D(random.randint(0,self.world.h), random.randint(0,self.world.h)) self.temp_ore = [] self.discovered_ore = [] self.ore_to_forget = [] self.current_energy = self.energy_capacity self.state = "Exploring" self.counter = 0 self.bases = [] self.perception_radius = P self.communication_radius = I self.current_friend = None self.exploration_radius = random.randint(15, 30) for i in range(len(self.world.agents)): if self.world.agents[i].group_ids == {0}: self.bases.append(self.world.agents[i]) self.memory_capacity = self.memory_capacity - len(self.bases) pass
def step(self): self.move_rel(Vec2D.random_grid_dir()) self.emit_event(brush_radius, "PAINT", self.pos())
if event_type == "PAINT": emit_pos = data dir = -self.vec_to(emit_pos) dist = dir.magnitude() dir_angle = (dir.angle() + (self.world.time * 0.1)) % (math.pi * 2) hue = dir_angle / (2 * math.pi) if dist < brush_radius: self.color = colorsys.hsv_to_rgb(hue, 1, 1) if dist < brush_radius * 0.5: self.color = Colors.WHITE for x in range(size): for y in range(size): world.add_agent(Canvas(), Vec2D(x, y)) class Brush(Agent): color = Colors.WHITE start_target: Vec2D = None reached_target = False def step(self): self.move_rel(Vec2D.random_grid_dir()) self.emit_event(brush_radius, "PAINT", self.pos()) world.add_agent(Brush(), Vec2D(size // 2, size // 2)) vis = Visualizer(world, scale=3, target_speed=100)
def step(self): if not self.world.ended: ##################################################################################### if self.dist(self.bases[self.find_nearest_base()].pos()) + 15 > self.current_energy: self.state = "Returning" if self.state == "Exploring": if self.counter < self.exploration_radius : self.move_towards(self.destination) self.group_collision_ids = {2, 3} self.consume_energy(Q) else: self.temp_ore = self.box_scan(rng = self.perception_radius, group_id = 1) #Only performs scans when moving self.consume_energy(self.perception_radius) #Consuming energy due to perception radius for i in range(len(self.temp_ore)): # Add ore into memory until cap. if len(self.discovered_ore) <= self.memory_capacity and self.temp_ore[i] not in self.discovered_ore: self.discovered_ore.append(self.temp_ore[i]) if self.discovered_ore != None: self.emit_event(self.communication_radius, "Pickup request", self.discovered_ore + [self.idx]) self.consume_energy(1) # Consume 1 energy unit due to communication if len(self.discovered_ore) == self.memory_capacity: self.state = "Requesting" # Reset the counter and make a new destination self.counter = 0 self.destination = Vec2D(random.randint(0,self.world.h), random.randint(0,self.world.h)) ##################################################################################### elif self.state == "Requesting": # Counter has just been set to zero and we already have a new destionation, # but we stay (using that counter) until a Transporter has releived us of some memory-space if self.counter % 5 == 0: # Tries 10 times every fifth step to make pickup-request self.emit_event(self.communication_radius, "Pickup request", self.discovered_ore) self.consume_energy(1) # Consume 1 energy unit due to communication if self.counter > 50 : # Give up and go exploring again... will in reality only move once and try again self.counter = 0 self.state = "Exploring" self.discovered_ore = [] ##################################################################################### elif self.state == "Choosing": if self.discovered_ore != []: for i in range(len(self.ore_to_forget)): if self.ore_to_forget[i] in self.discovered_ore: self.discovered_ore.remove(self.ore_to_forget[i]) self.emit_event(self.communication_radius, "Choose transporter", [self.current_friend, self.idx]) self.current_friend = None self.state = "Exploring" # Now the explorers should not get stuck.... ##################################################################################### elif self.state == "Returning": self.destination = self.world.agents[self.find_nearest_base()].pos() self.move_towards(self.destination) self.consume_energy(Q) if self.pos() == self.destination: # Maybe change this into dist(pos, base)< 1.5 (lidt snyd) self.group_collision_ids = set() self.current_energy = self.energy_capacity self.exploration_radius = random.randint(15, 30) self.counter = 0 self.destination = Vec2D(random.randint(0,self.world.h), random.randint(0,self.world.h)) self.discovered_ore = [] self.current_friend = None self.state = "Exploring" if self.current_energy <= 0: print("Agent " + str(self.idx) + " died") self.world.remove_agent(self.idx) self.counter = self.counter + 1 pass
def step(self): if not self.world.ended: if self.dist(self.bases[self.find_nearest_base()].pos()) + 15 > self.current_energy: self.destination = self.bases[self.find_nearest_base()].pos() self.state = "Returning" ##################################################################################### if self.state == "Searching": self.group_collision_ids = {2, 3} if self.counter < 20 : self.move_towards(self.destination) self.consume_energy(Q) else: self.counter = 0 self.destination = Vec2D(random.randint(0,self.world.h), random.randint(0,self.world.h)) ##################################################################################### elif self.state == "Pickup" : if len(self.ore_in_inventory) >= self.inventory_capacity: # Inventory full self.destination = self.bases[self.find_nearest_base()].pos() self.state = "Returning" elif len(self.ore_to_pick_up) < 1: self.state = "Searching" else: # Picking a new target self.current_ore = self.ore_to_pick_up[0] #random.randint(0, len(self.ore_to_pick_up)-1) if self.current_ore.idx in self.world.active_agents: #if self.current_ore.picked == False: self.destination = self.current_ore.pos() self.move_towards(self.destination) self.consume_energy(Q) self.state = "Moving" else: self.ore_to_pick_up.remove(self.current_ore) self.state = "Pickup" ##################################################################################### elif self.state == "Moving": self.move_towards(self.destination) self.consume_energy(Q) if self.pos() == self.destination: #deactive ore and remove from memory self.ore_to_pick_up.remove(self.current_ore) if self.current_ore.idx in self.world.active_agents: #if self.current_ore.picked == False: self.current_ore.pickup(self) # Tell the ore that it has been picked up self.ore_in_inventory.append(self.current_ore) self.consume_energy(1) #Picking an ore costs 1 energy self.state = "Pickup" ##################################################################################### elif self.state == "Acknowledging": # self.temp_ore now has as many ores as I can handle. Acknowledge back with my and friend's ID self.emit_event(self.communication_radius, "Pickup acknowledgement", self.temp_ore + [self.current_friend, self.idx]) self.consume_energy(1) self.state = "Pickup" ##################################################################################### elif self.state == "Returning": self.move_towards(self.destination) self.consume_energy(Q) if self.pos() == self.destination : self.group_collision_ids = set() self.bases[self.find_nearest_base()].deposit(self.ore_in_inventory) # Depositing ore into base self.ore_in_inventory = []# Removing ore from inventory' self.current_energy = self.energy_capacity #Recharging #if self.ore_to_pick_up != []: # self.destination = self.ore_to_pick_up[0].pos() #else: # This is not very smart... self.destination = Vec2D(random.randint(0,self.world.h), random.randint(0,self.world.h)) self.state = "Pickup" ##################################################################################### self.counter = self.counter + 1 if self.current_energy <= 0: print("Agent " + str(self.idx) + " died") self.world.remove_agent(self.idx) pass
def step(self): ##################################################################################### if self.dist(world.agents[0].pos()) + 10 > self.current_energy: #print("Transporter " + str(self.idx) + " almost out of energy. Returning to base") self.state = "Returning" if self.state == "Searching": self.group_collision_ids = {2, 3} if self.counter < 15 : self.move_towards(self.destination) self.consume_energy(Q) else: self.counter = 0 self.destination = Vec2D(random.randint(0,world.h), random.randint(0,world.h)) ##################################################################################### elif self.state == "Pickup" : if len(self.ore_in_inventory) > self.inventory_capacity: #print("Inventory full on " + str(self.idx) + ". Returning to base") self.destination = self.bases[self.pick_base()].pos() self.state = "Returning" elif len(self.ore_to_pick_up) < 2: #print("Ran out of ore to find. Searching for an Explorer") self.state = "Searching" else: # Picking a new target self.current_ore = self.ore_to_pick_up[0] #random.randint(0, len(self.ore_to_pick_up)-1) if self.current_ore.picked == False: self.destination = Vec2D(self.current_ore.pos().x, self.current_ore.pos().y) self.move_towards(self.destination) self.consume_energy(Q) self.state = "Moving" else: self.ore_to_pick_up.remove(self.current_ore) self.state = "Pickup" ##################################################################################### elif self.state == "Moving": self.move_towards(self.destination) self.consume_energy(Q) if self.pos() == self.destination: #deactive ore and remove from memory self.ore_to_pick_up.remove(self.current_ore) if self.current_ore.picked == False: #print("Found valid ore. Picking ore from world.") self.current_ore.pickup(self) # Tell the ore that it has been picked up self.ore_in_inventory.append(self.current_ore) self.consume_energy(1) #Picking an ore costs 1 energy self.state = "Pickup" ##################################################################################### elif self.state == "Returning": self.move_towards(self.destination) self.consume_energy(Q) if self.pos() == self.destination : self.bases[self.find_nearest_base()].deposit(self.ore_in_inventory) # Depositing ore into base self.ore_in_inventory = []# Removing ore from inventory' self.current_energy = self.energy_capacity #Recharging self.state = "Searching" #print("Agent number " + str(self.idx) + " has " + str(len(self.ore_to_pick_up)) + " to pick up") self.counter = self.counter + 1 if self.current_energy <= 0: print("Agent " + str(self.idx) + " died") world.remove_agent(self.idx) pass
def step(self): self.move_rel(Vec2D.random_grid_dir())
for i in range(len(data)): if data[i] not in self.ore_to_pick_up:# Make sure there are no duplicates self.ore_to_pick_up.append(data[i]) self.state = "Pickup" if event_type == "Base full": print("Base full, going to returning state" + str(len(data))) self.destination = self.bases[self.pick_base()].pos() self.state = "Returning" pass def cleanup(self): pass # Add the agents to the world. for i in range(N): world.add_agent(Base(), pos = Vec2D(random.randint(0,world.h), random.randint(0,world.h))) # Dispurse robots equally amongst bases initially for i in range(X): for j in range(N): world.add_agent(Explorer(), pos = world.agents[j].pos()) for i in range(Y): for j in range(N): world.add_agent(Transporter(), pos = world.agents[j].pos()) # Add ore on the map (as agents) ore_total = world.w * world.h * D # The density of ores is multiplied with the mapsize to make the correct amount of ore for i in range(int(ore_total)): world.add_agent(Ore())
def step(self): super().before_step() if self.state == "MOVE_TO_TARGET": self.color = Colors.GREEN if self.reached_target(): if self.at_base(): self.dir = Vec2D.random_dir() if self.ore_data: transporters = (self.box_scan(self.mp.P // 2, TRANSPORTER + str(self.company_id)))[:self.mp.S] self.consume_energy(self.mp.P) self.ore_data = (len(transporters), self.ore_data[1]) self.state = "EMIT_EVENT_ORE_POS" else: self.state = "SCAN" else: if not self.move_towards(self.target): self.move_in_dir(Vec2D.random_grid_dir()) self.consume_energy(self.mp.Q) elif self.state == "SCAN": self.color = Colors.GREY25 agents = self.box_scan(self.mp.P // 2) self.consume_energy(self.mp.P) ores = [a for a in agents if ORE in a.group_ids] explorers = [a for a in agents if EXPLORER in a.group_ids] transporters = [a for a in agents if TRANSPORTER in a.group_ids] if ores: rel_ore_pos = [self.vec_to(o.pos()) for o in ores] rel_ore_cog = sum(rel_ore_pos, Vec2D()) / len(ores) if rel_ore_cog.magnitude() > self.mp.P / 4: # TODO: set max iterations self.color = Colors.MAGENTA self.target = self.world.torus(self.pos() + rel_ore_cog.round()) self.state = "MOVE_TO_TARGET" else: rel_ore_pos = [self.vec_to(o.pos()) for o in ores] tsm_idx = tsm.iterative_inf_norm_tsm(rel_ore_pos, n=1000) ores = [ores[i] for i in tsm_idx] ore_data = [(o.idx, o.pos()) for o in ores] self.ore_data = (len(transporters), ore_data) if transporters: self.state = "EMIT_EVENT_ORE_POS" else: self.target = self.base.pos() self.state = "MOVE_TO_TARGET" elif explorers: other_expl = random.choice(explorers) dir = other_expl.vec_to(self.pos()) dir = dir / dir.magnitude() if not dir.is_zero_vec() else Vec2D.random_dir() self.target = self.world.torus(other_expl.pos() + (dir * 20).round()) self.state = "MOVE_TO_TARGET" else: self.set_new_random_rel_target() self.state = "MOVE_TO_TARGET" elif self.state == "EMIT_EVENT_ORE_POS": self.color = Colors.WHITE self.emit_event(self.mp.I // 2, "ORE_POSITIONS", self.ore_data, TRANSPORTER + str(self.company_id)) self.consume_energy(1) self.ore_data = None self.set_new_random_rel_target() self.state = "MOVE_TO_TARGET" super().after_step()
group_ids = {1} group_collision_ids = { 0, 1 } # Not able to enter wall tiles or other Mover tiles def step(self): self.move_rel(Vec2D.random_grid_dir()) # Create walls x1, x2 = round(size * 0.3), round(size * 0.7) y1, y2 = round(size * 0.6), round(size * 0.8) for x in (x1, x2): for y in range(y1 + 1): world.add_agent(Wall(), Vec2D(x, y)) for y in range(y2, size): world.add_agent(Wall(), Vec2D(x, y)) for y in (y1, y2): for x in range(x1 + 1, x2): world.add_agent(Wall(), Vec2D(x, y)) # Add Mover agents for _ in range(200): world.add_agent(Mover(), Vec2D(size // 2, size // 4)) # Start and visualize simulation vis = Visualizer(world, scale=3, target_speed=200) vis.start()