""" mind.py Copyright (C) 1998-1999 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. """ from copy import copy from types import * from thing import thing from event import * from know import know from mem_map import mem_map from vmind import vmind from debug import debug import wtime,mgoal import dictlist, const, geometry, mgoal import interlinguish il=interlinguish import ontology ont=ontology class dead(Exception): pass rev_cmp={'>':'<'} class memory: def __init__(self): self.events=[] self.places={} def destroy(self): self.events=None self.places=None def remember_place(self, place): self.places[place.get_xyz()]=place def recall_place(self, xyz, radius=0): if not radius: try: return [(0.0,self.places[xyz])] except KeyError: return [] res=[] for p in self.places.keys(): d=geometry.distance(p,xyz) if d<=radius: res.append((d,self.places[p])) res.sort() return res def remember_event(self, event): "add new memory with age" self.events.append([event,1.0]) def recall_event(self, event, cmp): "return list of memories with same command" found=[] for (e,age) in self.events: if apply(cmp,(event,e)): found.append(e) return found def forget(self): "age memories and forgot too old ones" for m in self.events: m[1]=m[1]-0.1 #remove forgotten things self.events=filter(lambda m:m[1]>const.fzero,self.events) class eye(thing): def __init__(self, mind): thing.__init__(self, name=mind.name) self.mind=mind def destroy(self): self.mind=None def move_event(self,e): m=self.mind target=e.loc w=e.what if e.loc==m: m.add_thing(w) #if its part of inventory, use its xyz if hasattr(target,"xyz"): w.xyz=None w.place=target else: w.xyz=target w.place=None if w==m and not m.place: m.place=m.get_rknowledge("xyz",w.xyz) def make_event(self,e): m=self.mind if e.source==m: m.add_thing(e.what) if e.desc=="birth": return self.mind.teach_children(e.what) def change_event(self,e): t=e.what t.status=t.status+e.amount def fire_event(self,e): m=self.mind if e.loc!=m.place: return [event("move",what=m, loc=e.loc)] return [event("extinguish",what=e.what, target=e.what)] def destroy_event(self,e): return self.mind.destroy_event(e) class speech(thing): def __init__(self, mind): thing.__init__(self, name=mind.name) self.mind=mind self.verb_dict={} self.iverb_dict={} def destroy(self): self.mind=None #verb handling def know_verb(self,e,say): m=self.mind sub=say.subject obj=say.object if type(obj)==StringType: m.add_knowledge("place",sub,obj) else: m.add_knowledge("xyz",sub,obj) def learn_verb(self,e,say): self.mind.add_goal(say.subject,say.object) def own_verb(self,e,say): m=self.mind if say.subject==m: m.add_thing(say.object) def buy_verb(self,e,say): self=self.mind if e.source.id!=self.id: t=self.things.get(say.subject) if t: t=t[0] self.remove_thing(t) return [event("move", what=t, loc=e.source)] def _verb(self, e, say): if say.interlinguish: return self.interlinguish(e,say.interlinguish) print "<",e.command,":",`say`,">" #Interlinguish handling def be_verb1_i(self, e, say): m=self.mind res=il.match_importance(say) if res: return m.add_importance(res['sub'].id,'>',res['obj'].id) else: return self.print_ui("Unkown assertion:",e) def print_ui(self, msg, e): print msg,`e`,e.what.interlinguish[0].lexlink.id[1:] def _i(self, e,say): return self.print_ui("Unknown Interlinguish 'verb':",e) def interlinguish(self, e,say): v=say[0].lexlink.id[1:] method=get_dict_func(self,self.iverb_dict,v+"_i",self._i) return method(e,say) def analyse(self, e): say=e.what method=get_dict_func(self,self.verb_dict, say.verb+"_verb",self._verb) return method(e,say) class mind(vmind): "minds: (=npc)" def __init__(self,id): vmind.__init__(self,id) self.eyes=eye(self) self.speech_center=speech(self) self.knowledge=know() self.mem=memory() self.things={} self.reverse_knowledge() self.goals=[] self.debug=debug(self.name+".mind.log") def __str__(self): s="\n" return s+">\n" def destroy(self): thing.destroy(self) self.things=None self.mem.destroy() self.eyes.destroy() self.eyes=None raise dead def reverse_knowledge(self): self.rknow=know() for (k,v) in self.knowledge.xyz.items(): if not self.rknow.xyz.get(v): self.rknow.add("xyz",v,k) def get_rknowledge(self, what, key): d=getattr(self.rknow,what) return d.get(key) def get_knowledge(self, what, key): d=getattr(self.knowledge,what) return d.get(key) def add_knowledge(self,what,key,value): self.knowledge.add(what,key,value) if what=="xyz": self.rknow.add("xyz",value,key) def add_importance(self, sub, cmp, obj): self.add_knowledge('importance',(sub,obj),cmp) self.add_knowledge('importance',(obj,sub),rev_cmp[cmp]) def cmp_goal_importance(self, g1, g2): id1=g1.key[1] id2=g2.key[1] l1=ont.get_isa(id1) l2=ont.get_isa(id2) for s1 in l1: for s2 in l2: cmp=self.knowledge.importance.get((s1.id,s2.id)) if cmp: return cmp=='>' return 1 def add_goal(self, name, str_goal): goal=eval("mgoal."+str_goal) goal.str=str_goal if type(name)==StringType: goal.key=eval(name) else: goal.key=name self.add_knowledge("goal",name,goal) for i in range(len(self.goals)-1,-1,-1): if self.cmp_goal_importance(self.goals[i],goal): self.goals.insert(i+1,goal) return self.goals.insert(0,goal) def add_thing(self,thing): if not thing.xyz: thing.xyz=self.get_knowledge("xyz",thing.place) dictlist.add_value(self.things,thing.name,thing) def find_thing(self, thing): if StringType==type(thing): #return found list or empty list return self.things.get(thing,[]) found=[] for t in self.things.get(thing.name,[]): if t==thing: found.append(t) return found def remove_thing(self, thing): #I don't own this anymore (it may not exist) dictlist.remove_value(self.things, thing) #goal section def fulfill_goals(self,time): "see if all goals are fulfilled: if not try to fulfill them" for g in self.goals: res=g.check_goal(self,time) if res!=None: return res def teach_children(self, child): res=[] for k in self.knowledge.xyz.keys(): es=esay('',verb='know',subject=k,object=self.knowledge.xyz[k]) res.append(event('say',target=child,what=es)) for k in self.knowledge.place.keys(): es=esay('',verb='know',subject=k,object=self.knowledge.place[k]) res.append(event('say',target=child,what=es)) for g in self.goals: es=esay('',verb='learn',subject=g.key,object=g.str) res.append(event('say',target=child,what=es)) for im in self.knowledge.importance.keys(): cmp=self.knowledge.importance[im] if cmp=='>': s,i=il.importance(im[0],cmp,im[1]) es=esay(s,interlinguish=i) res.append(event('say',target=child,what=es)) return res #event handling: #e is current input event #may return new events def sight_event(self,e): t=e.what if hasattr(t,"command"): return self.eyes.analyse_event(t) elif hasattr(t,"is_thing"): #CHEAT: will be removed if string.find(t.type,"house")>=0: self.mem.remember_place(t) elif t.id==self.id: #CHEAT: not anymore used self.__dict__.update(t.kw) if type(self.place)==StringType and not self.xyz: self.xyz=self.get_knowledge("xyz",self.place) def destroy_event(self,e): self.remove_thing(e.what) id=e.what.id if self.map.things.has_key(id): del self.map.things[id] if e.what.id==self.id: self.destroy() return [] def say_event(self,e): #need something easier that just plain text #CHEAT! w=e.what if isinstance(w,esay): return self.speech_center.analyse(e) if hasattr(w,"is_thing"): self.add_thing(w) w.place=self.get_rknowledge("xyz",w.xyz) def think(self,time,input): output=None for e in input: res=self.analyse_event(e) #empty list is output too if res!=None and output==None: output=res if output!=None: return output output=self.fulfill_goals(time) if output==None: output=[] return output def run_step(self,time,input): """run one time step: try to achive all goals""" try: self.mem.forget() output=self.think(time,input) for e in output: self.mem.remember_event(e) if e.command=="move": if type(e.loc)==StringType: e.loc=self.get_knowledge("xyz",e.loc) except dead: output=[] self.debug([str(time),input,output]) return output