def transact(self, me): employer = me.get_knowledge('employer', me) if employer: print('Already employed by ' + employer) return Operation( "talk", Entity(say="Sorry, I am currently working for someone else.")) who = me.map.get(self.who) if not who: print("Who am I talking to") return if self.payed < self.cost: return Operation( "talk", Entity(say=who.name + " you owe me " + str(self.cost - self.payed) + " coins.")) res = Oplist() me.add_knowledge('employer', me.entity.id, who.id) # FIXME add the new goal goal = Accompany(who.id) me.goals.insert(0, goal) res.append( Operation("talk", Entity(say="I will help you out until sundown today."))) self.irrelevant = 1 return res
def completed(self): res = Oplist() # Find one charcoal and one ore amongst the children and delete them, and create one iron ingot. charcoals = self.usage.tool.find_in_contains(charcoal_filter) if len(charcoals): # We have charcoal, lets see if we also have something to smelt. We'll go through the map of ores to find a match. for key, value in ores.items(): inputs = self.usage.tool.find_in_contains(value) if len(inputs) > 0: res.append( Operation("delete", Entity(inputs[0].id), to=inputs[0])) res.append( Operation("delete", Entity(charcoals[0].id), to=charcoals[0])) new_entity = Entity(parent=key, loc=self.usage.tool.id) res.append( Operation("create", new_entity, to=self.usage.tool.id)) res.append( Operation( "imaginary", Entity( description="You successfully refine the ore." ), to=self.usage.actor.id, from_=self.usage.actor.id)) return res
def consume(instance): """ When drinking the potion the __effects should be applied to the drinker, and the potion destroyed. In addition, if a script handler is registered in the __handler property it will be called as well. """ op_list = Oplist() op_list += Operation("delete", Entity(instance.tool.id), to=instance.tool) handler_props = instance.tool.props["__handler"] if handler_props is not None: mod_name, func_name = handler_props["name"].rsplit('.', 1) mod = importlib.import_module(mod_name) func = getattr(mod, func_name) result = func(instance) if result: op_list.append(result) effects_prop = instance.tool.props["__effects"] if effects_prop is not None: # Copy over all props in "__effects" to a "set" op. for prop_name, effect in effects_prop.items(): ent = Entity(instance.actor.id) ent[str(prop_name)] = effect op_list += Operation("set", ent, to=instance.actor.id) msg_prop = instance.tool.props["__message"] if msg_prop is not None: op_list += Operation("imaginary", Entity(description=str(msg_prop)), to=instance.actor.id, from_=instance.actor.id) op_list.append(instance.actor.start_action("drinking", 1)) return server.OPERATION_BLOCKED, op_list
def do(self, me): if (self.tool in me.things) == 0: # print "No tool" return tool = me.find_thing(self.tool)[0] if not hasattr(me, 'right_hand_wield') or me.right_hand_wield != tool.id: # FIXME We need to sort out how to tell seed one is wielding return Operation("wield", Entity(tool.id)) id = me.get_knowledge('focus', self.seed) if id is None: return seed = me.map.get(id) if seed is None: me.remove_knowledge('focus', self.seed) return if not seed.visible: me.remove_knowledge('focus', self.seed) return # Check that the seed isn't too close to other sources (to prevent us from planting too closely) sources_all = me.map.find_by_filter(self.source_filter) for thing in sources_all: #TODO: add "distance_between"; this won't work dist = me.steering.distance_to(thing, ai.EDGE, ai.EDGE) if dist is not None and dist < self.spacing: # We've found a source which is too close to the seed, so we'll not plant this one me.remove_knowledge('focus', self.seed) return return Operation("use", Entity(seed.id, objtype="obj"))
def tick(self): (valid, err) = self.usage.is_valid() if not valid: return self.irrelevant(err) self.usage.actor.send_world(Operation("sight", self.usage.op)) target = self.usage.get_arg("targets", 0) instance = self.usage # Ignore pos if target: if instance.actor.can_reach(target): damage = 0 damage_attr = getattr(instance.actor.props, "damage_" + instance.op.parent) if damage_attr: damage = damage_attr hit_op = Operation('hit', Entity(damage=damage, hit_type=instance.op.parent, id=instance.actor.id), to=target.entity) return server.OPERATION_BLOCKED, hit_op, Operation( 'sight', hit_op) else: return server.OPERATION_BLOCKED, instance.actor.client_error( instance.op, "Too far away") else: return server.OPERATION_BLOCKED
def do_peck(self, me): if not self.last_time or time.time() - self.last_time > self.interval: self.last_time = time.time() # stop moving me.steering.set_destination() return Operation("use", Operation("consume", Entity(me.entity.id, targets=[Entity(me.entity.parent.id, pos=me.entity.location.pos)])))
def strike(instance): """Strike another entity with your fists.""" # If there's a cooldown we need to mark the actor cooldown = getattr(instance.tool.props, "cooldown_" + instance.op.parent) if cooldown and cooldown > 0.0: instance.tool.send_world(Operation('set', Entity(instance.tool.id, ready_at=server.world.get_time() + cooldown), to=instance.tool.id)) # Send sight even if we miss instance.actor.send_world(Operation("sight", instance.op)) # Unarmed strike only handles one target target = instance.get_arg("targets", 0) # Ignore pos if target: if instance.actor.can_reach(target): damage = 0 damage_attr = getattr(instance.actor.props, "damage_" + instance.op.parent) if damage_attr: damage = damage_attr hit_op = Operation('hit', Entity(damage=damage, hit_type=instance.op.parent), to=target.entity, id=instance.actor.id) return server.OPERATION_BLOCKED, hit_op, Operation('sight', hit_op) else: return server.OPERATION_BLOCKED, instance.actor.client_error(instance.op, "Too far away") else: return server.OPERATION_BLOCKED
def do(self, me): if (self.tool in me.things) == 0: # print "No tool" return tool = me.find_thing(self.tool)[0] if not hasattr(me, 'right_hand_wield') or me.right_hand_wield != tool.id: # FIXME We need to sort out how to tell seed one is wielding return Operation("wield", Entity(tool.id)) id = me.get_knowledge('focus', self.seed) if id is None: return seed = me.map.get(id) if seed is None: me.remove_knowledge('focus', self.seed) return if not seed.visible: me.remove_knowledge('focus', self.seed) return # Check that the seed isn't too close to other sources (to prevent us from planting too closely) sources_all = me.map.find_by_filter(self.source_filter) spacing_sqr = self.spacing * self.spacing for thing in sources_all: sqr_dist = square_distance(seed.location, thing.location) if sqr_dist and sqr_dist < spacing_sqr: # We've found a source which is too close to the seed, so we'll not plant this one me.remove_knowledge('focus', self.seed) return return Operation("use", Entity(seed.id, objtype="obj"))
def strike(instance): # Check that we can reach the target with our weapon extra_reach = 0.0 if instance.tool.props.reach: extra_reach = instance.tool.props.reach # If there's a cooldown we need to mark the actor Usage.set_cooldown_on_attached(instance.tool, instance.actor) # Send sight even if we miss instance.actor.send_world(Operation("sight", instance.op)) # Melee weapons only handles one target target = instance.get_arg("targets", 0) if target: # Ignore pos if instance.actor.can_reach(target, extra_reach): damage = 0 if instance.tool.props.damage: damage = instance.tool.props.damage hit_op = Operation('hit', Entity(damage=damage, hit_type=instance.op.id), to=target.entity) return server.OPERATION_BLOCKED, hit_op, Operation('sight', hit_op) else: return server.OPERATION_BLOCKED, instance.actor.client_error( instance.op, "Too far away") else: return server.OPERATION_BLOCKED
def hit_operation(self, op): res = Oplist() arg = op[0] if arg: # Place the explosion at the point of collision. new_location = rules.Location(self.location.parent, arg.pos) entity = Entity(parent="explosion", location=new_location, mode="fixed") mode_data = self.props.mode_data actor_id = self.id # Check if there's an entity ref contained in the mode_data prop, # and if so attach that to the "entity_ref" prop of the explosion. # This way the explosion can properly attribute any Hit op it sends to the actor which fired the item. if mode_data: entity_ref = mode_data['$eid'] if entity_ref is not None: actor_id = entity_ref entity["entity_ref"] = {"$eid": actor_id} damage_explosion = self.props.damage_explosion if damage_explosion is not None: entity["damage"] = damage_explosion res.append(Operation("create", entity, to=self.id)) res.append(Operation("delete", Entity(self.id), to=self.id)) return server.OPERATION_HANDLED, res
def sift_operation(self, op): newloc = self.location.copy() newloc.velocity = Vector3D() item = Gravestone.items[randint(0, 5)] newloc.pos = newloc.pos + Vector3D(uniform(-1, 1), uniform(-1, 1), uniform(-1, 1)) return Operation("create", Entity(name=item, parent=item, location=newloc.copy()), to=self) + \ Operation("imaginary", Entity(description="You dig up a bone from the grave."), to=op.id, from_=op.id)
def consume_operation(self, op): if len(op) > 0: arg = op[0] if arg.consume_type == "fire": # Determine the burn speed, i.e. how much to remove of the status for each burn burn_speed = 0.1 burn_speed_prop = self.props._burn_speed if burn_speed_prop: burn_speed = burn_speed_prop nourish_ent = Entity() nourish_ent.consume_type = arg.consume_type nourish_op = Operation("nourish", nourish_ent, to=op.from_) status_prop = self.props.status if status_prop: return server.OPERATION_BLOCKED, nourish_op, Operation( "set", Entity(self.id, status=status_prop - burn_speed), to=self) else: return server.OPERATION_BLOCKED, nourish_op return server.OPERATION_IGNORED
def tick(self): (valid, err) = self.usage.is_valid() if not valid: return self.irrelevant(err) self.usage.actor.send_world(Operation("sight", self.usage.op)) target = self.usage.get_arg("targets", 0) if target: # Take a swing extra_reach = 0.0 if self.usage.tool.props.reach: extra_reach = self.usage.tool.props.reach if self.usage.actor.can_reach(target, extra_reach): damage = 0 if self.usage.tool.props.damage: damage = self.usage.tool.props.damage hit_op = Operation('hit', Entity(damage=damage, hit_type=self.usage.op.parent, id=self.usage.actor.id), to=target.entity) return server.OPERATION_BLOCKED, hit_op else: return server.OPERATION_BLOCKED, self.usage.actor.client_error( self.usage.op, "Too far away") return server.OPERATION_BLOCKED
def hit_operation(self, op): arg = op[0] if arg: hit_op = op.copy() res = Oplist() if hasattr(arg, 'damage'): # Apply any armor modifiers armor = self.get_prop_float("armor", 0) status_decrease = (arg.damage - armor) / 100.0 # Check if there's a modifier for the specific type of hit. if hasattr(arg, 'hit_type') and self.props["__modifier_hit_type_" + arg.hit_type]: status_decrease = status_decrease * self.props[ "__modifier_hit_type_" + arg.hit_type] print("Hit for {} damage".format(status_decrease)) status_decrease = max( 0.0, status_decrease) # Make sure it's not negative hit_op[0].damage = status_decrease if status_decrease > 0: res.append( Operation("set", Entity(self.id, {"status!subtract": status_decrease}), to=self.id)) return server.OPERATION_BLOCKED, res, Operation('sight', hit_op) return server.OPERATION_IGNORED
def delete_operation(self, op): res = Oplist() # Restore status if it's zero. if self.has_prop_float("status"): res += Operation("set", Entity(self.id, status=1.0), to=self.id) # Respawn in a spawn area respawn_alias = self.get_prop_string("_respawning") if respawn_alias: respawn_entity = server.get_alias_entity(respawn_alias) if respawn_entity: pos = Spawner.get_spawn_pos(respawn_entity) if pos: location = Location() location.pos = pos # Randomize orientation rotation = random.random() * math.pi * 2 location.orientation = physics.Quaternion(physics.Vector3D(0, 1, 0), rotation) location.parent = respawn_entity.location.parent # Emit a sight of this entity being defeated res += Operation("sight", Operation("defeated", Entity(self.id))) res += Operation("move", Entity(self.id, location=location), to=self.id) res += Operation("imaginary", Entity(description="You were killed and will be respawned."), to=self.id, from_=self.id) return server.OPERATION_BLOCKED, res
def completed(self): res = Oplist() if self.is_valid(): for input_def in self.temporaries["inputs"]: input_entities = self.usage.actor.find_in_contains( input_def["criteria"]) needed_amount = input_def["amount"] for entity in input_entities: entity_amount = entity.get_prop_int("amount", 1) amount_to_delete = min(needed_amount, entity_amount) res.append( Operation("delete", Entity(entity.id, amount=amount_to_delete), to=entity)) needed_amount = needed_amount - amount_to_delete if needed_amount <= 0: break for output_def in self.temporaries["outputs"]: res.append( Operation("create", output_def, to=self.usage.tool.id)) craft_name = self.usage.tool.get_prop_string("craft_name", "tool") res.append( Operation( "imaginary", Entity(description="You successfully create '{}'.".format( craft_name)), to=self.usage.actor.id, from_=self.usage.actor.id)) return res
def tick_operation(self, op): if len(op) > 0: arg = op[0] if arg.name == self.__class__.__name__: res = Oplist() # Handle the world being recreated by checking for 0 if op.refno == self.tick_refno or self.tick_refno == 0: minds_prop = self.get_prop_list("_minds") if hasattr(arg, "type") and arg.type == "remove": # Check that the entity hasn't gotten a new mind in the meantime if minds_prop is None or len(minds_prop) == 0: # Move entity to limbo limbo_entity = server.get_alias_entity("limbo") if limbo_entity and self.location.parent != limbo_entity: # Store the current position in "__respawn" so we can spawn back there. res += Operation( "set", Entity(self.id, __respawn={ "loc": self.location.parent.id, "pos": self.location.pos }), to=self.id) res += Operation("move", Entity(self.id, loc=limbo_entity.id), to=self.id) else: # Only respawn if there's a mind if minds_prop is not None and len(minds_prop) > 0: res += self.respawn() return server.OPERATION_BLOCKED, res
def respawn(self): limbo_entity = server.get_alias_entity("limbo") # If we're in limbo we should respawn if limbo_entity and self.location.parent == limbo_entity: respawn_prop = self.props["__respawn"] if respawn_prop: set_op = Operation("set", Entity(self.id, __respawn=None), to=self.id) if hasattr(respawn_prop, "pos") and hasattr( respawn_prop, "loc"): return Operation("move", Entity(self.id, pos=respawn_prop.pos, loc=respawn_prop.loc), to=self.id), set_op elif hasattr(respawn_prop, "spawn") and respawn_prop.spawn: # Respawn in a spawn area respawn_entity = server.get_alias_entity( respawn_prop.spawn) if respawn_entity: location = respawn_entity.location return Operation("move", Entity(self.id, location=location), to=self.id), set_op else: print( "Could not get any entity with alias '{}'.".format( respawn_prop.spawn))
def tick_operation(self, op): res = Oplist() if Ticks.verify_tick(self, op, res, self.tick_interval): # Make ourselves go away after ten ticks by decreasing our status. res.append( Operation("set", Entity(self.id, {"status!subtract": 0.1}), to=self.id)) damage_prop = self.props.damage if self.parent and damage_prop is not None: # If there's an "entity_ref" prop it's the reference to the actor which caused the poisoning. actor_id = self.id entity_ref_prop = self.props.entity_ref if entity_ref_prop is not None: actor_id = entity_ref_prop["$eid"] res.append( Operation('hit', Entity(hit_type="poison", id=actor_id, damage=damage_prop), to=self.parent.id)) return server.OPERATION_HANDLED, res return server.OPERATION_IGNORED
def equip_melee_weapon(self, me): # First check if we're holding a weapon attached_current = me.get_attached_entity("hand_primary") has_attached = False if attached_current: has_attached = True # Check that the attached entity can be used to strike usages = attached_current.get_prop_map("usages") if usages: for usage, _ in usages.items(): if usage in weapon_usages: self.weapon_usage = usage return None # Current tool isn't a weapon, or we have nothing attached, try to find one, # and if not unequip so we can fight with our fists for child in me.entity.contains: usages = child.get_prop_map("usages") if usages: for usage, _ in usages.items(): if usage in weapon_usages: self.weapon_usage = usage return Operation("wield", Entity(child.id, attachment="hand_primary")) # Couldn't find any weapon to wield, check if we should unwield the current tool so we can fight with our fists if has_attached: return Operation("wield", Entity(attachment="hand_primary")) return None
def attack_ranged(self, me): enemy = self.get_enemy(me) # check that we can reach the target, and if so attack it distance = me.steering.distance_to(enemy, ai.EDGE, ai.EDGE) if distance is None: print("Could not calculate distance.") return attached_current = me.get_attached_entity("hand_primary") tasks_prop = me.entity.get_prop_map('tasks') if distance < 50: move_to_face = me.face(enemy) if attached_current: # Check if we're already drawing if tasks_prop and "draw" in tasks_prop: # Check if we can release draw_task = tasks_prop["draw"] # print("draw task {}".format(str(draw_task))) usages = draw_task["usages"] for usage in usages: if usage.name == "release": direction = (enemy.location.pos + enemy.location.bbox.center) - (me.entity.location.pos + me.entity.location.bbox.center) direction.normalize() return move_to_face + Operation("use", Root(args=[Entity("release", direction=[direction])], id="draw", objtype="task")) return True direction = enemy.location.pos - me.entity.location.pos direction.normalize() return move_to_face + Operation("use", Operation("draw", Entity(attached_current.id, direction=[direction])))
def do_strike(self): self.usage.actor.send_world(Operation("sight", self.usage.op)) # If there's a cooldown we need to mark the actor Usage.set_cooldown_on_attached(self.usage.tool, self.usage.actor) target = self.usage.get_arg("targets", 0) if target: # Take a swing # Check that we can reach the target with our weapon extra_reach = 0.0 if self.usage.tool.props.reach: extra_reach = self.usage.tool.props.reach if self.usage.actor.can_reach(target, extra_reach): damage = 0 if self.usage.tool.props.damage: damage = self.usage.tool.props.damage hit_op = Operation('hit', Entity(damage=damage, hit_type=self.usage.op.parent, id=self.usage.actor.id), to=target.entity) return server.OPERATION_BLOCKED, hit_op else: return server.OPERATION_BLOCKED, self.usage.actor.client_error(self.usage.op, "Too far away") else: print("No target") return server.OPERATION_BLOCKED
def harvest_operation(self, op): res = Oplist() if self.props.fruits and self.props.fruits > 0 and self.props.fruit_name: res.append( Operation("create", Entity(parent=self.props.fruit_name, loc=op.id), to=self)) res.append( Operation("set", Entity(self.id, {"fruits!subtract": 1}), to=self)) res.append( Operation( "imaginary", Entity(description="You harvest an {} from the {}.".format( self.props.fruit_name, self.type)), to=op.id, from_=op.id)) else: res.append( Operation( "imaginary", Entity( description="There aren't any {}s in this {}.".format( self.props.fruit_name, self.type)), to=op.id, from_=op.id)) return server.OPERATION_BLOCKED, res
def stop_usage(self, args): # Check that the usage still is valid (valid, _) = self.usage.is_valid() self.irrelevant() res = Oplist() if valid and self.fish_on_hook: worms = self.usage.actor.find_in_contains( entity_filter.Filter("entity instance_of types.annelid")) if len(worms): fish_type = self.fishes[randint(0, len(self.fishes) - 1)] res.append( Operation("create", Entity(parent=fish_type, loc=self.usage.actor.id, mind=None), to=self.usage.tool)) # Delete the worm res.append( Operation("delete", Entity(id=worms[0].id), to=worms[0].id)) res.append( Operation( "imaginary", Entity( description="You caught a {}.".format(fish_type)), to=self.usage.actor.id, from_=self.usage.actor.id)) return server.OPERATION_HANDLED, res
def event(self, me, op, say): object = say[1].word thing = me.map.get(object) who = me.map.get(op.to) if thing is None: if object != self.what: return Operation("talk", Entity(say=who.name + ", I am not interested in buying your " + str(object) + ".")) me.goals.insert(0, BuyFrom(self.what, self.cost, op.to)) return Operation("talk", Entity(say=who.name + " which " + object + " would you like to sell?")) if self.what not in thing.type: return if thing in me.find_thing(self.what): return # price=me.get_knowledge("price", thing.type[0]) price = self.cost * int(thing.mass) res = Oplist() coins = me.find_thing("coin") if len(coins) < int(price): print("Coins: " + str(len(coins)) + " Cost: " + str(self.cost)) return Operation("talk", Entity(say="I can't afford any " + self.what + "s at the moment.")) for i in range(0, int(price)): coin = coins[0] me.remove_thing(coin) res.append(Operation("move", Entity(coin.id, location=Location(who, Point3D(0, 0, 0))))) res.append(Operation("talk", Entity(say="Thankyou " + who.name + ", come again."))) me.add_thing(thing) return res
def think_look_operation(self, op): """Sends back information about goals. This is mainly to be used for debugging minds. If no arguments are specified all goals will be reported, else a match will be done using 'index'. The information will be sent back as a Think operation wrapping an Info operation. This method is automatically invoked by the C++ BaseMind code, due to its *_*_operation name. """ think_op = Operation("think") goal_info_op = Operation("info") goal_infos = [] if not op.get_args(): # get all goals for (index, goal) in enumerate(self.goals): goal_infos.append(Entity(index=index, report=goal.report())) else: for arg in op.get_args(): goal = self.goals[arg.index] if goal and goal is not None: goal_infos.append( Entity(index=arg.index, report=goal.report())) goal_info_op.set_args(goal_infos) think_op.set_refno(op.get_serialno()) think_op.set_args([goal_info_op]) res = Oplist() res = res + think_op return res
def consume(instance): """ When drinking the potion the __effects should be applied to the drinker, and the potion destroyed """ op_list = Oplist() op_list += Operation("delete", Entity(instance.tool.id), to=instance.tool) effects_prop = instance.tool.props["__effects"] if effects_prop is not None: for prop_name, effect in effects_prop.items(): actual_value = effect effect_prop = instance.actor.props[prop_name] if effect_prop is not None: actual_value = effect_prop + effect ent = Entity(instance.actor.id) ent[str(prop_name)] = actual_value op_list += Operation("set", ent, to=instance.actor.id) msg_prop = instance.tool.props["__message"] if msg_prop is not None: op_list += Operation("imaginary", Entity(description=str(msg_prop)), to=instance.actor.id, from_=instance.actor.id) return server.OPERATION_BLOCKED, op_list
def xp_property_update(self): xp = self.get_prop_float("xp") if xp is not None: level_from_xp = int(math.floor(xp / 100)) level = self.get_prop_int("level") if level is None or level != level_from_xp: return Operation("set", Entity(self.id, level=level_from_xp), to=self.id), \ Operation("imaginary", Entity(description="You are now at level {}!".format(level_from_xp)), to=self.id, from_=self.id)
def burn_operation(self, op): ret = Oplist() for fuel in self.contains: if hasattr(fuel, "burn_speed"): ret.append(Operation("burn", op[0], to=fuel)) if op[0].props.status > 1.0: to_ = op[0].id ret.append(Operation("extinguish", op[0], to=to_)) return ret
def process(self, me): if (self.wbuy in me.things) == 0: return if (self.tool in me.things) == 0: return tool = me.find_thing(self.tool)[0] if not self.wield: self.wield = True return Operation("wield", Entity(tool.id)) thing = me.find_thing(self.wbuy)[0] return Operation("use", Entity(thing.id, objtype="obj"))
def commune_path(self, op): """Sends back information about the path.""" think_op = Operation("think") path = [] my_path = self.path # print("path size: " + str(len(my_path))) for point in my_path: path.append([point.x, point.y, point.z]) think_op.set_args([Entity(path=path, current_path_index=self.current_path_index)]) res = Oplist() res = res + think_op return res
def think_look_operation(self, op): """Sends back information about goals. This is mainly to be used for debugging minds. If no arguments are specified all goals will be reported, else a match will be done using 'index'. The information will be sent back as a Think operation wrapping an Info operation. This method is automatically invoked by the C++ BaseMind code, due to its *_*_operation name. """ think_op = Operation("think") goal_info_op = Operation("info") goal_infos = [] if not op.get_args(): # get all goals for (index, goal) in enumerate(self.goals): goal_infos.append(Entity(index=index, report=goal.report())) else: for arg in op.get_args(): goal = self.goals[arg.index] if goal and goal is not None: goal_infos.append(Entity(index=arg.index, report=goal.report())) goal_info_op.set_args(goal_infos) think_op.set_refno(op.get_serialno()) think_op.set_args([goal_info_op]) res = Oplist() res = res + think_op return res
def commune_all_thoughts(self, op, name): """Sends back information on all thoughts. This includes knowledge and goals, as well as known things. The thoughts will be sent back as a "think" operation, wrapping a Set operation, in a manner such that if the same think operation is sent back to the mind all thoughts will be restored. In this way the mind can support server side persistence of its thoughts. A name can optionally be supplied, which will be set on the Set operation. """ think_op = Operation("think") set_op = Operation("set") thoughts = [] for what in sorted(self.knowledge.knowings.keys()): d = self.knowledge.knowings[what] for key in sorted(d): if what != "goal": object_val = d[key] if type(object_val) is Location: # Serialize Location as tuple, with parent if available if object_val.parent is None: location = object_val.position else: location = ("$eid:" + object_val.parent.id, object_val.pos) goal_object = str(location) else: goal_object = str(d[key]) thoughts.append(Entity(predicate=what, subject=str(key), object=goal_object)) if len(self.things) > 0: things = {} for (id, thinglist) in sorted(self.things.items()): idlist = [] for thing in thinglist: idlist.append(thing.id) things[id] = idlist thoughts.append(Entity(things=things)) if len(self.pending_things) > 0: thoughts.append(Entity(pending_things=self.pending_things)) set_op.set_args(thoughts) think_op.set_args([set_op]) if not op.is_default_serialno(): think_op.set_refno(op.get_serialno()) if name: set_op.set_name(name) res = Oplist() res = res + think_op return res
def tick_operation(self, op): """periodically reassess situation This method is automatically invoked by the C++ BaseMind code, due to its *_operation name. """ args = op.get_args() if len(args) != 0: if args[0].name == "think": # It's a "thinking" op, which is the base of the AI behaviour. # At regular intervals the AI needs to assess its goals; this is done through "thinking" ops. op_tick = Operation("tick") # just copy the args from the previous tick op_tick.set_args(args) op_tick.set_future_seconds(const.basic_tick + self.jitter) op_tick.set_to(self.id) for t in self.pending_things: thing = self.map.get(t) if thing and thing.type[0]: self.add_thing(thing) self.pending_things = [] result = self.think() if self.message_queue: result = self.message_queue + result self.message_queue = None return op_tick + result
def commune_goals(self, op, goal_entity): """Sends back information about goals only.""" think_op = Operation("think") set_op = Operation("set") thoughts = [] # It's important that the order of the goals is retained for goal in self.goals: if hasattr(goal, "str"): goal_string = goal.str else: goal_string = goal.__class__.__name__ thoughts.append(Entity(goal=goal_string, id=goal_string)) set_op.set_args(thoughts) think_op.set_args([set_op]) think_op.set_refno(op.get_serialno()) res = Oplist() res = res + think_op return res
def setup_operation(self, op): """called once by world after object has been made send first tick operation to object This method is automatically invoked by the C++ BaseMind code, due to its *_operation name.""" # CHEAT!: add memory, etc... initialization (or some of it to __init__) # Setup a tick operation for thinking think_tick_op = Operation("tick") think_tick_op.set_to(self.id) think_tick_op.set_args([Entity(name="think")]) # Setup a tick operation for moving move_tick_op = Operation("tick") think_tick_op.set_to(self.id) move_tick_op.set_args([Entity(name="move")]) move_tick_op.set_future_seconds(0.2) return Operation("look") + think_tick_op + move_tick_op