""" event.py Copyright (C) 1998 Aloril This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ------------------------------------------------------------ see event doc string ething(id,name="foo",type="thing.mind") event("look",what=ething(id,name="foo",type="thing.mind")) event("say",what=esay(?,?)) Some examples of messages: "event('make',what=ething('_Nisuf3',name='Nisuf',type='farmer'),loc=(20, 50, 300))" "event('destroy', what='_Nisuf3')" "event('move', what='_Nisuf3', loc=(-50, 50, 290))" "event('move', what='_axe10', loc='_Nisuf3')" "event('fire', what='_fire', loc='_house2', target='_house2')" """ import string,re from types import * id_pat=re.compile(r"_(.*)_(\d+)") class id_unknown(Exception): pass class event_base: def str_value(self, value, name=""): t=type(value) if t==StringType: if value[0]=="_": m=id_pat.match(value) return ''+m.group(1)+"" return value elif t==TupleType and len(value)==3: if name!="xyz": return ""+`value`+"" elif t==InstanceType: if isinstance(value,event_base): return str(value) elif hasattr(value,"is_thing"): return self.str_value(value.id) elif name=="interlinguish": l=[] for v in value: l.append(str(v)) return string.join(l,"\n") return `value` def strv(self, var): value=self.__dict__[var] if value: return self.l.append("<"+var+">"+\ self.str_value(value,var)+\ "") else: return "" def reprv(self, var): value=self.__dict__[var] if value: self.l.append(var+"="+`value`) def type_str_(self,var): value=self.__dict__[var] t=type(value) if t==StringType: if value[0]=='_': return 'id' else: return 'string' elif t in [IntType,FloatType]: return 'number' elif t in [TupleType,ListType]: if len(value)==3: return 'xyz' else: return 'list' elif t==InstanceType: if isinstance(value,ething): return 'ething(..)' elif isinstance(value,esay): return 'esay(..)' elif isinstance(value,event): return value.generate_type_string() elif hasattr(value,"is_thing"): return 'id' elif value.__class__.__name__=="world_time": return 'time' else: return 'other_instance:'+value.__class__.__name__ elif t==NoneType: return "" else: return 'other:'+`t` def type_str(self,var): str=self.type_str_(var) if str: self.l.append(var+":"+str) def __str__(self): beg=self.str_beg() name=self.xml_name var_list=self.var_list if len(var_list)<=1: return beg+"" self.l=[] for var in var_list[1:]: self.strv(var) return beg+string.join(self.l,"\n")+"\n" def __repr__(self): name=self.__class__.__name__ var_list=self.var_list if len(var_list)==0: return name+"()" elif len(var_list)==1: return name+"("+`getattr(self,var_list[0])`+")" self.l=[] for var in var_list[1:]: self.reprv(var) return name+"("+`getattr(self,var_list[0])`+","+string.join(self.l,",")+")" def generate_type_string(self): name=self.__class__.__name__ var_list=self.var_list if len(var_list)==0: return name+"()" elif len(var_list)==1: return name+"("+`getattr(self,var_list[0])`+")" self.l=[] for var in var_list[1:]: self.type_str(var) return name+"("+`getattr(self,var_list[0])`+","+string.join(self.l,",")+")" class event(event_base): #__dict__ doesn't define order """this is main method of communication between things EVENT ATTRIBUTES types: id string: it starts with underscore, then name, then unique integer Example: "_Nisuf_5" 12222234 1: All strings that start with underscore are id strings 2: For debugging 3: Separator 4: Unique integer id not all these are needed (command and what are always needed) command: type of event: examples: "move", "make", "destroy", "say", "fire" type: string source: sender of event (world sets this if not set) type: id string target: receiver of event (you should set this for any thing that changes things, for example delete and change events) type: id string (in future also others, like: circle(loc,radius) desc: description of event type: string what: to what thing event relates or operates type: id string type string or ething or esay or string (attribute name) or (inside server actual thing) what_desc: description of above type: string loc: location of event type: id string or tuple (x,y,z) will likely change to: (id string, (x,y,z)) format loc_desc: description of above type: string amount: how big fire, how strong visual signal, how much to change object type: type of attribute that is changed time: time of event (world sets this if not set) type: mktime compatible tuple: (612, 1, 6, 8, 0, 0.0, 0, 6, -1) DIFFERENT COMMANDS: command "make": what="thing to make" as string or ething optional desc=for example "birth" optional loc=place for thing to appear (otherwise it appears in what issued event) issuers: mind: event("make",what="axe", what_desc="ordinary axe") body: event("make", desc="birth", what=ething(...)) house: event("make",what=fire) command "destroy": what=id string of thing to destroy command "change": what=what to change (is string or attribute name) amount=amount of change Here 'what' could be attribute name instead of id of thing. If target doesn't have that attribute it's initialized to given amount. Otherwise it's added to given amount. If 'what' is an id, then status attribute is changed. Target then would have id of target or in future some area or maybe some Python code or if not set then everything is changed. command "look": what=like change target=like change Will result in sight event, where 'what' is asked thing: if asked thing was attribute, then 'what' is its value if asked thing was id (or not defined), then return all attributes as ething source=target in look event command "move": what=what to move loc=location to move into command "cut": CHEAT! (will likely change) what=what thing is used in cutting command "sight": what=event (for example move, destroy or make) or ething command "say": what=esay command "sound" (not used yet): what=event command "fire": what=fire loc=place of fire (for observers) target=target of fire amount=how big it is command "extinguish": what=fire to extinguish target=same as what command "goal": what=resulting event list from decision, example: [event('move',source='_farmer',target='_farmer',what='_farmer', loc=(12.5431347914, 95.4016955914, 265.44628788))] what_desc=decision derivation string, example: goal('find place for home and build it'). goal('find place for home and make it'). goal('find place for home not too near or far from others'). find_place() command "illegal": what=event what_desc=description about what's wrong: source_xyz, target_xyz command "debug": what=on or off command "NYI" (Not Yet Implemented): desc=description about what should have been implemented command "imaginary": desc=description about what events happened ;-) command "empty" (NOP, not really used) metaevents for engine.py: command "step" (run one tick in world) """ var_list=["command", "source", "target", "desc", "what", "what_desc", "loc", "loc_desc", "amount", "time"] is_event=1 xml_name="event" def __init__(self, command, source=None, target=None, desc=None, what=None, what_desc=None, loc=None, loc_desc=None, amount=None, time=None): self.command=command self.source=source self.target=target self.desc=desc self.what=what self.what_desc=what_desc self.loc=loc self.loc_desc=loc_desc self.amount=amount self.time=time def str_beg(self): return "<"+self.xml_name+' command="'+self.command+'">' def copy(self): e=event(self.command, self.source, self.target, self.desc, self.what, self.what_desc, self.loc, self.loc_desc, self.amount, self.time) try: if hasattr(e.what,"is_event"): e.what=e.what.copy() except AttributeError: pass return e def replace_thing_with_id(self): if hasattr(self.source,"is_thing"): self.source=self.source.id if hasattr(self.target,"is_thing"): self.target=self.target.id if hasattr(self.what,"is_thing"): self.what=self.what.id elif hasattr(self.what,"is_event") or isinstance(self.what,esay): self.what=self.what.replace_thing_with_id() if hasattr(self.loc,"is_thing"): self.loc=self.loc.id return self def replace_id_with_thing(self,find_thing): try: if type(self.source)==StringType and self.source[0]=='_': self.source=find_thing(self.source) if type(self.target)==StringType and self.target[0]=='_': self.target=find_thing(self.target) if type(self.what)==StringType and self.what[0]=='_': self.what=find_thing(self.what) elif hasattr(self.what,"is_event") or isinstance(self.what,esay): self.what=self.what.replace_id_with_thing(find_thing) elif isinstance(self.what,ething): t=self.what if hasattr(t,"copy") and \ type(t.copy)==StringType and \ t.copy[0]=='_': t.kw['copy']=t.copy=find_thing(t.copy) if type(self.loc)==StringType and self.loc[0]=='_': self.loc=find_thing(self.loc) return self except id_unknown, id: raise id_unknown, (id[0], self) class ething(event_base): """ first is id or when thing doesn't yet exist, then use name as id type: what kind of thing is going to be created (example: "farmer") other attributes are attributes for thing (like: sex="female") Examples: ething("Nisuf",type="farmer",sex="male") ething("_Nisuf3",name="Nisuf",type="thing.vbody.body.farmer",sex="male") """ var_list=["id", "name", "type"] xml_name="thing" def __init__(self, id, **kw): if not kw.has_key("name"): kw["name"]=id self.var_list=["id"]+kw.keys() self.id=id self.__dict__.update(kw) self.kw=kw def str_beg(self): return "<"+self.xml_name+">"+self.str_value(self.id)+"\n" class esay(event_base): """ verb: string subject: string or id string object: string or id string adjective: string type: string string: string (this is for PC to PC communication) examples: esay('',verb='own',subject='_Nisuf',object='_house') esay('',verb='know',subject='axe',object='smithy') esay('',verb='know',subject='smithy',object=(20, 10, 305)) esay('',verb='learn',subject='chop trees',object= "cut_something(self,'chop trees', 'winter', 'forest','axe')") """ var_list=["string","interlinguish", "verb","subject","object","adjective","type"] xml_name="say" def __init__(self, string="", interlinguish=[], verb="", subject="", object="", adjective="", type=""): self.string=string self.interlinguish=interlinguish self.verb=verb self.subject=subject self.object=object self.adjective=adjective self.type=type def str_beg(self): return "<"+self.xml_name+">"+self.string def replace_thing_with_id(self): if hasattr(self.subject,"is_thing"): self.subject=self.subject.id if hasattr(self.object,"is_thing"): self.object=self.object.id return self def replace_id_with_thing(self,find_thing): sub=self.subject if type(sub)==StringType and len(sub) and sub[0]=='_': self.subject=find_thing(sub) obj=self.object if type(obj)==StringType and len(obj) and obj[0]=='_': self.object=find_thing(obj) return self def get_dict_func(self, dict, func_str, func_undefined): try: return dict[func_str] except KeyError: try: func=dict[func_str]=getattr(self,func_str) except AttributeError: func=dict[func_str]=func_undefined return func def get_event_func(self,e): return get_dict_func(self,self.event_dict, e.command+"_event",self.undefined_event) def events_replace_thing_with_id(self, input): input2=map(event.copy,input) return map(event.replace_thing_with_id,input2) def events_replace_id_with_thing(self, input): return map(event.replace_id_with_thing, input,[self.find_thing_by_id]*len(input)) def xml_event_list(el,time=None): l=map(str,el) if time: return ''+string.join(l,"\n")+"" return ""+string.join(l,"\n")+""