def __init__(self,name='Place Holder',station=None, logger=None): self.my_tasks = TaskTracker() self.id = util.register(self) self.name = name if logger: self.logger = logging.getLogger(logger.name + '.' + self.name) elif station: self.logger = logging.getLogger(station.logger.name + '.' + self.name) else: self.logger = logging.getLogger(util.generic_logger.name + '.' + self.name) self.loggername = self.logger.name self.needs = dict() self.needs['Idle Curiosity']=Need('Idle Curiosity', self, 100, 0, 0, self.new_idle_task, None) self.task = None #currently active task self.action = None #placeholder for graphical animation or tweening or w/e self.task_abandon_value = 5 #if a task's importance outweighs the current task by this much, we drop and switch self.location = None self.station = station self.inventory = Stowage(0.5) self.path=None self.held=None self.sprite=None self.xyz = np.array([ 0, 0, 0 ]) self.orientation = np.array([ 0, 0, 0 ]) self.speed = 1.0 #meter per second travel time, "A leisurely float" if self.station is not None: self.station.actors[self.id] = self self.location = self.station.random_location()[1] self.xyz = self.station.loc_to_xyz(self.location) self.refresh_image()
def __init__(self,initial_module=None, name=None, logger=None): self.modules=dict() self.exterior_objects=[] self.resources=ResourceBundle() self.paths=nx.Graph() self.tasks=TaskTracker() self.actors=dict() self.name = name if name else "GenericStation" self.logger = logging.getLogger(logger.name + '.' + self.name) if logger else util.generic_logger if initial_module: self.berth_module(None,None,initial_module,None)
def __init__(self,name='Place Holder',station=None, logger=None): self.my_tasks = TaskTracker() self.id = str(uuid.uuid4()) self.name = name self.logger = logging.getLogger(logger.name + '.' + self.name) if logger else util.generic_logger self.needs = dict() self.needs['Idle Curiosity']=Need('Idle Curiosity', self, 100, 0, 0, self.new_idle_task, None) self.task = None #currently active task self.action = None #placeholder for graphical animation or tweening or w/e self.task_abandon_value = 5 #if a task's importance outweighs the current task by this much, we drop and switch self.location = None self.station = station self.inventory = Stowage(0.5) self.path=None self.held=None self.xyz = np.array([ 0, 0, 0 ]) self.orientation = np.array([ 0, 0, 0 ]) self.speed = 1.0 #meter per second travel time, "A leisurely float" if not hasattr(self,'imgfile'): self.imgfile = "images/placeholder_actor.tif" self.refresh_image()
def __init__(self,initial_module=None, name=None, logger=None, mission_control = None): self.modules=dict() self.id = util.register(self) self.exterior_objects=[] self.resources=ResourceBundle() self.paths=nx.Graph() self.tasks=TaskTracker() self.actors=dict() self.name = name if name else "GenericStation" self.logger = logging.getLogger(logger.name + '.' + self.name) if logger else util.generic_logger self.loggername = self.logger.name self.docked_stations = [] self.location = 'LEO' self.position = 'Approach' self.mission_control = mission_control self.sprite = None self.refresh_image() if initial_module: self.dock_module(None,None,initial_module,None)
class Station(): def __init__(self,initial_module=None, name=None, logger=None, mission_control = None): self.modules=dict() self.id = util.register(self) self.exterior_objects=[] self.resources=ResourceBundle() self.paths=nx.Graph() self.tasks=TaskTracker() self.actors=dict() self.name = name if name else "GenericStation" self.logger = logging.getLogger(logger.name + '.' + self.name) if logger else util.generic_logger self.loggername = self.logger.name self.docked_stations = [] self.location = 'LEO' self.position = 'Approach' self.mission_control = mission_control self.sprite = None self.refresh_image() if initial_module: self.dock_module(None,None,initial_module,None) def __getstate__(self): d = dict(self.__dict__) del d['logger'] return d def __setstate__(self, d): self.__dict__.update(d) self.logger = logging.getLogger(self.loggername) if self.loggername else util.generic_logger def refresh_image(self): if util.GRAPHICS == 'cocos2d': if self.sprite is None: self.sprite = util.Layer() def dock_module(self, my_module, my_dock, module, mod_dock, instant = False): if module and not self.modules: self.modules[module.id]=module module.station = self module.refresh_station() self.paths = module.paths.copy() self.position = 'Docked' return if not my_module: my_module = random.choice( [ self.modules[m] for m in self.modules if self.modules[m].get_random_dock() ] ) if not my_module.id in self.modules: assert False, "Requested module not part of station" if module.id in self.modules: assert False, "Requested new module already part of station" if not my_dock: my_dock = my_module.get_random_dock() if not mod_dock: mod_dock = module.get_random_dock(side_port_allowed=False) #attempt docking assert module.dock(mod_dock, my_module, my_dock) if module.station != self and not module.station in self.docked_stations: #merge stations other_station = module.station n=self.paths.nodes() e=self.paths.edges(data=True) self.paths.add_nodes_from(other_station.paths.nodes()) self.paths.add_edges_from(other_station.paths.edges(data=True)) other_station.paths.add_nodes_from(n) other_station.paths.add_edges_from(e) self.docked_stations.append(other_station) other_station.docked_stations.append(self) module.connect(mod_dock, my_module, my_dock, instant) #remove if hanging outside if module in self.exterior_objects: self.exterior_objects.remove(module) #merge resources self.resources.grow() self.modules[module.id]=module self.logger.info(''.join(["Modules berthed: ",my_module.short_id,'(',my_dock,')',' to ',module.short_id,'(',mod_dock,')'])) def join_station(self, other_station): if not other_station in self.docked_stations: self.logger.warning('Attempting to join two stations that are apparently not docked.') for m in other_station.modules.keys(): other_station.modules[m].station = self other_station.modules[m].refresh_station() if not m in self.modules: self.modules[m] = other_station.modules[m] else: self.modules[other_station.modules[m].id] = other_station.modules[m] other_station.modules.pop(m) for a in other_station.actors.keys(): other_station.actors[a].station = self self.actors[a] = other_station.actors[a] self.actors[a].refresh_station() other_station.actors.pop(a) if other_station in self.docked_stations: self.docked_stations.remove(other_station) def percolate_location(self,init_mod): self.reset_module_touches() init_mod.percolate_location() def split_station(self, docking_ring): '''Splits off the module WITH the given docking ring into a new station, percolates it to connected modules''' if not docking_ring or not docking_ring.installed or not docking_ring.docked: return self.reset_module_touches() docking_ring.docked.touched = True new_station_list = docking_ring.installed.percolate() if len(new_station_list) == len(self.modules.values()) -1: self.logger.warning(''.join(["Attempting to split a doubly or-higher connected module from station"])) pass #Validate new station for n in new_station_list: if n.manifest and not n.manifest.satisfied: self.logger.info("Station splitting failed: at least one split module has unsatisfied manifest!") return False new_station = Station(None, "Return Station", self.logger) new_station.position='Docked' self.docked_stations.append(new_station) new_station.docked_stations.append(self) new_station.paths.add_nodes_from(self.paths.nodes()) new_station.paths.add_edges_from(self.paths.edges(data=True)) util.scenario.add_station(new_station) for a in self.actors.keys(): if self.get_module_from_loc(self.actors[a].location) in new_station_list: self.actors[a].station = new_station new_station.actors[a] = self.actors[a] self.actors[a].refresh_station() self.actors.pop(a) for m in new_station_list: m.station = new_station new_station.modules[m.id] = m m.refresh_station() self.modules.pop(m.id) self.logger.info(''.join(["Successfully split station! New station: ",util.short_id(new_station.id)])) return new_station def undock_station(self,other_station): if other_station == self: return if other_station in self.docked_stations: self.docked_stations.remove(other_station) else: return #prune nodes, edges for n in self.paths.nodes(): if self.get_module_from_loc(n) == None: self.paths.remove_node(n) for e in self.paths.edges(): if not (e[0] in self.paths and e[1] in self.paths): self.paths.remove_edge(e) other_station.undock_station(self) def reset_module_touches(self): for m in self.modules.values(): m.touched=False def get_safe_distance_orient(self): return np.array([-30,-30+60*random.random(),0]), np.array([ -math.pi +2*math.pi*random.random(), 0 ]) def position_at_safe_distance(self,module): station=None if isinstance(module, Station): station = module module = module.modules.values()[0] #TODO calculate boundary of station, multiply by 1.25 safe_location, safe_orient = self.get_safe_distance_orient() module.location = 2*safe_location module.orientation = safe_orient if station is not None: station.percolate_location(module) if not module.station: self.exterior_objects.append(module) module.refresh_image() def begin_docking_approach(self,module,dock=None): dock_comp, d, d = self.search( EquipmentFilter( target='Docking Computer' ) ) if not dock_comp: #TODO fail more gracefully assert False, 'Docking initialized with no active docking computer! WTF mang?' dock_comp.dock_module([module,dock],[None,None]) def begin_undocking_approach(self,module,dock=None): dock_comp, d, d = self.search( EquipmentFilter( target='Docking Computer' ) ) if not dock_comp: #TODO fail more gracefully assert False, 'Undocking initialized with no active docking computer! WTF mang?' dock_comp.undock_module([module,dock]) def get_random_dock(self, side_port_allowed = True, modules_to_exclude=[]): hits=[] for m in [n for n in self.modules.values() if not n in modules_to_exclude]: d = m.get_random_dock( side_port_allowed ) if d: hits.append( [ m, d ] ) random.shuffle(hits) hits.sort(key=lambda tup: tup[0], reverse=True) return hits[0] if hits else [None, None] def search(self, filter_, modules_to_exclude=[]): hits=[] if [m for m in self.modules.values() if not m in modules_to_exclude] == []: return [None, None, None] for m in [n for n in self.modules.values() if not n in modules_to_exclude]: [obj, loc, score] = m.search(filter_) hits.append( [ obj, loc, score ] ) random.shuffle(hits) hits.sort(key=lambda tup: tup[2], reverse=True) #print hits return hits[0] if hits and hits[0][2] else [None, None, None] def random_location(self, modules_to_exclude=[]): if [m for m in self.modules.values() if not m in modules_to_exclude] == []: return [None, None, None] module = random.choice([m for m in self.modules.values() if not m in modules_to_exclude]) return [None, module.filterNode( module.node('Inside') ), None] def update(self,dt): self.resources.update(dt) self.tasks.update(dt) #print [[t.name,str(t.touched)] for t in self.tasks.tasks] for m in self.modules.keys(): if m in self.modules: self.modules[m].update(dt) for a in self.actors.values(): a.update(dt) def loc_to_xyz(self,loc, percolate=True): [ node, name ] = separate_node(loc) module = self.get_module_from_loc(loc, percolate) if name == "Inside": return module.location return module.getXYZ(module.nodes[loc]) def xyz_to_module(self, xyz): pass #needs collision detection def get_module_from_loc(self, loc, percolate=True): [ node, name ] = separate_node( loc ) module = [ self.modules[ m ] for m in self.modules if self.modules[ m ].id == node ] if not module: if percolate: for s in self.docked_stations: new_loc = s.get_module_from_loc(loc,False) if new_loc != None: return new_loc return None return module[ 0 ] def draw(self, window): if not window: return self.logger.warning("Requested draw to Nonetype.") for m in self.exterior_objects: m.draw(window) for m in self.modules.values(): m.draw(window) for a in self.actors: self.actors[a].update_location() self.actors[a].sprite.draw()
class Actor(object): def __init__(self,name='Place Holder',station=None, logger=None): self.my_tasks = TaskTracker() self.id = str(uuid.uuid4()) self.name = name self.logger = logging.getLogger(logger.name + '.' + self.name) if logger else util.generic_logger self.needs = dict() self.needs['Idle Curiosity']=Need('Idle Curiosity', self, 100, 0, 0, self.new_idle_task, None) self.task = None #currently active task self.action = None #placeholder for graphical animation or tweening or w/e self.task_abandon_value = 5 #if a task's importance outweighs the current task by this much, we drop and switch self.location = None self.station = station self.inventory = Stowage(0.5) self.path=None self.held=None self.xyz = np.array([ 0, 0, 0 ]) self.orientation = np.array([ 0, 0, 0 ]) self.speed = 1.0 #meter per second travel time, "A leisurely float" if not hasattr(self,'imgfile'): self.imgfile = "images/placeholder_actor.tif" self.refresh_image() def refresh_image(self): self.img = util.load_image(self.imgfile) def draw(self,window): zoom=util.ZOOM l= self.path.current_coords if (self.path and not self.path.completed) else self.station.loc_to_xyz( self.location ) self.img.blit(zoom*l[0], zoom*l[1], 0) def drop(self): pass #TODO drop held item def new_idle_task(self,timeout,severity): t=Task(''.join(['Satisfy Idle Curiosity']), owner = self, timeout = None, task_duration = 150, severity='IGNORABLE', fetch_location_method=self.station.random_location,logger=self.logger) return t def update(self,dt): self.my_tasks.update(dt) for n in self.needs.values(): n.update(dt) self.inventory.update(dt) if self.task and self.task.task_ended(): self.task=None #'grab new task' _curr_value = -5 if not self.task else self.task.task_value() _new_task = self.my_tasks.fetch_open_task() if not self.station else max(self.my_tasks.fetch_open_task(), self.station.tasks.fetch_open_task()) #print "TASK VALUES", self.my_tasks.fetch_open_task() if _new_task and _new_task.task_value() > _curr_value + self.task_abandon_value: if self.task: self.task.drop() self.task = _new_task self.task.assign(self) #'work on task' if not self.task: return if not self.task.location: self.task.target, self.task.location, d = self.task.fetch_location() #Grab location #print self.task.name, self.task.target, self.task.location if not self.task.location: self.task.drop() self.task=None return if self.location == self.task.location: #work on task #print "Check", self.task.name self.task.do_work(dt) #print [[c.name, c.volume] for c in self.inventory.contents] else: if self.task.location and not self.task.location == self.location: #go to location if self.path and not self.path.completed: self.path.traverse_step(dt*self.speed) else: #print self.task.name, self.task.target, self.task.location new_path = PathingWidget(self,self.station.paths,self.location, self.task.location, self.xyz) if not new_path.valid: assert False, "ERROR: some kind of pathing error!" self.path = new_path self.path.traverse_step(dt*self.speed) def transfer_node(self, new_loc ): '''moving to new node, exchange air flow''' my_mod = self.station.get_module_from_loc( self.location ) new_mod = self.station.get_module_from_loc( new_loc ) my_mod.atmo.mix( new_mod.atmo, 1.0 ) def summarize_needs(self, ret_string=False): if ret_string: out = 'Needs' for n in self.needs.keys(): #print n, self.needs[n].current_severity() out = ''.join([out,'; ',n,'-',self.needs[n].current_severity()]) return out #what a huge PITA return [[n, self.needs[n].current_severity()] for n in self.needs.keys()] def log_status(self): #TODO log task #self.logger.info(self.summarize_needs(True)) self.logger.info(self.task.name if self.task else "Task: idling")
class Actor(object): def __init__(self,name='Place Holder',station=None, logger=None): self.my_tasks = TaskTracker() self.id = util.register(self) self.name = name if logger: self.logger = logging.getLogger(logger.name + '.' + self.name) elif station: self.logger = logging.getLogger(station.logger.name + '.' + self.name) else: self.logger = logging.getLogger(util.generic_logger.name + '.' + self.name) self.loggername = self.logger.name self.needs = dict() self.needs['Idle Curiosity']=Need('Idle Curiosity', self, 100, 0, 0, self.new_idle_task, None) self.task = None #currently active task self.action = None #placeholder for graphical animation or tweening or w/e self.task_abandon_value = 5 #if a task's importance outweighs the current task by this much, we drop and switch self.location = None self.station = station self.inventory = Stowage(0.5) self.path=None self.held=None self.sprite=None self.xyz = np.array([ 0, 0, 0 ]) self.orientation = np.array([ 0, 0, 0 ]) self.speed = 1.0 #meter per second travel time, "A leisurely float" if self.station is not None: self.station.actors[self.id] = self self.location = self.station.random_location()[1] self.xyz = self.station.loc_to_xyz(self.location) self.refresh_image() def __getstate__(self): d = dict(self.__dict__) del d['logger'] del d['sprite'] #d.pop('station') #TODO delete #d.pop('needs')#TODO delete return d def __setstate__(self, d): self.__dict__.update(d) util.register(self,self.id) self.logger = logging.getLogger(self.loggername) if self.loggername else util.generic_logger self.sprite=None self.refresh_image() def refresh_image(self): if gv.config['GRAPHICS'] == 'pyglet': import graphics_pyglet if self.sprite: self.sprite.delete() self.sprite = graphics_pyglet.LayeredSprite(name=self.name,batch=util.actor_batch ) self.sprite.add_layer('ActorBase',util.load_image("images/npc_crafty_bot__x1_idle0_png_1354839494_crop.png")) self.sprite.owner = self def update_location(self): zoom = gv.config['ZOOM'] l= self.path.current_coords if (self.path and not self.path.completed) else self.station.loc_to_xyz( self.location ) self.xyz=l self.sprite.update_sprite(zoom*l[0], zoom*l[1],0) def drop_held(self): if self.held is None: return module = self.station.get_module_from_loc( self.location ) module.stowage.add(self.held) self.held = None def new_idle_task(self,timeout,severity): t=Task(''.join(['Satisfy Idle Curiosity']), owner = self, timeout = None, task_duration = 150, severity='IGNORABLE', fetch_location_method=self.station.random_location,logger=self.logger) return t def refresh_station(self): self.task=None self.path=None #self.xyz = self.station.loc_to_xyz( self.location ) if self.station: self.logger = logging.getLogger(self.station.logger.name + '.' + self.name) def update(self,dt): self.my_tasks.update(dt) for n in self.needs.values(): n.update(dt) self.inventory.update(dt) if self.task and self.task.task_ended(): self.task=None return #'grab new task' _curr_value = -5 if not self.task else self.task.task_value() _new_task = self.my_tasks.fetch_open_task() if not self.station else max(self.my_tasks.fetch_open_task(), self.station.tasks.fetch_open_task()) #print "TASK VALUES", self.my_tasks.fetch_open_task() if _new_task and _new_task.task_value() > _curr_value + self.task_abandon_value: if self.task: self.task.drop() self.task = _new_task self.task.assign(self) self.logger.info("New task:"+self.task.name) #'work on task' if not self.task: return if not self.task.location: self.task.target, self.task.location, d = self.task.fetch_location() #Grab location if not self.task.location: self.task.drop() self.task=None return if self.location == self.task.location: #work on task self.task.do_work(dt) else: if self.task.location and not self.task.location == self.location: #go to location if self.path and not self.path.completed: if not self.path.traverse_step(dt*self.speed): self.logger.warning("Pathing error: Path suddenly invalid "+self.task.name+"!") self.task.drop() self.task=None return else: #print self.task.name, self.task.target, self.task.location new_path = PathingWidget(self,self.station.paths,self.location, self.task.location, self.xyz) if not new_path.valid: self.logger.warning("Pathing error: "+self.task.name+": !") self.task.drop() self.task=None return self.path = new_path self.path.traverse_step(dt*self.speed) def transfer_node(self, new_loc ): '''moving to new node, exchange air flow''' my_mod = self.station.get_module_from_loc( self.location ) new_mod = self.station.get_module_from_loc( new_loc ) my_mod.mix_neighbor(new_mod, 1.0 ) def summarize_needs(self, ret_string=False): if ret_string: out = 'Needs' for n in self.needs.keys(): #print n, self.needs[n].current_severity() out = ''.join([out,'; ',n,'-',self.needs[n].current_severity()]) return out #what a huge PITA return [[n, self.needs[n].current_severity()] for n in self.needs.keys()] def log_status(self): #TODO log task #self.logger.info(self.summarize_needs(True)) self.logger.info(self.task.name if self.task else "Task: idling")
class Station(): def __init__(self,initial_module=None, name=None, logger=None): self.modules=dict() self.exterior_objects=[] self.resources=ResourceBundle() self.paths=nx.Graph() self.tasks=TaskTracker() self.actors=dict() self.name = name if name else "GenericStation" self.logger = logging.getLogger(logger.name + '.' + self.name) if logger else util.generic_logger if initial_module: self.berth_module(None,None,initial_module,None) def berth_module(self, my_module, my_dock, module, mod_dock, instant = False): if module and not self.modules: self.modules[module.id]=module module.station = self module.refresh_equipment() self.paths = module.paths.copy() return if not my_module: my_module = random.choice( [ self.modules[m] for m in self.modules if self.modules[m].get_random_dock() ] ) if not my_module.id in self.modules: assert False, "Requested module not part of station" if module.id in self.modules: assert False, "Requested new module already part of station" if not my_dock: my_dock = my_module.get_random_dock() if not mod_dock: mod_dock = module.get_random_dock(side_port_allowed=False) #attempt docking assert module.berth(mod_dock, my_module, my_dock, instant) #remove if hanging outside if module in self.exterior_objects: self.exterior_objects.remove(module) #merge resources self.resources.grow() self.modules[module.id]=module self.logger.info(''.join(["Modules berthed: ",my_module.short_id,'(',my_dock,')',' to ',module.short_id,'(',mod_dock,')'])) def begin_docking_approach(self,module): #TODO calculate boundary of station, multiply by 1.25 safe_location = np.array([-30,-30+60*random.random(),0]) module.location = safe_location module.orientation = np.array([ -math.pi +2*math.pi*random.random(), 0 ]) self.exterior_objects.append(module) module.refresh_image() dock_comp, d, d = self.search( EquipmentFilter( target='Docking Computer' ) ) if not dock_comp: #TODO fail more gracefully assert False, 'Docking initialized with no active docking computer! WTF mang?' dock_comp.dock_module([module,None],[None,None]) def search(self, filter_): hits=[] for m in self.modules.values(): [obj, loc, score] = m.search(filter_) hits.append( [ obj, loc, score ] ) random.shuffle(hits) hits.sort(key=lambda tup: tup[2], reverse=True) #print hits return hits[0] if hits and hits[0][2] else [None, None, None] def random_location(self): module = random.choice(self.modules.values()) return None, module.filterNode( module.node('Inside') ), None def update(self,dt): self.resources.update(dt) self.tasks.update(dt) for m in self.modules: self.modules[m].update(dt) for a in self.actors: self.actors[a].update(dt) def loc_to_xyz(self,loc): [ node, name ] = separate_node(loc) module = [self.modules[m] for m in self.modules if self.modules[m].id == node] if not module: return None module = module[0] if name == "Inside": return module.location return module.getXYZ(module.nodes[loc]) def xyz_to_module(self, xyz): pass #needs collision detection def get_module_from_loc(self, loc): [ node, name ] = separate_node( loc ) module = [ self.modules[ m ] for m in self.modules if self.modules[ m ].id == node ] if not module: return None return module[ 0 ] def draw(self, window): if not window: return self.logger.warning("Requested draw to Nonetype.") for m in self.exterior_objects: m.draw(window) for m in self.modules.values(): m.draw(window) for a in self.actors: self.actors[a].draw(window)