""" 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)+\
""+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+""+name+">"
self.l=[]
for var in var_list[1:]:
self.strv(var)
return beg+string.join(self.l,"\n")+""+name+">\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")+""