""" world.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.
"""

import whrandom

from event import *
from thing import thing
from debug import debug
import dictlist, wtime
from misc import *

class filter:
    def __init__(self):
        self.types={}
    def analyse(self,e):
        str=e.generate_type_string()
        self.types[str]=e.copy()
    def print_types(self):
        for t in self.types.keys():
            print t,":"
            print "\t",self.types[t],"\n"

#whole world
class world:
    "whole world"
    def __init__(self):
        self.next_id=0
        self.things={}
        self.time=wtime.world_time()
        self.events=[]
        self.event_dict={}
        self.id_dict={}
        self.filt=filter()
        self.debug=debug("world.log")
        self.illegal_thing=thing(name="illegal",place=None,xyz=(0,0,0))
        self.id_dict['illegal']=self.illegal_thing
        self.new_events([event("make",what=self.illegal_thing)])
    def get_id(self,name):
        self.next_id=self.next_id+1
        return "_"+name+"_"+`self.next_id`
    def get_client_id(self):
        id=self.get_id("client")
        self.id_dict[id]="client"
        return id
    def add_thing(self,thing):
        "add thing to things list and assign it id"
        dictlist.add_value(self.things,thing.name,thing)
        id=self.get_id(thing.name)
        thing.id=id
        self.id_dict[id]=thing
        thing.w=self
    def remove_thing(self, thing):
        "remove thing from things list and set its id to illegal_thing"
        res=dictlist.remove_value(self.things, thing)
        self.id_dict[thing.id]=self.illegal_thing #reserve id indefinitely
        thing.w=None
        return res
    def get_thing_list(self):
        "return list of things"
        res=[]
        for tl in self.things.values():
            res=res+tl
        return res
    def __str__(self):
        s=str(self.time)+"\n"
        for t in self.get_thing_list(): s=s+", "+`t`
        return s
    def __repr__(self): return `"world"`
    def destroy(self):
        for tl in self.things.values():
            for t in tl:
                t.destroy()
##     def look_all(self):
##         res=[]
##         for t in self.get_thing_list():
##             res.append(event('look',what=t.id,loc=t.get_xyz()))
##         return res
    #event handling: 
    #m has current thing, e is current event(=output) from that thing
    #may update self.events
    def make_event(self,e,m):
        t=e.what
        if not hasattr(t,"is_thing"):
            #it's ething
            if not hasattr(t,"type"): t.type="thing"
            tc=get_thing_class(t.type)
            t=apply(tc,(),t.kw)
        self.add_thing(t)
        e.what=t.get_ething()
        return [event("sight",what=e)]
    def destroy_event(self,e,m):
        if e.what.id!="_illegal":
            if self.remove_thing(e.what):
                return [event("sight",what=e)]
##     def look_event(self,e,m):
##         try:
##             t=self.id_dict[e.what]
##             self.events.append(event("look",source=m,
##                                      what=ething(t.id,name=t.name,type=t.get_type())))
##         except KeyError:
##             pass
    def time_event(self,e,m):
        return [event("time",what=str(self.time))]
    def debug_event(self,e,m):
        d=[str(self.time),[e],[]]
        if e.what=="on":
            self.debug.set(1)
            self.debug(d)
        else:
            self.debug(d)
            self.debug.set(0)
    def undefined_event(self,e,m):
        return [e]
    def filter_event(self,e):
        self.filt.analyse(e)
    def analyse_event(self,e,m=None):
        """m has current mind, e is current event(=output) from that mind
           may update self.event"""
        if not e.source: e.source=m
        if not e.time: e.time=self.time
        self.filter_event(e)
        return get_event_func(self,e)(e,m)
    def analyse_input(self,input,m=None):
        """m has current mind, e is current event(=output) from that mind
           may update self.event"""
        output=[]
        for e in input:
            res=self.analyse_event(e,m)
            if res:
                for o in res:
                    self.filter_event(o)
                    output.append(o)
        return output
    def new_events(self,input):
        output=self.analyse_input(input)
        self.debug(["new_events: "+str(self.time),input,output])
        self.events=self.events+output
        return output
    def run_step(self):
        #age all things
        self.time.step()
        for tl in self.things.values():
            for t in tl: t.age=t.age+self.time.stepseconds
        #add sight events about houses
        #CHEAT!: not effective and doesn't take into account range or obstacles
        for h in self.things.get('house',[]):
            self.events.append(event("sight",what=h))
        #let minds think
        output=[]
        #separate targeted and non targeted events
        tevents={}
        events=[]
        for e in self.events:
            if e.target:
                if tevents.has_key(e.target.id):
                    tevents[e.target.id].append(e)
                else:
                    tevents[e.target.id]=[e]
            else:
                events.append(e)
        #fire events
        for t in self.get_thing_list():
            elist=tevents.get(t.id,[])+events
            res=t.run_step(self.time,elist)
            if res: #optimize away null message lists
                output.append([t,res])
        self.events=[]
        for (m,mo) in output:
            for e in mo:
                #m has current mind, e is current event(=output) from that mind
                res=self.analyse_event(e,m)
                if res:
                    self.events=self.events+res
                
        self.debug([str(self.time),output,self.events])
        return self.events

    Source: geocities.com/siliconvalley/station/4279/src

               ( geocities.com/siliconvalley/station/4279)                   ( geocities.com/siliconvalley/station)                   ( geocities.com/siliconvalley)